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

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

При настройке обмена данными между конфигурациями «Управление торговлей 10.3» и «Розница 1.0» разработчики часто сталкиваются с необходимостью переноса сложных иерархических структур. Типичный пример — перенос серий номенклатуры из источника (УТ) в серийные номера приемника (Розница) с одновременной генерацией или переносом штрихкодов в регистр сведений Штрихкоды.

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

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

Почему возникает ошибка «Объект не найден» при записи штрихкода?

Давайте проанализируем стандартный жизненный цикл объекта при загрузке через КД 2.1. Когда XML-пакет читается обработчиком загрузки, для каждого объекта создается программный экземпляр в оперативной памяти:

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

Если мы пытаемся в обработчике «После загрузки» обратиться к регистру сведений Штрихкоды и выполнить запись с отбором по Объект.Ссылка, платформа выдает ошибку либо создает пустую запись. Набор записей не может быть привязан к ссылке, которой физически не существует в СУБД на шаге 4. Для решения этой проблемы рассмотрим два метода.

Способ 1. Принудительная запись объекта в обработчике «После загрузки»

Это самый быстрый и простой способ решения проблемы «в лоб». Мы принудительно записываем новый серийный номер в базу данных непосредственно перед тем, как начнется работа с регистром сведений Штрихкоды. Таким образом, к моменту создания набора записей ссылка на владельца гарантированно существует.

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


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

// Теперь ссылка гарантированно существует в СУБД.
// Создаем набор записей регистра сведений "Штрихкоды" с отбором по нашему объекту.
НаборЗаписей = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Владелец.Установить(Объект.Ссылка);
НаборЗаписей.Прочитать();

Если НаборЗаписей.Количество() = 0 Тогда
    // Если штрихкода еще нет, добавляем новую запись
    НовыйНомер = НаборЗаписей.Добавить();
    НовыйНомер.Владелец = Объект.Ссылка; // Указываем владельца
    НовыйНомер.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.Code39; // Указываем тип штрихкода
    НовыйНомер.ШтрихКод = Объект.КодСерийногоНомера; // Переносим код штрихкода
    НаборЗаписей.Записать();
ИначеЕсли НаборЗаписей.Количество() = 1 Тогда
    // Если запись уже есть, обновляем значение штрихкода при необходимости
    НовыйНомер = НаборЗаписей[0];
    НовыйНомер.ШтрихКод = Объект.КодСерийногоНомера;
    НаборЗаписей.Записать();
КонецЕсли;

Преимущества метода: Простота реализации, весь код сосредоточен в одном обработчике ПКО.

Недостатки метода: Нарушается транзакционность загрузки КД. Принудительная запись объектов в обход штатного механизма КД может приводить к снижению скорости загрузки при больших объемах данных.

Способ 2. Декларативный метод с использованием ПКО и входящих данных (Рекомендуемый)

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

Выполним настройку по шагам:

Шаг 1. Создание ПКО для регистра сведений «Штрихкоды»

Создадим новое правило конвертации объектов (ПКО):

  1. Источник: Оставьте пустым (не указывайте объект источника).
  2. Приемник: Выберите РегистрСведенийСсылка.Штрихкоды.
  3. Назовем это ПКО, например, ШтрихкодыСерийныхНомеров.
  4. В таблице свойств (ПКС) добавьте три реквизита: Владелец, Штрихкод, ТипШтрихкода.
  5. Для каждого из этих свойств установите флаг «Получить из входящих данных».
  6. Для свойства Владелец укажите правило конвертации (ПКО) — то самое ПКО, которое конвертирует серии номенклатуры источника в серийные номера приемника (например, ПКО СерииНоменклатуры_СерийныеНомера).

Шаг 2. Выгрузка данных из источника через ПВД или обработчик ПКО

Теперь нам нужно инициировать выгрузку записи регистра. Сделать это лучше всего в обработчике «После выгрузки» ПКО СерииНоменклатуры_СерийныеНомера справочника-источника. Напишем алгоритм, который находит штрихкод серии в источнике и передает его в приемник через наше новое ПКО регистра:


// Выбираем штрихкод серии номенклатуры из регистра базы-источника (УТ)
Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	Штрихкоды.Штрихкод КАК Штрихкод,
|	Штрихкоды.ТипШтрихкода КАК ТипШтрихкода
|ИЗ
|	РегистрСведений.Штрихкоды КАК Штрихкоды
|ГДЕ
|	Штрихкоды.СерияНоменклатуры = &Серия";
Запрос.УстановитьПараметр("Серия", Источник.Ссылка);

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

Особенности для подарочных сертификатов

Если в вашей базе-источнике серии номенклатуры используются в качестве подарочных сертификатов (как описано в Сообщении 7 темы), у них может физически не быть записей в регистре Штрихкоды на стороне УТ. Однако в Рознице 1.0 наличие штрихкода для сертификата является обязательным условием для его корректного считывания на кассе.

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


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

Этот подход гарантирует стабильную загрузку данных без коллизий «незаписанного объекта», сохраняет высокую скорость обмена и позволяет гибко управлять генерацией сопутствующих данных в базе-приемнике.

← На главную