Коллеги, доброго времени суток!

Подскажите пожалуйста:

В разделе "Счета" при изменении количества/цен продуктов идет автоматический пересчет "Суммы" счета. Как я понял код, отвечающий за изменение находится в пакете Invoice => схеме объекта InvoiceProduct => подпроцессе SubProcessScriptAmountChange => внутри скрипта ScriptAmountChange, который отрабатывает при получении сообщения события InvoiceProductSaved или InvoiceProductDeleted. Поиск по сообществу показал, что видимо просто так переопределить код внутри скрипта нельзя, если он не вынесен в метод. Чтобы заменить логику его работы нужно создать свой подпроцесс с входами через те же сообщения (но со своими названиями) и в конце вызываемого скрипта перед return вписать

ActivatedEventElements.Remove("InvoiceProductSaved");

ActivatedEventElements.Remove("InvoiceProductDeleted");

что я и сделал, создал подпроцесс по образу и подобию с родительским (два входных сообщения через исключащее "ИЛИ" по безусловной связи идут в скрипт), однако после сохранения, публикации и обновлении стурктуры БД дополнительная логика не отрабатывает, из чего я делаю вывод, что до скрипта почему-то дело не доходит.

У моих входных событий совпадают с родительскими поля "Сообщение" (InvoiceProductSaved и InvoiceProductDeleted), но отличаются "Название" (иначе компилятор предупреждает, что override неправильно делаю, и получается только hide.. ну и всё равно не работает), поле "Условие" в связи от исключащего ИЛИ пустое, судя по "Исходному коду" это как раз то, что нужно, т.к. в этом случае функция всегда возвращает true.

Пытался и напрямую оба события на скрипт завязать - всё равно не работает.

Вопрос соответственно - что я делаю не так?

Нравится

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

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

Описанное решение выглядит правильно. 

Для перекрытия логики по родительскому сигналу, необходимо в дочернем БП объекта подписаться на аналогичное событие объекта и в скрипте перед return true  вставить:

if (ActivatedEventElements.Contains("InvoiceProductSaved")) {

    ActivatedEventElements.Remove("InvoiceProductSaved")

}

Проверьте, что БП в дочернем объекте помещен в "Событийный подпроцесс".

Так же, вы хотите удалить сразу два сигнала. Поэтому, советую выполнять проверку какой сигнал пришел и удалять его( как в примере выше).

Спасибо!

Попробовал в другом объекте (OrderProduct) проверить. Создал в процессе замещающего объекта событийный подпроцесс, в него поместил одно начальное событие (сообщение OrderProductSaved) из него прямой переход на скрипт, в котором три строчки:

global::Common.Logging.ILog _Logger = global::Common.Logging.LogManager.GetLogger("Client");

_Logger.Info("Order product saved event test");

return true;

Одновременно в переопределенный метод RecalculateOrderAmount вписываю в начале:

global::Common.Logging.ILog _Logger = global::Common.Logging.LogManager.GetLogger("Client");

_Logger.Info("Order product saved event test 2, "+GetPropertiesData());

Метод вызывается только в родительском процессе по цепочке от сообщений OrderProductSaved или OrderProductDeleted.

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

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

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

Добрый день!

Проверила ваш кейс у себя, всё получилось.

Вот как я делала:

Событийный подпроцесс - http://prntscr.com/jhpu81

Задание-сценарий - http://prntscr.com/jhpuoz

Добавила продукты в счете - http://prntscr.com/jhpuz6

Сумма не считается - http://prntscr.com/jhpv9a

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

Надо сделать, чтобы при импорте операций из 1С пересчитывалась сумма счета. Пробовал делать так:

function OnBeforeRecordImport(Param, Dataset, Select1C) {
        // Пересчет суммы для счета
        RecalcAmount(Dataset.Values('InvoiceID'));
}

и подключил скрипт scr_InvoiceWorkspace, но при работе ругается на BaseWorkspace.GridDataset в функции RecalcAmount

Как вообще это правильно сделать?

Нравится

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

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

Попробуйте в Вашем скрипте создать такую же функцию (название можно поменять, например, RecalcImportedInvoiceAmount), и в ней вместо строчки

var InvoiceDataset = BaseWorkspace.GridDataset;

вставить блок

