Имя: Пароль:
1C
1С v8
Не хватает события ПослеЗаписи на уровне объекта
0 MigAV
 
10.04.13
11:09
Есть конфа УПП на платформе 8.2 в режиме совместимости с 8.1.

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

Что бы реализовать этот механизм сделали следующее:

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

               "ВЫБРАТЬ
               |    ПланДатыПоступленияСрезПоследних.Номенклатура,
               |    РазмещениеЗаказовПокупателейОстатки.ЗаказПокупателя,
               |    ПланДатыПоступленияСрезПоследних.ПланДата
               |ИЗ
               |    РегистрНакопления.РазмещениеЗаказовПокупателей.Остатки(, ЗаказПокупателя В (&Заказ)) КАК РазмещениеЗаказовПокупателейОстатки
               |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ЗаказыПоставщикам.Остатки КАК ЗаказыПоставщикамОстатки
               |        ПО РазмещениеЗаказовПокупателейОстатки.ЗаказПоставщику = ЗаказыПоставщикамОстатки.ЗаказПоставщику
               |            И РазмещениеЗаказовПокупателейОстатки.Номенклатура = ЗаказыПоставщикамОстатки.Номенклатура
               |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.элк_ПланДатыПоступления.СрезПоследних КАК ПланДатыПоступленияСрезПоследних
               |            ПО РазмещениеЗаказовПокупателейОстатки.ЗаказПоставщику = ПланДатыПоступленияСрезПоследних.ЗаказПоставщику
               |                И РазмещениеЗаказовПокупателейОстатки.Номенклатура = ПланДатыПоступленияСрезПоследних.Номенклатура";

Текст запроса дал что бы было понимание, какие регистры задействованы.

В итоге ПередЗаписью в дополнительных свойствах документа сохраняется состояние по срокам поставки до сохранения изменений документа в БД.

Далее пошел следующим путем, который и вызывает у меня сомнения. Сделал подписку на ОбработкуПроведения всех тех документов. В ней принудительно вызываю запись движений документа (Источник.Движения.Записать()). И затем уже получаю новое состояние регистров, сравниваю со старым и высылаю уведомления об изменениях.

Понятно, что рассылка уведомлений по почте - операция не быстрая, транзакция будет проходить дольше соответственно увеличивается продолжительность блокировки ресурсов транзакцией.
Плюс в принципе Источник.Движения.Записать() в обработке проведения - пне есть бест практикс.

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

Еще более геморный вариант, рассчитывать до начала проведения какое будет новое сотояние регистров, исходя из текущего отредактированного состояния документа и состояния регистров до внесения изменений. Но здесь еще больший гемор, т.к. опять разных документов много, плюс в УПП удаление движений регистров происходит мудренно (завист от регистра, режима проведения документа), в общем не вариант.

На самом деле в 1С не хватает события ПослеЗаписи  на уровне объекта, которое стреляло бы после завершения транзакции записи и проведения документа.
1 В тылу врага
 
10.04.13
11:10
ненужно объекту ничего такого вне транзакции
2 Волшебник
 
10.04.13
11:10
используй подписку
3 В тылу врага
 
10.04.13
11:11
(2) какую такую подписку?
4 Волшебник
 
10.04.13
11:11
(3) подписки на события
5 В тылу врага
 
10.04.13
11:11
(4) какую такую подписку на событие?
я имею ввиду на какое событие у объекта вне транзакции?
6 Нуф-Нуф
 
10.04.13
11:12
1. перед записью запоминать в допсвойствах
2. при записи документов - если выполняется условие - писать в регистр сведений ИнформацияДляОтправкиПоПочте
3. Регламентным заданием обрабатывать регистр ИнформацияДляОтправкиПоПочте, отправлять по почте и удалять записи ИнформацияДляОтправкиПоПочте
7 MigAV
 
10.04.13
11:14
(6) в событии при записи документа Вы не получите новое состояние регистров, т.к. данное событие происходит до обработки проведения
8 В тылу врага
 
10.04.13
11:15
(7) можно в событии ОбработкаПроведения
9 Волшебник
 
10.04.13
11:17
(5) на событие Проведение для документов или Запись для справочников. Я уже ответил на вопрос, а ты всё придираешься
10 В тылу врага
 
10.04.13
11:19
(9) отвечать надо правильно, ты говоришь про события В транзакции, а он ВНЕ
11 MigAV
 
10.04.13
11:20
(8) (9) Ну я же пишу что так и делаю, но при этом приходится делать Движения.Записать() после чего если уж и не отправлять уведомления, то как минимум опять делать запрос к регистрам и анализировать их изменения и на это время повышается вероятность блокировок, т.к. уже произведена запись.
12 Maxus43
 
10.04.13
11:21
(10) объясни Зачем тебе это событие сначала
13 В тылу врага
 
10.04.13
11:21
(12) мне? да ты чего, мужик, мне не надо, это автору
14 MigAV
 
