В процессе сопровождения систем на базе 1С:Комплексная автоматизация (КА) или 1С:ERP часто возникает задача по разделению нумерации. Например, когда крупный заказчик требует, чтобы в номерах документов (Реализаций, Счет-фактур) присутствовал определенный символ или использовалась отдельная последовательность. Иногда требуется изменение механизма нумерации, чтобы вносить документы задним числом, не сбивая общий поток. Рассмотрим, почему стандартные попытки решить эту задачу "в лоб" через код приводят к сбою всей нумерации в базе, и разберем правильные подходы к реализации.
Рассмотрим ситуацию, когда программист пытается добавить букву "К" в конец номера документа в процедуре ПриЗаписи. На первый взгляд, это кажется логичным, но на практике приводит к тому, что все последующие документы для других контрагентов начинают получать странные номера (например, букву "К" посередине или смещение префикса).
Выясним причину такого поведения:
ХХ00-00001К, система анализирует его структуру. Буква в конце (постфикс) сбивает парсер платформы. Она может ошибочно принять часть номера за префикс или решить, что это новый формат приращения. В таких случаях может потребоваться поиск и нормализация нестандартных номеров, чтобы привести базу в порядок.ПриЗаписи — это слишком поздний этап. К этому моменту номер уже должен быть окончательно сформирован. Изменение номера "на лету" в момент записи заставляет платформу заново пересчитывать индексы, что часто ведет к непредсказуемым результатам.Проанализируем архитектуру 1С:Комплексная автоматизация. Она построена на Библиотеке Стандартных Подсистем (БСП), где за нумерацию отвечает подсистема "Префиксация объектов". Вместо того чтобы добавлять букву в конец номера (что платформа не любит), мы добавим её в префикс. Например, вместо НЛ00-000001 мы получим НЛК0-000001. Если база уже запущена, возможно, потребуется общее изменение нумерации документов и установка префикса для существующих объектов.
Для реализации этого метода нам не нужно менять модуль документа. Мы воспользуемся механизмом расширения и переопределим логику формирования префикса. Разберем по шагам:
ПрефиксацияОбъектовПереопределяемый.ПриУстановкеПрефикса.Посмотрим на пример кода, который нужно внедрить в расширение:
Процедура Расш1_ПриУстановкеПрефикса(Объект, Префикс) Экспорт
// Проверяем, что это нужный нам тип документа
Если ТипЗнч(Объект) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда
// Проверяем условие по контрагенту
// Лучше использовать ДополнительныеРеквизиты или Сегменты, но для примера возьмем наименование
Если Объект.Контрагент.Наименование = "ООО КЛЕВ" Тогда
// Добавляем символ 'К' к текущему префиксу
// Было "НЛ00-", станет "НЛК0-"
Префикс = Префикс + "К";
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Преимущества этого метода:
НЛК0 как отдельный префикс и ведет для него независимый счетчик.НЛ00) никак не страдает.Если бизнес-требование жестко настаивает на символе именно в конце номера или на полностью кастомном формате (например, если разрабатывается уникальный номер документа на 100 лет с использованием года в теле номера), необходимо использовать специально предназначенное для этого событие объекта — ПриУстановкеНовогоНомера. Проанализируем ситуацию: в этом событии мы можем подавить стандартную логику платформы.
Разберем пример реализации в модуле объекта документа:
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Если условие выполняется, берем управление на себя
Если ЗначениеЗаполнено(Контрагент) И Контрагент.Наименование = "ООО КЛЕВ" Тогда
// Отключаем стандартный механизм 1С
СтандартнаяОбработка = Ложь;
// Получаем последний номер из нашего самописного регистра
// Важно: запрос должен быть эффективным!
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Максимум(Нумерация.ПоследнийНомер) КАК Номер
|ИЗ
| РегистрСведений.НумерацияКлев КАК Нумерация";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
НовыйПорядковыйНомер = 1;
Если Выборка.Следующий() И Выборка.Номер <> NULL Тогда
НовыйПорядковыйНомер = Выборка.Номер + 1;
КонецЕсли;
// Формируем строку номера. ХХ00 - префикс организации
// ЧЦ=6; ЧН=; ЧГ=0 - форматирование числа с ведущими нулями
ЭтотОбъект.Номер = "НЛ00-" + Формат(НовыйПорядковыйНомер, "ЧЦ=6; ЧН=; ЧГ=0") + "К";
КонецЕсли;
КонецПроцедуры
Важный нюанс: При использовании этого метода вы обязаны самостоятельно гарантировать уникальность номера. Если два пользователя одновременно начнут создавать документы, они могут получить одинаковый номер из регистра, так как запись в регистр обычно происходит только ПриЗаписи документа. Поэтому первый способ с префиксами гораздо надежнее.
Автор исходного вопроса пытался использовать метод Документы.РеализацияТоваровУслуг.ПолучитьНовыйНомер(). Проанализируем, почему это не лучший выбор внутри процедур самого объекта. Данный метод генерирует номер и "бронирует" его в кэше. Если вы вызываете его внутри обработчика, который и так должен установить номер, вы создаете избыточную нагрузку на механизм нумерации и можете получить пропуски в номерах.
Для того чтобы "подсмотреть" следующий номер, не занимая его, лучше использовать запрос к таблице документов с сортировкой по номеру (учитывая префикс) или обращаться к механизмам БСП: ПрефиксацияОбъектов.СформироватьВсеПрефиксыНомера.
Подведем итоги нашего исследования проблемы нумерации в 1С:КА:
ПрефиксацияОбъектовПереопределяемый — самый чистый и безопасный способ реализации раздельной нумерации.ПриУстановкеНовогоНомера или перед открытием формы (для новых объектов).Рассмотренные подходы позволят вам реализовать требуемый функционал, сохранив при этом стабильность работы информационной базы и чистоту программного кода.