При разработке в среде «1С:Предприятие 8» программисты часто сталкиваются с ситуацией, когда код, написанный в обработчиках ПередЗаписью или ПриЗаписи модуля объекта, игнорируется платформой. Кажется, что программа просто «пролетает» мимо этих процедур, даже если в них установлены точки останова. Рассмотрим подробно причины этого явления и разберем по шагам, как восстановить нормальную работу логики записи.
Это самая распространенная причина, с которой столкнулся автор обсуждения. Рассмотрим механизм работы платформы при интерактивной записи объекта (из формы). Платформа 1С соблюдает строгую последовательность событий. Если для какого-либо реквизита в метаданных установлено свойство Проверка заполнения: Выдавать ошибку, цепочка событий выглядит так:
ПередЗаписью (на клиенте и на сервере).ОбработкаПроверкиЗаполнения.ПередЗаписью модуля объекта.Проанализируем ситуацию: если вы пытаетесь заполнить обязательный реквизит именно в процедуре ПередЗаписью модуля объекта, вы опаздываете. Платформа обнаруживает, что поле пустое, еще на втором этапе, выдает ошибку пользователю и прекращает выполнение транзакции. До вашего кода дело просто не доходит.
Как решить:
Вариант А: Перенесите логику заполнения поля в обработчик ОбработкаПроверкиЗаполнения модуля объекта. Разберем пример кода:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Заполняем поле до того, как платформа выдаст ошибку
Если Не ЗначениеЗаполнено(ВашРеквизит) Тогда
ВашРеквизит = "Значение по умолчанию";
КонецЕсли;
КонецПроцедуры
Вариант Б: Исключите реквизит из списка проверяемых программно, если его заполнение планируется позже:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Удаляем реквизит из массива проверки
Позиция = ПроверяемыеРеквизиты.Найти("ВашРеквизит");
Если Позиция <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(Позиция);
КонецЕсли;
КонецПроцедуры
Иногда при ручном копировании кода или создании процедур «вручную» (прописью текста в модуле) связь между процедурой и событием объекта может не установиться. Проанализируем, как это проверить.
Выясним причину с помощью конфигуратора. Откройте модуль объекта, найдите процедуру ПередЗаписью. Обратите внимание на выпадающие списки в верхней части окна редактора кода. В левом списке должен быть выбран Объект, а в правом — само событие ПередЗаписью. Если процедура написана в тексте, но не выбрана в этом списке, платформа её не увидит.
Рассмотрим быстрый способ проверки: нажмите сочетание клавиш Ctrl + Alt + P (встать на обработчик). Если платформа предложит создать новую процедуру вместо перехода к существующей, значит, связь разорвана. Чтобы восстановить её, просто выберите событие из списка и укажите вашу процедуру.
В современных конфигурациях активно используются расширения. Выясним, как они могут блокировать выполнение кода в основной конфигурации. Если в расширении создан одноименный обработчик события с аннотацией &Вместо, то код основной программы будет полностью проигнорирован, если разработчик расширения не вызвал метод ПродолжитьВызов().
Проанализируем ситуацию в расширении. Проверьте, нет ли там процедуры следующего вида:
&Вместо("ПередЗаписью")
Процедура Расш1_ПередЗаписью(Отказ, ПараметрыЗаписи)
// Если здесь нет вызова ПродолжитьВызов(),
// основная процедура модуля объекта не запустится!
// ПродолжитьВызов(Отказ, ПараметрыЗаписи);
КонецПроцедуры
Если вы обнаружили такой код, необходимо добавить вызов оригинальной процедуры, чтобы сохранить преемственность логики.
До того как управление перейдет в модуль объекта, срабатывают события формы. Разберем ситуацию, когда запись прерывается еще в интерфейсном слое. Проверьте процедуры ПередЗаписью и ПередЗаписьюНаСервере в модуле формы документа или справочника.
Если в коде формы встречается условие, устанавливающее Отказ = Истина, или СтандартнаяОбработка = Ложь, то выполнение может завершиться до обращения к серверным методам объекта. Также стоит проверить, не задействованы ли подписки на события (объект ПодпискиНаСобытия в дереве метаданных), которые могут отменять запись по своим внутренним алгоритмам.
Иногда код на самом деле выполняется, но программист этого не видит. Разберем технические нюансы отладки:
-debug). Если он выключен, точки останова в модуле объекта (который всегда выполняется на сервере при записи) срабатывать не будут.Сообщить(), могут «пропадать», если произошел критический сбой. Для гарантированной проверки используйте запись в журнал регистрации:
ЗаписьЖурналаРегистрации("ПроверкаСобытия",
УровеньЖурналаРегистрации.Информация, , , "Процедура ПередЗаписью сработала!");
Если ваши процедуры ПередЗаписью или ПриЗаписи игнорируются, выполните следующие действия:
ОбработкаПроверкиЗаполнения.Ctrl + Alt + P, что процедуры в модуле корректно назначены как обработчики событий.&Вместо для данного объекта.Помните, что архитектурно правильным считается заполнение технических реквизитов именно в модуле объекта, но только в том случае, если эти реквизиты не заблокированы механизмами валидации платформы на более ранних этапах.