Как перенести данные из плоского классификатора в подчиненный справочник Единицы Измерения в 1С:Конвертация данных 2.1?

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

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

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

В этой статье мы подробно разберем два надежных способа решения этой задачи: стандартный декларативный метод через использование структуры ИсходящиеДанные и альтернативный программный метод создания подчиненных объектов при загрузке номенклатуры.

Способ 1. Использование механизма ИсходящиеДанные в ПКС и формирование ключа в ПКО

Давайте проанализируем стандартный подход, к которому пришел автор темы на форуме. Суть метода заключается в том, что мы принудительно передаем контекст владельца (номенклатуры) из источника в правило конвертации свойств (ПКС) единицы измерения, используя транзитную структуру параметров.

Разберем этот процесс по шагам.

Шаг 1. Настройка ПКС в объекте-владельце

В правиле конвертации свойств (ПКС) для реквизита ЕдиницаИзмерения (например, внутри табличной части документа или в самом справочнике Номенклатура) перед выгрузкой необходимо сформировать структуру с контекстом. В обработчике «Перед выгрузкой» ПКС пишем следующий код:


ИсходящиеДанные = Новый Структура;
ИсходящиеДанные.Вставить("Владелец", ОбъектКоллекции.Номенклатура);
ИсходящиеДанные.Вставить("Единица", ОбъектКоллекции.ЕдиницаИзмерения);
ИсходящиеДанные.Вставить("Наименование", ОбъектКоллекции.ЕдиницаИзмерения.Наименование);
ИсходящиеДанные.Вставить("Коэффициент", 1);

В данном коде мы упаковываем ссылку на номенклатуру-владельца, саму единицу из классификатора, ее текстовое наименование и коэффициент по умолчанию в структуру ИсходящиеДанные. Эта структура автоматически передается в связанное правило конвертации объектов (ПКО) для единиц измерения.

Шаг 2. Настройка ПКО для подчиненного справочника

Теперь перейдем в ПКО для справочника ЕдиницыИзмерения. Поскольку реального объекта-источника для подчиненного справочника у нас нет (мы передаем только структуру параметров), нам нужно правильно настроить сопоставление выгружаемых данных. Для этого используется обработчик «Перед выгрузкой» в ПКО.

В исходном решении автора использовался следующий код:


КлючВыгружаемыхДанных = ЗначениеВСтрокуВнутр(Источник) + ЗначениеВСтрокуВнутр(ВходящиеДанные.Владелец);

Давайте проанализируем эту строку. Использование функции ЗначениеВСтрокуВнутр для формирования уникального ключа выгрузки действительно решает задачу, но имеет существенные недостатки: снижает общую производительность выгрузки из-за тяжелых операций преобразования типов и неоправданно увеличивает объем итогового XML-файла выгрузки.

Мы рекомендуем использовать более современный и оптимизированный вариант формирования КлючВыгружаемыхДанных через уникальные идентификаторы (UUID):


КлючВыгружаемыхДанных = СокрЛП(Источник.Ссылка.УникальныйИдентификатор()) + "/" + СокрЛП(ВходящиеДанные.Владелец.УникальныйИдентификатор());

Такой составной ключ гарантирует стопроцентную уникальность комбинации «Классификатор + Номенклатура-Владелец», работает мгновенно и занимает минимум места в XML-файле.

Шаг 3. Важные настройки свойств ПКО в Конвертации данных

Чтобы избежать логических ошибок при загрузке данных в базу-приемник, обязательно выполните следующие настройки в ПКО ЕдиницыИзмерения:

  1. Установите флаг «Не запоминать выгруженные объекты». Если этого не сделать, система кэширует первую выгруженную единицу (например, «шт») и при выгрузке последующих товаров с такой же единицей подставит старую ссылку. В результате у разных товаров окажется один и тот же элемент подчиненного справочника, что нарушит целостность базы данных.
  2. На вкладке «Поля поиска» ПКО укажите комбинацию полей: Владелец и ЕдиницаПоКлассификатору (или Наименование). Поиск должен осуществляться строго в контексте владельца.

Способ 2. Программное создание подчиненных единиц на стороне приемника (Рекомендуемый)

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

Давайте рассмотрим этот метод подробнее.

При загрузке номенклатуры в базу-приемник мы можем программно проверить, создана ли для нее соответствующая единица измерения. Если единицы нет, мы создаем ее «на лету» в обработчике «После загрузки» ПКО Номенклатура.

Посмотрим на пример реализации такого кода:


Если НЕ Объект.ЭтоГруппа Тогда
    // Проверяем, создана ли уже подчиненная единица для данного владельца
    ВыборкаЕдиниц = Справочники.ЕдиницыИзмерения.Выбрать(, Объект.Ссылка);
    Если НЕ ВыборкаЕдиниц.Следующий() Тогда
        
        // Создаем новый элемент подчиненного справочника ЕдиницыИзмерения
        НоваяЕд = Справочники.ЕдиницыИзмерения.СоздатьЭлемент();
        НоваяЕд.Владелец = Объект.Ссылка;
        
        // Связываем с классификатором, который был загружен в соответствующий реквизит номенклатуры
        НоваяЕд.ЕдиницаПоКлассификатору = Объект.БазоваяЕдиницаИзмерения; 
        НоваяЕд.Наименование = СокрЛП(Объект.БазоваяЕдиницаИзмерения);
        НоваяЕд.Коэффициент = 1;
        
        // Записываем элемент с отключением лишних бизнес-проверок для ускорения загрузки
        НоваяЕд.ОбменДанными.Загрузка = Истина;
        НоваяЕд.Записать();
        
        // Связываем саму номенклатуру с только что созданной единицей
        Объект.ЕдиницаХраненияОстатков = НоваяЕд.Ссылка;
        Объект.Записать();
        
    КонецЕсли;
КонецЕсли;

Преимущества программного подхода:

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

← На главную