Как в 1С:Конвертация данных 2.1 выгрузить один документ в несколько и организовать их повторный поиск?

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

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

Реализовать такую логику стандартными интерактивными правилами КД 2.1 невозможно. В процессе реализации возникают три серьезные технические проблемы:

  1. Затирание данных при выгрузке: движок КД 2.1 считает исходный документ одним объектом и по умолчанию выгружает в XML только последний сгенерированный документ.
  2. Идентификация объектов при повторном обмене: у созданных в приемнике документов нет прямого аналога-ссылки в источнике, из-за чего стандартный поиск по УИД не работает.
  3. Удаление «лишних» документов при изменении источника: если в первый раз из одного документа создалось 4 перемещения, а после изменения ТЧ при повторной выгрузке должно создаться только 3, то четвертый документ зависает в базе-приемнике как неактуальный «мусор».

В этой статье мы подробно разберем, как решить все эти проблемы штатными инструментами КД 2.1 без внесения изменений в метаданные типовой конфигурации-приемника.

Шаг 1. Настройка ПВД и разделение данных с помощью «ВыгрузитьПоПравилу»

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

Рассмотрим алгоритм настройки ПВД по шагам:

  1. Создаем ПВД для нашего исходного документа.
  2. В свойстве «Способ выборки» указываем «Произвольный алгоритм».
  3. В обработчике события Перед обработкой пишем код выборки данных. Мы будем обходить строки табличной части исходного документа, группировать их по нужному нам признаку (например, по складам или видам операций) и передавать во временные таблицы значений для последующей генерации документов.

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


// Создаем фиктивную структуру или Таблицу Значений, имитирующую будущий документ
ТЗДок = Новый ТаблицаЗначений;
ТЗДок.Колонки.Добавить("Ссылка");
ТЗДок.Колонки.Добавить("Дата");
ТЗДок.Колонки.Добавить("Номер");
ТЗДок.Колонки.Добавить("Товары");
ТЗДок.Колонки.Добавить("СкладПолучатель");

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

В правиле конвертации объектов (ПКО) ПередачаТоваров_ДляЗаказНаряда у нас не должно быть указано объекта-источника. Все свойства (ПКС) в данном ПКО настраиваются с флагом «Получить из входящих данных».

Шаг 2. Решение проблемы затирания через «КлючВыгружаемыхДанных»

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

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

Выполним это в обработчике «Перед выгрузкой» ПКО создаваемого документа:


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

Этот простой шаг гарантирует, что в результирующем файле выгрузки XML появятся все сгенерированные нами документы в виде отдельных узлов.

Шаг 3. Организация поиска документов в базе-приемнике без доработки метаданных

При повторной синхронизации нам крайне важно найти именно те документы в базе-приемнике, которые были созданы из конкретного исходного документа ранее. Изменять метаданные типовой БП (добавлять новые реквизиты поиска) крайне нежелательно. Рассмотрим два надежных архитектурных решения этой задачи.

Вариант А. Запись поискового ключа в комментарий документа

Самый простой и не требующий никаких настроек конфигурации способ — запись уникального строкового ключа в стандартный реквизит Комментарий документа-приемника.

Для этого в ПКО документа настраиваем ПКС для свойства Комментарий. В обработчике «Перед выгрузкой» ПКС пишем:


// Помещаем в комментарий уникальную метку связи
Значение = "ИД_Источника: " + Строка(Источник.Ссылка.УникальныйИдентификатор()) + " | Индекс: " + Строка(ВходящиеДанные.ИндексДокумента);

В ПКО в обработчике «Поля поиска» пишем поисковый запрос к базе-приемнику:


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

Вариант Б. Использование механизма «Дополнительные сведения» (БСП)

Если засорять комментарии пользователей не хочется, задействуем типовой механизм дополнительных сведений Библиотеки Стандартных Подсистем (БСП), который развернут практически во всех современных конфигурациях 1С.

Мы можем настроить в КД 2.1 выгрузку записей регистра сведений ДополнительныеСведения параллельно с выгрузкой документов. В качестве свойства будет выступать предопределенный (или созданный в режиме «1С:Предприятие») элемент плана видов характеристик ДополнительныеРеквизитыИСведения, а в качестве значения — строковый уникальный ключ связи (УИД источника + индекс).

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

Шаг 4. Обработка «устаревших» документов (актуализация изменений)

Сложнейшая проблема сценария «один ко многим» — изменение состава строк в источнике. Например, в документе-источнике удалили строки, привязав их к другим складам. При первой выгрузке было создано 4 документа в приемнике. При повторной должно создаться только 2. Как избавиться от оставшихся двух документов, которые теперь неактуальны и содержат старые данные?

Рассмотрим два сценария решения этой проблемы.

Сценарий А: «Мягкая очистка» перед загрузкой

Этот метод подразумевает, что перед тем, как загрузить обновленные документы, мы находим все ранее созданные по этому источнику объекты и помечаем их на удаление. В процессе загрузки актуальные документы снимут пометку удаления, а лишние — останутся помеченными.

В ПКО создаваемого документа в обработчике «Перед загрузкой» пишем следующий код:


// Выполняем поиск всех документов в базе-приемнике, созданных по текущему источнику ранее
УИД_Источника = ПараметрыОбъекта["УИД_Источника"];

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

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

Сценарий Б: Передача списка актуальных ключей

Если пометка удаления всех документов «на лету» замедляет процесс обмена или неприемлема по соображениям бизнес-логики, применим схему постобработки:

  1. В ПВД при выгрузке исходного документа формируется массив актуальных индексов (или уникальных ключей), которые реально выгружаются в данный момент.
  2. Этот массив передается в базу-приемник в параметрах пакета данных (структура ПараметрыОбъекта).
  3. В обработчике «После загрузки» ПКО документа-приемника мы получаем этот массив. Запросом находим все документы в базе по нашему УИД-источника и сравниваем их с массивом полученных актуальных ключей.
  4. Те документы, ключи которых не найдены в присланном массиве, программно помечаются на удаление или непосредственно удаляются из базы.

Использование Правил очистки данных (ПОД)

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

Резюме

Мы детально разобрали, как решить задачу выгрузки «один ко многим» в КД 2.1. Использование ПВД с произвольной выборкой в сочетании с переопределением КлючВыгружаемыхДанных решает проблему разделения документов на стороне источника. Хранение УИД-связки в комментариях или дополнительных сведениях БСП гарантирует точный повторный поиск документов-приемников, а алгоритмы автоматической «мягкой очистки» позволяют поддерживать актуальность данных без риска засорения информационной базы неактуальными транзакциями.

← На главную