Доброе время суток!

Полтора месяца назад, в этом блоге я писал о идее быстрых заказов:
http://community.terrasoft.ua/blogs/3253

За это время идею воплотили в жизнь, немного изменили... Менеджерам понравилось :))
Модуль быстрых заказов включили в наше решение для дистрибьюторов: http://www.it-sfera.com.ua/ru/crm-reshenija/distribution/distribution-fu...

Проведу краткую презентацию подбора продуктов в счет (продукт в корзину добавляем нажатием клавиши Insert) с дальнейшей отгрузкой со склада: QuickOrdering-20090613.avi (5,3 Мб)

Нравится

Поделиться

5 комментариев

Как по мне - вариант быстрее, чем в стандартной коробке, но не самый быстрый в плане работы оператора. Если оператору необходимо заносить большое количество заявок в день - необходимы не значительные доработки самой логики выбора товара.
Но, в целом, супер!!!

Да, действительно впечетляет!

Спасибо!

С помощью "Корзины" можно так же формировать накладные с типом "Ожидание", которые потом одним действием превращаются в накладные с типом "Приход" :)

Вообще, там еще много всего интересного... ;) Мне этот наш проект очень нравится!

--
www.it-sfera.com.ua
Terrasoft Solution Partner

Да. Действительно интересная вещь. Нужно будет себе такое же сделать. :)

спасибо :)

--
www.it-sfera.com.ua
Terrasoft Solution Partner

Показать все комментарии

Предлагаю один из вариантов решения поставленной задачи.

1. В ds_InvoiceScript добавить функцию:

function ChangeCurrencyID(InvoiceID, CurrencyID) {
  if (IsEmptyValue(InvoiceID) || IsEmptyValue(CurrencyID)) {
   return;
   }
  if (!Assigned(InvoiceScript.OffDataset)) {
   InvoiceScript.OffDataset =
   Services.GetNewItemByUSI('ds_OfferingInInvoice');
   }
 var Dataset = InvoiceScript.OffDataset;
  Dataset.DisableEvents();
  ApplyDatasetFilter(Dataset, 'InvoiceID', InvoiceID, true);
  Dataset.Open();
 while (!Dataset.IsEOF) {
   Dataset.Edit();
   Dataset.Values('CurrencyID') = CurrencyID;
   Dataset.Post();
   Dataset.GotoNext();
  }
ApplyDatasetFilter(Dataset, 'InvoiceID', InvoiceID, false);
Dataset.Close();
}

2. В обработчике события OnDatasetAfterPost счета вставить вызов функции:
ChangeCurrencyID(Dataset.Values('ID'), Dataset.Values('CurrencyID'));

3. Сохранить все внесенные изменения. Перезапустить приложение и протестировать работоспособность системы.

Желаю удачи!

С уважением,
Мельникова Екатерина

Нравится

Поделиться

1 комментарий

Судя по функции, она делает только замену валюты в продуктах счета. А пересчет где делается?

Показать все комментарии

добавил в стандартный отчет - Счет с НДС(Россия) сумму прописью при помощи вычилсяемого поля.
Ниже привожу оброботчик вычисляемого поля (обработчик брал с форума)

function ds_ReportOfferingsInInvoiceOnDatasetCalcFields(Dataset) {
//amount to string
var DatasetObject = new Object;

Dataset.DisableEvents();
if (!DatasetObject.IsCalculated) {
var SumDataset = Dataset.SelectQuery.Open();
SumDataset.GotoFirst();
var Sum = 0;
var SumTax = 0;
while (!SumDataset.IsEOF) {
Sum = Sum + SumDataset('BasicAmount');
SumTax = SumTax + SumDataset('BasicTaxAmount')
SumDataset.GotoNext();
}
var StringSum = Sum.toString()
var StringSumTax = SumTax.toString()
DatasetObject.IsCalculated = true;
var Result = AmountToStr(StringSum, 'ru', 'RUR');
var ResultTax = AmountToStr(StringSumTax, 'ru', 'RUR');
Dataset.Values('TotalStr') = Result;
Dataset.Values('TotalStrTax') = ResultTax;
}
Dataset.EnableEvents();
}

все считается правильно, переводится в слова корректно.
У меня проблема вывод полученной строки (суммы прописью) в отчете. Вывожу ее при помощи стандартного Memo.
Напомню, что в отчете два датасета - ds_ReportInvoiceWithNDSForRussia (master) и ds_ReportOfferingInInvoice (detail). Вычисляемое поля для суммы прописью высчитывается в ds_ReportOfferingInInvoice.

Если кладу мемо не на бенд (просто на старницу), или на бенд master-a (или его child), то все работает.

Но если кладу мемо на бенды завязанные на detail или на ReportSummary или на PageFooter, то появляется ошибка Источник данных '%s' не открыт.
1. Как обойти эту ошибку?
2. Глобально задача, отображить это поле где-то под detail (списком товаров) на каком-нибудь бенде.

