При разработке или доработке справочников в платформе «1С:Предприятие» разработчики нередко сталкиваются с ситуацией, когда системная автонумерация начинает работать со странным шагом: каждый новый элемент получает код через один от предыдущего (например, 000000144, 000000146, 000000148). При этом в модулях объекта и подписках на события может не быть никакого явного кода генерации номера, а замер производительности показывает чистое выполнение стандартных механизмов записи. Разберем детально механику возникновения этой ошибки и выясним, как вернуть корректную последовательную нумерацию.
Чтобы понять суть сбоя, проанализируем, как платформа «1С:Предприятие» управляет последовательностями номеров. За генерацию кодов отвечает внутренний системный механизм — Менеджер автонумерации. Он выделяет номера из системного пула и кеширует их на сервере.
Шаг через единицу (+2 к каждому новому записанному элементу) возникает из-за двойного запроса номера за один цикл создания и сохранения объекта:
Автонумерация. При интерактивном открытии окна создания нового элемента форма сразу обращается к менеджеру автонумерации и резервирует очередной номер (например, 000000145).Объект.Код в управляемых формах или к Код в обычных формах) либо код программно очищается перед записью, то к моменту начала транзакции записи реквизит объекта остается пустым (Код = "").РежимАвтонумерацииОбъектов по умолчанию имеет значение НеОсвобождатьАвтоматически, первый выданный номер (000000145) не возвращается обратно в пул и навсегда теряется. В результате каждый новый записанный элемент получает номер через один.Самое быстрое и правильное решение в описанной ситуации — отключить предварительное резервирование кода формой:
После отключения этого свойства номер не будет генерироваться заранее при открытии формы элемента. Платформа назначит код один-единственный раз — непосредственно в момент записи объекта в базу данных.
Если по бизнес-логике требуется, чтобы пользователь видел новый код сразу в момент открытия формы, необходимо гарантировать корректную передачу полученного номера в реквизиты объекта:
Объект.Код. Для обычных форм в свойстве Данные должно стоять Код.ПередЗаписью или ПередЗаписьюНаСервере нет алгоритмов, которые затирают или обнуляют значение реквизита кода.Еще одна распространенная причина перескакивания номеров — ошибка в обработчике события ПриУстановкеНовогоКода в модуле объекта справочника. Если разработчик программно вызывает метод генерации номера, но забывает отключить штатный механизм, платформа выполняет автонумерацию повторно.
Посмотрим на пример правильного оформления данного события:
Процедура ПриУстановкеНовогоКода(СтандартнаяОбработка, Префикс)
// Если мы формируем код вручную или вызываем метод УстановитьНовыйКод:
Префикс = "ОС-";
// Если требуется полностью переопределить генерацию кода:
// ЭтотОбъект.УстановитьНовыйКод(Префикс);
// СтандартнаяОбработка = Ложь; // Обязательно отключаем штатный вызов!
КонецПроцедуры
Если строка СтандартнаяОбработка = Ложь; отсутствует при программном вызове метода УстановитьНовыйКод(), произойдет ровно такое же задвоение инкремента счетчика.
Если после устранения причин нумерация продолжает идти со смещением или в последовательности образовались «дыры» из-за закешированных пулов, выполним сброс механизма нумерации. Для этого запустим процедуру обновления пространства номеров:
ОбновитьНумерациюОбъектов(Метаданные.Справочники.ОсновныеСредства);
Вызов метода ОбновитьНумерациюОбъектов сбрасует серверный счетчик и актуализирует его по реальному максимальному коду, записанному в таблице базы данных. Обратите внимание: выполнение данного метода доступно только пользователям с административными правами.