Проблемы с нумерацией в программных продуктах 1С, особенно в таких сложных конфигурациях, как Бухгалтерия государственного учреждения (БГУ), встречаются довольно часто. Ситуация, когда стандартная функция ОбновитьНумерациюОбъектов() не приносит желаемого результата, а новые документы получают номера «с начала» или из глубокого прошлого, может поставить в тупик даже опытного разработчика. В рамках этой статьи мы подробно разберем, как устроена автонумерация, почему порядок строк в коде имеет решающее значение (в чем часто помогает разобраться статический анализатор кода проектов) и как окончательно навести порядок в реестре документов.
Для начала проанализируем, как платформа 1С:Предприятие 8.3 генерирует новый номер. В современных версиях используется механизм автоматического управления номерами. Для повышения производительности система не обращается к базе данных каждый раз, когда пользователю нужно просто открыть форму нового документа. Вместо этого сервер приложений «бронирует» диапазон номеров в кэше.
Однако у этого механизма есть обратная сторона. Если в базе данных появляется документ с номером, нарушающим логику (например, вместо БАБГ-000805 кто-то вручную ввел БАБГ-999999), система может решить, что числовой предел исчерпан. Функция ОбновитьНумерациюОбъектов() призвана сбросить этот кэш и заставить систему заново вычислить максимальный номер, исходя из существующих записей. Но важно понимать: если «кривой» номер физически остается в базе, обновление кэша не поможет — система снова наткнется на него и продолжит выдавать некорректные значения.
Рассмотрим конкретный пример кода, который часто приводит к сбою нумерации. Проанализируем фрагмент, представленный в обсуждении:
// Ошибочный порядок действий
новдок = Документы.ТребованиеНакладная0315006.СоздатьДокумент();
новдок.Организация = Справочники.Организации.НайтиПоКоду("000000001");
новдок.УстановитьНовыйНомер();
новдок.Дата = ТекущаяДата();
Сообщить(новдок.Номер);
На первый взгляд код кажется логичным, но в нем кроется фундаментальная ошибка. В 1С:БГУ нумерация большинства документов является периодической (как правило, в пределах года). Когда мы вызываем метод УстановитьНовыйНомер() до того, как объекту присвоена Дата, система пытается определить номер для пустой даты (01.01.0001).
Поскольку в периоде «начало времен» документов обычно нет, система выдает первый свободный номер, например 000001. Если же разработчик запускал этот код несколько раз, в базе могли появиться «невидимые» записи или записи с пустыми датами, из-за чего счетчик в этом пустом периоде начал расти (например, до 000805), не затрагивая реальную нумерацию текущего года.
Чтобы метод УстановитьНовыйНомер() отработал корректно, необходимо строго соблюдать последовательность инициализации реквизитов, от которых зависит префиксация и периодичность. Разберем исправленный вариант кода:
// Правильный порядок действий
НовыйДокумент = Документы.ТребованиеНакладная0315006.СоздатьДокумент();
// 1. Сначала устанавливаем дату, чтобы определить период нумерации
НовыйДокумент.Дата = ТекущаяДата();
// 2. Устанавливаем организацию, так как от нее зависит префикс номера
НовыйДокумент.Организация = Справочники.Организации.НайтиПоКоду("000000001");
// 3. Только теперь вызываем метод установки номера
НовыйДокумент.УстановитьНовыйНомер();
Сообщить(НовыйДокумент.Номер);
В этом случае система сначала поймет, что номер нужно искать в пределах текущего года и с учетом префикса организации. Только после этого она обратится к базе данных (или кэшу), найдет там последний актуальный номер и инкрементирует его.
Если даже при правильном коде нумерация продолжает сбиваться, значит, в базе данных присутствуют документы, которые «сбивают с толку» алгоритм 1С. Выясним, как их найти и обезвредить:
БАБГ-806 вместо БАБГ-000806), автоматика может сломаться. Система перестает понимать, где заканчивается числовая часть.БАБГ-002679а) гарантированно останавливает автонумерацию.Если вы обнаружили, что нумерация «встала», а документов для исправления слишком много, лучше всего использовать готовую внешнюю обработку для перенумерации документов. Если же вы решили действовать вручную, выполните следующие действия:
Delete для очистки.ОбновитьНумерациюОбъектов(Метаданные.Документы.ТребованиеНакладная0315006) через консоль кода, чтобы очистить серверный кэш.В конфигурациях вроде БГУ за нумерацию часто отвечает не только платформа, но и механизмы Библиотеки стандартных подсистем (БСП). В таких системах работают подписки на события ПриУстановкеНовогоНомера. Чтобы лучше ориентироваться в доступном функционале, рекомендуем использовать справочник по методам БСП с примерами использования.
Если вы программируете в такой среде, помните, что вызов УстановитьНовыйНомер() инициирует выполнение целого каскада процедур в общих модулях. Эти процедуры могут проверять префиксы подразделений или узлов РИБ. Для автоматизации этих процессов можно внедрить расширение, обеспечивающее установку префикса у документов по условию.
Таким образом, секрет стабильной нумерации заключается в трех составляющих: строгий порядок инициализации объекта в коде, отсутствие ручных правок формата номера пользователями и своевременное обновление кэша нумерации при возникновении коллизий.