Почему реквизит с типом Дата передается как строка в приемник при обмене через КД 3 (EnterpriseData) и как это исправить?

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

При доработке типовых обменов по технологии Конвертация данных 3.0 (КД 3) на базе формата EnterpriseData разработчики часто сталкиваются с ситуацией, когда добавленный в расширение XDTO-пакета реквизит с типом Дата (например, ДатаНачалаДействия) на стороне базы-приемника считывается в объект ДанныеXDTO как обычная строка. В результате стандартные механизмы БСП не могут корректно сопоставить и записать это свойство в базу данных.

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


Выясняем причину: почему типовые даты работают, а новые приходят строкой?

Для того чтобы понять суть проблемы, нам нужно заглянуть под капот механизма сериализации XDTO в платформе 1С:Предприятие. Когда база-приемник читает XML-файл сообщения обмена, она выполняет следующий код в общем модуле ОбменДаннымиXDTOСервер:


ТипОбъектаXDTO = ФабрикаXDTO.Тип(КомпонентыОбмена.ФайлОбмена.URIПространстваИмен, КомпонентыОбмена.ФайлОбмена.ЛокальноеИмя);
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(КомпонентыОбмена.ФайлОбмена, ТипОбъектаXDTO);

Типовые реквизиты конфигурации описаны в основном XDTO-пакете (например, EnterpriseData_1_16_2). Платформа заранее инициализирует фабрику XDTO с использованием этих статических схем. В схеме для каждого стандартного реквизита даты жестко указан тип xs:date или xs:dateTime. Фабрика XDTO, видя эти типы в схеме, автоматически преобразует строковое представление даты из XML (например, "2023-10-25") в стандартный тип 1С Дата.

