Работа с обменом данных через универсальный формат (EnterpriseData) часто требует доработки стандартных схем XDTO. Однако при попытке изменить заимствованный пакет XDTO в расширении конфигурации разработчики сталкиваются с рядом ограничений платформы. Самая распространенная ошибка: «Значение контролируемого свойства не совпадает со значением в расширяемой конфигурации». В этой статье мы подробно разберем, как правильно модифицировать пакеты XDTO в расширениях, добавить собственные реквизиты и заставить обмен работать с обновленной схемой.
Когда мы заимствуем пакет XDTO в расширение, платформа по умолчанию устанавливает жесткий контроль соответствия свойств заимствованного объекта и объекта основной конфигурации. Это делается для того, чтобы расширение не нарушало целостность данных основной программы.
Если мы просто добавим реквизит в существующий объект пакета или попробуем изменить тип свойства, при запуске предприятия платформа выдаст ошибку. Более того, даже если удастся технически добавить поле, стандартные механизмы сериализации (СериализаторXDTO) могут игнорировать изменения, продолжая использовать оригинальную схему из основной конфигурации.
Мы рассмотрим два основных подхода к решению этой задачи: «мягкое» изменение (для простых случаев, например, перечислений) и создание новой версии формата (для добавления полей и изменения структуры).
Если ваша задача сводится к добавлению нового значения в перечисление (например, новая ставка НДС) внутри пакета XDTO, можно обойтись настройкой свойств заимствования.
Разберем действия по шагам:
Чтобы платформа разрешила внесение изменений, необходимо снять контроль с определенных свойств. Для добавления значения в перечисление часто помогает следующая последовательность:
Однако, как показывает практика, этот метод нестабилен для добавления новых реквизитов в сложные типы (документы, справочники), так как механизм обмена EnterpriseData жестко привязан к версиям схем.
Для полноценного добавления реквизитов (например, добавления поля в табличную часть документа) наиболее надежным решением является создание собственной версии формата обмена. Это позволяет избежать конфликтов с типовым кодом и гарантирует, что ваши изменения будут корректно обработаны сериализатором.
Суть метода заключается в создании копии пакета с измененным пространством имен (Namespace) и регистрации этой новой версии в механизмах обмена.
Вместо того чтобы мучиться с заимствованием типового пакета, мы создадим его клон в расширении.
EnterpriseData_1_8) в файл XML.URI пространства имен у нового пакета. Например, если оригинал был http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.8, измените его на http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.81 (или добавьте свой суффикс).Теперь нужно «научить» систему видеть нашу версию 1.81. Для этого необходимо переопределить несколько методов в общих модулях, отвечающих за обмен. Обычно это модули ОбменДаннымиXDTOСервер, ОбменДаннымиУТ (или аналогичные для вашей конфигурации, например КА или ERP).
Рассмотрим пример переопределения функции, которая сообщает системе, какие версии формата доступны. Используем аннотацию &После или &Вместо (в зависимости от архитектуры модуля, безопаснее использовать &После для коллекций).
// Модуль: ОбменДаннымиУТ (или аналогичный БП/КА)
// Расширяем процедуру заполнения доступных версий
&После("ДоступныеВерсииУниверсальногоФормата")
Процедура Расш_ДоступныеВерсииУниверсальногоФормата(ВерсииФормата)
// Регистрируем нашу версию 1.81 и указываем менеджер обмена для нее
// МенеджерОбменаЧерезУниверсальныйФормат - это общий модуль, содержащий правила конвертации (в отличие от универсальной выгрузки данных, работающей без программирования)
ВерсииФормата.Вставить("1.81", МенеджерОбменаЧерезУниверсальныйФормат);
КонецПроцедуры
Далее необходимо вмешаться в процесс определения поддерживаемых объектов. Когда узлы обмениваются информацией, они «договариваются» о версии. Нам нужно подменить версию 1.8 на 1.81 для нужных объектов.
В модуле ОбменДаннымиXDTOСервер (или ОбменДаннымиПовтИсп, зависит от конфигурации) находим функцию ПоддерживаемыеОбъектыФорматаКорреспондента (или ЗаполнитьПоддерживаемыеОбъектыXDTO).
// Модуль: ОбменДаннымиXDTOСервер
&Вместо("ПоддерживаемыеОбъектыФорматаКорреспондента")
Функция Расш_ПоддерживаемыеОбъектыФорматаКорреспондента(УзелОбмена, Режим)
// Получаем стандартную таблицу объектов
ТаблицаОбъекты = ПродолжитьВызов(УзелОбмена, Режим);
// Проходим по таблице и подменяем версию на нашу кастомную
Для Каждого Строка Из ТаблицаОбъекты Цикл
// Если объект поддерживает версию 1.8, переключаем его на нашу 1.81
Если Строка.Версия = "1.8" Тогда
Строка.Версия = "1.81";
КонецЕсли;
КонецЦикла;
Возврат ТаблицаОбъекты;
КонецФункции
Также может потребоваться корректировка в процедуре заполнения поддерживаемых объектов, если конфигурация использует структуру настроек:
// Пример для модуля ОбменДаннымиXDTOСервер
&После("ЗаполнитьПоддерживаемыеОбъектыXDTO")
Процедура Расш_ЗаполнитьПоддерживаемыеОбъектыXDTO(КомпонентыОбмена)
// В структуре КомпонентыОбмена может потребоваться явное указание версии
// Это зависит от конкретного релиза БСП
Если КомпонентыОбмена.Свойство("ВерсияФорматаОбмена") И КомпонентыОбмена.ВерсияФорматаОбмена = "1.8" Тогда
КомпонентыОбмена.ВерсияФорматаОбмена = "1.81";
КонецЕсли;
КонецПроцедуры
После внесения изменений в код и пакеты XDTO, обмен может продолжать работать по старой версии (1.8). Это происходит потому, что настройки версий кэшируются в регистре сведений НастройкиОбменаДаннымиXDTO (или аналогичном) при создании настройки синхронизации. Для оперативного пересоздания настроек обмена при тестировании можно использовать обработку для быстрого создания узлов планов обмена.
Чтобы изменения вступили в силу, у вас есть два пути:
НастройкиОбменаДаннымиXDTO (через Функции для технического специалиста) и для вашего узла обмена вручную исправьте версию формата с "1.8" на "1.81".После того как мы заставили систему использовать наш пакет 1.81, необходимо обеспечить заполнение новых полей данными. Это делается в модуле менеджера обмена (обычно МенеджерОбменаЧерезУниверсальныйФормат). Так как модуль очень большой, его лучше также расширять точечно.
Вам нужно найти процедуру ПКО (Правило Конвертации Объектов) для вашего документа и добавить туда код заполнения свойства.
// Расширение модуля МенеджерОбменаЧерезУниверсальныйФормат
&После("ПКО_Документ_ПриобретениеТоваровУслуг_Отправка_ПриОбработке")
Процедура Расш_ПКО_Документ_ПриобретениеТоваровУслуг_Отправка_ПриОбработке(ДанныеИБ, ДанныеXDTO, КомпонентыОбмена, СтекВыгрузки)
// Предположим, мы добавили реквизит "NewField" в пакете
// Нам нужно передать значение из документа в объект XDTO
// Важно: Проверяем, что текущая версия формата именно 1.81,
// чтобы не сломать обмен со старыми базами
Если КомпонентыОбмена.ВерсияФорматаОбмена = "1.81" Тогда
// Создаем свойство, если оно предусмотрено схемой, но не заполнено
// Или просто присваиваем значение, если структура XDTO уже инициализирована
Попытка
ДанныеXDTO.NewField = ДанныеИБ.МойНовыйРеквизит;
Исключение
// Обработка ошибки, если свойство не найдено в пакете
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Также не забывайте про правила конвертации свойств (ПКС), если вы используете декларативное описание правил обмена. В таком случае в процедуру инициализации правил нужно добавить описание нового свойства.
&После("ПКО_Документ_ПриобретениеТоваровУслуг_ЗаполнитьСвойстваШапки")
Процедура Расш_ПКО_Документ_ПриобретениеТоваровУслуг_ЗаполнитьСвойстваШапки(ПравилаОбработки, КомпонентыОбмена)
Если КомпонентыОбмена.ВерсияФорматаОбмена = "1.81" Тогда
// Добавляем ПКС: (Коллекция, ИмяВПриемнике, ИмяВИсточнике)
ДобавитьПКС(ПравилаОбработки, "NewField", "МойНовыйРеквизит");
КонецЕсли;
КонецПроцедуры
Изменение XDTO-пакетов в расширении возможно, но требует системного подхода. Простого "заимствования" часто недостаточно из-за жесткого контроля типов.
Наиболее рабочий алгоритм:
ДоступныеВерсии..., ПоддерживаемыеОбъекты...), подменяя старую версию на новую.