Механизм нумерации документов в современных типовых конфигурациях 1С (таких как Бухгалтерия Предприятия 3.0, ERP, ЗУП) часто вызывает вопросы у разработчиков. Ситуация, когда в обработчике ПриЗаписи номер уже сформирован, а попытки изменить его приводят к непредсказуемым последствиям, встречается регулярно. В этой статье мы подробно разберем, как устроена архитектура нумерации в Библиотеке Стандартных Подсистем (БСП), рассмотрим типичные ошибки «ручного» управления номерами и выясним, как грамотно вмешиваться в этот процесс.
Рассмотрим ситуацию, с которой столкнулся автор темы. Имеется конфигурация на базе БСП (например, БП 3.0 КОРП). Разработчик пытается перехватить момент присвоения номера документу, чтобы изменить префикс или алгоритм нумерации.
При отладке выясняется следующее:
ПриЗаписи (в модуле объекта) номер документа уже заполнен и содержит префикс.ПрефиксацияОбъектовБПСобытия.УстановитьПрефикс....Возникает вопрос: в какой момент платформа присваивает номер и куда «копать», чтобы изменить это поведение?
Прежде чем пытаться изменить код, давайте разберем порядок вызова событий при записи нового документа. Это критически важно для понимания.
Когда пользователь нажимает кнопку «Записать» (или документ записывается программно), события выстраиваются в следующую цепочку:
Важный нюанс: Платформа 1С присваивает новый номер в тот момент, когда к нему происходит первое обращение (чтение свойства Номер), либо непосредственно перед записью в базу данных, если номер пустой. В типовых решениях подписки на события часто принудительно вызывают установку префикса, что инициирует генерацию номера.
Если нам нужно вмешаться в нумерацию, единственно верным местом для этого является обработчик ПриУстановкеНовогоНомера в модуле объекта. Здесь можно реализовать расширение, которое позволит автоматически устанавливать префиксы у документов исходя из ваших условий. Давайте посмотрим, как это должно выглядеть.
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Пример установки префикса организации
// Платформа сама добавит цифровой код после префикса
// Если нужно задать свой префикс:
Префикс = "СвойПрефикс";
// Если мы хотим полностью свою нумерацию (не рекомендуется):
// СтандартнаяОбработка = Ложь;
// Но тогда мы обязаны сами сформировать и присвоить Номер в коде!
КонецПроцедуры
Если вы попытаетесь изменить номер в процедуре ПередЗаписью или ПриЗаписи, вы будете бороться с уже отработавшим механизмом платформы. Более того, согласно стандартам разработки 1С, в подписках на событие запрещается менять данные объекта, если событие подразумевает, что объект уже сформирован или записан.
В ходе обсуждения проблемы выяснилось, что причиной странного поведения был «наследственный» код, оставшийся от предыдущих разработчиков. Как не сломать нумерацию в таких случаях? Давайте проанализируем этот антипаттерн, чтобы никогда его не повторять.
Была написана функция, которая пыталась найти последний номер запросом:
Запрос.Текст =
"ВЫБРАТЬ
| МАКСИМУМ(РеализацияТоваровУслуг.Номер) КАК Номер
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Дата МЕЖДУ &ДатаНач И &ДатаОкон
| И РеализацияТоваровУслуг.Организация = &Организация
| И НЕ РеализацияТоваровУслуг.Номер ПОДОБНО ""%П%""";
Почему этот код (известный в профессиональной среде как «говнокод») опасен?
Номер — строковое. Поиск максимума по строке, особенно с условием ПОДОБНО (LIKE), заставляет СУБД сканировать огромные объемы данных. При росте базы запись документов будет тормозить всё сильнее.Если вы столкнулись с ситуацией, когда номер присваивается «не так», не спешите писать запросы. Используйте отладчик грамотно. Автор темы использовал замер производительности, но есть более эффективный метод для таких случаев — использование стека вызовов.
Давайте разберем алгоритм поиска:
ПередЗаписью.ПередЗаписью.Скорее всего, вы увидите там цепочку вызовов из общих модулей БСП, связанных с префиксацией (например, Нумерация.УстановитьНомерДокумента или подписки на события). Это покажет вам точное место, где формируется префикс.
Автор упоминал, что установка СтандартнаяОбработка = Ложь приводила к пустому номеру и невозможности записи. Это логично.
Параметр СтандартнаяОбработка = Ложь в событии ПриУстановкеНовогоНомера говорит платформе: «Не делай ничего, я (программист) сам возьму на себя ответственность за генерацию уникального номера». Если после этого вы не присвоите ЭтотОбъект.Номер = "КакойТоНомер", документ останется без номера. Программное управление номерами документов требует обязательного явного присвоения значения свойству Номер, иначе платформа выдаст ошибку.
Чтобы корректно настроить нумерацию:
ПриУстановкеНовогоНомера для нужного документа.Префикс = "" (пустая строка).НумерацияПереопределяемый), если конфигурация это позволяет.Помните: 1С хранит номер как строку. Стандартный формат [Префикс][Число] позволяет платформе корректно инкрементировать числовую часть. Если же вам требуется навести порядок в уже существующих данных, вам поможет внешняя обработка «Перенумерация документов» или инструмент для общего изменения нумерации и установки префиксов. Подобные подходы актуальны и для справочников — например, когда требуется реализовать свою нумерацию табельных номеров в ЗУП 3.1. Любое отклонение от стандартного формата без веской причины принесет вам головную боль при поддержке системы в будущем.