Как реализовать конвертацию данных из одного объекта в несколько и передать параметры в ПКО

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

При настройке обмена данными между конфигурациями 1С часто возникает задача, когда структура метаданных в источнике и приемнике существенно различается. Одной из самых сложных ситуаций является конвертация «один в несколько». Например, в управленческой базе документ ВозвратОтПокупателя содержит список реализаций в табличной части, а в бухгалтерской базе на каждую реализацию должен быть создан отдельный документ возврата. Рассмотрим подробно, как решить эту задачу с помощью программных обработчиков в 1С:Конвертация данных 2.0.

Архитектура решения: разделение одного объекта на несколько

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

Разберем основные этапы реализации:

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

Шаг 1. Программная выгрузка в ПВД

В правилах выгрузки данных (ПВД) для конкретного объекта необходимо использовать обработчик ПередВыгрузкой. Здесь мы формируем запрос или выбираем данные документа-источника, а затем в цикле вызываем выгрузку. Проанализируем пример кода:


// Обработчик ПВД "ПередВыгрузкой"
// Отменяем стандартную обработку, так как будем выгружать объект вручную в цикле
Отказ = Истина;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВозвратТЧ.Ссылка КАК Ссылка,
    |   ВозвратТЧ.ДокументОтгрузки КАК ДокументОтгрузки
    |ИЗ
    |   Документ.ВозвратОтПокупателя.Товары КАК ВозвратТЧ
    |ГДЕ
    |   ВозвратТЧ.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Объект); // Если выгружается конкретный объект
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Формируем структуру данных, которые нужно передать в ПКО
    // Эти данные не обязательно должны быть в реквизитах источника
    СтруктДанных = Новый Структура;
    СтруктДанных.Вставить("ДокументОтгрузки", Выборка.ДокументОтгрузки);
    СтруктДанных.Вставить("УникальныйКлючСвязи", Строка(Выборка.Ссылка.УникальныйИдентификатор()) + Строка(Выборка.ДокументОтгрузки.УникальныйИдентификатор()));

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

Обратите внимание на использование ВыгрузитьПоПравилу. Третьим параметром мы передаем ИсходящиеДанные. Это критически важно, так как именно эта структура позволит нам в приемнике понять, какой именно «под-документ» мы сейчас создаем.

Шаг 2. Получение данных в ПКО (ВходящиеДанные)

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

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

Однако, если задача стоит в проверке существования объекта по сложной связке (например, по Регистру Сведений в приемнике), нам понадобится обработчик ПриЗагрузке в ПКО. Выясним причину: именно в этот момент мы можем решить, нужно ли создавать новый объект или найти существующий по кастомному алгоритму.


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

Шаг 3. Передача сложных структур через параметры

Иногда возникают ситуации, когда ВходящиеДанные могут «теряться» при глубокой вложенности вызовов или когда требуется передать массив объектов. Рассмотрим альтернативный и очень надежный способ передачи данных через Параметры Объекта.

В ПКС можно создать виртуальное свойство (без указания источника) и установить флаг «Передавать данные в параметр». Чтобы передать сложную структуру или таблицу, рекомендуется использовать сериализацию в строку, так как XML-парсер конвертации может некорректно обрабатывать типы внутри структур.

Разберем пример передачи структуры через ПКС:


// В ПКС (Перед выгрузкой)
СтруктураПараметров = Новый Структура("Реализация, Склад, Автор", Источник.Реализация, Источник.Склад, Источник.Автор);
Значение = ЗначениеВСтрокуВнутр(СтруктураПараметров);

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


// В ПКО (ПослеЗагрузки)
Если ПараметрыОбъекта <> Неопределено Тогда
    Данные = ЗначениеИзСтрокиВнутр(ПараметрыОбъекта["ИмяВашегоПараметра"]);
    // Теперь в переменной "Данные" у нас полноценная структура
    Объект.Комментарий = "Загружено по реализации: " + Данные.Реализация;
КонецЕсли;

Синхронизация и предотвращение дублей

При реализации схемы «один в несколько» ключевой проблемой становится повторная загрузка. Если документ в источнике изменится, при повторной выгрузке ПВД снова запустит цикл и попытается создать несколько документов. Чтобы не плодить дубли, проанализируем стратегию использования вспомогательного Регистра Сведений в базе-приемнике:

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

Важный нюанс: Если при загрузке вы понимаете, что документ не должен создаваться (например, строка ТЧ в источнике пустая или не прошла валидацию), используйте Отказ = Истина в обработчике ПриЗагрузке. Это предотвратит создание пустой карточки объекта в базе приемнике.

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

← На главную