При использовании классического механизма Конвертации данных 2.1 (КД 2) программисты часто сталкиваются с неприятной особенностью: объекты, созданные в расширениях конфигурации, ведут себя «неправильно» при обмене — для этого подойдёт подсистема для настройки обмена по правилам Конвертации данных. Основная проблема проявляется в том, что при выгрузке данных через обработку УниверсальныйОбменДаннымиXML для новых справочников или документов из расширения не выгружается Уникальный Идентификатор (GUID). В результате при загрузке в базу-приемник возникают ошибки или создаются дубли, так как поиск по идентификатору становится невозможным.
В этой статье мы подробно разберем, почему это происходит, как платформа 1С работает с типами расширений (поможет инструмент анализа структуры расширений и их влияния на объекты) и как модифицировать стандартную обработку выгрузки, чтобы решить проблему раз и навсегда.
Рассмотрим типичную ситуацию. Мы создали расширение и добавили в него новый справочник, например, GUD_АдресаМагазинов. Мы выгрузили структуру конфигурации с помощью MD83Exp.epf, настроили правила обмена в КД 2.1 и пытаемся выполнить выгрузку. Проанализируем содержимое сформированного XML-файла. Для обычного справочника из основной конфигурации узел объекта выглядит полноценно:
<Объект Тип="СправочникСсылка.Валюты" Имя="Валюты">
<Ссылка>
<Свойство Имя="{УникальныйИдентификатор}" Тип="Строка">
<Значение>c0be710e-6e9e-11ef-835b-d23c2dac05d8</Значение>
</Свойство>
</Ссылка>
...
</Объект>
Однако для объекта из расширения картина меняется. В блоке <Ссылка> отсутствует свойство {УникальныйИдентификатор}, а вместо него выгружаются только поля поиска (Код или Наименование). При попытке загрузить такой файл обработка УниверсальныйОбменДаннымиXML выдает ошибку: «Ошибка при вызове конструктора (УникальныйИдентификатор) ... Недопустимое значение параметра». Это происходит потому, что загрузчик ожидает строку формата GUID, а получает пустое значение или некорректные данные.
Проанализируем работу модуля объекта обработки УниверсальныйОбменДаннымиXML. В процессе выгрузки каждого объекта система должна определить: является ли текущее значение ссылочным типом? Если да — нужно извлечь его GUID. Для этого во многих версиях обработки используется вспомогательная функция ЗначениеСсылочногоТипа().
Посмотрим на типичную реализацию этой функции в старых версиях обработки:
Функция ЗначениеСсылочногоТипа(Значение)
Тип = ТипЗнч(Значение);
Возврат Тип <> Тип("Неопределено")
И (Справочники.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ Документы.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ Перечисления.ТипВсеСсылки().СодержитТип(Тип)
... );
КонецФункции
Именно здесь кроется корень проблемы. В платформе 1С до версии 8.3.20 (а также в более новых версиях, если установлен режим совместимости 8.3.19 и ниже), системные коллекции Справочники.ТипВсеСсылки(), Документы.ТипВсеСсылки() и другие возвращают набор типов только из основной конфигурации. Объекты, добавленные в расширениях, в эти коллекции просто не попадают!
Таким образом, когда код обработки проверяет ссылку на справочник из расширения, функция ЗначениеСсылочногоТипа() возвращает Ложь. Система «думает», что перед ней не ссылка, а некий примитивный тип или структура, и пропускает шаг выгрузки Уникального Идентификатора.
Чтобы обработка корректно определяла типы из расширений независимо от режима совместимости, нам нужно изменить подход к проверке типа. Мы не будем полагаться на коллекции ТипВсеСсылки(), а воспользуемся глобальным методом поиска метаданных по типу.
Рассмотрим, как должна выглядеть исправленная функция. Откроем модуль объекта обработки УниверсальныйОбменДаннымиXML и найдем функцию ЗначениеСсылочногоТипа — для этого есть инструментарий разработчика для анализа метаданных и отладки. Заменим ее содержимое на следующий код:
Функция ЗначениеСсылочногоТипа(Значение)
Перем Тип;
Тип = ТипЗнч(Значение);
// Используем поиск в метаданных, который видит и расширения
ОбъектМетаданных = Метаданные.НайтиПоТипу(Тип);
Если ОбъектМетаданных = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
// Проверяем, относится ли найденный объект к ссылочным типам
ИмяИерархии = ОбъектМетаданных.ПолноеИмя();
Если СтрНайти(ИмяИерархии, "Справочник.") > 0
Или СтрНайти(ИмяИерархии, "Документ.") > 0
Или СтрНайти(ИмяИерархии, "ПланВидовХарактеристик.") > 0
Или СтрНайти(ИмяИерархии, "ПланСчетов.") > 0
Или СтрНайти(ИмяИерархии, "ПланВидовРасчета.") > 0
Или СтрНайти(ИмяИерархии, "Перечисление.") > 0 Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Важный момент: использование Метаданные.НайтиПоТипу() гарантирует, что система найдет описание объекта, даже если он находится в расширении. После такой правки выгрузка начнет корректно определять GUID для расширенных объектов, и файл обмена станет валидным.
Как мы уже выяснили, поведение коллекций ТипВсеСсылки было изменено в платформе версии 8.3.20. Если вы переведете конфигурацию (и основной проект, и расширение) на режим совместимости 8.3.20 или выше, то стандартная обработка может заработать без внесения правок в код. Однако это не всегда возможно в продуктивных системах, так как смена режима совместимости требует полного регрессионного тестирования всей базы.
Если же вы используете современную платформу (например, 8.3.25), но режим совместимости базы установлен как 8.3.16, вы все равно столкнетесь со «старым» поведением. В этом случае правка кода обработки остается единственным быстрым решением.
Для того чтобы в самой конфигурации «Конвертация данных 2.1» вы могли настраивать правила для объектов расширения, их нужно правильно выгрузить — для этой задачи есть автоматизация настройки и запуска обмена по правилам КД 2.1. Рассмотрим основные правила:
MD83Exp.epf непосредственно в той информационной базе, где подключены и активны ваши расширения.расш1_). Это поможет избежать конфликтов имен при сопоставлении в КД.СправочникСсылка.GUD_АдресаМагазинов).Если задача переноса данных разовая и вы не хотите погружаться в отладку КД 2.1, проанализируем альтернативы:
EnterpriseData (XDTO) изначально проектировалась с учетом расширяемости. В КД 3.0 расширение просто добавляет свои свойства в пакет XDTO, что делает механизм более гибким, хотя и требует больше усилий при первоначальной настройке.Мы выяснили, что КД 2.1 вполне работоспособна в связке с расширениями, если знать об особенностях работы платформы с типами данных. Основная проблема — игнорирование типов расширений в методах ТипВсеСсылки при низких режимах совместимости. Исправив функцию ЗначениеСсылочногоТипа в обработке УниверсальныйОбменДаннымиXML, вы сможете беспрепятственно обмениваться данными любых объектов, независимо от того, где они созданы.