Как правильно перенести План Видов Характеристик и свойство "ТипЗначения" в 1С через Конвертацию Данных?

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

При настройке обмена данными между конфигурациями 1С часто возникают сложности с переносом нестандартных объектов метаданных. Если вы хотите сделать процесс более надежным и современным, можно рассмотреть универсальный обмен XML (КД 2) + RabbitMQ, однако базовые принципы остаются неизменными. Одной из таких задач является перенос Плана Видов Характеристик (ПВХ), например, справочника "Статьи доходов" в конфигурациях "Комплексная автоматизация" или "ERP", что часто требуется, если вы выполняете перенос данных из УПП в ERP 2.5 / КА 2.

Рассмотрим ситуацию, когда необходимо перенести данные между двумя идентичными по релизу базами, используя правила обмена (формат XML). Для этих целей удобно использовать обмен по правилам Конвертации данных 2.1 для ERP, КА, УТ 11, но в процессе создания правил мы сталкиваемся с тремя типовыми проблемами:

  1. Ссылочные свойства (например, "Группа финансового учета") не переносятся.
  2. Группы (папки) создаются как элементы.
  3. Свойство ТипЗначения (имеющее тип ОписаниеТипов) не выгружается корректно, вызывая ошибки вида "Неверный тип ОпределениеТипа".

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

Проблема 1: Почему не переносятся ссылочные свойства?

При создании правил конвертации (ПКО) для ПВХ вы можете заметить, что простые типы (строки, числа) переносятся, а ссылочные реквизиты остаются пустыми, даже если в правилах выгрузки (ПВД) они выбраны.

Причина: Механизм конвертации данных не может автоматически выгрузить ссылочный объект, если для него не определено Правило Конвертации Объектов (ПКО). Если конфигурации идентичны, 1С не "угадывает" правило автоматически для вложенных свойств.

Решение:

Для каждого ссылочного реквизита (например, ГруппаФинансовогоУчета) необходимо:

  1. Создать отдельное ПКО для справочника, на который ссылается реквизит (подобная техника широко применяется, например, в правилах обмена Комплексная автоматизация 2.5 -> WMS 5).
  2. В ПКО основного объекта (ПВХ) для свойства ГруппаФинансовогоУчета явно указать это правило конвертации.

Если вам не нужно переносить весь справочник-ссылку целиком, а достаточно найти его по полям поиска (например, по коду или наименованию), убедитесь, что в правиле для этого справочника настроена синхронизация полей.

Проблема 2: Группы создаются как элементы

Это классическая проблема при переносе иерархических объектов. Вы выгружаете иерархию, свойство ЭтоГруппа стоит в значении Истина, но в базе-приемнике создается обычный элемент, а не папка.

Причина: Платформа 1С создает объект в базе-приемнике до того, как будут прочитаны все его свойства. По умолчанию для иерархических справочников и ПВХ создается элемент. Если свойство ЭтоГруппа обрабатывается после создания объекта, изменить тип существующего объекта с элемента на группу программно бывает проблематично или невозможно без специального режима загрузки.

Решение 1 (Настройка полей поиска):

Самый простой и действенный способ, найденный на практике — заставить систему учитывать признак группы на этапе идентификации объекта. Для этого в Правилах конвертации свойств (ПКС) необходимо установить флаг "Поиск" для следующих свойств:

Когда флаг поиска установлен на ЭтоГруппа, обработка загрузки считывает это свойство одним из первых, чтобы найти объект. Если объект не найден и создается новый, система уже знает значение этого свойства и корректно инициализирует его как группу.

Решение 2 (Разделение правил):

Более "академичный" подход — создать два разных ПКО:

  1. ПВХ_СтатьиДоходов_Элемент
  2. ПВХ_СтатьиДоходов_Группа

В ПВД (Правиле выгрузки данных) в обработчике ПередВыгрузкой прописать условие:


Если Объект.ЭтоГруппа Тогда
    ИмяПКО = "ПВХ_СтатьиДоходов_Группа";
Иначе
    ИмяПКО = "ПВХ_СтатьиДоходов_Элемент";
КонецЕсли;

В ПКО для группы свойство ЭтоГруппа можно вообще не брать из источника, а задать жестко как константу true (отключить флаг "Получить из входящих данных"). Однако на практике Решение 1 работает быстрее и проще в настройке.

Проблема 3: Перенос свойства "ТипЗначения" (ОписаниеТипов)

