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