Пример выбора несколько обработчиков событий записи объекта для решения одной задачи


Данная публикация предназначена для начинающих разработчиков и является продолжением статьи «Обработчики событий при записи объектов. Зачем и что за чем?» (ссылка далее). Содержит пример использования несколько обработчиков событий для решения одной задачи и объясняется почему выбраны именно они.

Ссылка на теоретическую часть тут //infostart.ru/public/1098803/  А в данной публикации рассмотрим пример из жизни

Пример выбора несколько обработчиков событий записи объекта для решения одной задачи.

Бывают задачи, когда потребуется использовать несколько обработчиков для решения одной задачи. Например, надо запросить информацию у пользователя во время записи: «Будем создавать новый документ на основании этой записи?» и, если пользователь ответит утвердительно, то надо создать новый документ  с ссылкой на записываемый объект.   Причем запись нового документа надо выполнять в  транзакции,  т.к. если текущая запись по каким то причинам будет отменена, то и уже созданный и записанный документ не должен остаться в базе данных.

Для решения этой задачи потребуется использовать обработчики события модуля формы по двум причинам:

1) Диалог с пользователем возможен только на клиенте, а клиентские обработчики есть только в модуле формы. Поэтому для диалога будем  использовать клиентскую процедуру модуля формы ПередЗаписью(), и сохраним ответ пользователя в  параметре этой процедуры «ПараметрыЗаписи».

&НаКлиенте
Процедура ПередЗаписью(ОтказПараметрыЗаписи)
    Если 
Вопрос("Будем создавать новый документ?"РежимДиалогаВопрос.ДаНет)=КодВозвратаДиалога.Да тогда
        
ПараметрыЗаписи.Вставить("Ответ","Да");
    Иначе
        
ПараметрыЗаписи.Вставить("Ответ","Нет");
    КонецЕсли;
КонецПроцедуры

2) А в процедуре  ПриЗаписиНаСервере() модуля формы примем этот параметр и в зависимости от него будем создавать документ или нет. Почему именно эта процедура? Потому что:

  • Это событие выполняется в транзакции (в случае сбоев, чтобы новый документ не остался в базе)  
  • Содержит параметр «ПараметрыЗаписи», в котором уже содержится ответ пользователя создавать или нет, который передался из процедуры ПередЗаписью()
  • Ссылка уже создана и можно создавать новый документ, используя эту ссылку (через параметр обработчика ТекущийОбъект.Ссылка).

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

&НаСервере
Процедура ПриЗаписиНаСервере(ОтказТекущийОбъектПараметрыЗаписи)
    Если 
ПараметрыЗаписи.Ответ="Да" Тогда
        
ДокОбъект=Документы.Продажа.СоздатьДокумент();
        
ДокОбъект.Дата=ТекущаяДата();
        
ДокОбъект.ДокументОснованиеТекущийОбъект.Ссылка;
        
//..заполняем табличную часть и реквизиты
        
ДокОбъект.Записать();
    КонецЕсли;
КонецПроцедуры

 

