← вся теориятеория к собесу · Проведение документов

Порядок событий записи и проведения в 1С

разбор писал Даниил, автор Сеньорчика

Зачем это спрашивают

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

// Так спрашивают: «В каком порядке срабатывают события при записи документа из формы?» «Где проверять обязательные реквизиты?» «Сработает ли ПередЗаписьюНаСервере при записи из кода?» «Как передать флаг в обработчик записи?»

Порядок событий

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

ПередЗаписью и ПриЗаписи срабатывают и при записи без проведения. ОбработкаПроведения только при проведении, и только в ней формируют движения.

Где что писать

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

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

Флаги и загрузка

Иногда вызывающему нужно сказать обработчику «пропусти пересчёт в этот раз». Для этого у объекта есть ДополнительныеСвойства: структура, которая живёт, пока жив экземпляр объекта, и не попадает ни в базу, ни в обмен.

Первая строка обработчика проверяет ОбменДанными.Загрузка: если объект пришёл обменом, бизнес-логику пропускают, потому что источник уже всё посчитал.

// вызывающий код
Объект.ДополнительныеСвойства.Вставить("НеПересчитыватьЦены", Истина);
Объект.Записать(РежимЗаписиДокумента.Проведение);

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

Внешние действия

Проведение идёт в транзакции. Письмо клиенту, HTTP-запрос на сайт или сообщение в очередь из ОбработкаПроведения уйдут сразу, а транзакция потом может откатиться: письмо отправлено, документ не проведён. Вдобавок медленный внешний вызов держит открытой транзакцию и блокировки остатков.

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

Как отвечать: «Где ты будешь формировать движения документа и где проверять, что заполнен склад?»

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

Ответ кладёт каждую задачу в своё событие и объясняет почему, включая неочевидное поведение проверки заполнения у документов. Замечание про события формы закрывает частую ошибку.

На чём валят

  • −Проверяют обязательность реквизитов в ПередЗаписью. Дублируют механизм и мешают записать черновик. Берут Проверку заполнения и ОбработкаПроверкиЗаполнения.
  • −Ждут ПередЗаписьюНаСервере формы при программной записи. События формы срабатывают только из формы. Общую логику держат в модуле объекта.
  • −Отправляют письмо или HTTP-запрос из ОбработкаПроведения. Действие не откатится и держит блокировки. Ставят в очередь и отправляют после фиксации.
  • −Пересчитывают данные выше проверки ОбменДанными.Загрузка. Обмен пересчитает данные в приёмнике. Проверку ставят первой строкой.

Проверь себя

Пять вопросов из банка по этой подтеме. Всего их 11, остальные разбираются в тренажёре.

  1. #oc_object_events1 / 5
    Для чего обработчик ОбработкаЗаполнения модуля объекта?
    A)Заполнить табличную часть при каждом открытии формы
    B)Проверить заполненность реквизитов
    C)Заполнить движения регистров при проведении документа
    D)Заполнить новый объект, например на основании
    показать ответ и разбор
    +D)Заполнить новый объект, например на основании

    // разбор: ОбработкаЗаполнения получает ДанныеЗаполнения: ссылку-основание при вводе на основании или структуру значений. Там заполняют реквизиты нового объекта. Проверку обязательности делает ОбработкаПроверкиЗаполнения, движения — ОбработкаПроведения.

  2. #oc_object_events2 / 5
    Когда для документа вызывается ОбработкаПроверкиЗаполнения?
    A)Только при интерактивном открытии формы документа
    B)При каждой записи, как у справочника
    C)При проведении, а не при простой записи
    D)Только при программной записи методом Записать()
    показать ответ и разбор
    +C)При проведении, а не при простой записи

    // разбор: У документов проверка заполнения выполняется при проведении: черновик можно записать с пустыми полями. У справочников и других объектов она срабатывает при записи. Проверка запускается интерактивно из формы или методом ПроверитьЗаполнение(), программная запись Записать() её сама не вызывает.

  3. #oc_object_events3 / 5
    Что доступно в ПриЗаписи модуля объекта, чего ещё нет в ПередЗаписью?
    A)Возможность отменить запись через Отказ
    B)Ссылка нового объекта уже есть, объект записан в базу
    C)Доступ к реквизитам и табличным частям
    D)Открытая транзакция записи объекта
    показать ответ и разбор
    +B)Ссылка нового объекта уже есть, объект записан в базу

    // разбор: ПриЗаписи вызывается после записи объекта в базу внутри той же транзакции: у нового объекта уже есть ссылка, её можно сохранить в связанные записи. Отменить запись можно и там, установив Отказ, и в ПередЗаписью. Транзакция открыта в обоих обработчиках.

  4. #oc_object_events4 / 5
    Нужно передать признак «записано из обработки загрузки» из кода в ПередЗаписью объекта. Как правильно?
    A)Через глобальную переменную
    B)Через ДополнительныеСвойства объекта
    C)Через реквизит формы, который видит модуль объекта
    D)Через параметр сеанса, установленный перед записью
    показать ответ и разбор
    +B)Через `ДополнительныеСвойства` объекта

    // разбор: ДополнительныеСвойства — структура у объекта, которая живёт вместе с экземпляром и доступна во всех его обработчиках записи. Так передают флаги и подготовленные данные между кодом записи и обработчиками. Параметры сеанса и глобальные переменные общие для всего сеанса и легко «протекают» в чужие записи.

  5. #oc_object_events5 / 5
    В каком обработчике модуля объекта по стандартам проверяют заполненность реквизитов, зависящую от условий?
    A)ОбработкаПроверкиЗаполнения
    B)ПередЗаписью с Отказ
    C)ПриЗаписи, когда объект уже записан в базу
    D)ОбработкаПроведения перед формированием движений
    показать ответ и разбор
    +A)`ОбработкаПроверкиЗаполнения`

    // разбор: ОбработкаПроверкиЗаполнения получает массив ПроверяемыеРеквизиты: туда платформа кладёт реквизиты с признаком «Проверка заполнения», а код добавляет или убирает условно обязательные. Сообщения выводятся у полей формы. В ПередЗаписью такую проверку стандарты не пишут: она дублирует механизм и не срабатывает при черновой записи документа.

дальше

Теорию прочитал. Навык ставится повторением

В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, бесплатная часть практики — одна сессия дня в сутки.