В процессе организации складского учета нередко возникает потребность в коротких, удобных для чтения и поиска артикулах вида «X001», где «X» — буква родительской папки, а «001» — порядковый номер позиции внутри группы. При этом стандартные поля Код и Артикул в справочнике Номенклатура часто уже заняты для синхронизации с бухгалтерскими системами или хранения номеров поставщиков. Разберем, как правильно подойти к решению этой задачи: от использования штатных механизмов конфигурации до надежной программной реализации собственного нумератора.
Прежде чем приступать к доработке конфигурации, проанализируем типовой функционал 1С:Управление торговлей 11. Часто необходимость в создании нового реквизита возникает из-за неоптимального использования стандартных полей.
Артикул занято кодами контрагентов, правильнее использовать штатный справочник НоменклатураКонтрагентов (подсистема «Номенклатура поставщиков»). Перенос информации поставщиков в предназначенную для этого структуру позволяет освободить основной реквизит Артикул для складских нужд предприятия без изменения конфигурации.ШтрихкодыНоменклатуры. Платформа поддерживает генерацию коротких кодов (Code 128, EAN-8), которые без доработок поддерживаются складскими терминалами и шаблонами печати этикеток.Если специфика учета все же требует создания собственного дополнительного реквизита с маской «Символ + Порядковый номер», выясним, с какими подводными камнями сталкивается разработчик.
Часто предлагается вычислять следующий номер простым подсчетом количества элементов в группе через функцию КОЛИЧЕСТВО в запросе. Выясним причину, почему такой подход опасен в рабочей базе:
МАКСИМУМ в языке запросов сравнивает строки лексикографически. Без строгой длины и ведущих нулей строка «X10» окажется меньше строки «X2», что приведет к сбою генерации.Чтобы гарантировать уникальность артикулов в транзакции и избежать коллизий, разберем по шагам создание счетчика на базе независимого регистра сведений в расширении конфигурации.
Создадим регистр сведений НумераторАртикулов со следующей структурой:
Префикс (Тип: Строка, длина 10) — хранит букву группы или ссылку на папку номенклатуры.ТекущийНомер (Тип: Число, длина 10, точность 0).Реализуем процедуру генерации в модуле менеджера или общем серверном модуле. Обязательно установим исключительную управляемую блокировку:
Функция ПолучитьСледующийАртикул(Знач Префикс) Экспорт
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.НумераторАртикулов");
ЭлементБлокировки.УстановитьЗначение("Префикс", Префикс);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
НачатьТранзакцию();
Попытка
Блокировка.Заблокировать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Нумератор.ТекущийНомер КАК ТекущийНомер
|ИЗ
| РегистрСведений.НумераторАртикулов КАК Нумератор
|ГДЕ
| Нумератор.Префикс = &Префикс";
Запрос.УстановитьПараметр("Префикс", Префикс);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
СледующийНомер = Выборка.ТекущийНомер + 1;
Иначе
СледующийНомер = 1;
КонецЕсли;
МенеджерЗаписи = РегистрыСведений.НумераторАртикулов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Префикс = Префикс;
МенеджерЗаписи.ТекущийНомер = СледующийНомер;
МенеджерЗаписи.Записать(Истина);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
// Форматируем число с добавлением ведущих нулей до требуемой длины (например, 3 знака)
СтрокаНомера = Формат(СледующийНомер, "ЧЦ=3; ЧВН=; ЧГ=0");
Возврат Префикс + СтрокаНомера;
КонецФункции
Разберем подключение вызова генерации нового кода через расширение конфигурации. Перехватим обработчик ПередЗаписью справочника Номенклатура.
Проанализируем обязательные проверки, которые необходимо выполнить перед формированием значения:
ЭтоГруппа.ОбменДанными.Загрузка: если выполняется синхронизация с другой базой (например, с 1С:Бухгалтерией), перезаписывать код нельзя.
&Вместо("ПередЗаписью")
Процедура Расш_ПередЗаписью(Отказ)
// Выполняем стандартную логику конфигурации
ПродолжитьВызов(Отказ);
Если Отказ Или ОбменДанными.Загрузка Или ЭтоГруппа Тогда
Возврат;
КонецЕсли;
// Проверяем, является ли элемент новым или реквизит пуст
Если ЭтоНовый() Или ПустаяСтрока(ДополнительныйАртикул) Тогда
ПрефиксГруппы = "";
Если ЗначениеЗаполнено(Родитель) Тогда
ПрефиксГруппы = ВРег(Лев(СокрЛП(Родитель.Наименование), 1));
Иначе
ПрефиксГруппы = "X";
КонецЕсли;
ДополнительныйАртикул = МодульНумерации.ПолучитьСледующийАртикул(ПрефиксГруппы);
КонецЕсли;
КонецПроцедуры
Для первоначальной нумерации 5000 уже созданных позиций напишем внешнюю обработку. Проанализируем алгоритм ее работы:
Номенклатура, сгруппированные по родительским папкам.НумераторАртикулов.Такой подход обеспечивает непрерывность нумерации: существующие позиции получают упорядоченные номера, а все вновь создаваемые элементы продолжают последовательность без риска дублирования.