Если же мы расширяем формат и добавляем новое свойство, ситуация меняется. Автоматическое приведение типов может дать сбой по одной из следующих причин:

  1. Неверный тип в расширении пакета XDTO: Если при создании свойства в расширении пакета в конфигураторе был по ошибке указан тип string вместо date (http://www.w3.org/2001/XMLSchema).
  2. Различие пространств имен (Namespace): Расширение формата располагается в собственном пространстве имен (отличном от типового). Если база-приемник при чтении файла не смогла корректно сопоставить пространство имен расширения со своей фабрикой XDTO, то все неизвестные свойства считываются как обычные текстовые узлы (строки).
  3. Настройки версии формата в КД 3: При импорте структуры формата в информационную базу «Конвертация данных 3» добавленное свойство могло определиться как строка. Сгенерированные правила обмена (модуль менеджера обмена) в таком случае не содержат информации о необходимости типизации данного поля.

Решение 1: Быстрое исправление через обработчик "ПриКонвертацииДанныхXDTO"

Если вам необходимо быстро решить задачу и вы не хотите тратить время на повторную перегенерацию схем, регистрацию пространств имен и перезагрузку правил в КД 3, вы можете обработать значение свойства вручную на стороне приемника.

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

Шаг 1. В модуле менеджера обмена базы-приемника найдите процедуру, отвечающую за получение данных вашего объекта (например, ДобавитьПКО_Справочник_ДоговорыКонтрагентов_Получение).

Шаг 2. Убедитесь, что ваше расширенное свойство добавлено в состав ПКС (Правила конвертации свойств). Обратите внимание на четвертый параметр функции ДобавитьПКС. Если мы хотим обрабатывать свойство алгоритмами, здесь должна быть передана единица (или Истина в зависимости от версии БСП), указывающая на получение значения алгоритмом:


ПространствоИмен = "";
ОбменДаннымиXDTOСервер.ИнициализироватьРасширениеПравилаКонвертацииОбъекта(ПравилоКонвертации, ПространствоИмен);

// Четвертый параметр = 1 указывает на использование алгоритмов при конвертации
ДобавитьПКС(СвойстваШапки, "ДатаНачалаДействия", "ДатаНачалаДействия", 1, , ПространствоИмен);

Шаг 3. Перейдем к обработчику события. В модуле менеджера обмена (или в соответствующем обработчике ПКО в КД 3) необходимо прописать код преобразования полученной строки в полноценную дату 1С. Для этого используется системная функция XMLЗначение():


Процедура ПКО_Справочник_ДоговорыКонтрагентов_Получение_ПриКонвертацииДанныхXDTO(ДанныеXDTO, ДанныеПовторногоИспользования, ПолученныеДанные, КомпонентыОбмена)
    
    // Проверяем наличие нашего свойства в XDTO
    Если ДанныеXDTO.Свойство("ДатаНачалаДействия") И ЗначениеЗаполнено(ДанныеXDTO.ДатаНачалаДействия) Тогда
        
        ЗначениеРеквизита = ДанныеXDTO.ДатаНачалаДействия;
        
        // Если значение пришло в виде строки, принудительно конвертируем его в Дату
        Если ТипЗнч(ЗначениеРеквизита) = Тип("Строка") Тогда
            Попытка
                ПолученныеДанные.ДатаНачалаДействия = XMLЗначение(Тип("Дата"), ЗначениеРеквизита);
            Исключение
                ЗаписьЖурналаРегистрации("ОбменДанными.ОшибкаТипизацииДаты",
                    УровеньЖурналаРегистрации.Предупреждение, , ,
                    "Не удалось сконвертировать дату начала действия: " + ЗначениеРеквизита);
            КонецПопытки;
        Иначе
            // Если платформа сама смогла типизировать (например, после обновления схем)
            ПолученныеДанные.ДатаНачалаДействия = ЗначениеРеквизита;
        EndIf;
        
    КонецЕсли;

КонецПроцедуры

Этот подход гарантирует стабильную работу обмена даже в том случае, если схемы конфигураций источника и приемника временно рассинхронизированы.


Решение 2: Корректная настройка пакетов XDTO для автоматической типизации

Если вы стремитесь к красивому и правильному решению без написания лишнего "костыльного" кода в обработчиках, необходимо заставить платформу саму распознавать тип данных. Для этого выполним следующие действия:

Шаг 1. Проверка типов в XDTO-пакете конфигуратора
Откройте конфигуратор вашей базы (и источника, и приемника). Найдите ваше расширение XDTO-пакета. Откройте свойства вашего реквизита ДатаНачалаДействия. Убедитесь, что в поле Тип выбрано стандартное значение типа даты из пространства XML-схем: date (http://www.w3.org/2001/XMLSchema).

Шаг 2. Регистрация расширения пространства имен
Платформа должна знать, какие расширения формата подключены к обмену. Для этого в обеих базах в общем модуле ОбменДаннымиПереопределяемый найдите процедуру ПриПолученииДоступныхРасширенийФормата и добавьте туда регистрацию вашего пакета:


Процедура ПриПолученииДоступныхРасширенийФормата(МассивРасширений) Экспорт
    
    // Добавляем URI пространства имен вашего расширения формата
    МассивРасширений.Добавить("http://www.your-company.ru/Exchange/Extension");
    
КонецПроцедуры

Шаг 3. Обновление метаданных в КД 3
Выгрузите обновленные XML-схемы из ваших конфигураций и загрузите их в базу "Конвертация данных 3". В справочнике "Версии формата" проверьте настройки вашего добавленного реквизита. Убедитесь, что КД 3 распознает его тип как Дата. Перегенерируйте модули менеджера обмена и загрузите их в базы источника и приемника.

После выполнения этих шагов платформа при чтении XML автоматически преобразует строку в дату, и в процедуру получения объекта данные придут уже в типизированном виде.


Как перехватить и проанализировать файл обмена XML?

Для диагностики типов данных критически важно уметь смотреть "сырые" данные, которые уходят из источника. Рассмотрим два самых простых способа получить XML-файл обмена:

Способ А. Перехват при выгрузке в каталог

Самый простой способ изучить файл — настроить синхронизацию через локальный каталог.

  1. В режиме «1С:Предприятие» откройте меню Администрирование — Синхронизация данных.
  2. Временно измените настройки подключения к базе-приемнику, выбрав вариант транспорта «Синхронизация через локальный или сетевой каталог».
  3. Запустите выгрузку данных.
  4. Перейдите в указанный сетевой каталог. Там появится архив формата .zip (например, Message_ИСТОЧНИК_ПРИЕМНИК.zip). Распакуйте его и откройте находящийся внутри XML-файл с помощью любого текстового редактора (Notepad++, VS Code) или интернет-браузера.

Способ Б. Использование точки останова в конфигураторе

Если обмен выполняется напрямую через веб-сервис или COM-соединение, файл создается во временной папке операционной системы и сразу удаляется. Поймать его можно с помощью отладки:

  1. Откройте конфигуратор базы-источника и найдите общий модуль ОбменДаннымиXDTOСервер.
  2. Установите точку останова в процедуре, выполняющей запись сообщения обмена (например, на строке вызова метода ЗаписатьСообщениеОбмена()).
  3. В момент остановки программы откройте меню Отладка — Оценка выражения (Shift+F9) и найдите переменную, содержащую путь к временному файлу (обычно это результат работы функции ПолучитьИмяВременногоФайла()).
  4. Скопируйте полученный путь, перейдите по нему в проводнике Windows и скопируйте временный файл в другую папку до того, как продолжите выполнение кода (так как при завершении процедуры файл будет удален системой).

В XML-файле найдите узел вашего объекта и посмотрите, как именно выглядит выгруженное свойство. Если оно выглядит как <ДатаНачалаДействия>2023-10-25</ДатаНачалаДействия> без указания префиксов пространства имен, а заголовок файла содержит корректное объявление вашего пространства имен расширения, значит, проблема кроется исключительно на стороне приемника (в регистрации расширения или правилах конвертации).

Используя предложенные методики, вы всегда сможете оперативно диагностировать и устранять любые проблемы с типизацией данных при интеграции систем на платформе 1С:Предприятие 8.

← На главную