При разработке собственных конфигураций или доработке типовых решений разработчики часто сталкиваются с ситуацией, когда запрос к базе данных для получения максимального номера документа возвращает некорректный результат. Например, при наличии документов с номерами PKKR8, PKKR9 и PKKR10 функция МАКСИМУМ(Проекты.Номер) вернет значение PKKR9.
Разберем подробно причину такого поведения платформы 1С и проанализируем варианты решения этой проблемы.
Проанализируем, как платформа 1С выполняет агрегатную функцию МАКСИМУМ в языке запросов. Реквизит Номер (или Код) по умолчанию имеет тип Строка. При выполнении запроса происходит посимвольное (лексикографическое) сравнение строк слева направо:
PKKR — у всех документов он одинаковый.PKKR9 пятым символом является "9", а у документа PKKR10 пятым символом является "1".Так как в таблице символов знак "9" больше знака "1", с точки зрения системы строка "PKKR9" оказывается больше строки "PKKR10". Язык запросов 1С не преобразует строки в числа на лету и не выполняет математическое сравнение.
Для того чтобы лексикографическая сортировка строк совпадала с математической, числовая часть номера должна иметь фиксированную длину с ведущими нулями. Равное количество разрядов гарантирует правильный порядок при сравнении.
Рассмотрим пример: если номера документов хранятся в формате PKKR00000009 и PKKR00000010, то при посимвольном сравнении строка PKKR00000010 будет признана большей, так как символ "1" в 11-м разряде больше символа "0".
Сформировать корректную строку с ведущими нулями на встроенном языке 1С можно с помощью функции Формат():
ЧисловойНомер = 10;
Префикс = "PKKR";
// Форматируем число с заполнением нулями до 8 знаков без группировки
СтрокаНомера = Префикс + Формат(ЧисловойНомер, "ЧЦ=8; ЧВН=; ЧГ=0");
// Результат: "PKKR00000010"
В платформах 1С:Предприятие для справочников и документов предусмотрен встроенный механизм нумерации. Нам нет необходимости писать собственные запросы для поиска максимального номера, если правильно настроены свойства объекта метаданных:
Строка, а также зададим нужную длину (например, 11 символов).УстановитьНовыйНомер().Рассмотрим применение метода в модуле объекта документа:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтоНовый() И Не ЗначениеЗаполнено(Номер) Тогда
// Автоматически находит последний номер с указанным префиксом и увеличивает его на 1
УстановитьНовыйНомер(Организация.Суффикс);
КонецЕсли;
КонецПроцедуры
Платформа 1С самостоятельно проанализирует существующие номера в базе, выделит числовую часть с конца строки, учтет ведущие нули и присвоит документу следующий порядковый номер.
Если изменить структуру номеров в существующей базе данных невозможно (например, номера уже записаны без ведущих нулей) и язык запросов не позволяет привести строки к числу, обработку максимума вычисляют на стороне сервера приложения.
Выберем запросом все номера документов с нужным префиксом, после чего в цикле выделим числовую часть и найдем истинный математический максимум:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Проекты.Номер КАК Номер
|ИЗ
| Документ.Проекты КАК Проекты
|ГДЕ
| Проекты.Организация = &Организация";
Запрос.УстановитьПараметр("Организация", Организация);
Выборка = Запрос.Выполнить().Выбрать();
МаксимальныйНомер = 0;
ДлинаПрефикса = СтрДлина(СокрЛП(Организация.Суффикс));
Пока Выборка.Следующий() Цикл
// Отрезаем префикс и получаем числовую часть
СтрокаЧисла = Сред(Выборка.Номер, ДлинаПрефикса + 1);
ЧисловойНомер = Число(СтрокаЧисла);
Если ЧисловойНомер > МаксимальныйНомер Тогда
МаксимальныйНомер = ЧисловойНомер;
КонецЕсли;
КонецЦикла;
СледующийНомерЧислом = МаксимальныйНомер + 1;
НовыйНомерДокумента = Организация.Суффикс + Формат(СледующийНомерЧислом, "ЧГ=0");
Во избежание ошибок при нумерации объектов в 1С рекомендуется:
ПриУстановкеНовогоНомера или метод УстановитьНовыйНомер()).PKKR9 способна сбить механизм автонумерации.