Ошибка Тип не определен при использовании ВыгрузитьПоПравилу в узлах обмена: причины и решение

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При работе с инструментом Конвертация данных 2.1 разработчики часто сталкиваются с ситуацией, когда правила обмена идеально работают в обработке УниверсальныйОбменДаннымиXML, но выдают критическую ошибку при запуске через штатный механизм синхронизации (узлы планов обмена). Одной из самых коварных является ошибка Тип не определен, возникающая в модуле обработки КонвертацияОбъектовИнформационныхБаз. Рассмотрим подробнее, почему это происходит и как правильно настроить выгрузку связанных объектов.

Анализ исходной ситуации

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

Типичный код, который вызывает проблему, выглядит следующим образом:


Если НЕ Источник.Ссылка.ЭтоГруппа Тогда
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    КомплектующиеНоменклатуры.Комплектующая КАК Номенклатура,
    |    КомплектующиеНоменклатуры.Количество
    |ИЗ
    |    РегистрСведений.КомплектующиеНоменклатуры КАК КомплектующиеНоменклатуры
    |ГДЕ
    |    КомплектующиеНоменклатуры.Номенклатура = &Номенклатура";
    
    Запрос.УстановитьПараметр("Номенклатура", Источник.Ссылка);
    ИсходныеКомплектующие = Запрос.Выполнить().Выгрузить();
    
    Если ИсходныеКомплектующие.Количество() > 0 Тогда
        ИсходящиеДанные = Новый Структура("Владелец, ИсходныеКомплектующие, Наименование");
        ИсходящиеДанные.Вставить("Владелец", Источник.Ссылка);
        ИсходящиеДанные.Вставить("Наименование", Источник.Ссылка.Наименование);
        ИсходящиеДанные.Вставить("ИсходныеКомплектующие", ИсходныеКомплектующие);
        
        // Вызов выгрузки по правилу без явного типа источника в ПКО
        ВыгрузитьПоПравилу(Источник.Ссылка, , ИсходящиеДанные, , "СпецификацииНоменклатуры");
    КонецЕсли;
КонецЕсли;

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

Выясним причину ошибки: механизм квитирования

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

При следующем сеансе обмена приемник отправляет обратно информацию о том, что объект с таким-то GUID успешно загружен. Для этого в XML-файле формируются узлы с информацией о регистрации. Проблема в том, что если в Правиле Конвертации Объектов (ПКО) не указан тип источника, система при выгрузке записывает в файл пустую строку в атрибут ТипИсточника. При чтении этого файла в базе-источнике функция ПрочитатьИнформациюОРегистрацииОбъекта() пытается сопоставить строковое представление типа из файла с метаданными и, встречая пустое значение, выбрасывает исключение Тип не определен.

Решение №1: Установка фиктивного типа источника

Проанализируем самый простой и эффективный способ исправления. Чтобы система 1С могла корректно идентифицировать объект при обратном чтении подтверждения, в ПКО СпецификацииНоменклатуры (которое используется в ВыгрузитьПоПравилу) необходимо обязательно заполнить поле "Объект источник".

  1. Откроем конфигурацию Конвертация данных.
  2. Найдем ПКО для СпецификацииНоменклатуры.
  3. В поле "Источник" выберем любой подходящий тип метаданных, например, СправочникСсылка.Номенклатура или сам регистр РегистрСведенийМенеджерЗаписи.КомплектующиеНоменклатуры.
  4. Это заставит систему записывать в XML-файл строковое имя типа, и при загрузке подтверждения в источнике ошибка исчезнет.

Важный момент: поскольку мы используем ИсходящиеДанные, фактические данные для заполнения объекта будут браться из структуры, а указанный тип источника будет использоваться только как "заглушка" для механизмов регистрации соответствий.

Решение №2: Отключение записи соответствий

Посмотрим на ситуацию с другой стороны. Если нам не нужно отслеживать связь между спецификацией в УТ и спецификацией в БП по GUID (например, если мы всегда ищем их по наименованию и владельцу), мы можем приказать системе не запоминать эти связи.

В настройках ПКО на закладке "Настройки выгрузки" можно установить флаг Не запоминать соответствия для этого правила. В этом случае:

Решение №3: Программное управление регистрацией

Рассмотрим более сложный, но гибкий вариант. В методе ВыгрузитьПоПравилу первым параметром передается Объект или Ссылка. Если мы передаем Источник.Ссылка, система пытается связать выгружаемую Спецификацию с объектом Номенклатура. Это архитектурно не совсем верно, так как один GUID источника (Номенклатуры) начинает соответствовать двум разным типам в приемнике (Номенклатуре и Спецификации).

Чтобы избежать путаницы в GUID, можно передать Неопределено в качестве первого параметра, если поиск в приемнике настроен только по полям поиска (например, по Владельцу и Наименованию спецификации):


ВыгрузитьПоПравилу(Неопределено, , ИсходящиеДанные, , "СпецификацииНоменклатуры");

В этом случае регистрация соответствия по GUID не будет выполнена, и конфликт типов при квитировании будет исчерпан.

Дополнительные рекомендации по регистрации изменений

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

Рекомендуем добавить в модуль набора записей регистра КомплектующиеНоменклатуры следующий код:


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

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

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

← На главную