При настройке обмена данными между конфигурациями на платформе 1С с использованием конфигурации «Конвертация данных 2.1» (КД 2) разработчики часто сталкиваются со следующей проблемой. Если реквизит-приемник имеет составной тип данных (например, включает в себя несколько перечислений и справочников), система при выгрузке не всегда может автоматически определить конечный тип. В результате значение выгружается как обычная строка, что приводит к ошибкам или некорректному заполнению реквизита при загрузке в базу-приемник.
В этой статье мы подробно разберем, почему возникает эта проблема, и рассмотрим несколько эффективных способов её решения как на этапе выгрузки данных, так и на этапе их загрузки.
Когда мы настраиваем Правило конвертации свойства (ПКС) для обычного (не составного) типа данных, система «знает» точный тип приемника по умолчанию. Но как только у реквизита появляется составной тип (например, ПеречислениеСсылка.ПорядокОтраженияАвансов и СправочникСсылка.ДоговорыКонтрагентов), выгрузка простого текстового значения без дополнительных указаний превращает его в строку. Платформа 1С в базе-приемнике не может сопоставить строку "ДоходУСН" с конкретным элементом перечисления, так как ожидает ссылку.
Рассмотрим по шагам три основных метода решения этой задачи.
Самый простой способ, который помогает в случаях, когда часть типов в составном реквизите приемника фактически не используется при данном обмене. Если в вашей конкретной задаче этот реквизит должен принимать только один определенный тип, мы можем вручную ограничить составной тип в настройках правил конвертации.
После этого тип свойства перестанет быть составным в рамках данного правила обмена, и система автоматически начнет приводить строковое значение к нужному ссылочному типу.
Если составной тип действительно необходим и должен динамически меняться в зависимости от выгружаемых данных, нам потребуется программно указать системе, какой тип данных мы передаем. Для этого используется обработчик «Перед выгрузкой» в ПКС.
Мы можем использовать предопределенные параметры ТипПриемника и ИмяПКО для жесткого связывания выгружаемого значения с конкретным типом.
Пример для значения перечисления:
Если нам нужно передать значение перечисления, мы пишем имя значения в переменную Значение и явно прописываем тип приемника в виде строки:
Значение = "ДоходУСН"; // Конечный идентификатор значения перечисления в базе-приемнике
ТипПриемника = "ПеречислениеСсылка.ПорядокОтраженияАвансов";
Пример для ссылочных типов (справочники или документы):
Если реквизит составного типа может содержать ссылки на разные справочники, нам необходимо динамически определять тип источника и указывать соответствующее Правило конвертации объектов (ПКО):
Если ТипЗнч(Источник.Владелец) = Тип("СправочникСсылка.Контрагенты") Тогда
ТипПриемника = "СправочникСсылка.Контрагенты";
ИмяПКО = "Контрагенты";
ИначеЕсли ТипЗнч(Источник.Владелец) = Тип("СправочникСсылка.Организации") Тогда
ТипПриемника = "СправочникСсылка.Организации";
ИмяПКО = "Организации";
КонецЕсли;
Часто разработчики сталкиваются с тем, что код в обработчике написан абсолютно верно, но при выгрузке тип все равно теряется, и в XML-файл записывается простая строка. Это происходит из-за внутренней оптимизации обработки выгрузки.
Чтобы решить эту проблему, перед выполнением выгрузки в обработке «Универсальный обмен данными XML» перейдите на вкладку «Дополнительные настройки» и снимите флаг «Использовать оптимизированный формат для длинных строк / двоичных данных». После отключения этой опции принудительно заданный ТипПриемника будет корректно транслироваться в XML-файл в виде специального атрибута.
Если у вас нет возможности изменять правила выгрузки (например, выгрузка идет из закрытой внешней системы) или если вы хотите гарантировать корректность данных непосредственно при записи в базу-приемник, обработку типа можно перенести на этап загрузки.
Для этого в ПКС в обработчике «При загрузке» (или «Перед загрузкой») мы перехватываем переданное строковое значение и преобразуем его в полноценную ссылку базы-приемника:
// Проверяем, что из файла пришла именно строка
Если ТипЗнч(Значение) = Тип("Строка") Тогда
Если Значение = "ДоходУСН" Тогда
// Находим реальное значение перечисления в приемнике и подставляем его в реквизит
Значение = Перечисления.ПорядокОтраженияАвансов.ДоходУСН;
ИначеЕсли Значение = "РасходУСН" Тогда
Значение = Перечисления.ПорядокОтраженияАвансов.РасходУСН;
КонецЕсли;
КонецЕсли;
Такой подход обеспечивает стопроцентную надежность заполнения реквизита, так как преобразование строки в ссылку происходит непосредственно средствами встроенного языка базы-приемника перед записью объекта.