Как правильно перехватить и изменить формирование номера документа в 1С:Бухгалтерия 3.0?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

Механизм нумерации документов в современных типовых конфигурациях 1С (таких как Бухгалтерия Предприятия 3.0, ERP, ЗУП) часто вызывает вопросы у разработчиков. Ситуация, когда в обработчике ПриЗаписи номер уже сформирован, а попытки изменить его приводят к непредсказуемым последствиям, встречается регулярно. В этой статье мы подробно разберем, как устроена архитектура нумерации в Библиотеке Стандартных Подсистем (БСП), рассмотрим типичные ошибки «ручного» управления номерами и выясним, как грамотно вмешиваться в этот процесс.

Постановка задачи: номер появляется «сам по себе»

Рассмотрим ситуацию, с которой столкнулся автор темы. Имеется конфигурация на базе БСП (например, БП 3.0 КОРП). Разработчик пытается перехватить момент присвоения номера документу, чтобы изменить префикс или алгоритм нумерации.

При отладке выясняется следующее:

  1. В обработчике события ПриЗаписи (в модуле объекта) номер документа уже заполнен и содержит префикс.
  2. Срабатывает подписка на событие или процедура общего модуля, например, ПрефиксацияОбъектовБПСобытия.УстановитьПрефикс....
  3. Даже если в этой процедуре принудительно очистить префикс, итоговый номер все равно формируется с префиксом или ведет себя некорректно.

Возникает вопрос: в какой момент платформа присваивает номер и куда «копать», чтобы изменить это поведение?

Архитектура нумерации: как это работает в БСП

Прежде чем пытаться изменить код, давайте разберем порядок вызова событий при записи нового документа. Это критически важно для понимания.

Когда пользователь нажимает кнопку «Записать» (или документ записывается программно), события выстраиваются в следующую цепочку:

  1. ПриУстановкеНовогоНомера (Модуль объекта). Это первое и самое важное событие для управления нумерацией. Именно здесь можно задать префикс.
  2. Подписки на событие «ПриУстановкеНовогоНомера». В типовых конфигурациях именно здесь срабатывает механизм БСП, который добавляет к префиксу, заданному в модуле (или пустому), префиксы организации и информационной базы.
  3. ПередЗаписью (Модуль объекта). В этот момент номер уже может быть сформирован, если он был запрошен ранее или если платформа решила его присвоить.
  4. ПриЗаписи (Модуль объекта). Документ уже в транзакции записи, номер гарантированно присвоен (если не было отказа).

Важный нюанс: Платформа 1С присваивает новый номер в тот момент, когда к нему происходит первое обращение (чтение свойства Номер), либо непосредственно перед записью в базу данных, если номер пустой. В типовых решениях подписки на события часто принудительно вызывают установку префикса, что инициирует генерацию номера.

Правильный способ перехвата номера

Если нам нужно вмешаться в нумерацию, единственно верным местом для этого является обработчик ПриУстановкеНовогоНомера в модуле объекта. Здесь можно реализовать расширение, которое позволит автоматически устанавливать префиксы у документов исходя из ваших условий. Давайте посмотрим, как это должно выглядеть.


Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
    // Пример установки префикса организации
    // Платформа сама добавит цифровой код после префикса
    
    // Если нужно задать свой префикс:
    Префикс = "СвойПрефикс"; 
    
    // Если мы хотим полностью свою нумерацию (не рекомендуется):
    // СтандартнаяОбработка = Ложь;
    // Но тогда мы обязаны сами сформировать и присвоить Номер в коде!
КонецПроцедуры

Если вы попытаетесь изменить номер в процедуре ПередЗаписью или ПриЗаписи, вы будете бороться с уже отработавшим механизмом платформы. Более того, согласно стандартам разработки 1С, в подписках на событие запрещается менять данные объекта, если событие подразумевает, что объект уже сформирован или записан.

Ошибки «ручной» нумерации: как делать не надо

В ходе обсуждения проблемы выяснилось, что причиной странного поведения был «наследственный» код, оставшийся от предыдущих разработчиков. Как не сломать нумерацию в таких случаях? Давайте проанализируем этот антипаттерн, чтобы никогда его не повторять.

Была написана функция, которая пыталась найти последний номер запросом:


Запрос.Текст = 
    "ВЫБРАТЬ
    |    МАКСИМУМ(РеализацияТоваровУслуг.Номер) КАК Номер
    |ИЗ
    |    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
    |ГДЕ
    |    РеализацияТоваровУслуг.Дата МЕЖДУ &ДатаНач И &ДатаОкон
    |    И РеализацияТоваровУслуг.Организация = &Организация
    |    И НЕ РеализацияТоваровУслуг.Номер ПОДОБНО ""%П%""";

Почему этот код (известный в профессиональной среде как «говнокод») опасен?

  1. Отсутствие транзакционной блокировки. Представим, что два бухгалтера одновременно создают документы. Оба потока выполнят этот запрос, получат один и тот же «максимальный» номер (например, 100), прибавят к нему 1 и попытаются записать документы с номером 101. Первый запишет успешно, второй получит ошибку «Номер не уникален», для устранения которой в запущенных случаях потребуется специальное исправление ошибки «Значение поля номер не уникально» путем синхронизации кэша нумератора.
  2. Проблемы производительности. Поле Номер — строковое. Поиск максимума по строке, особенно с условием ПОДОБНО (LIKE), заставляет СУБД сканировать огромные объемы данных. При росте базы запись документов будет тормозить всё сильнее.
  3. Нарушение логики префиксов. Игнорирование стандартных механизмов приводит к тому, что автонумерация платформы сбивается. Если платформа видит в базе «нестандартный» номер, она может начать использовать его как шаблон для следующих документов, создавая хаос в номерах.

Методика отладки: как найти виновного

Если вы столкнулись с ситуацией, когда номер присваивается «не так», не спешите писать запросы. Используйте отладчик грамотно. Автор темы использовал замер производительности, но есть более эффективный метод для таких случаев — использование стека вызовов.

Давайте разберем алгоритм поиска:

  1. Поставьте точку останова в модуле объекта документа в процедуре ПередЗаписью.
  2. Запустите создание документа в режиме предприятия.
  3. Когда отладчик остановится, не просто смотрите на значения переменных, а откройте окно Стек вызовов (Call Stack).
  4. Посмотрите, какие процедуры вызывались до попадания в ПередЗаписью.

Скорее всего, вы увидите там цепочку вызовов из общих модулей БСП, связанных с префиксацией (например, Нумерация.УстановитьНомерДокумента или подписки на события). Это покажет вам точное место, где формируется префикс.

Решение проблемы с пустым номером

Автор упоминал, что установка СтандартнаяОбработка = Ложь приводила к пустому номеру и невозможности записи. Это логично.

Параметр СтандартнаяОбработка = Ложь в событии ПриУстановкеНовогоНомера говорит платформе: «Не делай ничего, я (программист) сам возьму на себя ответственность за генерацию уникального номера». Если после этого вы не присвоите ЭтотОбъект.Номер = "КакойТоНомер", документ останется без номера. Программное управление номерами документов требует обязательного явного присвоения значения свойству Номер, иначе платформа выдаст ошибку.

Итог: правильный алгоритм действий

Чтобы корректно настроить нумерацию:

  1. Удалите любые «самописные» запросы на получение максимального номера. Доверьтесь платформе.
  2. Проверьте настройки в режиме «1С:Предприятие» (Администрирование -> Синхронизация данных), корректно ли заданы префиксы информационной базы и организации.
  3. Если нужно изменить логику, например, реализовать специфическую нумерацию счетов-фактур (поможет автоматизация отдельной нумерации авансовых счетов-фактур для 1С:Бухгалтерия) в пределах дня, используйте расширения или:
    • Создайте Подписку на событие ПриУстановкеНовогоНомера для нужного документа.
    • В обработчике подписки установите Префикс = "" (пустая строка).
    • Убедитесь, что ваша подписка выполняется после типовых подписок (порядок регулируется в дереве конфигурации), либо встраивайтесь в переопределяемые модули БСП (например, НумерацияПереопределяемый), если конфигурация это позволяет.

Помните: 1С хранит номер как строку. Стандартный формат [Префикс][Число] позволяет платформе корректно инкрементировать числовую часть. Если же вам требуется навести порядок в уже существующих данных, вам поможет внешняя обработка «Перенумерация документов» или инструмент для общего изменения нумерации и установки префиксов. Подобные подходы актуальны и для справочников — например, когда требуется реализовать свою нумерацию табельных номеров в ЗУП 3.1. Любое отклонение от стандартного формата без веской причины принесет вам головную боль при поддержке системы в будущем.

← На главную