Как передать произвольную табличную часть через AdditionalInfo в Конвертации Данных 3.0?

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет Промышленность, строительство и АПК
← На главную

Синхронизация данных между конфигурациями 1С на платформе 8.3 все чаще строится на базе технологии EnterpriseData (универсальный формат обмена). Этот подход, реализуемый с помощью инструмента Конвертация Данных 3.0 (КД 3), стандартизирует обмен, но накладывает жесткие ограничения на структуру передаваемых объектов. Типовые XDTO-пакеты формата описывают строго определенный набор реквизитов и табличных частей для каждого документа.

Разберем классическую проблему: вам необходимо настроить обмен документами между базами «Управление Нашей Строительной Фирмой» (УНСФ) и «Бухгалтерия Строительной Организации» (БСО). При переносе документа ОтчетПереработчика выясняется, что в типовом формате обмена EnterpriseData (версии 1.6 и выше) отсутствует описание табличной части Отходы. Как же передать эти данные без изменения типовой схемы обмена?

В этой статье мы подробно проанализируем ситуацию и рассмотрим три эффективных способа решения данной задачи: от быстрых «обходных» путей с использованием сериализации в JSON до архитектурно правильного расширения формата XDTO.

Почему прямая передача структуры в AdditionalInfo не работает?

Свойство AdditionalInfo (Дополнительная информация) присутствует практически у каждого объекта в формате EnterpriseData и имеет тип anyType. Теоретически туда можно поместить любые данные. Однако на практике попытка передать туда сложный массив структур со ссылочными типами данных (например, справочник Номенклатура) приводит к ошибкам сериализации.

Платформа 1С при выгрузке не понимает, по какому правилу конвертации (ПКО) нужно обработать ссылочные поля внутри произвольной структуры, если они не описаны в схеме XDTO. В результате на стороне приемника вы получите либо пустые значения, либо ошибки чтения XML/JSON. Выясним, как обойти это ограничение.

---

Вариант 1. Сериализация табличной части в JSON (Самый простой и надежный способ)

Поскольку свойство AdditionalInfo без проблем пропускает строковые данные, самым надежным решением будет предварительное преобразование таблицы значений в текстовую строку формата JSON на стороне источника и её последующий разбор на стороне приемника.

Важный нюанс: все ссылочные типы данных (номенклатуру, склады, контрагентов) перед упаковкой в JSON необходимо преобразовать в их строковые уникальные идентификаторы (UUID). Передавать ссылки напрямую «как есть» нельзя.

Шаг 1. Реализация на стороне источника (УНСФ)

В модуле менеджера обмена источника найдем обработчик ПКО для документа ОтчетПереработчика (например, ПКО_Документ_ОтчетПереработчика_ПриОтправкеДанных) и пропишем алгоритм выгрузки ТЧ в строку JSON:


// Получаем табличную часть "Отходы" из выгружаемого объекта
ТаблицаОтходов = ДанныеИБ.Отходы.Выгрузить();

МассивСтрок = Новый Массив;
Для Каждого СтрокаТЧ Из ТаблицаОтходов Цикл
    
    // Формируем простую структуру, где вместо ссылок используем строковые UUID
    СтруктураСтроки = Новый Структура;
    СтруктураСтроки.Вставить("Номенклатура", Строка(СтрокаТЧ.Номенклатура.УникальныйИдентификатор()));
    СтруктураСтроки.Вставить("Количество", СтрокаТЧ.Количество);
    СтруктураСтроки.Вставить("ДоляСтоимости", СтрокаТЧ.ДоляСтоимости);
    
    МассивСтрок.Добавить(СтруктураСтроки);
    
КонецЦикла;

// Сериализуем массив структур в формат JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивСтрок);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Безопасно инициализируем свойство AdditionalInfo, если его еще нет
Если Не ДанныеXDTO.Свойство("AdditionalInfo") Тогда
    ДанныеXDTO.Вставить("AdditionalInfo", Новый Структура);
КонецЕсли;

// Помещаем нашу JSON-строку в свойства XDTO объекта
ДанныеXDTO.AdditionalInfo.Вставить("ОтходыJSON", СтрокаJSON);

Шаг 2. Получение и разбор данных на стороне приемника (БСО)

На стороне приемника нам нужно перехватить переданную строку, десериализовать её и заполнить табличную часть создаваемого документа. Делать это удобнее в два этапа.

Сначала в обработчике ПриКонвертацииДанныхXDTO считываем JSON и помещаем полученный массив во временные дополнительные свойства объекта:


Если ДанныеXDTO.Свойство("AdditionalInfo") И ДанныеXDTO.AdditionalInfo.Свойство("ОтходыJSON") Тогда
    
    СтрокаJSON = ДанныеXDTO.AdditionalInfo.ОтходыJSON;
    
    // Читаем данные из JSON обратно в массив структур
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
    МассивСтрок = ПрочитатьJSON(ЧтениеJSON);
    
    // Передаем массив в ДополнительныеСвойства создаваемого объекта ИБ
    ПолученныеДанные.ДополнительныеСвойства.Вставить("ОтходыИзОбмена", МассивСтрок);
    
КонецЕсли;

Затем в обработчике ПередЗаписьюПолученныхДанных (когда сам документ и его основные реквизиты уже заполнены, но еще не записаны в базу) восстанавливаем ссылки по UUID и заполняем ТЧ документа:


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

---

Вариант 2. Использование программного интерфейса БСП для обработки XDTO