Нравится

14 комментариев

Посмотрите свойство CloseDataSource, датасета Fastreport.
Данное свойство должно находиться в состоянии False.

Спасибо, Николай, за совет. Но CloseDataSource уже проверял - False.

на какой строчке происходит ошибка?
убери вычисляемое поле , может ошибка не из-за него происходит

Денис, ошибка не из-за вычисляемого поля происходит. Если отображать любое другое поля из detail-запроса, то ошибка примерно такая же (только источник указывается явно, а не '%s').

Тут вопрос в том, на каких бендах можно отображать поля detail-запроса. По логике казалось, что если у соответствующего Dataset-a CloseDataSource ставить в false, то к полю запроса можно будет обратиться всегда.
Но на практике оказывается, что поля detail запроса можно вывести только на:
1. на child-ах detail-бенда
2. на master-бенде и его footer, child, header (если он находится над detail-бендом)
3. прямо на странице (не на бенде)
4. на самом detail-бенде.

а вот в footer-е, принадлежащему detail-бенду, отобразить поле нельзя - а здесь-то больше всего и хотелось.

!!!вообще очень хотелось бы узнать от знающих людей, когда можно обращаться к полям detail dataset-a. У меня сложилось впечатление, что к ним можно обращаться до тех пор пока detail запрос не отработает, а после датасет закрывается и доступ к полям исчезает.

В целом, свою проблему я решил, но про доступ к полям detail dataset-a хочется узнать.

Поделюсь как я решил свою задачу - может быть кому-то сэкономит время.

Была стандартная задача отобразить в счете сначала список товаров, под списком товаров отобразить количество наименований и сумму счета, а вот под ними отобразить сумму прописью.

Количество наименований и сумму счета отобразил в footer-е detail-бенда (detail бенд завязан на ds_ReportOfferingInInvoice). Количество наименования отобарзил при помощи переменной Line, сумму взял из master dataset (ds_ReportInvoiceWithNDSForRussia).
А вот сумму прописью - вычисляемое поле detail dataset- отобразить не удавалось из-за той самой ошибки.

Отображение суммы прописью обязательно хотелось расположить на каком-то бенде, иначе взаимное расположение отображаемой информации трудно контролировать.

Отобразить смог при помощи добавочного detail-бенде (привязнному к тому же ds_ReportOfferingInInvoice). На этом бенде расположил сумму прописью. Чтобы сумма не повторялась столько раз, сколько товаров в счете, надо в количестве строк (кажется rowcount или как-то так) поставить 1 (по умолчанию стоит 0).

Андрей, добрый день.

По поводу полей detail dataset'а Вы правы: не удавалось получить их значение ниже detail-бенда (да и, честно говоря, насчёт корректного получения значений датасета вне detail-бенда есть сомнения). Скорее всего, это связано с особенностями реализации Fast Report.

Вообще, если есть подобные задачи, их можно решать с помощью переменных в коде отчёта. Например, при обработке события OnBeforePrint detail-бенда записываем нужное значение из датасета в некоторую глобальную переменную, а в footer-бенд добавляем memo, содержащий имя этой переменной в квадратных скобках. В итоге получим необходимый результат.

Сори за оффтоп.
Пробую Ваш скрипт для расчета сумы стоимости продуктов в счете, но у меня отображает только стоимость первого в счете продукта, не суммируя остальных.
Цикл отслеживающий конец таблицы отрабатывает 9 раз при том что записей 3.
Может ли быть это связано с тем что у меня ТС 3.4.0.97

var DatasetObject = new Object;
	Dataset.DisableEvents();
	if (!DatasetObject.IsCalculated) 
		{
		var SumDataset = Dataset.SelectQuery.Open();
		SumDataset.GotoFirst();
		var Sum = 0;
		while (!SumDataset.IsEOF) 
			{
			Sum = Sum + SumDataset('BasicAmount');
			SumDataset.GotoNext();
			ShowInformationDialog('DatasetIsCalculated'+Sum.toString());
			}
		var StringSum = Sum.toString()
		DatasetObject.IsCalculated = true;
		var Result = AmountToStr(StringSum, 'ua', 'UAH');
		Dataset.Values('SumText') = Result;
	}
Dataset.EnableEvents();

Владимир, я рекомендовала бы считать итог средствами отчета Fast Report (если поле, по которому производится суммирование, выводится в датабэнд). Обратите внимание, memo, в котором рассчитывается сумма, должно находиться в футере датабэнда.

Либо же агрегирующей колонкой подзапроса.

В данном конкретном случае для диагностики необходимы Ваши сервисы отчета.

Анна, сума считается правильно. Мне нужна сумма прописью, но использовать функцию AmountToStr в отчете я не могу. В скрипте отчета, ds_ReportOfferingsInInvoiceScript не могу получить сумму :wink:

Владимир, наиболее вероятная проблема - Memo лежит не в футере бэнда.

