Как исправить сбившуюся нумерацию документов в 1С при использовании кастомных префиксов и РИБ?

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

Рано или поздно любой администратор или разработчик 1С сталкивается с ситуацией, когда пользователи начинают жаловаться на ошибку «Номер не уникален» при создании новых документов. В типовых конфигурациях автонумерация работает исправно до тех пор, пока в процесс не вмешивается человеческий фактор. Достаточно одному сотруднику вручную отредактировать номер, удалив лидирующие нули или случайно изменив префикс, как весь отлаженный механизм автоматического присвоения номеров выходит из строя.

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

Выясняем причину: почему сбивается автонумерация в 1С?

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

Логика работы ломается в следующих случаях:

  1. Удаление лидирующих нулей. Платформа рассчитывает на фиксированную длину номера (например, 11 символов для формата 00000000001). Если пользователь вручную сохраняет документ с номером 1 или 99, платформа при поиске максимального номера сравнивает первый символ строки. Символ «9» лексикографически больше, чем символ «0». Соответственно, короткий номер 9 система посчитает максимальным и попытается создать следующий документ с номером 10. Как только нумерация дойдет до 99, система упрется в предел разрядности и начнет выдавать ошибку уникальности.
  2. Разные раскладки в префиксах. Пользователи часто путают латинскую букву «C» и кириллическую «С». Для платформы это два абсолютно разных символа, из-за чего в базе начинают параллельно развиваться две независимые ветки нумерации с одинаковыми на первый взгляд префиксами.
  3. Использование некорректных символов. Ручной ввод дефисов, пробелов или спецсимволов гарантированно ломает алгоритм автоинкремента платформы.

Особенности и критические риски при работе в РИБ

Ситуация значительно усложняется, если пользователи работают в распределенной информационной базе (РИБ), а в системе реализован нетиповой механизм префиксации (например, подстановка префикса подразделения из настроек пользователя вместо префикса узла РИБ). В этом случае использование стандартных групповых обработок «в лоб» несет огромные риски:

  1. Конфликты синхронизации. Если запустить массовую автоматическую перенумерацию документов в одном из периферийных узлов РИБ при активном обмене данными, измененные документы мигрируют в другие узлы. Это вызовет массовое задвоение номеров и заблокирует регистрацию изменений.
  2. Уничтожение кастомных префиксов. Стандартные перенумераторы ориентируются исключительно на стандартные префиксы организаций и узлов. Если запустить их без предварительной подготовки, они перезапишут номера по общему шаблону, полностью стерев префиксы подразделений, которые были внедрены для удобства пользователей.

Поэтому перед началом любых работ по исправлению номеров необходимо полностью приостановить обмены данными в РИБ до завершения процесса перенумерации во всех базах!

Способ 1. Восстановление нумерации встроенными инструментами 1С

Если сбой произошел в типовой конфигурации и объем документов относительно небольшой, мы можем обойтись без написания кода, используя стандартный функционал:

  1. Экспресс-проверка ведения учета. Перейдем в раздел Отчеты — Анализ учета — Экспресс-проверка. Данный отчет позволяет быстро выявить нарушения хронологии и уникальности номеров в кассовых документах (ПКО и РКО) и счетах-фактурах. Прямо из отчета можно запустить штатную обработку перенумерации.
  2. Групповое изменение реквизитов. Это универсальный инструмент, который позволяет исправить номера пакетом. Для этого выполним следующие шаги:
    • Запустим обработку «Групповое изменение реквизитов».
    • Выберем интересующий нас тип документа и настроим отбор по периоду (например, текущий год).
    • В дополнительных параметрах обработки включим отображение служебных реквизитов и режим разработчика.
    • Сначала запишем во все выбранные документы временный пустой номер (или номер, состоящий из нулей).
    • Затем отключим режим разработчика и проведем повторное изменение реквизита Номер, оставив поле пустым. Платформа автоматически сгенерирует новые корректные последовательные номера по порядку дат, начиная с первого свободного.

Способ 2. Программный метод (анализ и исправление)

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

Рассмотрим, как оптимизировать алгоритм анализа документов, предложенный на форуме. Вместо непроизводительной выборки объектов через метод Выбрать() в цикле (который сильно нагружает базу данных), мы применим эффективный запрос к СУБД для группировки и поиска аномалий в длине номеров.

Проанализируем следующий код для анализа базы данных:


