Почему не записывается регистр сведений в обработчике "После загрузки" в 1С:Конвертация данных?

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

При настройке обмена через конфигурацию «Конвертация данных» многие разработчики сталкиваются с ситуацией: необходимо программно дозаполнить движения загружаемого документа в регистре сведений. Мы пишем код в обработчике После загрузки, отладчик показывает, что код выполняется без ошибок, данные присваиваются, но по итогу в базе данных изменения не сохраняются (поля остаются пустыми). Давайте разберем эту ситуацию по шагам и выясним причину такого поведения.

Анализ проблемы: как мы пытаемся сделать и почему это не работает

Рассмотрим типичный код, который разработчики добавляют в обработчик правила конвертации объекта (ПКО) После загрузки:


НаборЗаписей = РегистрыСведений.События.СоздатьНаборЗаписей();
ДатаНабора = ТекущаяДата();
НаборЗаписей.Отбор.Регистратор.Установить(Объект.Ссылка);
НаборЗаписей.Прочитать();
Для каждого СтрРег из НаборЗаписей цикл
    СтрРег.ГруппаСобытия = Справочники.ГруппыСобытий.НачислениеБонуса;
КонецЦикла;
НаборЗаписей.Записать();

На первый взгляд, все логично. Если запустить этот фрагмент во внешней обработке — он отработает безупречно. Однако внутри процесса загрузки данных он не дает нужного результата. Проанализируем причины:

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

Правильные способы решения задачи

Разберем несколько корректных подходов к решению данной проблемы, двигаясь от самых правильных к альтернативным.

Способ 1: Использование штатных визуальных настроек (Лучшая практика)

Самый корректный подход в «Конвертации данных» — отказаться от написания программного кода там, где это не требуется. Мы можем решить задачу настройкой Правил Конвертации Объектов (ПКО) и Правил Конвертации Свойств (ПКС).

Создайте отдельное ПКО для нужного регистра сведений (в нашем случае РегистрыСведений.События) или настройте ПКС для табличной части движений внутри ПКО самого документа. Нужное значение (например, Справочники.ГруппыСобытий.НачислениеБонуса) можно передавать или вычислять еще на этапе формирования файла выгрузки. Таким образом, принимающая база получит готовый XML с уже заполненными данными.

Способ 2: Работа с коллекцией движений в памяти загружаемого объекта

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

Изменим наш подход в обработчике После загрузки:


// Не используем прямое обращение к БД
// Работаем с коллекцией движений текущего загружаемого Объекта
ДвиженияСобытия = Объект.Движения.События;
ДвиженияСобытия.Прочитать(); // Читаем текущие движения, если они уже есть

Для Каждого СтрРег Из ДвиженияСобытия Цикл
    СтрРег.ГруппаСобытия = Справочники.ГруппыСобытий.НачислениеБонуса;
КонецЦикла;

// Мы НЕ вызываем ДвиженияСобытия.Записать() ! 
// Устанавливаем флаг, чтобы платформа записала модифицированный набор сама
ДвиженияСобытия.Записывать = Истина;

Способ 3: Отложенное проведение и перенос логики

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

Альтернативный путь (Костыльный вариант)

Для полноты картины упомянем решение, к которому прибегнул автор оригинального вопроса. Он использовал глобальный обработчик После загрузки данных (срабатывает, когда вся порция данных уже загружена в базу).

В этом обработчике пишется запрос к базе, который ищет все записи регистра с пустым полем ГруппаСобытия за период загрузки, и пакетно их обновляет. Мы не рекомендуем данный подход, так как он сильно замедляет обмен и является «костылем», однако в крайних случаях (например, когда обмен уже идет и нужно срочно исправить данные) он имеет место быть.

Подводим итоги

Обработчик После загрузки в «Конвертации данных» концептуально не предназначен для инициирования отдельных транзакций записи подчиненных наборов данных. Его задача — модификация свойств переменной Объект перед её сохранением платформой. Посмотрим на эту ситуацию как на правило: всегда модифицируйте свойства объекта в кэше, а сохранение оставьте стандартным механизмам платформы.

← На главную