Пожалуйста, предоставьте сервисы отчета, свзянанных датасетов и запросов для анализа проблемы.

Анна, вопрос уже на рассмотрении в службе поддержки.
Как только все разрешится, выложу результаты.
Пока определились с тем, что создали дополнительное поле в sq, подзапрос с расчетом итогов (суммирование). А потом функцией AmounttoStr, буду выводить результат в виде текста

"Лабьяк Олег Игоревич" написал:

Андрей, добрый день.

По поводу полей detail dataset'а Вы правы: не удавалось получить их значение ниже detail-бенда (да и, честно говоря, насчёт корректного получения значений датасета вне detail-бенда есть сомнения). Скорее всего, это связано с особенностями реализации Fast Report.

Вообще, если есть подобные задачи, их можно решать с помощью переменных в коде отчёта. Например, при обработке события OnBeforePrint detail-бенда записываем нужное значение из датасета в некоторую глобальную переменную, а в footer-бенд добавляем memo, содержащий имя этой переменной в квадратных скобках. В итоге получим необходимый результат.

С уважением,

Олег Лабьяк,

инженер-программист,

группа компаний Terrasoft.

Олег, а вариант глобальной переменной не для футера, а для мастер бенда детали пройдет?У меня не проходит. Нужно в мастер датасете посчитать сумму по детальке

Антон, уточните, пожалуйста, что именно у вас "не проходит" - значение из глобальной переменной не подставляется/не отображается или ошибку выдает?

Показать все комментарии

Здравствуйте!

Сегодня, в продолжение темы http://community.terrasoft.ua/forum/topic/3285, хочу все собранную информацию сохранить в одном удобочитаемом формате. Особое "Спасибо" Осауленко Александру!

И так, мы собрались перенести нумерацию счетов на сторону базы данных, но при этом использовать системные настройки. Беру последнюю сборку TS CRM 3.3.0

1. Открываем ds_InvoiceScript и комментируем 1 строчку :

function ds_InvoiceOnDatasetBeforePost(Dataset, DoPost) {
InvoiceScript.IsAppend  = (Dataset.State == dstInsert);
// SetItemSystemNumber('Invoice', Dataset,  'InvoiceNumber');
...

2. Открываем ds_wnd_InvoiceEditScript и опять комментируем 1 строчку :

function dlDataOnDatasetBeforePost(Dataset, DoPost) {
        //SetItemSystemNumber('Invoice', Dataset, 'InvoiceNumber');
...

3. В MS SQL создаем триггер:

CREATE TRIGGER tr_tbl_Invoice_IIN
ON [tbl_Invoice]
AFTER INSERT AS

BEGIN
IF (SYSTEM_USER = 'TS_REPLICATION') RETURN

DECLARE @ID uniqueidentifier, @Number nvarchar(250)
SET NOCOUNT ON;

DECLARE c_Invoices CURSOR
FOR SELECT [ID], [InvoiceNumber]
FROM inserted

OPEN c_Invoices
WHILE 1 = 1
BEGIN FETCH c_Invoices
INTO @ID, @Number

IF @@fetch_status = -1 BREAK
IF @@fetch_status = -2 CONTINUE

IF (@Number IS NULL)
begin
 UPDATE [tbl_SystemSetting]
 SET @Number = (SELECT REPLACE([StringValue], '%1', [IntegerValue] + 1)
 FROM [tbl_SystemSetting] WHERE [Code] = 'InvoiceMask'), [IntegerValue] = [IntegerValue] + 1
 WHERE [Code] = 'InvoiceNumber'

 UPDATE [tbl_Invoice]
 SET [InvoiceNumber] = @Number
 WHERE [ID] = @ID
 end

END
CLOSE c_Invoices
DEALLOCATE c_Invoices
END
GO

PS: вопрос к разработчикам: а зачем дважды присваивать номер (п. 1 и 2)?

Нравится

Поделиться

9 комментариев

Помоему в dlDataOnDatasetBeforePost лишнее присвоение

"Underscore a.k.a. _" написал:Помоему в dlDataOnDatasetBeforePost лишнее присвоение

Вот я и спрашиваю зачем его там прописали :)

--
www.it-sfera.com.ua
Terrasoft Solution Partner

Там, наверное проверка стоит в SetItemSystemNumber на заполненность поля, поэтому работает нормально и никто эту строчку не замечал.
Вообще как в анекдоте получается. "А если и второй билетик потеряю, то у меня проездной есть" :)

"Underscore a.k.a. _" написал:"А если и второй билетик потеряю, то у меня проездной есть" :)

+100 :)

--
www.it-sfera.com.ua
Terrasoft Solution Partner

Да. В wnd_InvoiceEditScript обработчик OnBeforePost лишний. В 331 такого нет, а вот в 330 осталось. Теперь и там нет

"Агеев Алексей Юрьевич" написал:В 331 такого нет, а вот в 330 осталось. Теперь и там нет

