Имя: Пароль:
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) Да узнать есть ли активная транзакция в системе можно, но Вы не узнаете с каким объектом она связана и с каким действием (событием).

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

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