Создание документов на основании других объектов — одна из самых частых задач в разработке на платформе 1С:Предприятие. Основным механизмом для реализации этой логики является событие ОбработкаЗаполнения. Однако начинающие разработчики часто сталкиваются с ситуацией, когда написанный код заполнения просто не срабатывает: отладчик не останавливается на точке останова, а система ведет себя так, будто обработчика вовсе не существует.
В этой статье мы подробно разберем, почему возникает такая проблема, проанализируем неочевидные ошибки в параметрах процедур, которые ломают логику условий, и рассмотрим два правильных варианта решения задачи: через локальный обработчик в модуле объекта и через создание полноценной подписки на событие.
Рассмотрим ситуацию, с которой столкнулся автор темы. В конфигурации "Управление торговлей 10.3" при вводе документа РеализацияТоваровУслуг на основании документа ЗаказПокупателя была написана следующая процедура в модуле объекта реализации:
Процедура РеализацияТоваровУслугОбработкаЗаполнения(Источник, Основание) Экспорт
Если ТипЗнч(Основание) <> Тип("ДокументСсылка.ЗаказПокупателя") Тогда
Сообщить("ОК");
КонецЕсли;
КонецПроцедуры
При запуске процесса создания на основании код не отрабатывал, а точка останова в начале процедуры игнорировалась платформой. Выяснилось, что разработчик совершил две критические ошибки:
Экспорт) не делает её обработчиком события. Платформа "не знает", что эту процедуру нужно вызывать, пока мы явно не свяжем её с событием в свойствах объекта метаданных.Давайте подробно разберем каждую из этих ошибок и выясним, как ведет себя платформа в таких сценариях.
Обратите внимание на параметры, которые объявил автор: (Источник, Основание).
Для локального обработчика события ОбработкаЗаполнения в модуле объекта стандартная сигнатура платформы выглядит так:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Когда платформа вызывает это событие, она передает параметры строго по их порядковому номеру, независимо от того, как вы их назвали в коде:
Источник) платформа передает **документ-основание** (ссылку на ЗаказПокупателя).Основание) платформа передает вспомогательный системный флаг СтандартнаяОбработка типа Булево (со значением Истина).Теперь проанализируем, что происходило в коде автора при проверке условий:
Сценарий 1. Использование оператора "<>" (Не равно)
Код выглядел так: Если ТипЗнч(Основание) <> Тип("ДокументСсылка.ЗаказПокупателя"). Из-за смещения параметров в переменной Основание фактически находилось булево значение Истина. Платформа выполняла сравнение: равен ли тип Булево типу ДокументСсылка.ЗаказПокупателя? Разумеется, они не равны. Условие "Не равно" возвращало истину, и система выводила сообщение "ОК" (когда обработчик всё же удавалось запустить).
Сценарий 2. Использование оператора "=" (Равно)
Когда автор исправила условие на знак равенства: Если ТипЗнч(Основание) = Тип(...), платформа начала проверять: равен ли тип Булево типу ссылки документа. Это условие всегда возвращало ложь, поэтому сообщение "ОК" перестало выводиться, создавая иллюзию того, что код вообще не выполняется.
Выяснив причины неверного поведения системы, перейдем к правильным вариантам реализации.
Если вам необходимо быстро реализовать заполнение в рамках одного документа и конфигурация находится на поддержке с возможностью изменения, выполним следующие шаги:
РеализацияТоваровУслуг.ОбработкаЗаполнения и нажмем на кнопку с лупой. Платформа автоматически свяжет событие с процедурой в модуле объекта и создаст заготовку с правильными параметрами.
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
// ДанныеЗаполнения — это наш документ-основание (ЗаказПокупателя)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
Сообщить("Событие обработчика в модуле объекта сработало успешно!");
// Здесь мы пишем логику заполнения реквизитов, например:
// ЭтотОбъект.Контрагент = ДанныеЗаполнения.Контрагент;
// ЭтотОбъект.ДоговорКонтрагента = ДанныеЗаполнения.ДоговорКонтрагента;
КонецЕсли;
КонецПроцедуры
Если вы хотите избежать изменения типовых модулей конфигурации (чтобы облегчить последующие обновления системы), правильным архитектурным решением будет использование объекта метаданных Подписка на событие. В этом случае весь код будет находиться в отдельном общем модуле.
Рассмотрим по шагам, как настроить подписку:
Сервер и Вызов сервера (в зависимости от режима работы конфигурации), а флаг Глобальный должен быть снят.Общие -> Подписки на события добавим новый объект.ДокументОбъект.РеализацияТоваровУслуг (именно объект, а не ссылку, так как заполняется новый, еще не записанный в базу документ).ОбработкаЗаполнения.Важное правило подписок на события: Сигнатура процедуры-обработчика в общем модуле всегда должна содержать на один параметр больше, чем стандартное событие в модуле объекта. Первым параметром всегда передается сам объект-источник, который инициировал событие.
Напишем правильный код для общего модуля:
Процедура РеализацияТоваровУслугОбработкаЗаполнения(Источник, ДанныеЗаполнения, СтандартнаяОбработка) Экспорт
// Параметр 'Источник' — это заполняемый объект (РеализацияТоваровУслугОбъект)
// Параметр 'ДанныеЗаполнения' — это документ-основание (ЗаказПокупателяСсылка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
// Заполняем реквизиты создаваемой реализации из заказа-покупателя:
Источник.Контрагент = ДанныеЗаполнения.Контрагент;
Источник.Организация = ДанныеЗаполнения.Организация;
Сообщить("Заполнение через Подписку на событие выполнено!");
КонецЕсли;
КонецПроцедуры
Для того чтобы процесс разработки и поиска ошибок проходил быстрее, рекомендуем учитывать несколько важных особенностей платформы 1С:
Сообщить(5/0);. Если при попытке создания документа система аварийно завершит работу с ошибкой "Деление на ноль", значит, событие успешно связано и управление передается в ваш код.ОбработкаЗаполнения всегда выполняется на стороне сервера. При отладке в клиент-серверном варианте базы данных убедитесь, что в конфигураторе включена отладка на сервере, а процесс отладчика подключен к серверным сессиям.ДокументОбъект.Заполнить(Основание). Помните, что при программном вызове (например, в фоновом задании) функция Сообщить() отработает в пустоту и пользователь не увидит сообщений на клиенте.Используя предложенные инструкции и понимание внутренней механики передачи параметров платформы 1С, вы сможете легко диагностировать и устранять любые проблемы, возникающие при автоматическом заполнении документов.