Если мне не изменяет память, то я его видел и в 3.2.0, и в 3.2.1

--
www.it-sfera.com.ua
Terrasoft Solution Partner

Есть у меня подозрения что он и в 3.0 был :)

Поправил и там. Но те сборки давно уже не пересобираются

Посмотрел в 3.1.0 и в 3.1.1 - там все гуд :)

--
www.it-sfera.com.ua
Terrasoft Solution Partner

Показать все комментарии

В контекстном меню Счета в Действиях отсутствует опция "пересчитать сумму". Есть только "Сгенерировать номер". Как добавить "пересчитать сумму"? Версия 3.3.0.42 x15

Нравится

5 комментариев

Т.е. в самом разделе в действиях он есть, а в контекстном меню грида нет? Или ни там ни там нет?

Ни там, ни там нет.

Тогда добавьте в окно раздела в меню, которое соответствует меню действий пункт amiRecalcAmount и повесьте на него

function amiRecalcAmountOnExecute(ActionMenuItem) {
    var Dataset = BaseWorkspace.GridDataset;
    if (IsDatasetEmpty(Dataset)) {
	    return;
	}
	Dataset.DisableEvents();
	try {
		var GridWindow = wndGridData.Window;
		var grdData = GridWindow.ComponentsByName('grdData');
		var ArrayIDs = GetArrayByCollection(grdData.SelectedIDs);
		var Passed = 0;
		for (var i = 0; i < ArrayIDs.length; i++) {
			var InvoiceID = ArrayIDs[i];
			Dataset.Locate('ID', InvoiceID);
 
			var CanUpdateInvoice =
				(GetCanUpdateTableGroup(Dataset)) &&
				(Dataset.GetCurrentRecordAccessLevel() == tfalFullAccess);
			if (!CanUpdateInvoice) {
				Passed++;
				continue;
			}
			RecalcAmount(InvoiceID);
		}
		var PassedMessage = '';
		if (Passed > 0) {
			PassedMessage = ' ' + "Пропущено %1 записей.";
			PassedMessage = FormatStr(PassedMessage, Passed);
		}
		var Message = "Выполнен пересчет для %1 записей." + PassedMessage;
		var Message = FormatStr(Message, ArrayIDs.length - Passed);
	    ShowInformationDialog(Message);
	} finally {
		Dataset.EnableEvents()
	}
}

Посмотрите, в скрипте раздела есть функция RecalcAmount?

Не могу найти раздел действий.
Где искал: Файл - Справочники - Настройка Справочников - Счет и там выбрал окно реестра (wnd_InvoiceGridArea).
Открывается Terrasoft Administrator, там захожу на невизуальные. На невизуальных есть amGrid и amDelete. Если добавлять элемент на amGrid, то действие добавиться в корень контекстного меню (не в действия).
Подскажите,пожалуйста, как правильно добраться до соотвествующего меню действий

Андрей, Вам необходимо добавить действие в сервис окна воркспейса wnd_InvoicesWorkspace.

Показать все комментарии

Здравствуйте!

Сегодня столкнулся с проблемой, что создавая счета, в базу были внесены для двух разных счетов одинаковые номера.
Менеджеры работают через Web-сервисы. Когда посмотрел на дату создания счетов с одинаковым номером, увидел разницу в 1 секунду!

Как избежать в будущем дублирование нумерации счетов, которые создаются за короткий промежуток времени?

Нравится

17 комментариев

Самым быстрым вариантом, думаю, будет сделать триггер.

Что бы не было дублирования номера должны генерится в одном месте. Логично в данном случае этим местом выбрать СУБД. Т.е. либо тригер, как предложил Александр Кравчук, но тогда не будет видно номера при редактировании. Либо слать запрос на получение номера до поста, но тогда в нумераци будут дырки.
Пока писал придумал еще простейший в реализации вариант - повесить уникальный ключ на поле :)

Сейчас задействована стандартная нумерация из системных настроек!

Решено перенести в тригер СУБД

--
Cogito, ergo sum

"Underscore a.k.a. _" написал:повесить уникальный ключ на поле :)

+1
Добавил :)

--
Cogito, ergo sum

Варианты

"Александр Кравчук" написал:
сделать триггер

или
"Underscore a.k.a. _" написал:
повесить уникальный ключ на поле

неудобны: или уникальный индекс будет выдавать ошибку или Вы не будет видеть какой номер у документа, счета и т.п.
Думаю самым приемлемым способом, будет светить какой-то номер во время добавления - пусть это будет через системные настройки, а перед добавлением пересчитывать на корректный: запускать ХП с выходным параметром, которая в свою очередь вычитывает текущее значение системной настройки, увеличивает на единицу, сохраняет и возвращает результат для сохранения в номере. Можно для надежности в транзакции ее запускать. Можно эту логику и в триггер вынести. Но тогда немного рассредоточится логика по формированию номера: и в конфигурации, и в триггере. Неудобно будет сопровождать. А ХП можно сделать универсальной - допустим только для числовых последовательностей.