65 Comments

  1. Поручик

    Очередной копипаст из мануалов.

    Reply
  2. vlad.frost

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

    Reply
  3. AlbinaAAA

    (1) обновила статью, учитывая ваше замечание.. но копипаста как такового и не было, разве, что параметры из СП выдернула.

    В материале использованы знания, полученные только на курсе и в результате реального опыта.

    Reply
  4. Maldiv

    В свое время тоже помучился с этим, когда пришлось дорабатывать код, где обработка событий происходила и в форме и на сервере. +1

    Reply
  5. Ibrogim
    5) Модуль объекта ПередЗаписью(Отказ)для всех объектов, кроме документов

    В этом обработчике можно дозаполнять реквизиты объекта или провести дополнительные проверки. Есть доступ к данным формы.

    Ошибка

    Reply
  6. AlbinaAAA

    (5) Угу, спасибо за внимательность 🙂 конечно, доступа к данным формы нет, так как модуль объекта..

    Reply
  7. FedorovEvg

    Мне кажется, что картинка из приложения к книжке Радченко была бы более уместна чем эта статья. Там последовательно, графически изображено как отрабатывают события, причем на всех уровнях (форма, модуль сервер). Не понимаю, зачем переписывать, это словами и указывать.

    Единственно, что для новичков не совсем логично, так это отработка событий ОбработкаПроверкиЗаполнения и ОбработкаПроверкиЗаполненияНаСервере не при записи объекта, а при проведении, НО никто не мешает проявить смекалку и вставить вызов процедуры ПроверитьЗаполнение() в процедуры ПередЗаписью у формы элемента.

    Reply
  8. AlbinaAAA

    (7)

    Мне кажется, что картинка из приложения к книжке Радченко была бы более уместна чем эта статья. Там последовательно, графически изображено как отрабатывают события, причем на всех уровнях (форма, модуль сервер). Не понимаю, зачем переписывать, это словами и указывать.

    Да всё просто на самом деле 🙂 Очень много людей предпочитает обучаться не по сухим схемам, а чтобы им объяснили простым человеческим языком и с примерами что и как. И, на мой взгляд, именно поэтому тысячи людей предпочитают платить тысячИ рублей за курсы проекта spec8.ru, вместо того, чтобы почитать Радченко за несколько сотен (а можно и бесплатно скачать). Потому что там тренеры простым человеческим языком объясняют сложные вещи и показывают «как надо и как не надо» и при этом на очень высоком профессиональном уровне. Так что, немалая категория людей предпочитает именно такой способ обучения, когда на словах.. и чем проще, тем лучше..

    Reply
  9. 4ur

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

    Reply
  10. higs

    А мне тоже понравилась раскладка по событиям. Просто, понятно, доступно. Спасибо!!

    Reply
  11. zipik

    спасибо за статью

    Reply
  12. zipik

    есть еще подписки на события..еще бы их разобрать

    Reply
  13. zipik

    зачем они и как их применять

    Reply
  14. zipik

    ведь уже есть вышеперечисленные обработчики

    Reply
  15. AlbinaAAA

    (12) zipik, тут посмотрите http://infostart.ru/public/154317/

    а если в двух словах, подписку на событие удобно использовать:

    1) в типовых конфигурациях, чтобы без проблем обновляться. Типовые объекты не трогаем, а свой функционал реализуем через подписку на событие, перехватывая нужное событие и перенаправляя в свой общий модуль через параметр «Обработчик» подписки (типовые общие модули лучше не трогать, опять-таки из-за обновления) где и пишем свой код.

    2) если нужно перехватить определенное событие для множества объектов. Например, для многих документов во время проведения нужно прописать выполнение одинакового действия. И чтобы не прописывать одно и то же в каждом документе и используется подписка на событие.

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

    Reply
  16. sonuchin3
    6) Модуль объекта ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)

    …Или ПриУстановкеНовогоКода(СтандартнаяОбработка,Префикс)

    … Эти событии вызываются для объектов у которых указано свойство «Автонумерация» и только для новых объектов.

    — Новый объект или нет — не имеет значения. А зависит от того, пустой ли номер (код).

    Т.е. если у нового объекта вручную задать код, то событие ПриУстановкеНовогоКода() не будет вызвано, а если у записанного объекта вручную очистить код, то событие ПриУстановкеНовогоКода() будет вызвано.

    Reply
  17. klel

    Большое спасибо аз полезную информацию, полезна новичкам =)

    Reply
  18. and_r

    Идея статьи очень хорошая, но тема, я считаю не раскрыта. Может какие-то примеры надо было привести, а так, соглашусь, что очень напоминает фрагмент из книг входящих в комплект поставки

    Reply
  19. AlbinaAAA

    (18) and_r, показательный пример, хорошо раскрывающий тему, в статье есть..может Вы невнимательно читали.. а громоздить статью простейшими примерами на каждый обработчик намеренно не стала, думаю, что статья от этого не стала бы более информативной, а уровень читабельности статьи бы снизился.. а то, что очень напоминает фрагмент из книг, это исключительно субьективное восприятие выбранной темы 🙂

    Reply
  20. AlbinaAAA

    (16) sonuchin3, очень ценное замечание! Спасибо!

    Reply
  21. Moll

    Благодарим автора за достаточно полезную информацию, которая несомненно полезна новичкам =]

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

    удачи на конкурсе 😉

    Reply
  22. AlbinaAAA

    (21) Moll, и Вам спасибо 🙂

    Reply
  23. SergeMalikov

    Альбина! И я вас поздравляю с победой в конкурсе. Надеюсь увидеть вас на продвинутом курсе.

    Reply
  24. AlbinaAAA

    Спасибо, Сергей! 🙂 я сейчас на конвертации, продвинутый после 🙂

    Reply
  25. psamt1k

    Спасибо! Полезно

    Reply
  26. Moll

    ну вот :]

    очередной раз пригодилась ваша статья, своеобразная такая шпаргалочка получилась, ещё раз благодаримс ;]

    ну и конечно же присоединяюсь к поздравлениям…

    удачи в следующих конкурсах

    Reply
  27. CaSH_2004

    (12)Меня тоже интересовал этот вопрос, в кратце ответ сводится к тому что перехватываются события модуля объекта, но только ПОСЛЕ их выполнения:

    — ПриУстановкеНовогоНомера / ПриУстановкеНовогоКода

    — ПриКопировании

    — ОбработкаЗаполнения

    — ПередЗаписью

    — ПриЗаписи

    — ПередУдалением

    — ОбработкаПроведения (только документы)

    — ОбработкаУдаленияПроведения (только документы)

    — ОбработкаПроверкиЗаполнения (только документы)

    Суть использования идентична указанному в статье. Непонятно только почему в статье Использование подписок сказано что идет замедление выполнения в подписке чем в модуле объекта, на мой взгляд они равноправны, так же как вызвать из модуля объекта процедуру общего модуля — тоже будет замедление, но оно ничтожно с самой процедурой

    Указаны только для Справочников и Документов, но есть еще и множество других объектов (всякие планы и регистры)

    Кстати не указана очередность обработкичков при проведении документа, что очень важно! Например она така:

    — МодульОбъекта.ПриЗаписи()

    — МодульОбъекта.ОбработкаПроведения()

    — МодульФормы.ПриЗаписиНаСервере()

    И вот возникает интересная дилема, предположим что при проведении 1-го документа, проверяется корректность созданного на его основании 2-го документа, а его мы заполняем только исходя из данных в управляемой форме в обработчике ПриЗаписиНаСервере().

    И вот что же делать если проверка выполняется ДО корректировки, а нужно ПОСЛЕ? Если бы в управляемом режиме был доступен параметр объекта ДополнительныеСвойства, то в него можно было бы внести нужные данные (я так раньше и делал) и в обработчике ПриЗаписи() все выполнить, до проверки в ОбработкаПроведения().

    На первый взгляд кажется что связь механизма записи в объекте в управляемом режиме абсолютно оторвана от заполнения формы, что очень плохо! Было бы неплохо чтобы ДополнительныеСвойства были взаимосвязаны с ПараметрыЗаписи, а то все они работают в пределах своей области.

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

    &НаСервере
    Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    Для Каждого Элемент Из ПараметрыЗаписи Цикл
    ТекущийОбъект.ДополнительныеСвойства.Вставить(Элемент.Ключ, Элемент.Значение);
    КонецЦикла;
    КонецПроцедуры

    После чего в объекте можно получить то что нам нужно и обработать это

    Reply
  28. AlbinaAAA
    Reply
  29. CaSH_2004

    (28) Ну как бы проводить 1-й документ по всем обработчикам — лишняя трата ресурсов при условии что потом все это отменится только из-за того что не удалось создать документ, например у меня Маршрут где 30 накладных которые нужно развести по клиента, и вот Маршрутный лист делает движения, и потом мы проверяем и перезаписываем все 29 накладных, а на 30-й вылетает ошибка и нужно все отменить.

    Поэтому для меня важно все проверки и записи на основании сделать ДО, а не ПОСЛЕ проведения основного документа — Маршрута.

    Проверяется соответствие накладных данным в Маршруте.

    А так все верно вроде, наверно я что-то не разглядел, поздно уже было…

    Reply
  30. AlbinaAAA

    (29) CaSH_2004, теперь понятно 🙂 ваша задача относится к категории оптимизации. Обработчик «ПриЗаписиНаСервере» в своем примере я использовала потому, что нужен был ПараметрЗаписи, в котором находился ответ пользователя на вопрос «создавать второй документ или нет?». А если решать вашу задачу, то этот ПараметрЗаписи нам и не нужен и потому ничто не мешает воспользоваться процедурой «ПриЗаписи», которая запускатся ДО процедуры «ОбработкаПроведения», но ссылка записываемого док-та уже есть, и потому можно создать документы на её основании и проверить их. Причем, можно сначала их записать все без проведения, проверить корректность, сохранить в коллекцию значений, а потом, если все док-ты прошли успешно проверку, перебрать коллекцию и провести созданные на основании первого документы. И всё это в процедуре «ПриЗаписи».

    Reply
  31. elvis1917

    Вопрос по примеру выбора обработчиков событий записи объекта:

    А если документ будет создавать и записываться программно — разве в ПараметрахЗаписи будет параметр Ответ? Не выдаст ли система ошибку?

    Reply
  32. AlexO

    Ну как всегда — за картинку, которая у меня уже года четыре, как нарисована, накидали сотни баллов 🙂

    И куча восторженных отзывов.

    Reply
  33. AlbinaAAA

    (31) elvis1917, когда объект записывается программно обработчики модуля формы не вызываются, а вызываются только обработчики модуля объекта. Потому ошибки не будет, так как процедура ПриЗаписиНаСервере, которая содержит параметр ПараметрыЗаписи — это обработчик модуля формы, потому при программной записи он просто не будет вызываться.

    Reply
  34. ivdic

    хотелось бы все это графически в виде блок схемы отобразить

    Reply
  35. rimma_n

    Полезная шпаргалка получилась, спасибо!

    Reply
  36. LexSeIch

    Мир этому дому.

    Полезная статья. Больше бы такой информации. Я имею в виду небольших заметок на конкретную тему. Читая их — что то обновляешь в памяти, что-то узнаешь новое… Да и из комментов порой узнаешь много интересного.

    Reply
  37. Alex1Cnic

    добавлю в свою базу знаний

    Reply
  38. KliMich

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

    И осветить, что такое подписка на события (как они туда вклиниваются и с чем ее едят)

    Reply
  39. Поручик

    (38) Скачай книгу Разработка управляемого интерфейса Хрусталёвой, там всё описано и нарисовано.

    Reply
  40. vlad.frost

    (0) Крутая публикация. Хотел плюс поставить, а я его оказывается уже ставил в прошлом году 🙂

    Reply
  41. Bukaska

    Я примерно понимаю, зачем эти все обработчики.

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

    И в итоге мы только перенаправляем из стандартных подсистем обработчики на свои перепиленные объекты, в результате чего пациент не на «Игле», в отличие от той ситуации, когда мы пилим в ней все что есть.

    Хотя ниче не спорю, перепилить конфу проще, чем сделать собственную подсистему с своими наработками)))

    Reply
  42. hame1e00n

    Спасибо, очень нужная информация, пригодилось 🙂

    Reply
  43. melenaspb

    Еще бы понять какие данные в каком обработчике использовать : Объект, ТекущийОбъект, ТекущийОбъект.Ссылка и т.п.

    Reply
  44. Ndochp

    (0) Столкнулся с проблемой, не пойму к какому событию подключаться.

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

    Проблема в том, что если в «ПриЗаписи» это все делать, то при ошибке проведения подчиненного документа падает исходная транзакция, а должен просто записываться непроведенный документ разнесения.

    Reply
  45. AlbinaAAA

    (44) Ndochp, я бы тоже использовала обработчик модуля объекта «ПриЗаписи», но новый документ бы просто записывала, без проведения, а потом там же(«ПриЗаписи») через попытку попробовала бы провеси этот новый документ. В таком случае транзакция не слетит.

    Reply
  46. kinazarov

    Спасибо за статью.

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

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

    Reply
  47. jobkostya1c8

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

    Reply
  48. jobkostya1c8

    (46) kinazarov, верно замечено. Приходится опытным путем устанавливать что все подписки на события выполняются после стандартных обработчиков Объекта (не формы) и и выполняются тоже только на сервере.

    Reply
  49. gesk

    Спасибо! У меня не было книжки Радченко под рукой

    Reply
  50. pvlunegov

    ПослеЗаписиНаСервере — выполняется после завершения Транзакции записи или проведения документа!

    Я нашел то, что искал!

    Огромное спасибо!

    Мне как раз нужно было событие, которое начинается после события ОбработкаПроведения.

    В модуле объекта, модуле менеджера — таких событий нет!

    Зато есть в модуле формы документа!

    Вопрос: Видимо ранее, в других версиях платформы, такого события не было? Или я не прав?

    Много программировал на 8.1 такого события не помню

    Видимо добавили в управляемых формах?

    Reply
  51. pvlunegov

    Еще раз спасибо за ответ на мучивший меня несколько часов ответ.

    Думал что нет такого события — После проведения.

    Оказывается, УЖЕ есть.

    Раньше точно не было.

    И это хорошо. 1с идет на встречу многочисленным просьбам программистов и вносит ДОПОЛНЕНИЯ в свою объектную модель.

    Почему бы не добавить событие в МОДУЛЬ ОБЪЕКТА — ПОСЛЕПРОВЕДЕНИЯ?

    Возможно я чего-то не знаю, но мне кажется обоснованным такое предложение.

    Видимо подводные камни реализации объектной модели в платформе 1с не дают изменять оную.

    Поэтому 1с поступила иначе — добавили событие в МОДУЛЬ ФОРМЫ ПослеПроведенияНаСервере.

    Ну хотя бы так. Уже легче жить.

    А как-же быть с проведением документа из формы списка? Ведь при этом не открывается форма, вызывается объектная модель документа.

    В ней нет события МОДУЛЯ ФОРМЫ ПослеПроведенияНаСервере.

    Косякс! 1с не отвечает на таковые вопросы или умалчивает.

    А вопрос то животрепещущий! В реальной жизни программиста ооочень актуальный!

    Вот я например, сделал обработку события МОДУЛЯ ФОРМЫ ПослеПроведенияНаСервере.

    После проведения документа теперь проводятся (с ошибками) пачка других документов.

    Приходит пользователь и говорит — при проведении из формы списка ваш алгоритм не работает!

    Я его посылаю на 1с (на 2 буквы), почти что на 3 буквы (1 не хватает).

    Reply
  52. Nicholas

    В обработчике ПриЗаписиНаСервере() можно использовать как Объект, так и ТекущийОбъект. В чем разница?

    Reply
  53. ineshyk

    (50)только учтите, что ПослеЗаписиНаСервере не всегда выполняется.

    Reply
  54. ineshyk

    (52)Разница в том, что в поле Объект нельзя переопределять значения, т.к. в базу запишется уже текущий объект.

    Reply
  55. AlexxSys

    Не понятен причина, зачем было удалять из объекта и подписки ПослеЗаписи — его заменить ничем нельзя.

    При записи —

    1. во первых до обработки проведения, т.е. движений нет, мало этого если этот документ существует в базе старые движения, т.е. если наш генерируемый документ опирается на движения — получишь или пустые движения или старые/неактуальные.

    2. И во вторых — данные объекта / ссылки видны только в транзакции, т.е. если у нас создается фоновое задание, то там будет битая ссылка без данных (допустим отправка объекта на сайт, в общем потоке — не стоит тормозить его, обычно делается другим потоком, так вот там данных не будет, все реквизиты пустые будут)

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

    Reply
  56. AntonSKT

    Очень понравился материал, как раз для тех кто еще начитает изучать

    Reply
  57. UserPro

    Это все замечательно. Но описание событий для регистров раскрыто слабовато.

    Reply
  58. Vlan

    «Прогаммисту, имеющеМУ…»

    Уж простите за педантичность. 🙂

    Reply
  59. mikl79

    на картинке не увидел стрелку «Запись движений документа», есть только «Запись не записанных…»

    Reply
  60. rozer

    Думаю имеет смысл дополнить описание про «ТекущийОбъект». А то очень не информативно описано, ну например кто-то может не знать что в


    ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)

    назначение «ТекущийОбъект» прямо противоположное чем в


    ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)

    ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)

    и менять его бесполезно уже и надо использовать «Объект» если что ну и т.п.

    В книге «Разработка управляемого интерфейса» кажется подробно все про это…

    Reply
  61. PLAstic

    Статья-дубль.

    https://infostart.ru/public/849540/

    Reply
  62. stein13

    копипаст/некопипаст…. какая разница! Иногда вспомнить не помешает.

    Reply
  63. Plotks2017

    Статья понравилась. Написана хорошо. Легко читается.

    Непонятно почему столько рейтинга набрала. Сложные статьи с редкими материалами набирают 10 от силы, а тут 400+ за самый базовый материал, что обязан знать каждый. Не в укор автору, просто мысли вслух, неужели средний уровень настолько низкий.

    Reply
  64. Plotks2017

    (62) дату статьи посмотри, спорный вопрос кто дубль =)

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *