При переносе данных между конфигурациями 1С (например, между базами ЗУП 2.5 или УПП) разработчики часто сталкиваются с ситуацией: при ручной выгрузке через обработку УниверсальныйОбменДаннымиXML все документы и связанные справочники переносятся корректно со всеми реквизитами. Однако при переходе на автообмен через планы обмена с использованием типовой обработки ОбменДаннымиXML поведение меняется: связанные элементы (сотрудники, должности, номенклатура) либо не создаются вовсе, либо создаются с заполненными полями поиска, но пустыми остальными реквизитами, а в документе может появиться представление <Объект не найден...>.
Разберем детально, почему так происходит, как устроена внутренняя оптимизация выгрузки в планах обмена и какими способами можно обеспечить корректный перенос данных.
Проанализируем техническую сторону работы подсистемы обмена данными на базе правил «Конвертации данных 2.1»:
ОбменДаннымиXML при работе в контексте планов обмена по умолчанию активируется оптимизация трафика. Типовой механизм предполагает, что нормативно-справочная информация (НСИ) должна регистрироваться и передаваться отдельно, а при передаче документов выгружаются только ссылки на связанные объекты (узлы ссылок с уникальным идентификатором GUID и ключевыми полями поиска), но не их свойства.Источник в обработчиках КД может содержать как непосредственный объект (СправочникОбъект, ДокументОбъект), так и ссылку (СправочникСсылка, ДокументСсылка). Если в алгоритмах правил конвертации свойств (ПКС) или ПКО не предусмотрена проверка типа, чтение реквизитов через точку от объекта или обращение к связанным регистрам может возвращать пустые значения.ОбменДаннымиXML для документов может выполняться очистка существующих движений с последующей попыткой проведения, тогда как УниверсальныйОбменДаннымиXML переносит движения как самостоятельные наборы записей. Если зависимый объект не был полностью записан к моменту проведения документа, документ не проведется или запишет битую ссылку.Для того чтобы заставить механизм выгрузки передавать связанные объекты полностью, а не только их ссылочные идентификаторы, необходимо программно отключить режим получения узла ссылки.
Рассмотрим, как скорректировать вызов функции ВыгрузитьПоПравилу. Четвертый параметр этой функции — ТолькоПолучитьУзелСсылки. Если передать туда значение Ложь, выгрузка сформирует полный XML-узел объекта:
// Пример вызова выгрузки зависимого объекта целиком
ВыгрузитьПоПравилу(ВыбЗапрос.Ссылка, , , Ложь, "ПриемНаРаботуВОрганизацию", , , );
Если требуется отключить режим выгрузки ссылок на уровне всего документа или конкретного правила, в обработчике Перед выгрузкой соответствующего ПКО можно явно установить служебную переменную:
ТолькоПолучитьУзелСсылки = Ложь;
НеВыгружатьОбъектыСвойствПоСсылкам = Ложь;
Благодаря этому объект будет выгружен в поток XML со всей иерархией реквизитов и табличных частей, а не в виде сокращенного описания ссылки.
Выясним, как избежать ошибок при обращении к данным источника, если в одном режиме передается ссылка, а в другом — объект. В обработчиках событий КД (например, Перед выгрузкой или При выгрузке) следует использовать универсальную конструкцию проверки:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КонтактнаяИнформация.Тип,
| КонтактнаяИнформация.Вид,
| КонтактнаяИнформация.Представление
|ИЗ
| РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
|ГДЕ
| КонтактнаяИнформация.Объект = &Объект";
// Универсальное получение ссылки независимо от того, передан объект или ссылка
Если Источник.Ссылка = Источник Тогда
Запрос.УстановитьПараметр("Объект", Источник);
Иначе
Запрос.УстановитьПараметр("Объект", Источник.Ссылка);
КонецЕсли;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ВыгрузитьПоПравилу(,, Выборка, Ложь, "КонтактнаяИнформация");
КонецЦикла;
Если правила конвертации менять нежелательно, чтобы сохранить типовую архитектуру обмена, необходимо гарантировать, что все связанные со справочниками и документами объекты зарегистрированы к обмену на узле.
Разберем реализацию через подписку на событие при записи документа в базе-источнике:
// В обработчике подписки на событие ПриЗаписи документа
Для Каждого Стр Из Источник.РаботникиОрганизации Цикл
Если ЗначениеЗаполнено(Стр.Сотрудник) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Стр.Сотрудник);
КонецЕсли;
Если ЗначениеЗаполнено(Стр.Должность) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Стр.Должность);
КонецЕсли;
Если ЗначениеЗаполнено(Стр.ПодразделениеОрганизации) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Стр.ПодразделениеОрганизации);
КонецЕсли;
КонецЦикла;
В этом случае при очередной сессии обмена типовая обработка ОбменДаннымиXML выгрузит зарегистрированные элементы справочников как самостоятельные полноценные объекты, и в базе-приемнике не возникнет пустых полей или отсутствующих ссылок.