ЗЫ

"Underscore a.k.a. _" написал:
в нумераци будут дырки.

Для этого есть или ну очень надуманные способы или запретить удаление :)

Соглашусь, что для

"Виталий Ковалишин aka samael" написал:
Как избежать в будущем дублирование нумерации счетов, которые создаются за короткий промежуток времени?

уникальный индекс самое то - на уровне сервера будет проверка целостности данных.

Такой вот вариант надумал:

CREATE TRIGGER tr_tbl_Invoice_IIN 
   ON  [tbl_Invoice]
   AFTER INSERT
AS 
BEGIN
	declare @ID uniqueidentifier, @NewNumber int,
		@Number nvarchar(250), @NumberMask varchar(10)
 
	SET NOCOUNT ON;
 
	select @ID = [ID], @Number = [InvoiceNumber] from inserted
 
    if (@Number is null)
    begin
	set @NumberMask = ( select [StringValue] from [tbl_SystemSetting] where [Code] = 'InvoiceMask' )
	set @NewNumber = ( select [IntegerValue] +1 from [tbl_SystemSetting] where [Code] = 'InvoiceNumber' )
	set @Number = REPLACE(@NumberMask, '%1', @NewNumber) 
	update [tbl_SystemSetting] set [IntegerValue] = @NewNumber where [Code] = 'InvoiceNumber'
	update [tbl_Invoice] set [InvoiceNumber] = @Number where [ID] = @ID
    end
 
END

--
Cogito, ergo sum

"Виталий Ковалишин aka samael" написал:
SELECT @ID = [ID], @Number = [InvoiceNumber] FROM inserted

Учтите, что inserted может содержать несколько записей.

"Осауленко Александр" написал:Думаю самым приемлемым способом, будет светить какой-то номер

А чем показывать в общем случае неправильный номер лучше, чем нек показывать его вообще.

"Осауленко Александр" написал:Учтите, что inserted может содержать несколько записей.

учтено:

ALTER TRIGGER tr_tbl_Invoice_IIN 
   ON  [tbl_Invoice]
   AFTER INSERT
AS 
BEGIN
	DECLARE @ID uniqueidentifier, @NewNumber int,
		@Number nvarchar(250), @NumberMask varchar(10)
 
SET NOCOUNT ON;
 
DECLARE  c_Invoices CURSOR FOR
  select [ID], [InvoiceNumber] from inserted
 
OPEN  c_Invoices
  WHILE 1 = 1
  BEGIN 
    FETCH c_Invoices
     INTO @ID, @Number
 
     IF @@fetch_status = -1 BREAK 
     IF @@fetch_status = -2 CONTINUE 
 
    if (@Number is null)
    begin
	set @NumberMask = ( select [StringValue] from [tbl_SystemSetting] where [Code] = 'InvoiceMask' )
	set @NewNumber = ( select [IntegerValue] +1 from [tbl_SystemSetting] where [Code] = 'InvoiceNumber' )
	set @Number = REPLACE(@NumberMask, '%1', @NewNumber) 
	update [tbl_SystemSetting] set [IntegerValue] = @NewNumber where [Code] = 'InvoiceNumber'
	update [tbl_Invoice] set [InvoiceNumber] = @Number where [ID] = @ID
    end
   END  
CLOSE c_Invoices
DEALLOCATE c_Invoices
 
END
GO

"Осауленко Александр" написал:Можно эту логику и в триггер вынести. Но тогда немного рассредоточится логика по формированию номера: и в конфигурации, и в триггере. Неудобно будет сопровождать.

Не нарушена, все из системных настроек :)

--
Cogito, ergo sum

"Underscore a.k.a. _" написал:
А чем показывать в общем случае неправильный номер лучше, чем нек показывать его вообще.

Я почти на 100% уверен, что такая ситуация будет очень редко, да еще и пользователь на это обратит внимание в 1 случае из 1000. Т.е. почти не реально :)

Обычно это решается созданием отдельной таблицы с хранением последнего номера. И генерацией номера в нужный момент (в момент создания счета или при сохранении - в зависимости от логики).

Самое главное - чтобы транзакция по получению номера и его увеличению была очень-очень короткая (намного короче, чем транзакция по сохранению всего счета). Возможна еще блокировки записи на время транзакции. Тогда одинаковых номеров не будет.

А "дырки" в такой нумерации - это практически неизбежное зло

"Владимир Соколов" написал:Обычно это решается созданием отдельной таблицы с хранением последнего номера. И генерацией номера в нужный момент (в момент создания счета или при сохранении - в зависимости от логики).

Владимир, я ничего не придумывал, просто использовал стандартную нумерацию счетов, которая:
1. хранит последний номер в таблице системных настроек
2. генерит номер при сохранении
:)

Все что нужно было, так это перенести логику со скриптов на уровень СУБД... Так и сделал!

