Как перенести единицы измерения номенклатуры и штрихкоды в Конвертации данных 2.1?

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

При настройке правил обмена в конфигурации «Конвертация данных 2.1» разработчики часто сталкиваются с ситуацией, когда данные справочника переносятся частично. Типичный пример — перенос справочника Номенклатура, у которого реквизиты ЕдиницаХраненияОстатков и ЕдиницаДляОтчетов остаются пустыми в базе-приемнике, несмотря на то, что подчиненный справочник ЕдиницыИзмерения успешно выгружается. Вторая сопутствующая задача — необходимость перенести связанные с товаром записи регистра сведений Штрихкоды, которые не переносятся по стандартным ссылкам из табличных частей документов.

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

Почему не заполняются единицы измерения: анализ циклической зависимости

Проанализируем механику работы универсального обмена. В типовых конфигурациях 1С элемент справочника ЕдиницыИзмерения подчинен конкретной номенклатуре через реквизит Владелец. В то же время сам элемент номенклатуры ссылается на единицы измерения в своих реквизитах ЕдиницаХраненияОстатков и ЕдиницаДляОтчетов.

Возникает классическая циклическая зависимость:

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

Кроме того, при обмене данными через универсальную обработку загрузка выполняется с установленным свойством ОбменДанными.Загрузка = Истина. Это отключает типовые прикладные обработчики событий конфигурации (например, ПередЗаписью или ПриЗаписи), которые при интерактивной работе пользователя автоматически создают базовую единицу измерения и подставляют ее в реквизиты новой карточки товара.

Способ 1. Устранение циклической ссылки через обработчик «ПослеЗагрузки»

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

Суть подхода заключается в том, чтобы не передавать реквизиты ЕдиницаХраненияОстатков и ЕдиницаДляОтчетов напрямую из базы-источника, а заполнять их уже после того, как номенклатура и все ее подчиненные единицы записаны в приемнике.

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

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

Такой алгоритм гарантирует, что реквизиты будут связаны с корректным элементом подчиненного справочника без риска зацикливания механизма обмена.

Способ 2. Контроль выгрузки владельца перед выгрузкой единицы

Другой вариант решения — принудительно выгрузить объект-владелец в тот момент, когда алгоритм обращается к выгрузке единицы измерения. Выясним, как это реализовать программно.

В ПКО ЕдиницыИзмерения в обработчике ПередВыгрузкой добавим проверку коллекции уже выгруженных объектов правила Номенклатура:


Если Правила.Номенклатура.Выгруженные[Источник.Владелец] = Неопределено Тогда
    ВыгрузитьПоПравилу(Источник.Владелец);
КонецЕсли;

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

Способ 3. Использование механизма «Входящие данные» и разделение ПКО

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

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

Чтобы исключить эту ошибку, разделим правила на два сценария:

  1. Создаем два независимых ПКО для справочника ЕдиницыИзмерения:
    • Основное ПКО: применяется для стандартной выгрузки по ссылкам из документов. Поля поиска: Владелец и классификатор единицы.
    • Вспомогательное ПКО: применяется только в ПКС ЕдиницаХраненияОстатков справочника Номенклатура. В нем для поля Владелец включается флаг «Получить из входящих данных».
  2. Либо в едином ПКО в ПКС для свойства Владелец в обработчике ПередВыгрузкой добавляем безопасную проверку наличия структуры:

Если ВходящиеДанные = Неопределено Тогда
    Значение = Источник.Владелец;
Иначе
    Значение = ВходящиеДанные.Владелец;
КонецЕсли;

Перенос записей регистра сведений «Штрихкоды»

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

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


Если Не Источник.ЭтоГруппа Тогда
    ОтборПоВладельцу = Новый Структура("Владелец");
    ОтборПоВладельцу.Владелец = Источник;
    
    Выборка = РегистрыСведений.Штрихкоды.Выбрать(ОтборПоВладельцу);
    Пока Выборка.Следующий() Цикл
        ВыгрузитьПоПравилу(Выборка, , , , "Штрихкоды");
    КонецЦикла;
КонецЕсли;

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

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

← На главную