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