Как избежать дублирования штрихкодов при одновременной записи документов в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При многопользовательской работе в 1С разработчики часто сталкиваются с ситуацией, когда штрихкод документа формируется в обработчике ПередЗаписью путем поиска максимального значения в регистре сведений с прибавлением единицы (МАКСИМУМ + 1). Если несколько операторов одновременно проводят или записывают документы, система считывает одно и то же значение счетчика для обоих сеансов, что приводит к созданию одинаковых штрихкодов.

Проанализируем причины этой проблемы и разберем несколько надежных способов ее решения: от наложения управляемых блокировок до изменения структуры штрихкода под стандарт EAN-13 с поддержкой распределенных информационных баз (РИБ).

Причины возникновения коллизий на уровне платформы

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

Разберем основные подходы, позволяющие гарантировать уникальность штрихкодов.

Решение 1. Использование управляемой блокировки данных перед вычислением номера

Если требуется сохранить классическую сквозную нумерацию штрихкодов, необходимо защитить операцию чтения и инкремента с помощью объекта БлокировкаДанных в транзакции. Блокировка должна накладываться до момента выполнения запроса на поиск максимума.

Посмотрим на пример реализации алгоритма с наложением исключительной блокировки на ресурс или измерение регистра:


УстановитьПривилегированныйРежим(Истина);
НачатьТранзакцию();

// Устанавливаем управляемую исключительную блокировку
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.Штрихкоды");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();

// Получаем следующий номер
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ЕСТЬNULL(МАКСИМУМ(Штрихкоды.ПорядковыйНомер), 0) + 1 КАК НовыйНомер
    |ИЗ
    |   РегистрСведений.Штрихкоды КАК Штрихкоды";

Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
НовыйНомер = Выборка.НовыйНомер;

// Формируем штрихкод EAN-13 с расчетом контрольного символа
БазовыйШтрихкод = "20" + Формат(НовыйНомер, "ЧЦ=10; ЧВН=; ЧГ=0");
КонтрольныйСимвол = РаботаСТорговымОборудованием.КонтрольныйСимволEAN(БазовыйШтрихкод, 13);
ИтоговыйШтрихкод = БазовыйШтрихкод + КонтрольныйСимвол;

// Записываем полученный штрихкод в регистр
МенеджерЗаписи = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = СсылкаНаДокумент;
МенеджерЗаписи.Штрихкод = ИтоговыйШтрихкод;
МенеджерЗаписи.ПорядковыйНомер = НовыйНомер;
МенеджерЗаписи.Записать();

ЗафиксироватьТранзакцию();

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

Решение 2. Формирование EAN-13 из реквизитов документа без блокировки регистра

Альтернативный метод, исключающий конкуренцию за общую таблицу, — формирование штрихкода на основе уникальных реквизитов самого документа (номера, даты, префикса). Так как стандарт EAN-13 требует ровно 13 цифровых символов (12 информационных разрядов + 1 контрольный), структуру данных необходимо строго распределить по разрядам.

Разберем по шагам логику генерации штрихкода в событии ПередЗаписью:

  1. Проверяем, не был ли штрихкод уже назначен ранее, чтобы избежать его изменения при повторном сохранении документа.
  2. Если документ новый, вызываем платформенный метод УстановитьНовыйНомер() для инициализации номера документа.
  3. Формируем 12-значную цифровую строку, включающую внутренний префикс (например, 20), последние цифры номера документа и метку времени создания.
  4. Вычисляем 13-й символ по алгоритму Modulo 10 (например, через функцию КонтрольныйСимволEAN).

Рассмотрим пример кода:


Если Не ЗначениеЗаполнено(ЭтотОбъект.Штрихкод) Тогда
    Если ЭтотОбъект.ЭтоНовый() И Не ЗначениеЗаполнено(ЭтотОбъект.Номер) Тогда
        ЭтотОбъект.УстановитьНовыйНомер();
    КонецЕсли;
    
    // Получаем последние 5 цифр номера документа
    ЧисловойНомер = СтроковыеФункцииКлиентСервер.ПолучитьСтрокуТолькоСЦифрами(ЭтотОбъект.Номер);
    НомерДляКода = Прав(ЧисловойНомер, 5);
    НомерДляКода = Формат(Число(НомерДляКода), "ЧЦ=5; ЧВН=; ЧГ=0");
    
    // Время создания (ЧЧммсс) - 6 цифр
    ВремяСоздания = Формат(ТекущаяДатаСеанса(), "ДФ=ЧЧммсс");
    
    // Формируем 12 знаков (1 префикс + 5 номер + 6 время)
    БазоваяСтрока = "2" + НомерДляКода + ВремяСоздания;
    
    // Расчет 13-го контрольного символа
    КонтрольныйСимвол = РаботаСТорговымОборудованием.КонтрольныйСимволEAN(БазоваяСтрока, 13);
    ЭтотОбъект.Штрихкод = БазоваяСтрока + КонтрольныйСимвол;
КонецЕсли;

Решение 3. Организация штрихкодирования в распределенных базах (РИБ)

В распределенных информационных базах генерация последовательных номеров в разных узлах неминуемо приведет к коллизиям при синхронизации. Для разделения пространств номеров используется позиционная структура EAN-13 с явным выделением кода узла РИБ:

  1. Разряды 1–2: Префикс внутреннего учета предприятия (диапазон 20–29 по стандарту GS1).
  2. Разряды 3–4: Цифровой код узла РИБ (от 01 до 99). Буквенные префиксы узлов сопоставляются с фиксированными числами.
  3. Разряды 5–12: Локальный порядковый номер документа или счетчик на узле (8 знаков).
  4. Разряд 13: Контрольный символ EAN-13.

Такой подход полностью изолирует нумерацию узлов друг от друга и делает пересечение штрихкодов невозможным.

Решение 4. Использование служебного справочника-нумератора или пула номеров

Для высоконагруженных систем вычисление МАКСИМУМ + 1 по таблицам регистров считается неоптимальным. Выделим две проверенные архитектурные альтернативы:

  1. Служебный справочник: Платформа 1С оптимизирована для автоинкремента кодов справочников. Создание элемента в служебном справочнике (например, СчетчикиШтрихкодов) позволяет получить гарантированно уникальный номер средствами платформы без ручных запросов максимума.
  2. Пул свободных номеров: Регламентное задание заранее генерирует список доступных штрихкодов в буферную таблицу. При проведении документ резервирует первую свободную запись с краткосрочной блокировкой строки, что сводит задержки на запись практически к нулю.

Рекомендации по интеграции

При внедрении штрихкодирования обратите внимание на следующие правила:

  1. Обязательно проверяйте условие Не ЗначениеЗаполнено(ЭтотОбъект.Штрихкод) в обработчике ПередЗаписью, чтобы исключить генерацию нового кода при обычном перепроведении документа.
  2. Не сохраняйте 13-значные штрихкоды EAN без вычисления контрольной суммы, иначе внешние сканеры и терминалы сбора данных откажутся считывать такие коды.
  3. Если жестких ограничений по формату EAN-13 нет, переходите на формат Code 128 или QR-код, которые поддерживают алфавитно-цифровые строки произвольной длины и позволяют кодировать полные уникальные идентификаторы (GUID) документов без риска коллизий.
← На главную