У Планов Видов Характеристик есть стандартный реквизит ТипЗначения, который хранит объект метаданных ОписаниеТипов. Это сложный тип, который описывает, значения каких типов могут храниться в характеристике.

При стандартной генерации правил конвертации это свойство описывается так:


<Свойство Имя="ТипЗначения" Тип="ОпределениеТипа">
    <Пусто/>

При загрузке это вызывает ошибку, так как стандартные обработки обмена (особенно старых форматов XML) часто не умеют корректно десериализовать ОпределениеТипа "из коробки" без дополнительных манипуляций, либо структура XML не соответствует ожиданиям приемника.

Способ решения через модификацию обработки (для опытных разработчиков)

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

Шаг 1. На стороне отправителя (в правилах выгрузки)

Мы не можем просто выгрузить объект ОписаниеТипов. Нам нужно передать его строковое представление или идентифицируемые значения. В ПКС для свойства ТипЗначения в обработчике ПередВыгрузкой можно сформировать список типов, которые допустимы в вашей конфигурации, и передать конкретный тип, если он совпадает.

Пример кода для ПКС ТипЗначения (Источник):


// Создаем список всех возможных типов, которые мы ожидаем
СписокТиповЗначений = Новый СписокЗначений;
СписокТиповЗначений.Добавить("СправочникСсылка.Организации");
СписокТиповЗначений.Добавить("СправочникСсылка.Номенклатура");
СписокТиповЗначений.Добавить("СправочникСсылка.Контрагенты");
// ... добавляем другие необходимые типы

Значение = Неопределено;

// Проверяем, содержит ли ТипЗначения источника один из наших типов
Для Каждого ЭлементСписка Из СписокТиповЗначений Цикл
    // Важно: Тип() принимает имя типа строкой
    Если Источник.ТипЗначения.СодержитТип(Тип(ЭлементСписка.Значение)) Тогда
        Значение = ЭлементСписка.Значение; // Передаем строку, например "СправочникСсылка.Номенклатура"
        Прервать;
    КонецЕсли;
КонецЦикла;

Этот код найдет первый подходящий тип и передаст его строку-идентификатор. Внимание: этот метод упрощенный, он предполагает, что в ПВХ выбран один конкретный тип, а не составной. Для составных типов логику нужно усложнять (передавать массив строк).

Шаг 2. На стороне получателя (модификация обработки загрузки)

Стандартная функция чтения свойства в обработке обмена может падать на типе ОпределениеТипа. Необходимо перехватить чтение этого свойства.

В функции чтения объекта (обычно это ПрочитатьОбъект или аналог в модуле обработки обмена) нужно добавить обработку спец. типа. Если пришедшее значение — это строка с именем типа (которую мы сформировали выше), ее нужно превратить обратно в ОписаниеТипов.


// Фрагмент модифицированной функции загрузки
ТипСвойства = ПолучитьТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, Имя);
Значение    = ПрочитатьСвойство(ТипСвойства, ИмяПКО);

// Добавляем проверку для нашего случая
Если Имя = "ТипЗначения" И ТипЗнч(Значение) = Тип("Строка") Тогда
    // Пытаемся создать ОписаниеТипов из строки
    Попытка
        МассивТипов = Новый Массив;
        МассивТипов.Добавить(Тип(Значение));
        Значение = Новый ОписаниеТипов(МассивТипов);
    Исключение
        // Если тип не найден в этой базе
        Значение = Новый ОписаниеТипов("Строка"); // Fallback
    КонецПопытки;
КонецЕсли;

Альтернативный (архитектурно правильный) подход

Править код типовых обработок — плохая практика, так как при обновлении изменения пропадут. В "Конвертации данных 2.1" и совместимых режимах КД 3.0 существует паттерн передачи сложных типов через строки без изменения движка.

Алгоритм действий:

  1. В ПКО свойства ТипЗначения отключить флаг "Из источника".
  2. В обработчике ПередВыгрузкой преобразовать Источник.ТипЗначения в строку (или список строк через запятую), используя внутренние имена метаданных. Присвоить это переменной Значение.
  3. В обработчике ПослеЗагрузки на стороне приемника взять полученную строку, разобрать её и сконструировать новый объект ОписаниеТипов.
  4. Присвоить полученный объект в Объект.ТипЗначения.

Пример кода для обработчика ПослеЗагрузки (в правилах):


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

Такой подход делает правила универсальными и не требует вмешательства в код обработок загрузки.

Резюме

Для успешного переноса ПВХ "Статьи доходов" между идентичными базами необходимо:

← На главную