Как реализовать сквозную нумерацию документов с разными префиксами в 1С

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

В процессе сопровождения и доработки типовых конфигураций 1С (таких как УПП, Комплексная автоматизация, ERP или Бухгалтерия предприятия) разработчики часто сталкиваются с требованием заказчика или бухгалтерии: организовать сквозную единую нумерацию документов независимо от установленного префикса организации или подразделения. Нередко к этому добавляется требование выводить префиксы в конце номера (например, 00001АМЗ) или разделять номера подразделений через дробь в соответствии с требованиями налоговых органов.

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

Особенности и ограничения штатного механизма нумерации 1С

Проанализируем логику, по которой платформа 1С формирует следующий номер документа при вызове метода УстановитьНовыйНомер() или при интерактивном создании объекта:

  1. Выделение числовой части: Платформа сканирует строку номера справа налево до первого нечислового символа. Все символы слева считаются префиксом, а числовая последовательность справа — инкрементируемым счетчиком.
  2. Изоляция цепочек нумерации: Если у документов разные символьные префиксы (например, АМЗ0001 и ОП0001), платформа воспринимает их как две абсолютно независимые последовательности. Сквозной инкремент между ними встроенными средствами невозможен.
  3. Проблема суффиксов (символов в конце строки): Если перенести префикс или буквенно-цифровой код в конец номера (например, 00001АМЗ), платформа не найдет числовой части справа, и автоматическая нумерация перестанет работать корректно — новые документы будут создаваться с одним и тем же номером или сбрасываться в начало.

Вариант 1. Разделение системного номера и номера для печати (Рекомендуемый)

Выясним причину большинства подобных требований: чаще всего сквозная нумерация и специфический формат требуются для регламентированных печатных форм (счет-фактура, ТОРГ-12, УПД) согласно Постановлению Правительства РФ № 1137, тогда как внутри базы данных документу достаточно иметь уникальный системный идентификатор.

Рассмотрим реализацию через разделение: системный номер формируется стандартными средствами платформы (что гарантирует высокую скорость записи и отсутствие блокировок), а преобразование в нужный формат выполняется исключительно в момент формирования печатной формы или выгрузки в ЭДО.

Разберем пример функции преобразования номера для печатной формы:


Функция СформироватьНомерДляПечати(ИсходныйНомер, ПрефиксОрганизации = "", КодПодразделения = "") Экспорт

    // 1. Очищаем номер от типовых лидирующих нулей и служебных префиксов
    НомерБезПрефикса = СокрЛП(ИсходныйНомер);
    Если Не ПустаяСтрока(ПрефиксОрганизации) И Найти(НомерБезПрефикса, ПрефиксОрганизации) = 1 Тогда
        НомерБезПрефикса = Сред(НомерБезПрефикса, СтрДлина(ПрефиксОрганизации) + 1);
    КонецЕсли;
    
    // Удаляем ведущие нули
    Пока Лев(НомерБезПрефикса, 1) = "0" И СтрДлина(НомерБезПрефикса) > 1 Цикл
        НомерБезПрефикса = Сред(НомерБезПрефикса, 2);
    КонецЦикла;
    
    // 2. Формируем номер по требованию (например, перенос префикса в конец или добавление дроби)
    Результат = НомерБезПрефикса;
    Если Не ПустаяСтрока(КодПодразделения) Тогда
        Результат = Результат + "/" + СокрЛП(КодПодразделения);
    КонецЕсли;
    
    Если Не ПустаяСтрока(ПрефиксОрганизации) Тогда
        Результат = Результат + ПрефиксОрганизации;
    КонецЕсли;
    
    Возврат Результат;

КонецФункции

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

Вариант 2. Отключение префиксов подразделений

Если задача заключается в обеспечении единой сквозной нумерации по организации в целом, а разделение нумерации происходило из-за заполненных префиксов в справочнике Подразделения, проанализируем типовые настройки:

  1. Перейдем в справочник Подразделения (или ПодразделенияОрганизаций).
  2. Очистим реквизит Префикс у подразделений, для которых не требуется отдельная независимая цепочка номеров.
  3. В обработчике подписки на событие или в процедуре ПриУстановкеНовогоНомера проверим, чтобы в формировании префикса участвовал только префикс самой организации.

После очистки префиксов подразделений платформа автоматически продолжит единую сквозную нумерацию документов в разрезе организации.

Вариант 3. Использование собственного счетчика на базе регистра сведений

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

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

  1. Создаем непериодический регистр сведений НумерацияДокументов с измерениями Организация, ТипДокумента, ПериодНумерации (Год) и ресурсом ТекущийНомер (Число).
  2. В обработчике ПередЗаписью документа в транзакции выполняем блокировку записи регистра, считываем значение, увеличиваем его на единицу и формируем строковый номер документа.

Разберем пример кода генерации номера в модуле объекта:


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

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

← На главную