В процессе работы в 1С:Управление производственным предприятием (УПП) ред. 1.2 пользователи часто сталкиваются с ситуацией, когда автоматическая нумерация документов «сбивается». Типичный пример: в базе велась последовательная нумерация (например, до номера 600), но после загрузки данных из системы «Клиент-банк» в базу попали платежные поручения с номерами вроде КТ000008266. Поскольку платформа 1С всегда ищет максимальный номер в пределах префикса для генерации следующего, новые документы начинают получать номера 8267, 8268 и так далее, пропуская огромный диапазон номеров.
Разберем детально, как вернуть нумерацию в нужное русло, проанализируем технические нюансы и программные способы решения этой задачи.
Механизм автонумерации в 1С работает по принципу поиска максимального значения строки в поле Номер среди документов данного вида с одинаковым префиксом. Платформа воспринимает номер как строку, находит «самый большой» с точки зрения алфавитного и числового порядка номер и прибавляет к нему единицу. Как только в базу попадает хотя бы один документ с аномально высоким номером, стандартный механизм «зацепляется» за него.
Проанализируем три основных пути решения проблемы: административный (самый надежный), программный (гибкий) и превентивный.
Вместо того чтобы писать сложный код, который будет бороться с платформенным механизмом, проще всего «увести» ошибочные документы из поля зрения автонумерации. Платформа считает номера уникальными только внутри одного префикса.
Пошаговый алгоритм действий:
КТ000008266 установим БН000008266 (где «БН» — Банковские Номера).КТ и номером выше 600, платформа автоматически предложит для нового документа номер 601.Важный нюанс: Чтобы платформа «забыла» старый максимальный номер, иногда требуется вызвать метод ОбновитьНумерациюОбъектов(). Это можно сделать через консоль кода:
ОбновитьНумерациюОбъектов(Метаданные.Документы.ПлатежноеПоручениеИсходящее);
Этот метод очищает кэш нумерации в оперативной памяти сервера, заставляя систему заново просканировать таблицу в базе данных.
Если по каким-то причинам изменять номера уже существующих документов нельзя, нам придется вмешаться в процесс создания нового объекта. Рассмотрим, как это реализовать правильно. Простая подмена номера в событии ПриЗаписи — не лучшее решение, так как это может вызвать конфликты при одновременной работе пользователей.
Правильнее всего использовать событие объекта ПриУстановкеНовогоНомера. Разберем пример кода, который находит реально последний по дате номер и инкрементирует его.
Пример реализации в модуле документа:
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Отключаем стандартный механизм, если нужно полностью контролировать процесс
// СтандартнаяОбработка = Ложь;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ПлатежноеПоручениеИсходящее.Номер КАК Номер
|ИЗ
| Документ.ПлатежноеПоручениеИсходящее КАК ПлатежноеПоручениеИсходящее
|ГДЕ
| ПлатежноеПоручениеИсходящее.Дата МЕЖДУ &НачалоГода И &КонецГода
| И ПлатежноеПоручениеИсходящее.Номер ПОДОБНО &ПрефиксПоиск
|УПОРЯДОЧИТЬ ПО
| ПлатежноеПоручениеИсходящее.Дата УБЫВ,
| ПлатежноеПоручениеИсходящее.Ссылка УБЫВ";
Запрос.УстановитьПараметр("НачалоГода", НачалоГода(Дата));
Запрос.УстановитьПараметр("КонецГода", КонецГода(Дата));
// Ищем только "наши" номера, исключая аномальные, если они имеют другой формат
Запрос.УстановитьПараметр("ПрефиксПоиск", "КТ000000%");
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
ТекущийНомерСтр = Выборка.Номер;
// Извлекаем числовую часть. Предположим, префикс занимает 2 знака
ЧисловаяЧасть = Сред(ТекущийНомерСтр, 3);
НовыйНомерЧислом = Число(ЧисловаяЧасть) + 1;
// Важно: используем Формат, чтобы избежать пробелов-разделителей (1 000)
// ЧГ=0 убирает группировку разрядов
НовыйНомерСтр = Формат(НовыйНомерЧислом, "ЧЦ=9; ЧВН=; ЧГ=0");
ЭтотОбъект.Номер = "КТ" + НовыйНомерСтр;
КонецЕсли;
КонецПроцедуры
Проанализируем критическую ошибку, упомянутую в обсуждении. Многие начинающие разработчики используют конструкцию Строка(Число). Посмотрим, что произойдет, когда номер документа достигнет 1000. Система 1С по умолчанию при преобразовании числа в строку добавляет неразрывный пробел в качестве разделителя разрядов. Вместо "1000" вы получите "1 000".
Для корректной работы с номерами необходимо всегда использовать функцию Формат() с параметром ЧГ=0 (ЧГ — Группировка). Разберем параметры подробнее:
ЧЦ=9 — общая длина числовой части.ЧВН= — выводить лидирующие нули (чрезвычайно важно для сохранения длины номера 1С).ЧГ=0 — отмена группировки разрядов пробелами.Чтобы ситуация не повторилась, выясним причину появления «плохих» номеров. Обычно это происходит из-за настроек обработки импорта банковской выписки. В типовых решениях есть опция «Устанавливать номера документов из файла».
Рекомендуемая настройка:
НомерВходящегоДокумента.Номер документа 1С должен генерироваться системой автоматически по порядку. Это обеспечит хронологическую стройность учета и отсутствие конфликтов с автонумерацией.Подводя итог, можно сказать, что самым «чистым» решением является исправление префиксов у ошибочно загруженных документов. Это не требует изменения конфигурации и сохраняет типовой механизм работы платформы. Если же вы выбираете программный путь, обязательно учитывайте следующее:
ПриУстановкеНовогоНомера вместо ПриЗаписи.Строка(), всегда применяйте Формат() с отключенной группировкой разрядов.Применение этих подходов позволит вам поддерживать порядок в базе данных и избежать регулярных жалоб пользователей на «прыгающие» номера платежных поручений.