Как устранить появление битых ссылок на владельца при переносе подчиненных справочников в Конвертации данных 2.1?

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

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

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

Рассмотрим типовую архитектуру данных на примере справочников Организации и РегистрацииВНалоговомОргане. В типовых конфигурациях 1С между ними существует перекрестная связь:

  1. В справочнике Организации присутствует реквизит РегистрацияВНалоговомОргане, ссылающийся на подчиненный справочник.
  2. Справочник РегистрацииВНалоговомОргане подчинен справочнику Организации, то есть его реквизит Владелец ссылается обратно на организацию.

Когда в ПКО «Организации» конвертируется свойство РегистрацияВНалоговомОргане, механизм сериализации КД 2 не завершает формирование XML-узла текущего элемента, а сразу приступает к выгрузке значения ссылочного типа. В процессе выгрузки подчиненной регистрации по правилу «РегистрацииВНалоговомОргане» выгружается и ее реквизит Владелец. В результате в итоговом файле обмена подчиненный элемент физически записывается выше родительской организации.

При чтении данных приемником первой начинает обрабатываться регистрация в ИФНС. На этапе сопоставления в обработчик «Поля поиска» в коллекцию СвойстваПоиска попадает ссылка на организацию, которая в базе-приемнике еще не записана. Платформенный поиск по владельцу завершается неудачей, а при попытке записи нового элемента подчиненного справочника платформа или код модуля объекта выдают ошибку, так как ссылка владельца указывает на несуществующий объект.

Решение 1. Разрыв циклической связи и перенос выгрузки в обработчик

Наиболее надежный и чистый способ — разорвать цикл на стороне источника, исключив автоматическую выгрузку подчиненного реквизита при обработке полей организации. Разберем по шагам, как это реализовать:

  1. В ПКО «Организации» перейдем к ПКС РегистрацияВНалоговомОргане и отключим его стандартную выгрузку (снимем признак выгрузки либо укажем в обработчике «Перед выгрузкой свойства» директиву Отказ = Истина;).
  2. Откроем обработчик «После выгрузки» для ПКО «Организации» и явно инициируем выгрузку подчиненного объекта с помощью процедуры ВыгрузитьПоПравилу().

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


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

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

Для обратной привязки созданной регистрации к организации в базе-приемнике используем обработчик «После загрузки» или «После записи» в ПКО «РегистрацииВНалоговомОргане», программно обновляя соответствующий реквизит у владельца.

Решение 2. Создание подчиненного объекта в событии владельца без отдельного ПКО

Если конфигурация-приемник находится на типовой поддержке, а модуль объекта подчиненного справочника выполняет строгие проверки реквизитов владельца даже при флаге ОбменДанными.Загрузка = Истина, целесообразно полностью отказаться от отдельного ПКО для подчиненного справочника.

Разберем реализацию этого подхода:

  1. В ПКО «Организации» в обработчике «Перед выгрузкой» собираем все данные подчиненной регистрации в структуру и помещаем их в параметры выгружаемого объекта:

ПараметрыОбъекта = Новый Структура;
ПараметрыОбъекта.Вставить("РегистрацияКод", Источник.РегистрацияВНалоговомОргане.Код);
ПараметрыОбъекта.Вставить("РегистрацияКПП", Источник.РегистрацияВНалоговомОргане.КПП);
ПараметрыОбъекта.Вставить("РегистрацияНаименование", Источник.РегистрацияВНалоговомОргане.Наименование);
ПараметрыОбъекта.Вставить("РегистрацияОКТМО", Источник.РегистрацияВНалоговомОргане.КодПоОКТМО);
  1. В ПКО «Организации» в базе-приемнике в обработчике «После записи» программно создаем или находим подчиненный элемент, передавая уже гарантированно существующую ссылку Ссылка:

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

Решение 3. Использование идентификаторов поиска владельца в параметрах

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

  1. В обработчике «Перед выгрузкой» ПКО «РегистрацииВНалоговомОргане» передаем реквизиты поиска владельца (например, ИНН организации) в ПараметрыОбъекта:

ПараметрыОбъекта = Новый Структура("ИННВладельца", Источник.Владелец.ИНН);

  1. В базе-приемнике в ПКО «РегистрацииВНалоговомОргане» в обработчике «Поля поиска» проверяем валидность ссылки владельца и при необходимости переопределяем ее:

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

Важно помнить: разделение циклов через выгрузку подчиненных элементов в обработчике «После выгрузки» или управление последовательностью выгрузки с помощью разных Правил выгрузки данных (ПВД) полностью исключает появление незаписанных ссылок и обеспечивает корректную работу типовых механизмов контроля конфигурации.

← На главную