Как выполнить код после записи объекта в базу-приемник при использовании Конвертации данных 2.1?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке правил обмена в Конвертации данных 2.1 (КД 2.1) часто возникает задача выполнить определенную логику (например, вызвать процедуру из общего модуля) только после того, как объект физически появился в базе данных. Это критично, если процедура делает запросы к базе, проверяет остатки или должна оперировать уже существующей ссылкой на объект. В этой статье мы подробно разберем, как реализовать этот механизм, учитывая все технические нюансы обмена данными.

Способ 1. Использование обработчика ПКО «После загрузки» с принудительной записью

Рассмотрим стандартное поведение системы. Обработчик После загрузки в правиле конвертации объекта (ПКО) вызывается в тот момент, когда все реквизиты объекта уже заполнены данными из файла, но сам метод Записать() еще не был вызван. Чтобы выполнить код, зависящий от наличия объекта в базе, нам необходимо инициировать запись самостоятельно.

Проанализируем пример кода, который можно разместить в обработчике «После загрузки» для ПКО:


// Проверим, является ли объект новым или он уже записан
Если Не Объект.ЭтоГруппа Тогда
    // Если ссылка еще не сформирована в базе (объект новый), записываем его принудительно
    Если Объект.ЭтоНовый() Или НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
        Попытка
            Объект.Записать();
        Исключение
            Сообщить("Ошибка при принудительной записи: " + ОписаниеОшибки());
            Отказ = Истина;
            Возврат;
        КонецПопытки;
    КонецЕсли;

    // Теперь, когда объект точно есть в базе, вызываем нужную процедуру
    ОбщийМодульСервер.ОбработатьОбъектПослеЗагрузки(Объект.Ссылка);
    
    // Чтобы избежать двойной записи (самой КД), сбрасываем флаг модифицированности
    ОбъектМодифицирован = Ложь;
КонецЕсли;

Важный момент: Мы используем ОбъектМодифицирован = Ложь;. Это крайне важная строка. Если вы вызвали Объект.Записать() вручную, а затем не сбросили этот флаг, стандартный алгоритм обработки обмена вызовет Записать() еще раз в конце процедуры. Это приведет к лишней нагрузке и повторному срабатыванию всех подписок на события «При записи».

Способ 2. Глобальная обработка через событие «После загрузки данных»

Если нам необходимо выполнить действия не поштучно для каждого объекта, а массово после завершения всей загрузки, мы можем воспользоваться глобальным событием конвертации. Рассмотрим, как передать ссылки на загруженные объекты в этот обработчик.

Для начала, в событии «Перед загрузкой данных» (на уровне всей конвертации) инициализируем коллекцию для хранения ссылок:

Параметры.Вставить("СписокЗагруженныхОбъектов", Новый Массив);

Затем в ПКО нужного нам объекта в событии «После загрузки» будем добавлять ссылку в этот массив:


Если НЕ Отказ Тогда
    // Добавляем ссылку в наш глобальный параметр
    Параметры.СписокЗагруженныхОбъектов.Добавить(Объект.Ссылка);
КонецЕсли;

Наконец, в глобальном событии конвертации «После загрузки данных» мы проанализируем накопленные данные и выполним финальную обработку:


Для Каждого СсылкаИзСписка Из Параметры.СписокЗагруженныхОбъектов Цикл
    // Вызываем процедуру для массовой обработки или анализа
    ОбщийМодульСервер.ФинальнаяОбработкаОбъекта(СсылкаИзСписка);
КонецЦикла;

Нюансы работы с Дополнительными свойствами

Часто возникает ситуация, когда процедура в общем модуле или модуле объекта должна знать, что запись происходит именно в контексте обмена данными. Для этого рекомендуется использовать структуру ДополнительныеСвойства. Посмотрим на пример:

В коде ПКО «После загрузки» пишем:


Объект.ДополнительныеСвойства.Вставить("ЗагрузкаИзКД", Истина);
// Если нужно, записываем принудительно
Объект.Записать();

В модуле объекта (базы-приемника) в обработчике ПередЗаписью или ПриЗаписи мы можем проверить этот флаг:


Если ДополнительныеСвойства.Свойство("ЗагрузкаИзКД") Тогда
    // Выполняем специфическую логику только для обмена
КонецЕсли;

Анализ безопасности: Режим записи и Попытка-Исключение

Выясним причину, по которой принудительную запись всегда стоит оборачивать в блок Попытка...Исключение. В базе-приемнике могут существовать жесткие проверки в коде конфигурации (в модулях объектов или подписках). Если ручной вызов Объект.Записать() в КД приведет к ошибке, это может прервать весь процесс загрузки пакета данных.

Разберем основные рекомендации при ручной записи в КД:

  1. Всегда проверяйте Объект.ЭтоГруппа, если работаете со справочниками, так как логика обработки групп и элементов часто отличается.
  2. Используйте переменную Отказ. Если ваша внешняя процедура вернула ошибку, установка Отказ = Истина в обработчике КД позволит системе корректно зафиксировать проблему в логах обмена.
  3. Для документов учитывайте режим записи. Если вам нужно просто сохранить документ без проведения, используйте Объект.Записать(РежимЗаписиДокумента.Запись);.

Таким образом, мы проанализировали основные способы выполнения кода после записи в КД 2.1. Использование принудительной записи в связке с флагом ОбъектМодифицирован = Ложь является наиболее гибким и часто используемым решением в повседневных задачах программиста 1С.

← На главную