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