Как реализовать конвертацию данных «один ко многим» и передать параметры из ПВД в ПКО

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

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

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

Постановка задачи и выбор стратегии

Рассмотрим ситуацию: в источнике есть документ, где реализации указаны в табличной части. В приемнике нам нужно создать столько документов, сколько уникальных реализаций указано в этой таблице. Основная проблема здесь заключается в том, что стандартный механизм синхронизации по УникальномуИдентификатору (GUID) не сработает: у одного источника один GUID, и если просто выгружать его несколько раз, в приемнике один и тот же документ будет постоянно перезаписываться.

Для решения нам потребуется:

  1. Использовать произвольный алгоритм в ПВД для итерации по данным.
  2. Передавать уникальные ключи строк (например, GUID реализации) в ПКО.
  3. Настроить поиск в ПКО по составному ключу.

Шаг 1: Реализация логики в ПВД (Правила выгрузки данных)

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

Проанализируем пример кода, который нужно разместить в ПВД. Допустим, мы хотим выгрузить документ «ВозвратТоваров», разделяя его по документам отгрузки:


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

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

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

// Обязательно устанавливаем Отказ, чтобы штатная выгрузка не сработала
Отказ = Истина;

Шаг 2: Передача данных в параметры ПКО

Многие разработчики совершают ошибку, полагая, что данные из ВыгрузитьПоПравилу автоматически попадут в объект приемника. На самом деле, данные из параметра ВходящиеДанные доступны только на стороне источника. Чтобы они «долетели» до базы-приемника, их нужно пробросить через Параметры ПКО.

Выполним следующие действия в интерфейсе настройки КД:

  1. Откроем наше ПКО (например, «ВозвратТоваровПриемник»).
  2. Перейдем на закладку «Параметры».
  3. Добавим новый параметр, назовем его ДокументОтгрузкиGUID.
  4. В ПКС (Правила конвертации свойств) для этого параметра установим флаг «Передавать данные в параметр».

Теперь в обработчике ПКС ПередВыгрузкой для этого параметра пропишем код получения данных из входящей структуры:


// В ПКС параметра "ДокументОтгрузкиGUID" -> Перед выгрузкой
Если ВходящиеДанные <> Неопределено Тогда
    // Получаем GUID документа отгрузки и приводим к строке
    // Это важно для надежной передачи сложных типов
    Значение = Строка(ВходящиеДанные.ИдентификаторСтроки);
КонецЕсли;

Важный нюанс: Если вам нужно передать сложную структуру или массив, используйте методы ЗначениеВСтрокуВнутр() на стороне источника и ЗначениеИзСтрокиВнутр() на стороне приемника. Это гарантирует, что данные не потеряются при сериализации в XML.

Шаг 3: Обработка данных в приемнике (При загрузке)

Когда объект попадает в базу-приемник, управление переходит к обработчику ПриЗагрузке. Здесь нам доступны прочитанные из файла параметры через коллекцию ПараметрыОбъекта.

Разберем ситуацию: как нам найти нужный документ в приемнике, если их там несколько? Мы не можем полагаться только на УИД источника. Нам нужно реализовать поиск по комбинации: УИД источника + Идентификатор реализации.

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


// В обработчике "Поля поиска"
ИдентификаторРеализации = ПараметрыОбъекта["ДокументОтгрузкиGUID"];

Если ЗначениеЗаполнено(ИдентификаторРеализации) Тогда
    
    // Здесь мы пишем запрос к базе-приемнику. 
    // Предполагается, что при первой загрузке мы сохранили связку УИДов в Регистр Сведений
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   СвязиДокументов.СсылкаНаОбъект
        |ИЗ
        |   РегистрСведений.СвязиПриПереносе КАК СвязиДокументов
        |ГДЕ
        |   СвязиДокументов.УИДИсточника = &УИДИсточника
        |   И СвязиДокументов.УИДРеализации = &УИДРеализации";
    
    Запрос.УстановитьПараметр("УИДИсточника", Строка(Источник.УникальныйИдентификатор()));
    Запрос.УстановитьПараметр("УИДРеализации", ИдентификаторРеализации);
    
    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        СсылкаНаОбъект = Выборка.СсылкаНаОбъект;
    КонецЕсли;

КонецЕсли;

Шаг 4: Сохранение связей после загрузки

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


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

Особенности использования дополнительных свойств

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

Пример использования:


// В "При загрузке"
Объект.ДополнительныеСвойства.Вставить("МойСпецПараметр", ПараметрыОбъекта["ДокументОтгрузкиGUID"]);

// Затем в любом другом месте, где доступен "Объект"
Значение = Объект.ДополнительныеСвойства.МойСпецПараметр;

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

Схема «один ко многим» в Конвертации данных 2.1 требует четкого разделения ответственности между обработчиками:

Проанализировав данную методику, мы видим, что она позволяет гибко настраивать обмен даже в тех случаях, когда структуры метаданных источника и приемника кардинально различаются. Главное — помнить о типизации передаваемых параметров и всегда использовать строковое представление для GUID при передаче через XML-пакеты.

← На главную