Как сопоставить объекты справочников через периодический регистр сведений в Конвертации данных 2.0?

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

При настройке обмена данными между базами 1С часто возникает ситуация, когда стандартные поля поиска (Код, Наименование, Уникальный идентификатор) не позволяют однозначно сопоставить объекты. Типичный пример: в разных базах справочники ведутся независимо, а связь между ними хранится в специальном периодическом регистре сведений. Задача усложняется, если соответствие меняется во времени и зависит от даты документа, который мы переносим. Разберем подробно, как реализовать такую схему в конфигурации «Конвертация данных 2.0» (КД 2.0).

Постановка задачи и анализ ситуации

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

Метод 1: Использование «Входящих данных» для передачи контекста

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

Чтобы решить эту проблему, воспользуемся структурой ВходящиеДанные. Рассмотрим пошагово:

  1. В ПКС (Правиле конвертации свойства) документа, где выбирается наш справочник, в обработчике «Перед выгрузкой» создадим структуру:
    
    ИмяПКО = "ВашеИмяПКО_Справочника";
    ВходящиеДанные = Новый Структура;
    ВходящиеДанные.Вставить("ДатаДокумента", Источник.Дата);
    
  2. Теперь в ПКО справочника, в обработчике «Перед выгрузкой» или непосредственно в ПКС (например, в поле «Код»), мы можем обратиться к этой дате:
    
    Если ВходящиеДанные <> Неопределено Тогда
        АктуальнаяДата = ВходящиеДанные.ДатаДокумента;
        // Здесь пишем запрос к регистру сведений в базе-источнике
    КонецЕсли;
    

Метод 2: Поиск на стороне базы-приемника через «Поля поиска»

Если периодический регистр сведений с соответствиями находится только в базе-приемнике, то логику поиска нужно перенести в обработчик «Поля поиска» соответствующего ПКО справочника. Это наиболее методически верный способ в архитектуре КД 2.0.

Разберем алгоритм действий:

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

Пример кода в обработчике «Поля поиска»:


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

Метод 3: Оптимизация и кэширование данных

Выполнение запроса к регистру для каждой строки документа или для каждого элемента справочника может критически замедлить выгрузку (проблема «N+1 запросов»). Чтобы этого избежать, применим технику кэширования.

Проанализируем ситуацию: если данных много, лучше один раз прочитать весь регистр в таблицу значений или соответствие (Map). В обработчике конвертации «Перед выгрузкой данных» инициализируем глобальный параметр:


Запрос = Новый Запрос("ВЫБРАТЬ КодИсточника, ОбъектПриемник, Период ИЗ РегистрСведений.Соответствия");
ТаблицаСоответствий = Запрос.Выполнить().Выгрузить();
Параметры.Вставить("КэшСоответствий", ТаблицаСоответствий);

В процессе дальнейшей выгрузки мы будем искать данные не запросом к БД, а методом НайтиСтроки() по таблице в оперативной памяти. Это ускоряет процесс в десятки раз.

Особенности работы с табличными частями

Часто реквизит-справочник, требующий замены, находится в табличной части документа. Посмотрим, как обращаться к данным в этом случае. В обработчике «Перед выгрузкой» ПКС табличной части нам доступен объект ОбъектКоллекции — это текущая строка таблицы.

Чтобы получить дату документа для поиска, используем обращение к владельцу:


// В ПКС реквизита табличной части
ДатаДляПоиска = Источник.Дата; 
ТекущийКод = ОбъектКоллекции.Номенклатура.Код;
// Далее вызываем алгоритм поиска по этим данным

Важные технические нюансы

При реализации подобных схем следует учитывать несколько критически важных моментов:

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

← На главную