При разработке правил обмена в Конвертации данных 2.1 (КД 2.1) часто возникает задача выполнить определенную логику (например, вызвать процедуру из общего модуля) только после того, как объект физически появился в базе данных. Это критично, если процедура делает запросы к базе, проверяет остатки или должна оперировать уже существующей ссылкой на объект. В этой статье мы подробно разберем, как реализовать этот механизм, учитывая все технические нюансы обмена данными.
Рассмотрим стандартное поведение системы. Обработчик После загрузки в правиле конвертации объекта (ПКО) вызывается в тот момент, когда все реквизиты объекта уже заполнены данными из файла, но сам метод Записать() еще не был вызван. Чтобы выполнить код, зависящий от наличия объекта в базе, нам необходимо инициировать запись самостоятельно.
Проанализируем пример кода, который можно разместить в обработчике «После загрузки» для ПКО:
// Проверим, является ли объект новым или он уже записан
Если Не Объект.ЭтоГруппа Тогда
// Если ссылка еще не сформирована в базе (объект новый), записываем его принудительно
Если Объект.ЭтоНовый() Или НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
Попытка
Объект.Записать();
Исключение
Сообщить("Ошибка при принудительной записи: " + ОписаниеОшибки());
Отказ = Истина;
Возврат;
КонецПопытки;
КонецЕсли;
// Теперь, когда объект точно есть в базе, вызываем нужную процедуру
ОбщийМодульСервер.ОбработатьОбъектПослеЗагрузки(Объект.Ссылка);
// Чтобы избежать двойной записи (самой КД), сбрасываем флаг модифицированности
ОбъектМодифицирован = Ложь;
КонецЕсли;
Важный момент: Мы используем ОбъектМодифицирован = Ложь;. Это крайне важная строка. Если вы вызвали Объект.Записать() вручную, а затем не сбросили этот флаг, стандартный алгоритм обработки обмена вызовет Записать() еще раз в конце процедуры. Это приведет к лишней нагрузке и повторному срабатыванию всех подписок на события «При записи».
Если нам необходимо выполнить действия не поштучно для каждого объекта, а массово после завершения всей загрузки, мы можем воспользоваться глобальным событием конвертации. Рассмотрим, как передать ссылки на загруженные объекты в этот обработчик.
Для начала, в событии «Перед загрузкой данных» (на уровне всей конвертации) инициализируем коллекцию для хранения ссылок:
Параметры.Вставить("СписокЗагруженныхОбъектов", Новый Массив);
Затем в ПКО нужного нам объекта в событии «После загрузки» будем добавлять ссылку в этот массив:
Если НЕ Отказ Тогда
// Добавляем ссылку в наш глобальный параметр
Параметры.СписокЗагруженныхОбъектов.Добавить(Объект.Ссылка);
КонецЕсли;
Наконец, в глобальном событии конвертации «После загрузки данных» мы проанализируем накопленные данные и выполним финальную обработку:
Для Каждого СсылкаИзСписка Из Параметры.СписокЗагруженныхОбъектов Цикл
// Вызываем процедуру для массовой обработки или анализа
ОбщийМодульСервер.ФинальнаяОбработкаОбъекта(СсылкаИзСписка);
КонецЦикла;
Часто возникает ситуация, когда процедура в общем модуле или модуле объекта должна знать, что запись происходит именно в контексте обмена данными. Для этого рекомендуется использовать структуру ДополнительныеСвойства. Посмотрим на пример:
В коде ПКО «После загрузки» пишем:
Объект.ДополнительныеСвойства.Вставить("ЗагрузкаИзКД", Истина);
// Если нужно, записываем принудительно
Объект.Записать();
В модуле объекта (базы-приемника) в обработчике ПередЗаписью или ПриЗаписи мы можем проверить этот флаг:
Если ДополнительныеСвойства.Свойство("ЗагрузкаИзКД") Тогда
// Выполняем специфическую логику только для обмена
КонецЕсли;
Выясним причину, по которой принудительную запись всегда стоит оборачивать в блок Попытка...Исключение. В базе-приемнике могут существовать жесткие проверки в коде конфигурации (в модулях объектов или подписках). Если ручной вызов Объект.Записать() в КД приведет к ошибке, это может прервать весь процесс загрузки пакета данных.
Разберем основные рекомендации при ручной записи в КД:
Объект.ЭтоГруппа, если работаете со справочниками, так как логика обработки групп и элементов часто отличается.Отказ. Если ваша внешняя процедура вернула ошибку, установка Отказ = Истина в обработчике КД позволит системе корректно зафиксировать проблему в логах обмена.Объект.Записать(РежимЗаписиДокумента.Запись);.Таким образом, мы проанализировали основные способы выполнения кода после записи в КД 2.1. Использование принудительной записи в связке с флагом ОбъектМодифицирован = Ложь является наиболее гибким и часто используемым решением в повседневных задачах программиста 1С.