Как преобразовать один объект источника в два взаимосвязанных объекта в Конвертации данных 2.1

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

В процессе разработки правил обмена часто возникает ситуация, когда структура данных в базе-источнике и базе-приемнике существенно различается. Одной из классических задач является разделение одного объекта (например, справочника с текстовым реквизитом) на два самостоятельных, но связанных между собой объекта в приемнике. Рассмотрим типичный пример: в источнике есть справочник ДисконтныеКарты, где ФИО владельца хранится просто строкой. В приемнике же требуется создать полноценный справочник Владельцы и установить ссылку на него в справочнике ДисконтныеКарты.

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

Способ 1. Использование ПКС с указанием правила конвертации (Стандартный метод)

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

Разберем по шагам алгоритм настройки:

  1. Создадим ПКО (Правило конвертации объектов) для справочника Владельцы. Настроим в нем поиск по наименованию.
  2. В основном ПКО для справочника ДисконтныеКарты найдем реквизит Владелец (который в приемнике является ссылкой на справочник).
  3. В поле Источник для этого свойства мы можем ничего не указывать или оставить текущее поле. Главное — выбрать созданное ранее ПКО для владельцев в колонке Правило конвертации.
  4. Теперь нам нужно передать строковое значение ФИО в правило для владельца. Для этого откроем обработчик Перед выгрузкой в ПКС реквизита Владелец и напишем следующий код:

// Значение — это то, что пойдет на вход ПКО "Владельцы"
// Источник.ВладелецФИО — это строковый реквизит из справочника в базе-источнике
Значение = Источник.ВладелецФИО;

При такой настройке система при выгрузке каждой карты увидит, что для свойства Владелец назначено отдельное правило. Она возьмет строку из Значение, создаст узел ссылки в XML и, встретив поиск по наименованию в приемнике, либо найдет существующего владельца, либо создаст нового.

Способ 2. Программная выгрузка через ВыгрузитьПоПравилу

Если логика создания владельца сложнее, чем просто передача строки (например, нужно заполнить дополнительные реквизиты владельца, которых нет в справочнике карт), можно воспользоваться методом ВыгрузитьПоПравилу. Рассмотрим ситуацию, когда нам нужно передать структуру данных.

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


// Формируем структуру данных для создания владельца
СтруктураВладельца = Новый Структура;
СтруктураВладельца.Вставить("Наименование", Источник.ВладелецФИО);
СтруктураВладельца.Вставить("Заметки", "Создан автоматически при переносе карты №" + Источник.Код);

// Выгружаем объект программно. 
// Результат функции — это ссылка (Узел ссылки в XML), которую мы передадим в ПКС
ВходящиеДанные = СтруктураВладельца;
ВыгрузитьПоПравилу(Источник, , ВходящиеДанные, , "Владельцы");

В самом ПКО Владельцы на вкладке Настройки необходимо установить флаг Получать из входящих данных. Это позволит системе искать значения реквизитов не в объекте-источнике, а в переданной структуре ВходящиеДанные.

Способ 3. Решение проблемы уникальности (Связь через GUID карты)

Рассмотрим критическую проблему, упомянутую в обсуждении: поиск владельца только по наименованию (ФИО) не всегда надежен, так как в базе могут быть полные однофамильцы. С другой стороны, у нас нет уникального идентификатора владельца в источнике, так как там это просто строка.

Один из изящных способов — использовать УникальныйИдентификатор самой дисконтной карты для синхронизации владельца, если мы точно знаем, что один владелец соответствует одной карте (или если нам допустимо создавать разных владельцев для разных карт одного человека).

В ПКО Владельцы в обработчике Поля поиска мы можем прописать произвольную логику. Но проще передать идентификатор карты в качестве ключа поиска. Проанализируем, как это реализовать:

  1. В ПКО владельца добавим поиск по какому-то уникальному полю (например, коду или специально созданному доп. реквизиту ИД_Источника).
  2. В ПКС этого поля при выгрузке передаем Источник.УникальныйИдентификатор().

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


// Пример в обработчике "Поля поиска" (ПКО Владельцы)
Если СвойстваПоиска.Свойство("Наименование") Тогда
    СсылкаНаОбъект = Справочники.Владельцы.НайтиПоНаименованию(СвойстваПоиска.Наименование, Истина);
КонецЕсли;

Способ 4. Установка связи "После загрузки" (Сценарный подход)

Если стандартные механизмы ПКС не позволяют корректно связать объекты (например, владелец должен выбираться по очень сложному алгоритму уже в базе-приемнике), можно использовать событие После загрузки.

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


// Событие "После загрузки" в ПКО ДисконтныеКарты
// Объект — это уже созданный/найденный справочник в приемнике

Если ЗначениеЗаполнено(Объект.ВладелецКартыСтрокой) Тогда
    // Ищем владельца в справочнике приемника
    НайденныйВладелец = Справочники.Владельцы.НайтиПоНаименованию(Объект.ВладелецКартыСтрокой);
    
    Если НайденныйВладелец.Пустая() Тогда
        // Создаем нового, если не нашли
        НовыйВладелец = Справочники.Владельцы.СоздатьЭлемент();
        НовыйВладелец.Наименование = Объект.ВладелецКартыСтрокой;
        НовыйВладелец.Записать();
        НайденныйВладелец = НовыйВладелец.Ссылка;
    КонецЕсли;
    
    // Устанавливаем связь
    Объект.Владелец = НайденныйВладелец;
    Объект.Записать();
КонецЕсли;

Этот метод часто называют "костылем", но в сложных корпоративных системах со специфической логикой поиска он обеспечивает 100% контроль над процессом связывания объектов.

Резюме и рекомендации

Проанализировав все подходы, можно сделать следующие выводы:

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

← На главную