Порядок событий записи и проведения в 1С
Запись документа проходит через цепочку событий формы и объекта, и в каждом событии своё правильное место для кода. На собесе просят назвать порядок, объяснить, где формировать движения, где проверять заполнение и почему письмо клиенту нельзя отправлять из проведения.
// Так спрашивают: «В каком порядке срабатывают события при записи документа из формы?» «Где проверять обязательные реквизиты?» «Сработает ли ПередЗаписьюНаСервере при записи из кода?» «Как передать флаг в обработчик записи?»
Порядок событий
При записи документа из формы события идут в таком порядке. Первые три относятся к форме, остальные к объекту, и при записи из кода срабатывают только события объекта:
ПередЗаписью и ПриЗаписи срабатывают и при записи без проведения. ОбработкаПроведения только при проведении, и только в ней формируют движения.
Где что писать
Обязательность реквизитов задают свойством «Проверка заполнения» и обработчиком ОбработкаПроверкиЗаполнения: у документа он срабатывает при проведении, а черновик можно записать с пустыми полями. Проверки обязательности в ПередЗаписью дублируют этот механизм и мешают сохранить черновик.
События формы срабатывают только при записи из формы. Обработка, которая записывает документ из кода, ПередЗаписьюНаСервере не вызовет, поэтому общую логику держат в событиях объекта.
Флаги и загрузка
Иногда вызывающему нужно сказать обработчику «пропусти пересчёт в этот раз». Для этого у объекта есть ДополнительныеСвойства: структура, которая живёт, пока жив экземпляр объекта, и не попадает ни в базу, ни в обмен.
Первая строка обработчика проверяет ОбменДанными.Загрузка: если объект пришёл обменом, бизнес-логику пропускают, потому что источник уже всё посчитал.
// вызывающий код
Объект.ДополнительныеСвойства.Вставить("НеПересчитыватьЦены", Истина);
Объект.Записать(РежимЗаписиДокумента.Проведение);
// модуль объекта
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Не ДополнительныеСвойства.Свойство("НеПересчитыватьЦены") Тогда
ПересчитатьЦены();
КонецЕсли;
КонецПроцедурыВнешние действия
Проведение идёт в транзакции. Письмо клиенту, HTTP-запрос на сайт или сообщение в очередь из ОбработкаПроведения уйдут сразу, а транзакция потом может откатиться: письмо отправлено, документ не проведён. Вдобавок медленный внешний вызов держит открытой транзакцию и блокировки остатков.
Очередь можно держать в регистре сведений: запись о необходимости отправки делается в той же транзакции и откатывается вместе с документом, а отправку выполняет регламентное задание.
Как отвечать: «Где ты будешь формировать движения документа и где проверять, что заполнен склад?»
Движения формирую в ОбработкаПроведения модуля объекта, это единственное событие, которое срабатывает только при проведении. Обязательность склада задаю свойством «Проверка заполнения», а сложные условия пишу в ОбработкаПроверкиЗаполнения: у документа она срабатывает при проведении, и черновик можно записать с пустым складом. В событиях формы такую логику не держу, при записи из кода они не сработают.
Ответ кладёт каждую задачу в своё событие и объясняет почему, включая неочевидное поведение проверки заполнения у документов. Замечание про события формы закрывает частую ошибку.
На чём валят
- −Проверяют обязательность реквизитов в ПередЗаписью. Дублируют механизм и мешают записать черновик. Берут Проверку заполнения и ОбработкаПроверкиЗаполнения.
- −Ждут ПередЗаписьюНаСервере формы при программной записи. События формы срабатывают только из формы. Общую логику держат в модуле объекта.
- −Отправляют письмо или HTTP-запрос из ОбработкаПроведения. Действие не откатится и держит блокировки. Ставят в очередь и отправляют после фиксации.
- −Пересчитывают данные выше проверки
ОбменДанными.Загрузка. Обмен пересчитает данные в приёмнике. Проверку ставят первой строкой.
Проверь себя
Пять вопросов из банка по этой подтеме. Всего их 11, остальные разбираются в тренажёре.
- Для чего обработчик
ОбработкаЗаполнениямодуля объекта?A)Заполнить табличную часть при каждом открытии формыB)Проверить заполненность реквизитовC)Заполнить движения регистров при проведении документаD)Заполнить новый объект, например на основаниипоказать ответ и разбор
+D)Заполнить новый объект, например на основании// разбор: ОбработкаЗаполнения получает ДанныеЗаполнения: ссылку-основание при вводе на основании или структуру значений. Там заполняют реквизиты нового объекта. Проверку обязательности делает ОбработкаПроверкиЗаполнения, движения — ОбработкаПроведения.
- Когда для документа вызывается
ОбработкаПроверкиЗаполнения?A)Только при интерактивном открытии формы документаB)При каждой записи, как у справочникаC)При проведении, а не при простой записиD)Только при программной записи методом Записать()показать ответ и разбор
+C)При проведении, а не при простой записи// разбор: У документов проверка заполнения выполняется при проведении: черновик можно записать с пустыми полями. У справочников и других объектов она срабатывает при записи. Проверка запускается интерактивно из формы или методом ПроверитьЗаполнение(), программная запись Записать() её сама не вызывает.
- Что доступно в
ПриЗаписимодуля объекта, чего ещё нет вПередЗаписью?A)Возможность отменить запись через ОтказB)Ссылка нового объекта уже есть, объект записан в базуC)Доступ к реквизитам и табличным частямD)Открытая транзакция записи объектапоказать ответ и разбор
+B)Ссылка нового объекта уже есть, объект записан в базу// разбор: ПриЗаписи вызывается после записи объекта в базу внутри той же транзакции: у нового объекта уже есть ссылка, её можно сохранить в связанные записи. Отменить запись можно и там, установив Отказ, и в ПередЗаписью. Транзакция открыта в обоих обработчиках.
- Нужно передать признак «записано из обработки загрузки» из кода в
ПередЗаписьюобъекта. Как правильно?A)Через глобальную переменнуюB)ЧерезДополнительныеСвойстваобъектаC)Через реквизит формы, который видит модуль объектаD)Через параметр сеанса, установленный перед записьюпоказать ответ и разбор
+B)Через `ДополнительныеСвойства` объекта// разбор: ДополнительныеСвойства — структура у объекта, которая живёт вместе с экземпляром и доступна во всех его обработчиках записи. Так передают флаги и подготовленные данные между кодом записи и обработчиками. Параметры сеанса и глобальные переменные общие для всего сеанса и легко «протекают» в чужие записи.
- В каком обработчике модуля объекта по стандартам проверяют заполненность реквизитов, зависящую от условий?A)
ОбработкаПроверкиЗаполненияB)ПередЗаписьюсОтказC)ПриЗаписи, когда объект уже записан в базуD)ОбработкаПроведенияперед формированием движенийпоказать ответ и разбор
+A)`ОбработкаПроверкиЗаполнения`// разбор: ОбработкаПроверкиЗаполнения получает массив ПроверяемыеРеквизиты: туда платформа кладёт реквизиты с признаком «Проверка заполнения», а код добавляет или убирает условно обязательные. Сообщения выводятся у полей формы. В ПередЗаписью такую проверку стандарты не пишут: она дублирует механизм и не срабатывает при черновой записи документа.
дальше
Теорию прочитал. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, бесплатная часть практики — одна сессия дня в сутки.