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