При настройке обмена данными между конфигурациями, например, «Бухгалтерия предприятия» и «ERP», часто возникает задача передать дополнительный реквизит, добавленный в основной конфигурации. В ряде случаев для переноса данных между не полностью идентичными конфигурациями может потребоваться адаптивная выгрузка и загрузка данных XML (подойдёт обработка выгрузки и загрузки XML с измененной структурой), но стандартный механизм универсального формата обмена (EnterpriseData) также требует доработки. Чтобы не снимать конфигурацию с поддержки, все изменения вносятся через расширение.
Рассмотрим ситуацию: в справочник Номенклатура добавлен новый реквизит МойРеквизит. Мы создали расширение, добавили в него свой XDTO-пакет, прописали обработчики для добавления реквизита в правила конвертации и для его заполнения при выгрузке. Отладчик показывает, что код выполняется, но в итоговом XML-файле обмена нашего реквизита нет. Выясним, в чем причина и как это исправить.
Давайте проанализируем, какие шаги были предприняты и где могла закрасться ошибка. Автор вопроса выполнил практически все необходимые действия:
Номенклатура добавлен реквизит МойРеквизит.EnterpriseData_1_16_2_ext) с уникальным пространством имен (http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16).http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16).ОбменДаннымиПереопределяемый.Код для регистрации расширения формата выглядит корректно:
&После("ПриПолученииДоступныхРасширенийФормата")
Процедура Расш1_ПриПолученииДоступныхРасширенийФормата(РасширенияФормата)
РасширенияФормата.Вставить("http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16" , "1.16");
КонецПроцедуры
И код для модификации правил обмена тоже:
&ИзменениеИКонтроль("ДобавитьПКО_Справочник_Номенклатура_Отправка")
#Вставка
ПространствоИмен = "http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16";
ОбменДаннымиXDTOСервер.ИнициализироватьРасширениеПравилаКонвертацииОбъекта(ПравилоКонвертации, ПространствоИмен);
ДобавитьПКС(СвойстваШапки, "МойРеквизит", "МойРеквизит",,, ПространствоИмен);
#КонецВставки
Проблема кроется в настройке самого XDTO-пакета. Автор создал в нем тип объекта КлючевыеСвойстваНоменклатура для добавления реквизита. Этого недостаточно. Чтобы система поняла, как "приклеить" ваш новый реквизит к стандартному объекту, нужно расширить сам тип объекта Справочник.Номенклатура, а не только его ключевые свойства. Чтобы убедиться, что структура пакета описана верно, можно использовать инструменты, позволяющие выполнить проверку валидности файла XML на соответствие схеме XSD.
Ключевая ошибка: в расширяющем XDTO-пакете не был создан тип для самого объекта Справочник.Номенклатура и, что самое важное, у него не был указан базовый тип из основного пакета. Без этого платформа не может связать стандартную структуру объекта с вашими дополнениями.
Разберем по шагам, как корректно настроить расширение формата.
Шаг 1. Создание и настройка XDTO-пакета в расширении
В дереве объектов расширения создайте новый XDTO-пакет, например, EnterpriseData_1_16_2_ext. Укажите для него уникальное пространство имен, например, http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16.
Шаг 2. Импорт основного пространства имен
В свойствах созданного пакета перейдите на вкладку «Директивы импорта» и добавьте пространство имен основного формата, который вы расширяете. Например, http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16. Это позволит вам ссылаться на типы данных из стандартного пакета.
Шаг 3. Создание расширяющего типа объекта
Это самый важный шаг. В своем пакете создайте новый «Тип объекта».
СправочникОбъект.Номенклатура.Базовый тип укажите полный тип объекта из основного пакета, который вы расширяете. Для этого нажмите кнопку выбора, в открывшемся окне найдите стандартный пакет (например, EnterpriseData_1_16_2) и выберите в нем нужный тип (например, СправочникОбъект.Номенклатура).МойРеквизит, указав для него нужный тип данных (например, string из пространства имен http://www.w3.org/2001/XMLSchema).Если ваша задача подразумевает более сложные изменения, такие как универсальный механизм добавления табличных частей, принцип расширения типов XDTO останется схожим, но потребует описания коллекций.
Шаг 4. Программная доработка правил и обработчиков
Код, приведенный автором, практически верен. Вы регистрируете расширение формата и добавляете новое свойство (ПКС) в правило конвертации объекта (ПКО).
Остается заполнить данными это свойство при выгрузке. Для этого используется обработчик события ПриОтправкеДанных.
&После("ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных")
Процедура Расш1_ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных(ДанныеИБ, ДанныеXDTO, КомпонентыОбмена, СтекВыгрузки)
// Добавляем значение нашего реквизита напрямую в объект XDTO
ДанныеXDTO.Вставить("МойРеквизит", ДанныеИБ.МойРеквизит);
КонецПроцедуры
После выполнения этих шагов новый реквизит должен корректно появиться в файле выгрузки в структуре объекта "Номенклатура".
Существует и другой, более простой путь, который не требует создания и настройки XDTO-пакетов. Универсальный формат обмена предусматривает специальную коллекцию ДополнительныеСведения (в XML это будет `AdditionalInfo`) почти для каждого объекта. Она предназначена для передачи произвольных данных, не описанных в основной структуре. В некоторых случаях полезно реализовать заполнение значения данных дополнительных сведений объекта из источника в приемник для синхронизации этих свойств.
Как это работает?
Вместо всей работы с XDTO-пакетами, вам достаточно в обработчике ПриОтправкеДанных добавить нужные данные в эту коллекцию.
&После("ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных")
Процедура Расш1_ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных(ДанныеИБ, ДанныеXDTO, КомпонентыОбмена, СтекВыгрузки)
// Проверяем, есть ли уже узел "ДополнительныеСведения"
Если ДанныеXDTO.Свойства().Получить("ДополнительныеСведения") = Неопределено Тогда
// Если нет, создаем его
Фабрика = КомпонентыОбмена.ФабрикаXDTO;
ТипДополнительныеСведения = Фабрика.Тип("http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16", "ArrayOfAdditionalInfo");
ДанныеXDTO.ДополнительныеСведения = Фабрика.Создать(ТипДополнительныеСведения);
КонецЕсли;
// Создаем новую запись для нашего реквизита
ТипЗаписи = Фабрика.Тип("http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16", "AdditionalInfo");
НоваяЗапись = Фабрика.Создать(ТипЗаписи);
НоваяЗапись.Имя = "МойРеквизит";
НоваяЗапись.Значение = ДанныеИБ.МойРеквизит;
// Добавляем запись в коллекцию
ДанныеXDTO.ДополнительныеСведения.Добавить(НоваяЗапись);
КонецПроцедуры
На принимающей стороне останется только прочитать эту коллекцию и обработать данные.
Преимущества:
Ключевой недостаток:
Этот метод имеет серьезное ограничение. Реквизиты, переданные через AdditionalInfo, выгружаются только при непосредственной выгрузке самого объекта (в нашем случае, справочника «Номенклатура»). Если же выгружается, например, документ «Реализация товаров и услуг», то в данных о номенклатуре, которые передаются в составе документа (как ссылка), этих дополнительных реквизитов не будет.
Выбор способа зависит от задачи:
AdditionalInfo. Это быстро и просто.При работе с обменами важно не только передать данные, но и обеспечить их целостность. Так, исправление правил обмена EnterpriseData позволяет избежать появления "битых ссылок" в справочниках. А для повышения стабильности системы в высоконагруженных базах рекомендуется оптимизация типовых обменов EnterpriseData, включая использование асинхронных механизмов.