--
Cogito, ergo sum

"Виталий Ковалишин aka samael" написал:

ALTER TRIGGER tr_tbl_Invoice_IIN
   ON  [tbl_Invoice]
   AFTER INSERT
AS
BEGIN
        DECLARE @ID uniqueidentifier, @NewNumber int,
...


Я бы еще добавил условие для репликации, даже если у Вас пока ее и нет, что бы потом не "шерстить" БД:

ALTER TRIGGER tr_tbl_Invoice_IIN
   ON  [tbl_Invoice]
   AFTER INSERT
AS
BEGIN
        IF (SYSTEM_USER = 'TS_REPLICATION') RETURN 
        DECLARE @ID uniqueidentifier, @NewNumber int,
...

Спасибо, Александр!

Тогда данное условие нужно во все новые триггеры добавить

IF (SYSTEM_USER = 'TS_REPLICATION') RETURN 

--
Cogito, ergo sum

Здравствуйте! В очередной раз поражаюсь возможностям T-SQL:

"Виталий Ковалишин aka samael" написал:

...
SET @NumberMask = ( SELECT [StringValue] FROM [tbl_SystemSetting] WHERE [Code] = 'InvoiceMask' )
        SET @NewNumber = ( SELECT [IntegerValue] +1 FROM [tbl_SystemSetting] WHERE [Code] = 'InvoiceNumber' )
        SET @Number = REPLACE(@NumberMask, '%1', @NewNumber)
        UPDATE [tbl_SystemSetting] SET [IntegerValue] = @NewNumber WHERE [Code] = 'InvoiceNumber'
UPDATE [tbl_Invoice] SET [InvoiceNumber] = @Number WHERE [ID] = @ID
...

...


Можно заменить на:

...
  UPDATE [tbl_SystemSetting]
  SET
     @Number = (SELECT REPLACE([StringValue], '%1', [IntegerValue] + 1)
                FROM [tbl_SystemSetting] WHERE [Code] = 'InvoiceMask'), 
     [IntegerValue] =  [IntegerValue] + 1
  WHERE [Code] = 'InvoiceNumber'
 
  UPDATE [tbl_Invoice]
  SET
     [InvoiceNumber] = @Number
  WHERE [ID] = @ID
...

Красота!:)

Абсолютно с Вами согласен! :)

--
Cogito, ergo sum

Показать все комментарии

Нравится

Поделиться

1 комментарий

Немного отредактировал процедуру и вывел отдельно функцию подбора товара и стоимости, в зависимости от метода расчета стоимости :)


--
«Настоящий руководитель чувствует ситуацию нутром, управляет людьми исключительно сердцем и может вдохнуть живую душу в проект, команду или всю организацию», - Tom DeMarco “The Deadline”

Показать все комментарии

Здравствуйте!!
в террасофте реализована следующая функциональность:
1. В разделе Продукты есть вкладка Цены, на которой можно указать оптовую и розничную цену (в деньгах)
2. В разделе Контрагенты есть вкладка Типы цен, на которой можно указать оптовую и розничную цену в датах
3. В раздел Счета добавить новый счет и указать дату, которая бы попадала в какой либо из промежутков дат, указанных в разделе Контрагенты. Затем создать на вкладке счетов Продукты новую запись. В результате в атрибут Цена карточки Продукты по счету автоматически подставляется тот тип цены из раздела Продукты, дата которого указана в карточке счета...

Мне нужно реализовать тоже только для раздела Документ. Подскажите какие скрипты и функции смотреть, где это реализовано для счета.

С уважением, Гашникова Екатерина

Нравится

3 комментария

Добрый день!

Спасибо за Ваш вопрос.

Для того, чтобы реализовать запрашиваемую Вами функциональность Вам необходимо сделать изменения в скрипте scr_OfferingUtils в функции SetValuesByPriceType по аналогии c реализацией для раздела Счета.
В разделе Счета данная функциональность реализована в функции DataChange, которая вызывается на событие SelfOnDatasetDataChange для ds_OfferingInInvoiceScript.

В функции SetValuesByPriceType реализована функциональность работы с ценами для разделов Счета, Проекты, а именно работа с ценами на закладке Продукты Менеджера деталей соответствующего раздела.

Будем рады ответить на все Ваши вопросы.

Terrasoft Support Team

