Как правильно реализовать поиск номенклатуры по артикулу в весовом штрихкоде в 1С:Розница 2.2?

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

При автоматизации розничной торговли нередко возникает задача интеграции нестандартных штрихкодов. В типовой конфигурации «1С:Розница 2.2» весовой товар идентифицируется с помощью префикса и кода SKU, однако заказчики часто просят зашивать в штрихкод формата EAN-13 артикул товара вместо кода SKU. Попытка решить эту задачу простой заменой констант в коде приводит к синтаксическим и логическим ошибкам. Разберем по шагам, почему возникает ошибка, как устроена обработка весовых штрихкодов и какими способами можно реализовать требуемый функционал.

Анализ архитектурной ошибки: почему нельзя написать Номенклатура.Артикул

Рассмотрим типовую ситуацию. Разработчик открывает экспортную функцию ПолученШтрихкодИзСШК в модуле обработки подключаемого оборудования и пытается получить артикул следующей конструкцией:

АртикулВесовогоТовара = Номенклатура.Артикул;

При выполнении этого кода система немедленно выдаст ошибку времени выполнения: «Переменная не определена (Номенклатура)». Выясним причину этой ошибки. Проанализируем сигнатуру функции:


Функция ПолученШтрихкодИзСШК(Штрихкод, Форма, СтруктураДействий = Неопределено) Экспорт

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

  1. Сканер считывает физический штрихкод и передает текстовую строку в обработчик.
  2. Функция парсинга разбирает строку на логические составляющие: префикс, идентификатор позиции (код товара) и весовую часть (вес или количество).
  3. По выделенному идентификатору выполняется запрос к базе данных, чтобы найти соответствующую ссылку на элемент справочника Номенклатура.
  4. Найденная номенклатура, характеристика и рассчитанное количество возвращаются в вызывающую форму документа (например, РМК или Чек ККМ).

Попытка обратиться к свойству Номенклатура.Артикул в начале функции нарушает эту причинно-следственную связь: мы пытаемся прочитать реквизит объекта, ссылку на который система еще не нашла.

Ограничения реквизита Артикул при работе со штрихкодами

Прежде чем переходить к доработке кода, обратим внимание на технические особенности реквизита Артикул в типовых конфигурациях 1С:

  1. Строковый тип данных и лидирующие нули. В метаданных реквизит Артикул имеет тип Строка. При разборе штрихкода EAN-13 под артикул выделяется фиксированное количество знаков (например, 5 символов). Если артикул в базе записан без лидирующих нулей (например, «123»), а из штрихкода вырезается подстрока «00123», прямое сравнение строк не найдет совпадения.
  2. Отсутствие контроля уникальности. В отличие от кода справочника или кода SKU, уникальность реквизита Артикул на уровне метаданных не контролируется. Если в базе окажется несколько позиций с одинаковым артикулом, система подставит первую попавшуюся запись, что приведет к пересорту на кассе.
  3. Индексация. Для быстрого поиска при сканировании реквизит должен быть проиндексирован. Если у реквизита Артикул не включена индексация, поиск по нему в базе с десятками тысяч позиций приведет к заметным задержкам на рабочем месте кассира.
  4. Связь с весами с печатью этикеток. Типовой обмен с весами с печатью этикеток в «1С:Розница 2.2» жестко завязан на регистр сведений КодыТоваровSKU. Если переписать разбор штрихкода на кассе под артикул, но не скорректировать логику выгрузки данных в весы, весы продолжат печатать на этикетках коды SKU, и сканер на кассе перестанет их распознавать.

Решение 1. Использование штатного регистра КодыТоваровSKU (рекомендуемый способ)

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

Привязку можно выполнить программно или типовой групповой обработкой. Посмотрим на пример кода, заполняющего регистр для весовой номенклатуры:


НаборЗаписей = РегистрыСведений.КодыТоваровSKU.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Номенклатура.Установить(СсылкаНаНоменклатуру);
НаборЗаписей.Прочитать();

Если НаборЗаписей.Количество() = 0 Тогда
    НоваяЗапись = НаборЗаписей.Добавить();
    НоваяЗапись.Номенклатура = СсылкаНаНоменклатуру;
    НоваяЗапись.SKU = Число(СсылкаНаНоменклатуру.Артикул);
    НаборЗаписей.Записать();
КонецЕсли;

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

Решение 2. Доработка логики разбора штрихкода через запрос к справочнику

Если заказчик настаивает на использовании штрихкода, в котором вместо префикса весового товара сразу идут первые цифры артикула (например, штрихкод начинается строго с цифры «2», а далее следуют 5 символов артикула), потребуется изменить алгоритм разбора штрихкода. Такие доработки рекомендуется выполнять в расширении конфигурации с аннотацией &Вместо, чтобы не снимать конфигурацию с поддержки.

Разберем по шагам логику модифицированного обработчика. Выделим из считанного штрихкода артикул и количество, после чего выполним точечный запрос к справочнику Номенклатура:


// Длина артикула в штрихкоде - 5 символов
// Длина веса - 5 символов (в граммах)
ДлинаАртикула = 5;

// Извлекаем подстроку артикула (начиная со второго символа, если первый - префикс 2)
СтрокаАртикула = Сред(Штрихкод, 2, ДлинаАртикула);

// Извлекаем весовую часть
СтрокаВеса = Сред(Штрихкод, 2 + ДлинаАртикула, 5);
ВесВКг = Число(СтрокаВеса) / 1000;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	Номенклатура.Ссылка КАК Номенклатура,
    |	ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка) КАК Характеристика,
    |	ЗНАЧЕНИЕ(Справочник.УпаковкиНоменклатуры.ПустаяСсылка) КАК Упаковка,
    |	&Количество КАК Количество
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Артикул = &Артикул
    |	И НЕ Номенклатура.ЭтоГруппа";

Запрос.УстановитьПараметр("Артикул", СокрЛП(СтрокаАртикула));
Запрос.УстановитьПараметр("Количество", ВесВКг);

РезультатЗапроса = Запрос.Выполнить();

Рассмотрим, что изменилось в структуре по сравнению с исходным кодом из темы:

  1. Мы больше не обращаемся к несуществующей переменной Номенклатура через точку.
  2. Поиск выполняется запросом по значению, вырезанному из штрихкода строковыми функциями Сред и СокрЛП.
  3. В запросе обязательно используется условие И НЕ Номенклатура.ЭтоГруппа, чтобы исключить случайное попадание на группу справочника.
  4. Результат запроса возвращает структуру полей, идентичную типовой (Номенклатура, Характеристика, Упаковка, Количество), что позволяет передать данные дальше в штатную процедуру ОбщегоНазначенияРТ.ПеренестиСтрокуВыборкиВСтруктуру без дополнительных модификаций.

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

← На главную