В процессе разработки в системе 1С:Предприятие часто возникает задача программного создания документов или изменения их нумерации. Начинающие разработчики нередко пытаются реализовать инкремент номера (прибавление единицы) «в лоб», используя обычные математические операции. Однако такой подход таит в себе множество подводных камней, начиная от банальных ошибок программирования и заканчивая поломкой всей системы автоматической нумерации в базе данных. В данной статье мы разберем, почему ручное сложение номера со строкой — это плохая практика, и как правильно использовать штатные механизмы платформы.
Рассмотрим ситуацию, с которой столкнулся автор темы. Попытка получить последний номер через запрос и прибавить к нему единицу выглядит следующим образом:
Функция ПолучитьПоследнийНомерРеал()
НомерДок = 0;
Запрос = Новый Запрос("ВЫБРАТЬ Первые 1 Док.Номер КАК Номер ИЗ Документ.РеализацияТоваровУслуг КАК Док УПОРЯДОЧИТЬ ПО Номер УБЫВ");
ВДЗ = Запрос.Выполнить().Выбрать();
Если ВДЗ.Следующий() Тогда
НомерДок = ВДЗ.Номер + 1;
КонецЕсли;
Возврат НомерДок;
КонецФункции
Проанализируем, почему этот код работает некорректно. Основная причина заключается в том, что поле Номер в документах 1С имеет тип Строка. Когда мы выполняем операцию ВДЗ.Номер + 1, платформа интерпретирует это как конкатенацию (склеивание) строк, а не арифметическое сложение. Именно поэтому вместо ожидаемого номера «БП-0000019» получается «БП-00000181».
Даже если попытаться преобразовать строку в число, прибавить единицу и вернуть обратно в строку, возникнет проблема ведущих нулей. Если номер документа имеет формат «0000018», то после преобразования в число 18 и прибавления единицы мы получим 19. При обратном преобразовании в строку без учета маски мы запишем «19». Для 1С это критично: система ищет максимальный номер по строковым правилам сортировки. Строка, начинающаяся на «9», будет считаться «больше», чем строка, начинающаяся на «0», что в конечном итоге приведет к сбою автонумерации у всех последующих документов.
Самый правильный и надежный способ присвоить документу следующий номер — воспользоваться встроенным методом объекта УстановитьНовыйНомер(). Этот метод заставляет платформу автоматически вычислить следующий свободный номер в соответствии с заданными в метаданных правилами (периодичность, длина номера, префиксы).
Разберем синтаксис этого метода. Важно помнить, что это именно процедура, она не возвращает значение, а устанавливает его непосредственно в свойство Номер объекта документа:
// Правильное использование в модуле объекта или при программном создании
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
// Устанавливаем номер с учетом префикса информационной базы или организации
НовыйДокумент.УстановитьНовыйНомер("БП");
НовыйДокумент.Записать();
Проанализируем ситуацию, если вам нужно вызвать этот метод для уже существующего, но еще не записанного в базу объекта. Попытка присвоить результат метода переменной, как в примере ДокРеализации.Номер = ДокРеализации.УстановитьНовыйНомер(), приведет к ошибке, так как метод не возвращает значения. Достаточно просто вызвать процедуру у объекта.
Часто нумерация должна зависеть от определенных условий, например, от организации или склада. Вместо того чтобы вручную формировать строку номера, рекомендуется использовать параметр Префикс. Рассмотрим подробнее механизм работы:
УстановитьНовыйНомер(Префикс) принимает строковый префикс.Если логика установки префикса сложная, лучше всего разместить её в модуле объекта в предопределенной процедуре ПриУстановкеНовогоНомера. Это событие вызывается платформой автоматически при вызове метода УстановитьНовыйНомер() или при интерактивном создании документа пользователем.
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Добавляем к стандартному префиксу код организации
Префикс = Префикс + Организация.Префикс;
// Можно добавить логику в зависимости от вида операции
Если ВидОперации = Перечисления.ВидыОперацийРеализации.Экспорт Тогда
Префикс = Префикс + "ЭК";
КонецЕсли;
КонецПроцедуры
Вернемся к вопросу использования запросов для получения последнего номера (как в Сообщении 0). Выясним причину, почему это опасно в многопользовательской среде. Между моментом, когда ваш запрос получил «последний» номер, и моментом, когда вы попытаетесь записать новый документ, другой пользователь может успеть создать документ и занять этот номер. Это приведет к ошибке неуникальности номера.
Штатный механизм 1С при использовании УстановитьНовыйНомер() работает более интеллектуально. В современных версиях платформы (8.3) управление нумерацией может происходить в двух режимах:
Если кто-то из пользователей вручную ввел номер, не соответствующий маске (например, вместо «БП-00018» ввел «99999»), автоматическая нумерация может перестать работать корректно. Система будет пытаться найти номер, следующий за «99999», и если длина номера ограничена, она выдаст ошибку. В такой ситуации необходимо:
Важный итог: Всегда доверяйте нумерацию платформе. Использование УстановитьНовыйНомер() гарантирует соблюдение уникальности, сохранение ведущих нулей и корректную сортировку в списках. Ручное манипулирование строкой номера оправдано только в крайне редких случаях при интеграции с внешними системами, где формат номера не соответствует стандартам 1С.