так поняла, что за вставку цен в продукт по счету отвечает функция SetValuesByPriceType внутри scr_OfferingUtils.
для решения своей задачи попробовала заменить везде в этой функции InvoiceID на DocumentID.
получилось следующее:
function SetValuesByPriceType(Dataset, ScriptObject) {
if (ScriptObject.WorkspaceFieldName == 'DocumentID') {
if (!Assigned(scr_OfferingUtils.AccountIDDocument)) {
var DocumentID = Dataset.Values('DocumentID');
scr_OfferingUtils.AccountIDDocument = GetDocumentParameterByDocumentID(
DocumentID,'AccountID');//CustomerID
scr_OfferingUtils.CurrenDateDocument = GetDocumentParameterByDocumentID(
DocumentID,'Date');
}
var AccountID = scr_OfferingUtils.AccountIDDocument;
var CurrentDate = scr_OfferingUtils.CurrenDateDocument;
} else if (ScriptObject.WorkspaceFieldName == 'OpportunityID') {
if (!Assigned(scr_OfferingUtils.AccountIDOpportunity)) {
var OpportunityID = Dataset.Values('OpportunityID');
scr_OfferingUtils.AccountIDOpportunity = GetOpportunityParameterByOpportunityID(
OpportunityID,'CustomerID');
scr_OfferingUtils.CurrenDateOpportunity = GetOpportunityParameterByOpportunityID(
OpportunityID,'StartDate');
}
var AccountID = scr_OfferingUtils.AccountIDOpportunity;
var CurrentDate = scr_OfferingUtils.CurrenDateOpportunity;
} else
return false;
var PriceCategoryID = GetPriceTypeOfferingByAccountID(AccountID, CurrentDate);
if (!IsEmptyValue(PriceCategoryID)) {
var ResultArray = GetOfferingPriceByPriceCategoryID(PriceCategoryID,
Dataset.Values('OfferingID'));
if (!IsEmptyValue(ResultArray)) {
SetOfferingValues(Dataset, ResultArray, ScriptObject);
return true;
}
}
var ResultArray = GetOfferingPriceByMainPrice(Dataset.Values('OfferingID'));
if (!IsEmptyValue(ResultArray)) {
SetOfferingValues(Dataset, ResultArray, ScriptObject);
return true;
}
return false;
}

Открываю раздел Документы, добавляю новый продукт, выбираю дату из любого промежутка, заданного в разделе Контрагенты на закладке Типы цен. Захожу на закладку Продукты по документам, добавляю новую карточку и при выборе продукта выдается ошибка 'Ошибка выполнения метода 'SelfOnDatasetDataChange'. Предполагается наличие объекта'

Скажите по правильному ли я пошла пути и если да, то как исправить ошибку?

Гашникова Екатерина

Добрый день.

Для того, чтобы реализовать требуемую функциональность Вам необходимо в scr_OfferingUtils добавить функцию

function GetDocumentParameterByDocumentID(DocumentID, Parameter) {
 
            var DocumentDataset = GetSingleItemByCode('ds_Document', 'scr_OfferingUtils');
 
            EnableDatasetFilters(DocumentDataset, false);
 
            ApplyDatasetIDFilter(DocumentDataset, DocumentID, true);
 
            DocumentDataset.Open();
 
            var Result = null;
 
            if (!IsDatasetEmpty(DocumentDataset)) {
 
                        Result = DocumentDataset.Values(Parameter);
 
            }
 
            DocumentDataset.Close();
 
            return Result;
 
}

Откорректировать функцию SetValuesByPriceType в скрипте scr_OfferingUtils необходимо таким образом

function SetValuesByPriceType(Dataset, ScriptObject) {
 
            if (ScriptObject.WorkspaceFieldName == 'InvoiceID') {
 
                        if (!Assigned(scr_OfferingUtils.AccountIDInvoice)) {
 
                                   var InvoiceID = Dataset.Values('InvoiceID');
 
                                   scr_OfferingUtils.AccountIDInvoice = GetInvoiceParameterByInvoiceID(
 
                                               InvoiceID,'CustomerID');
 
                                   scr_OfferingUtils.CurrenDateInvoice = GetInvoiceParameterByInvoiceID(
 
                                               InvoiceID,'InvoiceDate');
 
                        }
 
                        var AccountID = scr_OfferingUtils.AccountIDInvoice;
 
                        var CurrentDate = scr_OfferingUtils.CurrenDateInvoice;
 
            } else if (ScriptObject.WorkspaceFieldName == 'OpportunityID') {
 
                        if (!Assigned(scr_OfferingUtils.AccountIDOpportunity)) {
 
                                   var OpportunityID = Dataset.Values('OpportunityID');
 
                                   scr_OfferingUtils.AccountIDOpportunity = GetOpportunityParameterByOpportunityID(
 
                                               OpportunityID,'CustomerID');
 
                                   scr_OfferingUtils.CurrenDateOpportunity = GetOpportunityParameterByOpportunityID(
 
                                               OpportunityID,'StartDate');
 
                        }
 
                        var AccountID = scr_OfferingUtils.AccountIDOpportunity;
 
                        var CurrentDate = scr_OfferingUtils.CurrenDateOpportunity;
 
            } else if (ScriptObject.WorkspaceFieldName == 'DocumentID') {
 
                        if (!Assigned(scr_OfferingUtils.AccountIDDocument)) {
 
                                   var DocumentID = Dataset.Values('DocumentID');
 
                                   scr_OfferingUtils.AccountIDDocument = GetDocumentParameterByDocumentID(
 
                                               DocumentID,'AccountID');
 
                                   scr_OfferingUtils.CurrenDateDocument = GetDocumentParameterByDocumentID(
 
                                               DocumentID,'Date');
 
                        }
 
                        var AccountID = scr_OfferingUtils.AccountIDDocument;
 
                        var CurrentDate = scr_OfferingUtils.CurrenDateDocument;
 
            } else
 
                        return false;
 
            var PriceCategoryID = GetPriceTypeOfferingByAccountID(AccountID, CurrentDate);
 
            if (!IsEmptyValue(PriceCategoryID))        {
 
                        var ResultArray = GetOfferingPriceByPriceCategoryID(PriceCategoryID,
 
                                   Dataset.Values('OfferingID'));
 
                        if (!IsEmptyValue(ResultArray)) {
 
                                   SetOfferingValues(Dataset, ResultArray, ScriptObject);
 
                                   return true;
 
                        }
 
            }
 
            var ResultArray = GetOfferingPriceByMainPrice(Dataset.Values('OfferingID'));
 
            if (!IsEmptyValue(ResultArray)) {
 
                        SetOfferingValues(Dataset, ResultArray, ScriptObject);
 
                        return true;
 
            }
 
            return false;
 
}

