Как при переносе данных в КД 2 сохранить иерархию справочника контрагентов в определенную папку и обновить только родителя у найденных объектов?

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

При слиянии двух баз (например, основного предприятия и торгового дома) часто возникает задача перенести контрагентов с сохранением их структуры в строго определенную папку базы-приемника. Задача усложняется, если контрагенты в базах частично пересекаются. В этом случае синхронизацию приходится делать не по внутреннему идентификатору (УИД), а по комбинации полей: ИНН, КПП, Код, ЭтоГруппа. При этом существующие в приемнике контрагенты должны автоматически «перепрыгнуть» из своих старых папок в новую созданную иерархию торгового дома, а также восстановиться из помеченных на удаление, если это необходимо.

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

Сценарий и основные проблемы реализации

Давайте проанализируем исходную ситуацию. У нас есть две информационные базы. Нам нужно настроить правила конвертации объектов (ПКО) таким образом, чтобы:

  1. Вся иерархия из базы-источника перенеслась внутрь одной конкретной папки (например, «Торговый дом») в базе-приемнике.
  2. Поиск элементов выполнялся по полям ИНН, КПП, Код и обязательно ЭтоГруппа.
  3. Если контрагент уже существует в базе-приемнике, его карточка (наименование, адреса, телефоны) не должна перезаписываться из источника, но его положение в иерархии (родитель) должно обновиться, а пометка удаления — сняться.

---

Шаг 1. Перенос всей иерархии внутрь целевой папки («Торговый дом»)

Для того чтобы вся структура «легла» внутрь одной папки, нам необходимо переопределить родителя у тех элементов и групп, которые в базе-источнике находятся на самом верхнем уровне (в корне справочника). Если этого не сделать, они создадутся в корне справочника базы-приемника.

Рассмотрим, как настроить это через Правило конвертации свойств (ПКС) для реквизита Родитель в ПКО Контрагенты. Перейдем в обработчик события «Перед выгрузкой» для свойства Родитель и напишем следующий алгоритм:


Если Не ЗначениеЗаполнено(Источник.Родитель) Тогда
    // Если у элемента в базе-источнике нет родителя, 
    // принудительно направляем его в папку "Торговый дом"
    Значение = "КодПапкиТорговыйДом"; // Код целевой папки в базе-приемнике
    ИмяПКО = "Контрагенты"; // Имя ПКО для поиска или создания этой группы
Иначе
    // Если родитель в источнике заполнен, выгружаем его стандартно
    Значение = Источник.Родитель;
    ИмяПКО = "Контрагенты"; 
КонецЕсли;

При таком подходе поиск корневой папки будет осуществляться по указанному коду в приемнике. Все элементы, у которых в источнике родитель пустой, автоматически станут дочерними для папки «Торговый дом». Вся вложенная структура подчинения при этом сохранится без изменений.

---

Шаг 2. Передача родителя через параметры объекта

Иногда требуется передать уникальный идентификатор или иные сопутствующие данные родителя отдельно от стандартного механизма выгрузки свойств. Выясним, как это реализовать через параметры КД 2.

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

  1. Откройте ПКО Контрагенты и перейдите на вкладку «Параметры». Добавьте новый параметр с именем УИДРодителя.
  2. Создайте новое ПКС. Поле «Источник» оставьте пустым, в качестве «Приемника» выберите созданный параметр УИДРодителя и установите флаг «Передавать данные в параметр».
  3. В обработчике события «Перед выгрузкой» этого ПКС напишите код для получения УИД родителя:

Если ЗначениеЗаполнено(Источник.Родитель) Тогда
    Значение = Строка(Источник.Родитель.УникальныйИдентификатор());
Иначе
    Значение = "";
КонецЕсли;

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

Важный нюанс работы КД 2: В обработчиках событий «Перед загрузкой», «При загрузке» и «Поля поиска» коллекция ПараметрыОбъекта хранит только те параметры, для которых в правилах КД был установлен флажок «Поиск». Если этот флаг не установлен, прочитать параметры вы сможете только на этапе события «После загрузки».

Пример обращения к параметру в обработчике «После загрузки»:


Если ПараметрыОбъекта <> Неопределено Тогда
    УИДРодителяСтрокой = ПараметрыОбъекта["УИДРодителя"];
    Если ЗначениеЗаполнено(УИДРодителяСтрокой) Тогда
        // Здесь мы можем использовать полученный УИД для поиска родителя в приемнике
        УникальныйИд = Новый УникальныйИдентификатор(УИДРодителяСтрокой);
        НайденныйРодитель = Справочники.Контрагенты.ПолучитьСсылку(УникальныйИд);
    КонецЕсли;
КонецЕсли;

---

Шаг 3. Дешевый способ изменить родителя и снять пометку удаления у существующих контрагентов

Наиболее сложный момент: если контрагент в базе-приемнике уже существует (например, найден по ИНН/КПП), нам крайне важно переместить его в новую структуру папок и снять с него пометку на удаление. Но при этом мы не хотим перезаписывать остальные реквизиты объекта, чтобы не затереть актуальные данные карточки контрагента в рабочей базе.

Если мы установим стандартное свойство НеЗамещатьОбъект = Истина в обработчике «При загрузке», платформа заблокирует любые изменения найденного объекта, включая перенос в новую папку.

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


Если ОбъектНайден Тогда
    // Объект существовал в базе-приемнике. Нам нужно обновить только иерархию и пометку удаления.
    
    // Получаем ссылку на правильного родителя, переданного из файла
    НовыйРодитель = Ссылка.Родитель; 
    
    // Модифицируем свойства непосредственно у загружаемого объекта
    Объект.Родитель = НовыйРодитель;
    
    Если Объект.ПометкаУдаления Тогда
        Объект.ПометкаУдаления = Ложь; // Восстанавливаем из удаленных
    КонецЕсли;
    
    // Записываем объект самостоятельно в транзакции загрузки
    Объект.Записать();
    
    // Устанавливаем Отказ = Истина. 
    // Это отменит стандартную процедуру записи объекта платформой КД 2.
    // Благодаря этому остальные реквизиты (наименование, адреса) останутся нетронутыми.
    Отказ = Истина; 
КонецЕсли;

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

---

Шаг 4. Критически важный нюанс настройки полей поиска

Проанализируем частую ошибку, с которой сталкиваются разработчики при сопоставлении иерархических справочников по ИНН/КПП/Коду.

При настройке полей поиска в ПКО обязательно включайте реквизит ЭтоГруппа в состав ключевых полей поиска. Если этого не сделать, то при загрузке может возникнуть ситуация, когда группа из файла обмена сопоставится с элементом в базе-приемнике (или наоборот), из-за совпадения кодов. Это приведет к фатальной ошибке базы данных:

Попытка изменения свойства "ЭтоГруппа" у записанного объекта

Для предотвращения подобных сбоев настраивайте логику сопоставления раздельно: для групп поиск должен осуществляться только по коду/наименованию и признаку ЭтоГруппа, а для элементов — по ИНН, КПП, коду и обязательно признаку ЭтоГруппа.

← На главную