1С нет свободных кодов весовых штрихкодов
2024-01-24
Эта статья актуальна для конфигураций 1C Управление торговлей и Комплексная автоматизация.
Многие магазины используют весы с печатью этикеток для фасовки товаров типа конфет, печенья, заморозки и т.п. Это удобно, т.к. на кассе, кассиру не нужно вводить штрихкод и отдельно взвешивать товар, это очень ускоряет обслуживание.
Если магазин большой или это сеть магазинов, то, со временем, количество весовых товаров может перевалить за 10000, и тогда 1С больше не сможет выгрузить товары в весы. Дело в том, что каждый весовой товар имеет свой уникальный штрихкод в котором зашифрован префикс, код и вес. Стандартная длина штрихкода 13 символов, формула штрихкода такая - 23УТТТТВВВВВК:
23 - префикс штрихкода;
У - код узла;
ТТТТ - код товара;
ВВВВВ - вес товара;
К - контрольное число;
В 1С весовые штрихкоды хранятся в таком виде - 2_0000100000_.
Как понятно из формулы - код товара состоит из четырех цифр, а значит максимум составляет 9999. В большинстве случаев этого достаточно и очень редко весовых товаров может быть больше 10000, но как я уже говорил, что со временем, они могут накопиться. Самое интересное в этом то, что даже удаление устаревших товаров и штрихкодов не поможет в этом случае, потому что 1С просто берет максимальный код и сравнивает его с предельным значением.
На скриншоте выше, видно, что есть 1207 свободных кодов между 2_0878700000_ и 2_0999500000_, но 1С не будет пользоваться этим свободным диапазоном, а забьет свободные коды между 2_0999500000_ и 2_0999900000_, и когда она это сделает, то сформировать новые коды больше не получится.
Почему не хватает штрихкодов?
При выгрузке на весы, 1С формирует штрихкоды по порядку.
Разберем ситуацию: сеть магазинов работает более 10 лет. За это время в базе накопилось много устаревшей номенклатуры. По мере необходимости базу сворачивали и удаляли неиспользуемую номенклатуру вместе со штрихкодами, следовательно, некоторые штрихкоды освободились. И теперь мы имеем список штрихкодов, со свободными кодами не в конце(т.к. последние пришедшие товары их заняли), а внутри всего списка.
Видимо по логике разработчиков 1С такая ситуация или невозможна, или надо просто удалить все штрихкоды и сформировать их заново. Но этот вариант совершенно не приемлем: в магазине могут быть расфасованные товары со старыми этикетками, а после этой процедуры пробить на кассе их не получится.
Идеальным вариантом было бы чтобы 1С искала свободные коды не в конце, а по всему диапазону и занимала бы их.
Решение нехватки штрихкодов
Для решения этой проблемы нужно не просто брать максимальный штрихкод, а нужно найти все свободные штрихкоды и выбрать минимальный.
Функция формирования штрихкодов находится в регистре сведений "Штрихкоды номенклатуры" - ПолучитьМаксимальноеЗначениеКодаВесовыхШтрихкодов().
В нем находится простейший запрос:
"ВЫБРАТЬ | ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод, | ПОДСТРОКА(ШтрихкодыНоменклатуры.Штрихкод, 4, 4) КАК КодСтрока |ИЗ | РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры |ГДЕ | ШтрихкодыНоменклатуры.Штрихкод ПОДОБНО ""2_#ПрефиксУзла#____00000_"" | |УПОРЯДОЧИТЬ ПО | КодСтрока УБЫВ";
Нам же надо совсем другое: нужно получить все штрихкоды и вычесть их пула кодов от 0000 до 9999.
В общем, сначала формируем таблицу значений от 0000 до 9999, потом запросом вытаскиваем ее во временную таблицу, потом в другую временную таблицу выбираем все занятые штрихкоды, и третьим этапом объединяем таблицы и выбираем те коды, которых нет во второй.
Функция ПолучитьМаксимальноеЗначениеКодаВесовыхШтрихкодов() ТЗ = Новый ТаблицаЗначений; ТЗ.Колонки.Добавить("КодСтрока",Новый ОписаниеТипов("Строка",,,,Новый КвалификаторыСтроки(4,ДопустимаяДлина.Фиксированная))); Номер = 1; Пока Номер < 10000 Цикл НоваяСтрока = ТЗ.Добавить(); НоваяСтрока.КодСтрока = Формат(Номер, "ЧЦ=4; ЧВН=; ЧГ=0"); Номер = Номер + 1; КонецЦикла; ПрефиксУзла = Строка(Константы.ПрефиксШтрихкодовУзлаРИБ.Получить()); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ * |ПОМЕСТИТЬ ВТРядЧисел |ИЗ |&РядЧисел КАК РядЧисел; |// |ВЫБРАТЬ | ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод, | ПОДСТРОКА(ШтрихкодыНоменклатуры.Штрихкод, 4, 4) КАК КодСтрока |ПОМЕСТИТЬ ВТЗанятыеШК |ИЗ | РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры |ГДЕ | ШтрихкодыНоменклатуры.Штрихкод ПОДОБНО ""2_#ПрефиксУзла#____00000_"" ; | |// |ВЫБРАТЬ ПЕРВЫЕ 1 * |ИЗ |ВТРядЧисел КАК РядЧисел |ЛЕВОЕ СОЕДИНЕНИЕ |ВТЗанятыеШК КАК ЗанятыеШК |ПО РядЧисел.КодСтрока = ЗанятыеШК.КодСтрока |ГДЕ ЗанятыеШК.КодСтрока is NULL |УПОРЯДОЧИТЬ ПО |РядЧисел.КодСтрока |"; Запрос.Текст = СтрЗаменить(Запрос.Текст, "#ПрефиксУзла#", ПрефиксУзла); Запрос.УстановитьПараметр("РядЧисел", ТЗ); РезультатЗапроса = Запрос.Выполнить(); ОписаниеТипаЧисла = ОбщегоНазначения.ОписаниеТипаЧисло(15, 0); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); СвободныйКод = Новый Массив; Пока ВыборкаДетальныеЗаписи.Следующий() Цикл Возврат ОписаниеТипаЧисла.ПривестиЗначение(ВыборкаДетальныеЗаписи.КодСтрока) - 1; КонецЦикла; Возврат Неопределено; КонецФункции
Но и это еще не все, еще нужно изменить функцию в общем модуле ПодключаемоеОборудованиеOfflineВызовСервера - ДанныеТоваровДляВыгрузки.
Там формируются и записываются штрихкоды, причем берется самый последний и записывается следующий, нам же надо перед формированием штрихкода вызывать ранее измененную функцию и каждый раз получать новый свободный штрихкод. Для этого нужно изменить одну строчку:
МаксимальноеЗначениеКодаВесовыхШтрихкодов = МаксимальноеЗначениеКодаВесовыхШтрихкодов + 1; Заменяем на МаксимальноеЗначениеКодаВесовыхШтрихкодов = РегистрыСведений.ШтрихкодыНоменклатуры.ПолучитьМаксимальноеЗначениеКодаВесовыхШтрихкодов() + 1;
Конечно же, для удобства, я оформил эту функцию в виде расширения конфигурации.