10.04.13
11:23
Я же описал подробно зачем.
15 Maxus43
 
10.04.13
11:23
(11) надо отделить мух от котлет, не надо чтобы сам документ инициировал отправку почты. Создавай другой документ "Оповещение" например, при проведении твоего дока, который потом рег задание и будет отправлять по почте
16 MSII
 
10.04.13
11:24
В обработке проведения я бы только фиксировал сам факт необходимости рассылки по этому документу (в каком-то регистре сведений), а саму рассылку через обработчик ожидания, накопительно.
17 Maxus43
 
10.04.13
11:24
(15) + лучше в РС даже писать
18 IamAlexy
 
10.04.13
11:25
(0) призаписи для когопридумали?
19 Волшебник
 
10.04.13
11:25
(16) отдельным сеансом на сервере
20 MigAV
 
10.04.13
11:27
(18) Не для данной ситуации (см. очередность срабатывания событий)
21 Нуф-Нуф
 
10.04.13
11:39
"Сроки поставки задаются по-товарно в заказе поставщика и хранятся в регистре сведений".

почему бы не завязаться на события этого регистра Перед и ПриЗаписи.
22 Нуф-Нуф
 
10.04.13
11:40
перед записью запоминаем состояние, при записи анализируем, потом пишем данные в регистр ИнформацияКОтправке, и уже потом регламентным заданием делаем рассылку на основе ИнформацияКОтправке
23 Нуф-Нуф
 
10.04.13
11:41
получаем минимальное вмешательство в конфу и минимальные затраты в транзакции
24 Jolly Roger
 
10.04.13
11:44
(0) у тебя при удалении документа отправленные письма обратно возвращаются?..
25 Нуф-Нуф
 
10.04.13
11:44
кстати (22) так же учтет ситуацию в (24)
26 Киборг
 
10.04.13
12:20
отправлять в незавершенной транзакции нельзя, так как транзакция может откатиться, а откатить отправку уведомления не получится

событие редкое, поэтому регл задание прикручивать не хочется

правильно?


что если сделать так: подключить однократный обработчик ожидания, в котором
- если транзакция активна, то снова подключить тот же обработчик
- если транзакция неактивна, то проверить как она завершилась (вот это не знаю как сделать, может ВерсияДанных объекта проверить), если завершилась успешно, то отправить уведомление

Есть особенность такого решения: если за время ожидания тразакция успела завершиться и началась новая транзакция, в которой тоже надо уведомлять, то надо предусмотреть обработку очереди отправки уведомлений. Тогда надо изменить предложенный алгоритм.
27 MigAV
 
10.04.13
12:34
(21) Пробовал - хреновая идея. Во-первых события регистра срабатывают в общем случае дважды при проведении в момент удаления старых движений, в момент записи новых. Во-вторых в УПП практически все документы стоят в ручном режиме удаления движений и там реализован механизм оптимизации, в неоперативном режиме не из всех регистров удаляются старые записи, например в по регистру заказыпостащикам не удаляются, а по регистру резервов по-моему удаляются. Соответственно в событии перед записью запрос который обращается сразу к трем регистрам выдаст не весть что. Во вторых в событиях какого регистра отслеживать изменения - ведь в событии при записи какого-то одного регистра мы не знаем записались уже другие или нет. В конце концов представьте ситуацию из заказа поставщика просто удалили все товары со всеми сроками поставки, сработают события при удалении старых движений, а новых записей не будет, соответственно и событий не будет.
Короче могу еще 100+ причин назвать по которым данный метод считаю хреновым.

Ведь все просто нужно запомнить состояние регистров до сохранения изменений документа и получить их после и сравнить. (22) (15) Это как колхоз, который является следствием отсутствия события ПослеЗаписи на уровне объекта.
Почему 1С не реализовало такое событие. Судя по всему меньшим из зол будет перенести отправку уведомлений в событие ПослеЗаписи форм документов.
28 MigAV
 
10.04.13
12:42
(24) При удалении или отмене проведения например заказа поставщика или резервирования, высылается сообщение ответственным по заказам покупателей, о том что сроки поставки были такими-то, а теперь стали неопределенными. Вот и все это же просто информация, а не часть транзакции. Так же как и в он-лайн банкинге, вы просто получаете информацию о совершенных транзакциях, и если Вы например смс не получили это не значит, что транзакция должна быть отменена.
29 MigAV
 
10.04.13
14:37
(26) Да узнать есть ли активная транзакция в системе можно, но Вы не узнаете с каким объектом она связана и с каким действием (событием).

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

Но все равно считаю это колхозом. В идеале конечно хотелось бы избежать вызова Движения.Записать() в обработке проведения, т.к. потом другой разработчик может еще одну подписку добавить на обработку проведения, которая будет запускаться после моей и в которой будет какая-нибудь не очень быстрая обработка.
Но без события ПослеЗаписи объекта не получится избавиться от Движения.Записать().
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший