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;
Конечно же, для удобства, я оформил эту функцию в виде расширения конфигурации.