Передача через простой JSON-UUID имеет один существенный минус: если номенклатура, указанная в ТЧ «Отходы», является новой и еще не создана в базе-приемнике, метод ПолучитьСсылку() вернет так называемую «битую» (пустую) ссылку. При стандартном обмене КД 3 сама заботится о создании связанных объектов, но при ручном разборе UUID эта магия не работает.

Чтобы решить эту проблему, воспользуемся штатными функциями Библиотеки Стандартных Подсистем (БСП), которые умеют преобразовывать объекты 1С в XDTO-представления ссылок и обратно.

Реализация выгрузки на стороне источника:

Мы будем использовать метод БСП ОбменДаннымиXDTOСервер.ДанныеXDTOИзДанныхИБ(). Он сформирует корректный XDTO-объект ссылки, который платформа сможет сопоставить и создать в приемнике, если его там еще нет.


МассивСтрок = Новый Массив;

// Получаем ПКО для номенклатуры, чтобы БСП знала, по какому правилу её выгружать
ПравилоНоменклатуры = ОбменДаннымиXDTOСервер.ПКОПоИмени(КомпонентыОбмена, "Справочник_Номенклатура");

Для Каждого СтрокаТЧ Из ДанныеИБ.Отходы Цикл
    
    СтруктураСтроки = Новый Структура;
    
    // Превращаем ссылку 1С в структуру XDTO-данных формата EnterpriseData
    XDTOНоменклатура = ОбменДаннымиXDTOСервер.ДанныеXDTOИзДанныхИБ(КомпонентыОбмена, СтрокаТЧ.Номенклатура, ПравилоНоменклатуры);
    
    СтруктураСтроки.Вставить("Номенклатура", XDTOНоменклатура);
    СтруктураСтроки.Вставить("Количество", СтрокаТЧ.Количество);
    
    МассивСтрок.Добавить(СтруктураСтроки);
    
КонецЦикла;

// Записываем полученную структуру в AdditionalInfo
Если Не ДанныеXDTO.Свойство("AdditionalInfo") Тогда
    ДанныеXDTO.Вставить("AdditionalInfo", Новый Структура);
КонецЕсли;

ДанныеXDTO.AdditionalInfo.Вставить("ОтходыСтруктураXDTO", МассивСтрок);

Реализация загрузки на стороне приемника:

При получении данных платформа автоматически десериализует вложенную структуру XDTO. Нам остается лишь применить обратную функцию БСП — ОбменДаннымиXDTOСервер.ОбъектИБИзДанныхXDTO(), которая найдет существующую номенклатуру или создаст новую на основе переданных XML/JSON-данных:


// В обработчике ПриКонвертацииДанныхXDTO просто переносим структуру в доп. свойства
Если ДанныеXDTO.Свойство("AdditionalInfo") И ДанныеXDTO.AdditionalInfo.Свойство("ОтходыСтруктураXDTO") Тогда
    ПолученныеДанные.ДополнительныеСвойства.Вставить("ОтходыXDTO", ДанныеXDTO.AdditionalInfo.ОтходыСтруктураXDTO);
КонецЕсли;

Заполнение табличной части в обработчике ПередЗаписьюПолученныхДанных:


Если ПолученныеДанные.ДополнительныеСвойства.Sвойство("ОтходыXDTO") Тогда
    
    МассивСтрокXDTO = ПолученныеДанные.ДополнительныеСвойства.ОтходыXDTO;
    ПолученныеДанные.Отходы.Очистить();
    
    ПравилоНоменклатуры = ОбменДаннымиXDTOСервер.ПКОПоИмени(КомпонентыОбмена, "Справочник_Номенклатура");
    
    Для Каждого СтрокаXDTO Из МассивСтрокXDTO Цикл
        
        НоваяСтрока = ПолученныеДанные.Отходы.Добавить();
        
        // Восстанавливаем или создаем номенклатуру средствами БСП
        СсылкаНоменклатура = ОбменДаннымиXDTOСервер.ОбъектИБИзДанныхXDTO(КомпонентыОбмена, СтрокаXDTO.Номенклатура, ПравилоНоменклатуры);
        
        НоваяСтрока.Номенклатура = СсылкаНоменклатура;
        НоваяСтрока.Количество = СтрокаXDTO.Количество;
        
    КонецЦикла;
    
КонецЕсли;

---

Вариант 3. Использование расширения формата EnterpriseData (Архитектурно правильный путь)

Хотя первые два варианта отлично работают и широко применяются на практике для быстрой разработки, использование свойства AdditionalInfo для регулярного обмена полноценными табличными частями считается обходным решением («костылем»). При изменении структуры метаданных или обновлении конфигураций такие алгоритмы сложнее отлаживать.

Стандарты разработки фирмы «1С» рекомендуют использовать механизмы расширения формата обмена. Рассмотрим этот процесс по шагам:

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

Этот способ требует больше времени на проектирование и внедрение, но гарантирует максимальную производительность, строгую валидацию данных на этапе передачи и стабильность обмена при последующих обновлениях баз данных.

Резюме

Для быстрой реализации переноса нетиповой табличной части без изменения схем XML/JSON отлично подойдет Вариант 1 (сериализация в JSON), если вы уверены, что все ссылочные данные гарантированно сопоставлены в обеих базах. Если же есть вероятность переноса новых элементов (например, новой номенклатуры прямо внутри этого документа), используйте Вариант 2 с функциями БСП. Для крупных проектов со строгими требованиями к архитектуре внедряйте Вариант 3 с расширением XDTO-пакета.

← На главную