var InvoiceDataset = GetSingleItemByCode('ds_Invoice', 'RecalcImportedInvoiceAmount');
if (InvoiceDataset.State != dstInactive) {
	InvoiceDataset.Close();
}
ApplyDatasetIDFilter(InvoiceDataset, InvoiceID, true);
InvoiceDataset.Open();

А подскажите, пожалуйста, как бы сделать так, чтобы действие "Пересчитать сумму" выполнялось автоматически при добавлении продукта в счет?

После добавления продукта в счет, а именно по закрытию карточки продукта, отрабатывает событие OnNotify, в данном случае это обработчик wnd_OfferingsDetailTreeAreaOnNotify в скрипте wnd_OfferingsDetailTreeAreaScript. В него Вы и можете дописать блок, который порекомендовал Олег.

Спасибо большое!

Виталий, я немного поторопилась. То есть, спасибо, конечно, но поясните, пожалуйста, поподробнее!
Я в wnd_OfferingsDetailTreeAreaScript добавила ссылку на scr_InvoiceWorkspace, там продублировала функцию RecalcAmount, превратив ее в RecalcAmountMy, там по совету Олега заменила одну строку на блок кода, а также изменила строку

 
var UpdateDataset = GetOpenedDatasetByUSIWithFilter('ds_Invoice', 'ID',
		InvoiceID, 'RecalcAmountMy');

поменяв название последнего параметра.
В итоге получается, что в UpdateDataset все пусто. И запись не сохраняется, потому что в InvoiceDate null лежит.
Скорее всего, я что-то упустила. Подскажите, пожалуйста, что.

Проверьте, пожалуйста, что Вы действительно передаете в свою функцию корректный InvoiceID - ID счета, в который добавили продукт. Этот ID со скрипта продуктов в счете wnd_OfferingsDetailTreeAreaScript можно узнать так:

var InvoiceID = Self.Attributes('ParentItemID');

а затем передать его в свою функцию пересчета

RecalcAmountMy(InvoiceID);

Виталий, сделала так. Теперь ошибка не вылетает, под отладкой в RecalcAmountMy сумма считается верно, но почему-то сумма счета в итоге не изменяется. Если после этого сделать Действия->пересчет суммы - сумма счета меняется.
Я не совсем понимаю, как работает RecalcAmount, там много датасетов в которых я лично путаюсь - зачем какой, но я ее изменила только вот как подсказал Олег + внесла правку в одну строчку, поменяв название параметра с RecalcAmount на RecalcAmountMy. На всякий случай вернула изменения, но работает также. Amount считает верно, а в карточке счета изменений не происходит.

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

Виталий, я ваз дезинформировала! Прошу прощения!
На самом деле, пересчет происходит и в карточке все хорошо! Проблема в том, что реестр не рефрешится! А если через действия делать - рефрешится. Сейчас соображу, как это правильно сделать и все будет хорошо!
Еще раз прошу прощения за невнимательность.

	var InvoiceID = Self.Attributes('ParentItemID'); 
	RecalcAmountMy (InvoiceID);  
	var InvoiceDataset = Self.Attributes('WorkspaceDataset');
	RefreshDataset(InvoiceDataset);

Вот так работает!
P.S. где можно почитать про датасеты? Никак не могу в них разобраться.

Этот форум и есть одним большим FAQ по Террасофт. Конкретно по датасетам по памяти, к сожалению, Вам не подскажу. Посмотрите материалы в ветке "Разработчику", там есть FAQ и готовые варианты решений. Это конечно не детальное руководство по всем вопросам, но ответов можно найти много. Рекомендую также поиск по форуму - подбирайте подходящие ключевые слова.

Виталий, у меня вот еще уточнение возникло. При добавлении продуктов все отлично пересчитывается. Но вот, как показала практика, достаточно часто продукты из счета удаляются. И вот куда нужно повесить вызов волшебной функции пересчета, чтобы еще и при удалении сумма счета менялась?

Для того, чтобы при удалении продукта происходил пересчет суммы счета, переопределите событие OnClick кнопки btnDelete в wnd_OfferingsDetailTreeArea:

function btnDeleteOnClick(Control) {
scr_BaseTreeArea.btnDeleteOnClick(Control);
......
}

Спасибо, Наталия, попробую!

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