Процедура ПроанализироватьДлинуНомеров(ИмяДокумента, ВыбГод)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Ссылка КАК Ссылка,
        |	Номер КАК Номер
        |ИЗ
        |	Документ." + ИмяДокумента + " КАК Док
        |ГДЕ
        |	Дата МЕЖДУ &НачалоПериода И &КонецПериода";
        
    Запрос.УстановитьПараметр("НачалоПериода", НачалоГода(Дата(ВыбГод, 1, 1)));
    Запрос.УстановитьПараметр("КонецПериода", КонецГода(Дата(ВыбГод, 12, 31)));
    
    РезультатЗапроса = Запрос.Выполнить();
    Если РезультатЗапроса.Пустой() Тогда
        Сообщить("Документов типа " + ИмяДокумента + " за " + ВыбГод + " год не найдено.");
        Return;
    КонецЕсли;
    
    Выборка = РезультатЗапроса.Выбрать();
    ОбщееКоличество = Выборка.Количество();
    
    // Используем Соответствие для подсчета количества документов каждой длины
    СтатистикаДлин = Новый Соответствие;
    
    Пока Выборка.Следующий() Цикл
        ДлинаТекущегоНомера = СтрДлина(СокрЛП(Выборка.Номер));
        КоличествоДляДлины = СтатистикаДлин.Получить(ДлинаТекущегоНомера);
        Если КоличествоДляДлины = Неопределено Тогда
            СтатистикаДлин.Вставить(ДлинаТекущегоНомера, 1);
        Иначе
            СтатистикаДлин.Вставить(ДлинаТекущегоНомера, КоличествоДляДлины + 1);
        КонецЕсли;
    КонецЦикла;
    
    Сообщить("--- Анализ документов """ + ИмяДокумента + """ за " + ВыбГод + " год ---");
    Сообщить("Всего найдено документов: " + ОбщееКоличество);
    Для Каждого СтрокаСтатистики Из СтатистикаДлин Цикл
        Сообщить("Документов с длиной номера " + СтрокаСтатистики.Ключ + " симв.: " + СтрокаСтатистики.Значение);
    КонецЦикла;
    
КонецПроцедуры

После того как мы локализовали проблему и определили, какие именно документы имеют некорректную длину номера, мы можем запустить процедуру программного исправления. Чтобы сохранить логику нетиповых префиксов подразделений, мы будем сбрасывать номера документов и вызывать стандартный метод УстановитьНовыйНомер(), который обратится к кастомному алгоритму в модуле объекта.

Рассмотрим по шагам программный алгоритм перенумерации в транзакции:


Процедура ВыполнитьПеренумерацию(ИмяДокумента, НачалоПериода, КонецПериода)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Ссылка КАК Ссылка
        |ИЗ
        |	Документ." + ИмяДокумента + " КАК Док
        |ГДЕ
        |	Дата МЕЖДУ &НачалоПериода И &КонецПериода
        |УПОРЯДОЧИТЬ ПО
        |	Дата Возр";
        
    Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);
    Запрос.УстановитьПараметр("КонецПериода", КонецПериода);
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    НачатьТранзакцию();
    Попытка
        Пока Выборка.Следующий() Цикл
            ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();
            
            // Сбрасываем некорректный номер
            ДокОбъект.Номер = "";
            
            // Метод УстановитьНовыйНомер() автоматически сформирует правильный префикс
            // организации, узла РИБ или подразделения (если это прописано в модуле)
            ДокОбъект.УстановитьНовыйНомер();
            
            ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
        КонецЦикла;
        ЗафиксироватьТранзакцию();
        Сообщить("Перенумерация успешно завершена!");
    Исключение
        ОтменитьТранзакцию();
        ВызватьИсключение "Ошибка перенумерации: " + ОписаниеОшибки();
    КонецПопытки;
    
    // КРИТИЧЕСКИ ВАЖНЫЙ ШАГ: Сброс кэша нумерации на сервере 1С!
    ОбновитьНумерациюОбъектов(Метаданные.Документы[ИмяДокумента]);
    
КонецПроцедуры

Обратите внимание на вызов метода ОбновитьНумерациюОбъектов() в конце процедуры. Платформа 1С кэширует последние выданные номера в оперативной памяти сервера для повышения производительности. Если выполнить перенумерацию документов в базе данных, но не очистить этот кэш, сервер продолжит выдавать новые номера на основе старых «кривых» значений из своей памяти. Метод ОбновитьНумерациюОбъектов() принудительно сбрасывает этот кэш и заставляет систему рассчитать актуальный максимальный номер заново.

Профилактика: как навсегда запретить пользователям ломать нумерацию

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

Для этого мы можем применить один из следующих подходов:

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

← На главную