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