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