Terrasoft Support Team

Показать все комментарии

Здравствуйте!!
Написала скрипт, который при изменениии даты (PaymentDate)в карточке счета (tbl_Invoice)должен суммировать значения полей "Сумма" (Amount) таблицы операций (tbl_Cashflow)и заносить посчитанный результат в поле "Сумма оплаты" (PaymentAmount) таблицы "Счет" (tbl_Invoice).

Код написан внутри скрипта ds_InvoiceScript и выглядет следующим образом:
function DataChange(DataField){
.....
case ('PaymentDate'):
InvoiceScript.OnDataChangeDisabled = true;
try {
var InvoiceID = DataFields.ItemsByName('InvoiceID').Value;
var PaymentAmount = DataFields.ItemsByName('PaymentAmount').Value;
var Summ = GetDetailSummary('tbl_Cashflow', 'InvoiceID', InvoiceID, 'Amount', stSum);
if (IsEmptyValue(Summ))
{
Summ = 0;
}
SetFloatDataFieldWithRound(DataFields.ItemsByName('PaymentAmount'), Summ);
}
finally{
InvoiceScript.OnDataChangeDisabled = false;
}
break;
}
}
При попытке же изменить дату выдается ошибка: "Ошибка выполнения метода 'SelfOnDatasetDataChange".
Помогите, пожалуйста разобраться в чем дело.
С уважением, Гашникова Екатерина

Нравится

2 комментария

Добрый день, Екатерина!

Ошибка в строке:
var InvoiceID = DataFields.ItemsByName('InvoiceID').Value;
правильный вариант:
var InvoiceID = DataFields.ItemsByName('ID').Value;

Проверил, работает.
Желаю успехов!

Спасибо, большое!!!
Все заработало

Показать все комментарии

Осваиваю функциональность TS CRM вер.3.2.1.4. Сегодня столкнулся с ситуацией, набор продуктов в счете есть, сумма по продуктам считается, но попытка пересчитать сумму дает стабильно 0.00, вопрос куда смотреть?
Я раньше я сделал несколько счетов, начал по классической технологии -
1. Создал договор.
2. Созадал счет.
3. Набрал продукты в счет.
4. Нажал кнопку пересчет суммы.
самый первый счет тоже страдал аналогичной болезнью, я его удалил. Сделал заново, все сработало нормально, думал, може че не туда ткнул по неопытности... Потом два счета сделал, все отработало предсказуемо, а сегодня начал делать счет - опять 0-сумма. Я грешил на то что попробовал счет просто без договора создать, удалил его, создал договор, на детали счета добавил счет, добавил туда продукты и опять сумма -0.0 если надо могу скрин экрана прислать...

Нравится

2 комментария

Добрый день, Руслан!
1. Наличие значения в поле "Договор" карточки Счета на результат пересчета суммы не влияет.
2. Пересчет суммы означает:
а) суммирование значений поля "Итого (б.в.)" записей на детали Продукты в разделе счета,
б) помещение результата в поле "Сумма (б.в.)" для текущей записи в разделе Счета,
в) и вычисление значения поля "Сумма" исходя из значений полей "Сумма (б.в.)" и "Курс валюты" для текущей записи в разделе Счета.

Если в Вашем контрольном примере в некоторых из указанных полей стоят нули, то получение нулевого результата закономерно, и для исправления ситуации нужно, чтобы во всех указанных выше полях были установлены правильные значения. Наиболее вероятная причина - не указана валюта, а, следовательно, и курс валюты в карточке счета.

Да, действительно обратил внимание на отсутствие значения в поле Валюта в реквизитах шапки док-та - Счет, спасибо.

Показать все комментарии