Почему при обмене через БСП не создаются ссылочные объекты и как переносить связанные регистры?

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

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

Причины возникновения «битых» ссылок в БСП

Проанализируем механику работы подсистемы обмена данными в БСП в сравнении со стандартной обработкой выгрузки:

  1. Оптимизация пакета обмена: В отличие от универсальной обработки, стремящейся выгружать все связанные объекты целиком, БСП оптимизирует объем пакета. Если объект выгружается по ссылке (например, как реквизит строки документа) и для него не сработало собственное ПВД, подсистема формирует только узел ссылки (GUID и поля поиска), пропуская само тело объекта.
  2. Кэширование выгруженных ссылок: Если объект сначала попадает в выгрузку в виде ссылки, БСП кэширует его состояние. При последующей попытке выгрузить его реквизиты движок считает объект уже обработанным и не выгружает данные повторно.
  3. Недостаточность полей поиска: Если узел ссылки сформирован без ключевых реквизитов поиска, а поиск по идентификатору GUID не дал результата, база-приемник не может сопоставить объект и не имеет данных для его создания.

Решение 1. Принудительная выгрузка связанных объектов через ПКС

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

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

ВыгружатьОбъект = Истина;

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


// Сигнатура: ВыгрузитьПоПравилу(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ИмяПКО, УзелСсылки, ТолькоПолучитьУзелСсылки, ПроверятьСоответствиеУказанномуПКО, ВыгрузитьОбъект, ПринудительноВыгрузитьОбъект)
ВыгрузитьПоПравилу(Источник, , ВходящиеДанные, ИсходящиеДанные, "ИмяПКО", , Ложь, , Истина, Истина);

Важное замечание: Чтобы избежать зацикливания при перекрестных ссылках (например, у физического лица выгружаются дипломы, а у диплома есть реквизит «ФизЛицо»), в обратном ПКС для свойства родителя нужно обязательно ограничить глубину:


ТолькоПолучитьУзелСсылки = Истина;
ВыгрузитьОбъект = Ложь;

Решение 2. Корректная выгрузка связанных регистров сведений через ВыгрузитьРегистр

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

Рассмотрим правильный алгоритм выгрузки набора записей в обработчике ПКО «После выгрузки в файл» (или «После выгрузки»):

  1. Формируем запрос к регистру сведений с отбором по выгруженному объекту.
  2. Создаем структуру НаборЗаписей, содержащую две таблицы значений: Отбор и Строки.
  3. Описываем поля отбора (имя измерения, значение и признак использования).
  4. Заполняем строки набора записей.
  5. Вызываем метод ВыгрузитьРегистр.

Посмотрим на пример выгрузки паспортных данных физического лица:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПаспортныеДанныеФизЛиц.Период,
    |	ПаспортныеДанныеФизЛиц.ФизЛицо,
    |	ПаспортныеДанныеФизЛиц.ДокументСерия,
    |	ПаспортныеДанныеФизЛиц.ДокументНомер,
    |	ПаспортныеДанныеФизЛиц.ДокументДатаВыдачи,
    |	ПаспортныеДанныеФизЛиц.ДокументКодПодразделения,
    |	ПаспортныеДанныеФизЛиц.ДокументКемВыдан,
    |	ПаспортныеДанныеФизЛиц.ДокументВид
    |ИЗ
    |	РегистрСведений.ПаспортныеДанныеФизЛиц КАК ПаспортныеДанныеФизЛиц
    |ГДЕ
    |	ПаспортныеДанныеФизЛиц.ФизЛицо = &ФизЛицо";

Запрос.УстановитьПараметр("ФизЛицо", Источник);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Формируем таблицу отбора
    Отбор = Новый ТаблицаЗначений;
    Отбор.Колонки.Добавить("Имя");
    Отбор.Колонки.Добавить("Значение");
    Отбор.Колонки.Добавить("Использование");

    СтрокаОтбора = Отбор.Добавить();
    СтрокаОтбора.Имя = "ФизЛицо";
    СтрокаОтбора.Значение = Выборка.ФизЛицо;
    СтрокаОтбора.Использование = Истина;

    // Формируем таблицу записей
    Строки = Новый ТаблицаЗначений;
    Строки.Колонки.Добавить("Период");
    Строки.Колонки.Добавить("ФизЛицо");
    Строки.Колонки.Добавить("ДокументСерия");
    Строки.Колонки.Добавить("ДокументНомер");
    Строки.Колонки.Добавить("ДокументДатаВыдачи");
    Строки.Колонки.Добавить("ДокументКодПодразделения");
    Строки.Колонки.Добавить("ДокументКемВыдан");
    Строки.Колонки.Добавить("ДокументВид");

    Строка = Строки.Добавить();
    ЗаполнитьЗначенияСвойств(Строка, Выборка);

    // Упаковываем в структуру для передачи в БСП
    НаборЗаписей = Новый Структура("Отбор, Строки");
    НаборЗаписей.Отбор = Отбор;
    НаборЗаписей.Строки = Строки;

    ВыгрузитьРегистр(НаборЗаписей, , , , "ПаспортныеДанные");
КонецЦикла;

Особенность: выгрузка наборов без явного типа источника

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


// Добавляем фиктивную колонку Ссылка в ТЗ записей
Строки.Колонки.Добавить("Ссылка");

Строка = Строки.Добавить();
Строка.Ссылка = Выборка.Объект; // или Источник.Ссылка

Такой подход обеспечивает полную совместимость правил конвертации как с автономной обработкой «Универсальный обмен данными XML», так и с типовыми подсистемами обмена на базе БСП.

← На главную