При автоматизации розничной торговли нередко возникает задача интеграции нестандартных штрихкодов. В типовой конфигурации «1С:Розница 2.2» весовой товар идентифицируется с помощью префикса и кода SKU, однако заказчики часто просят зашивать в штрихкод формата EAN-13 артикул товара вместо кода SKU. Попытка решить эту задачу простой заменой констант в коде приводит к синтаксическим и логическим ошибкам. Разберем по шагам, почему возникает ошибка, как устроена обработка весовых штрихкодов и какими способами можно реализовать требуемый функционал.
Рассмотрим типовую ситуацию. Разработчик открывает экспортную функцию ПолученШтрихкодИзСШК в модуле обработки подключаемого оборудования и пытается получить артикул следующей конструкцией:
АртикулВесовогоТовара = Номенклатура.Артикул;
При выполнении этого кода система немедленно выдаст ошибку времени выполнения: «Переменная не определена (Номенклатура)». Выясним причину этой ошибки. Проанализируем сигнатуру функции:
Функция ПолученШтрихкодИзСШК(Штрихкод, Форма, СтруктураДействий = Неопределено) Экспорт
В параметры процедуры передается только считанная сканером строка Штрихкод, ссылка на форму и служебная структура действий. В момент считывания штрихкода система еще ничего не знает о товаре, стоящем за этой строкой. Механизм сканирования работает в строгой последовательности:
Номенклатура.Попытка обратиться к свойству Номенклатура.Артикул в начале функции нарушает эту причинно-следственную связь: мы пытаемся прочитать реквизит объекта, ссылку на который система еще не нашла.
Прежде чем переходить к доработке кода, обратим внимание на технические особенности реквизита Артикул в типовых конфигурациях 1С:
Артикул имеет тип Строка. При разборе штрихкода EAN-13 под артикул выделяется фиксированное количество знаков (например, 5 символов). Если артикул в базе записан без лидирующих нулей (например, «123»), а из штрихкода вырезается подстрока «00123», прямое сравнение строк не найдет совпадения.Артикул на уровне метаданных не контролируется. Если в базе окажется несколько позиций с одинаковым артикулом, система подставит первую попавшуюся запись, что приведет к пересорту на кассе.Артикул не включена индексация, поиск по нему в базе с десятками тысяч позиций приведет к заметным задержкам на рабочем месте кассира.КодыТоваровSKU. Если переписать разбор штрихкода на кассе под артикул, но не скорректировать логику выгрузки данных в весы, весы продолжат печатать на этикетках коды SKU, и сканер на кассе перестанет их распознавать.Самый надежный способ решить задачу заказчика без вмешательства в типовые алгоритмы конфигурации и поломки обновлений — синхронизировать артикул с регистром SKU. Если артикулы весового товара состоят только из цифр и укладываются в диапазон длины SKU (например, 5 знаков), числовое значение артикула можно записать в качестве SKU товара.
Привязку можно выполнить программно или типовой групповой обработкой. Посмотрим на пример кода, заполняющего регистр для весовой номенклатуры:
НаборЗаписей = РегистрыСведений.КодыТоваровSKU.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Номенклатура.Установить(СсылкаНаНоменклатуру);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() = 0 Тогда
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Номенклатура = СсылкаНаНоменклатуру;
НоваяЗапись.SKU = Число(СсылкаНаНоменклатуру.Артикул);
НаборЗаписей.Записать();
КонецЕсли;
В этом случае в штрихкоде продолжает использоваться типовой шаблон: префикс весового товара (например, «2» + константа) + SKU (совпадающий с артикулом) + вес + контрольный символ. Код конфигурации остается типовым, сохраняется корректная выгрузка в торговое оборудование, а штрихкоды стабильно читаются в РМК.
Если заказчик настаивает на использовании штрихкода, в котором вместо префикса весового товара сразу идут первые цифры артикула (например, штрихкод начинается строго с цифры «2», а далее следуют 5 символов артикула), потребуется изменить алгоритм разбора штрихкода. Такие доработки рекомендуется выполнять в расширении конфигурации с аннотацией &Вместо, чтобы не снимать конфигурацию с поддержки.
Разберем по шагам логику модифицированного обработчика. Выделим из считанного штрихкода артикул и количество, после чего выполним точечный запрос к справочнику Номенклатура:
// Длина артикула в штрихкоде - 5 символов
// Длина веса - 5 символов (в граммах)
ДлинаАртикула = 5;
// Извлекаем подстроку артикула (начиная со второго символа, если первый - префикс 2)
СтрокаАртикула = Сред(Штрихкод, 2, ДлинаАртикула);
// Извлекаем весовую часть
СтрокаВеса = Сред(Штрихкод, 2 + ДлинаАртикула, 5);
ВесВКг = Число(СтрокаВеса) / 1000;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Номенклатура,
| ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка) КАК Характеристика,
| ЗНАЧЕНИЕ(Справочник.УпаковкиНоменклатуры.ПустаяСсылка) КАК Упаковка,
| &Количество КАК Количество
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул = &Артикул
| И НЕ Номенклатура.ЭтоГруппа";
Запрос.УстановитьПараметр("Артикул", СокрЛП(СтрокаАртикула));
Запрос.УстановитьПараметр("Количество", ВесВКг);
РезультатЗапроса = Запрос.Выполнить();
Рассмотрим, что изменилось в структуре по сравнению с исходным кодом из темы:
Номенклатура через точку.Сред и СокрЛП.И НЕ Номенклатура.ЭтоГруппа, чтобы исключить случайное попадание на группу справочника.Номенклатура, Характеристика, Упаковка, Количество), что позволяет передать данные дальше в штатную процедуру ОбщегоНазначенияРТ.ПеренестиСтрокуВыборкиВСтруктуру без дополнительных модификаций.Таким образом, для чтения весового товара по артикулу необходимо сначала декомпозировать строку штрихкода на составные части и только затем находить ссылку на товар прямым запросом к справочнику или через заполнение регистра КодыТоваровSKU.