Проблема нарушения автоматической нумерации — это классическая ситуация, с которой сталкивается практически каждый администратор или разработчик 1С. Суть проблемы заключается в механизме платформы, который при создании нового документа ищет максимальное строковое значение номера в базе данных за текущий период и прибавляет к нему единицу. Если пользователь вручную ввел номер, начинающийся на букву, которая в алфавите стоит позже текущего префикса (например, «ЮКС» вместо «УУ»), система начнет отсчитывать новые номера от этого «неправильного» значения.
В данной статье мы разберем, как вернуть нумерацию в правильное русло, если перенумеровывать уже созданные документы категорически нельзя (например, они уже распечатаны и переданы контрагентам).
Разберем ситуацию: в базе есть документы с номерами УУ-001, УУ-002. Пользователь ошибочно вводит ЮКС/0245. Поскольку буква «Ю» в таблице кодировки находится значительно дальше буквы «У», платформа при попытке создать новый документ выполнит поиск максимума и обнаружит, что ЮКС/0245 больше любого номера, начинающегося на УУ. В итоге следующий документ получит номер ЮКС/0246.
Использование функции ОбновитьНумерациюОбъектов() в данном случае не дает результата, так как эта функция лишь обновляет кэш номеров в оперативной памяти сервера, но не игнорирует реально существующий «большой» номер в таблице базы данных. Чтобы исправить ситуацию, нам нужно «обмануть» алгоритм поиска максимума.
Проанализируем работу строковой сортировки. Символ пробела в таблице символов Unicode (и ASCII) стоит значительно раньше любых букв и цифр. Если мы добавим пробел в начало «неправильного» номера, для платформы этот номер станет «меньше» номеров, начинающихся с УУ.
ЮКС).ЮКС/0245, стало ЮКС/0245.СокрЛП() (TrimAll) при выводе номера, этот пробел исчезнет при печати и не будет виден пользователю.Рассмотрим пример кода для обработки таких документов:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МойДокумент.Ссылка КАК Ссылка,
| МойДокумент.Номер КАК Номер
|ИЗ
| Документ.МойДокумент КАК МойДокумент
|ГДЕ
| МойДокумент.Номер ПОДОБНО ""ЮКС%""";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
ОбъектДок = Выборка.Ссылка.ПолучитьОбъект();
ОбъектДок.Номер = " " + СокрЛП(Выборка.Номер);
ОбъектДок.ОбменДанными.Загрузка = Истина; // Чтобы не срабатывали проверки
ОбъектДок.Записать();
КонецЦикла;
После выполнения этой операции выполним метод ОбновитьНумерациюОбъектов(Метаданные.Документы.МойДокумент), и система снова начнет предлагать номера из серии УУ, так как они теперь являются «максимальными».
Если лидирующий пробел все же мешает (например, в списках документов виден небольшой отступ), можно использовать специальный символ U+200B (невидимый пробел с нулевой шириной). Проанализируем этот вариант: этот символ вообще не занимает места на экране и в печатной форме, но для базы данных это полноценный символ, который меняет результат сортировки.
Однако стоит учитывать, что не все шрифты и внешние системы корректно обрабатывают Unicode-символы нулевой ширины, поэтому обычный пробел считается более надежным и «проверенным» средством.
Если конфигурация позволяет вносить изменения (документ не находится в расширении или расширение позволяет перехватить событие), мы можем принудительно заставить систему искать новый номер в нужном нам диапазоне. Для этого воспользуемся обработчиком ПриУстановкеНовогоНомера в модуле объекта документа.
Рассмотрим, как это реализовать:
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Явно задаем префикс, который нам нужен
Префикс = "УУ-";
// Платформа теперь будет искать максимальный номер
// только среди тех, что начинаются на "УУ-"
КонецПроцедуры
Этот метод является самым «чистым» с точки зрения архитектуры 1С. Когда мы явно передаем префикс в процедуру, механизм автонумерации игнорирует все записи в таблице, которые не соответствуют этому префиксу. Документы ЮКС останутся в базе, но перестанут влиять на генерацию новых номеров.
Иногда после исправления номеров (удаления или добавления пробелов) система продолжает выдавать старую последовательность. Выясним причину: это происходит из-за кэширования номеров на стороне сервера приложений 1С (rphost). Чтобы гарантированно сбросить счетчик, выполним следующие шаги:
ОбновитьНумерациюОбъектов(Метаданные.Документы.ИмяВашегоДокумента);
Номер.Чтобы ситуация не повторилась, проанализируем возможные административные меры:
ПередЗаписью для всех документов, которая будет проверять соответствие номера заданному шаблону (маске) и выдавать предупреждение или отказ при попытке ручного ввода некорректного префикса.Подводя итог, отметим, что самым быстрым решением «здесь и сейчас» является добавление пробела перед ошибочно введенными номерами. Это позволяет восстановить работу отдела без остановки базы и без перепечатки документов.