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