Ошибка контроля уникальности номера при записи нового документа — одна из наиболее распространенных проблем при работе в программах 1С:Предприятие. Ситуация часто выглядит загадочно: визуально в журнале документов за текущий период последний номер, например, 936, однако платформа при попытке автонумерации не может назначить номер 937 и выдает ошибку о нарушении уникальности.
Разберем по шагам, почему возникает данный сбой, как с помощью отладчика узнать генерируемый программой номер и какими способами можно восстановить корректную автонумерацию.
Проанализируем основные факторы, приводящие к сбою механизма генерации номеров:
936 вместо 0000000936), платформа считает строку 936 старшей по отношению к строке 0000000936 и пытается сформировать следующий номер как 937, что приводит к сбоям длины строки или коллизиям с уже существующими номерами.Нумератор, цепочка номеров становится общей для всех документов этой группы (например, для платежных поручений, платежных ордеров и банковских выписок). В таком случае следующий номер может быть уже занят документом другого вида." 000000936") либо смешение латинских и кириллических букв в префиксах создает отдельную ветку автонумерации.01.01.0001 или будущий год) создает коллизию в соответствующем интервале.При интерактивном создании документа в событиях формы или в обработчике ПередЗаписью свойство Номер часто остается пустым, так как окончательное присвоение номера выполняется платформой непосредственно в момент записи в транзакции. Чтобы точно выяснить, какое значение пытается сгенерировать платформа, вызовем метод принудительной установки номера.
Рассмотрим, как это сделать в отладчике или внешней обработке:
// В обработчике ПередЗаписью модуля объекта или во внешней обработке:
ЭтотОбъект.УстановитьНовыйНомер();
Сообщить("Сгенерированный платформой номер: " + ЭтотОбъект.Номер);
Вызов метода УстановитьНовыйНомер() заполняет свойство Номер строкой, которую система считает следующей по порядку. Это позволяет сразу увидеть, есть ли в номере лишние пробелы, искаженные префиксы или сбитая разрядность.
Выясним, какие документы мешают правильной последовательности. Для этого выполним запрос к таблице документов за проблемный период без наложения фильтров по пометке удаления.
Посмотрим на пример текста запроса:
ВЫБРАТЬ
Док.Ссылка КАК Документ,
Док.Номер КАК Номер,
Док.Дата КАК Дата,
Док.ПометкаУдаления КАК ПометкаУдаления
ИЗ
Документ.ПлатежноеПоручениеИсходящее КАК Док
ГДЕ
Док.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&ДатаНачала, ГОД) И КОНЕЦПЕРИОДА(&ДатаНачала, ГОД)
УПОРЯДОЧИТЬ ПО
Док.Номер УБЫВ
При анализе результатов выборки обратим внимание на следующие моменты:
Если сбойные номера в базе данных были найдены и исправлены вручную (добавлены ведущие нули, удалены лишние пробелы), платформе необходимо дать команду пересчитать внутренние счетчики автонумерации. Для этого предназначен метод глобального контекста ОбновитьНумерациюОбъектов().
Разберем пример кода для обновления нумерации конкретного вида документа:
// Обновление нумерации для конкретного типа документа
ОбновитьНумерациюОбъектов(Метаданные.Документы.ПлатежноеПоручениеИсходящее);
// Если документ привязан к общему нумератору:
// ОбновитьНумерациюОбъектов(Метаданные.Нумераторы.ОсновнойНумератор);
Важно: вызов метода ОбновитьНумерациюОбъектов() без параметров выполняет полное сканирование всех таблиц информационной базы, что может занять много времени на крупных базах. Передача конкретного объекта метаданных обновляет нумератор точечно и моментально.
Если проблема возникла после восстановления базы данных из резервной копии (dt-файла или бэкапа СУБД) на рабочем сервере, причиной может являться сохраненный кэш номеров в процессах ragent / rphost.
Выполним следующие действия для исправления: