Как реализовать автоматическую нумерацию договоров в 1С:Управление торговлей 11.4

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

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

Способ 1. Использование Регистра Сведений для хранения счетчика

Это классический программный подход, который позволяет гибко управлять нумерацией. Мы создаем специальный Регистр Сведений, в котором будет храниться актуальное состояние счетчика номеров. Разберем этот процесс по шагам.

Во-первых, создадим непериодический регистр сведений, например, НумерацияДоговоров. В качестве измерений можно использовать Организация (если нужна раздельная нумерация по фирмам) и Год. В качестве ресурса добавим ПоследнийНомер с типом Число.

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


Функция ПолучитьСледующийНомерДоговора(Организация, ТекущийГод) Экспорт
    
    Блокировка = Новый БлокировкаДанных;
    ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.НумерацияДоговоров");
    ЭлементБлокировки.УстановитьЗначение("Организация", Организация);
    ЭлементБлокировки.УстановитьЗначение("Год", ТекущийГод);
    ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
    
    НачатьТранзакцию();
    Попытка
        Блокировка.Заблокировать();
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   НумерацияДоговоров.ПоследнийНомер КАК Номер
            |ИЗ
            |   РегистрСведений.НумерацияДоговоров КАК НумерацияДоговоров
            |ГДЕ
            |   НумерацияДоговоров.Организация = &Организация
            |   И НумерацияДоговоров.Год = &Год";
            
        Запрос.УстановитьПараметр("Организация", Организация);
        Запрос.УстановитьПараметр("Год", ТекущийГод);
        
        Выборка = Запрос.Выполнить().Выбрать();
        
        НовыйНомер = 1;
        Если Выборка.Следующий() Тогда
            НовыйНомер = Выборка.Номер + 1;
        КонецЕсли;
        
        // Записываем обновленный номер обратно в регистр
        МенеджерЗаписи = РегистрыСведений.НумерацияДоговоров.СоздатьМенеджерЗаписи();
        МенеджерЗаписи.Организация = Организация;
        МенеджерЗаписи.Год = ТекущийГод;
        МенеджерЗаписи.ПоследнийНомер = НовыйНомер;
        МенеджерЗаписи.Записать();
        
        ЗафиксироватьТранзакцию();
        Возврат НовыйНомер;
        
    Исключение
        ОтменитьТранзакцию();
        ЗаписьЖурналаРегистрации("Ошибка нумерации", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
        ВызватьИсключение "Не удалось получить номер договора, попробуйте еще раз.";
    КонецПопытки;
    
КонецФункции

Этот метод гарантирует, что два пользователя не получат один и тот же номер одновременно. Главное преимущество здесь — полный контроль над логикой (можно легко добавить префиксы или сбрасывать нумерацию каждый год).

Способ 2. Создание вспомогательного документа "Заключение договора"

Рассмотрим альтернативный вариант, который часто используется в крупных внедрениях. Вместо того чтобы пытаться "заставить" справочник нумероваться автоматически, мы создаем новый объект метаданных — документ ЗаключениеДоговора. Выясним причину, почему это удобно:

  1. Документы в 1С имеют встроенный механизм автонумерации. Нам не нужно писать код для инкремента.
  2. Документ позволяет хранить историю: кто, когда и на каких условиях инициировал создание договора.
  3. В документе можно сделать ссылку на сам элемент справочника ДоговорыКонтрагентов.

При такой схеме пользователь создает документ, проводит его, система присваивает номер, и этот номер программно записывается в карточку договора. Это архитектурно чистое решение, соответствующее логике 1С, где номерные сущности с привязкой ко времени чаще всего являются документами.

Способ 3. Использование Дополнительных сведений (БСП)

Если мы не хотим менять структуру метаданных (добавлять новые справочники или регистры), можно воспользоваться штатным механизмом Библиотеки стандартных подсистем (БСП) — Дополнительными сведениями. Посмотрим, как это реализовать.

В пользовательском режиме создадим новое дополнительное сведение "Номер договора" для объекта Договоры контрагентов. Теперь в коде внешней печатной формы или в расширении мы можем анализировать уже существующие значения этого сведения. Разберем пример функции, которая находит максимальный номер среди доп. сведений:


Функция НайтиПоследнийНомерИзДопСведений()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   МАКСИМУМ(ВЫРАЗИТЬ(ДополнительныеСведения.Значение КАК ЧИСЛО)) КАК МаксНомер
        |ИЗ
        |   РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
        |ГДЕ
        |   ДополнительныеСведения.Свойство.Заголовок = ""Номер договора""";
        
    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        Возврат ?(Выборка.МаксНомер = NULL, 0, Выборка.МаксНомер);
    КонецЕсли;
    Возврат 0;
КонецФункции

Важный нюанс: при использовании доп. сведений нужно быть осторожным с типами данных. Если номер хранится как строка, МАКСИМУМ может отработать некорректно (например, "10" будет меньше, чем "9"). Поэтому рекомендуется либо дополнять номера нулями слева (00001, 00002), либо хранить значение в числовом формате.

Способ 4. Включение стандартной нумерации через расширение

Проанализируем ситуацию, когда нам достаточно стандартного реквизита Номер. С помощью механизма расширений мы можем изменить свойства справочника ДоговорыКонтрагентов. По умолчанию в УТ он может быть настроен как "неавтоматический".

Мы можем создать расширение и в нем для справочника установить свойство Автонумерация в значение "Автоматически". После этого в модуле объекта (также через расширение) в процедуре ПередЗаписью можно использовать стандартный метод УстановитьНовыйНомер().

Однако, в УТ 11.4 часто используется общая подсистема префиксации объектов. Чтобы номер выглядел красиво (с префиксом организации), правильнее вызывать методы БСП:


// В расширении модуля объекта справочника ДоговорыКонтрагентов
&После("ПередЗаписью")
Процедура Расш_ПередЗаписью(Отказ)
    Если ЭтоНовый() И ПустаяСтрока(ЭтотОбъект.Номер) Тогда
        ПрефиксацияОбъектовСобытия.УстановитьНомерОбъекта(ЭтотОбъект);
    КонецЕсли;
КонецПроцедуры

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

Профессиональные советы по реализации

Рассмотрим несколько важных моментов, которые помогут сделать вашу систему нумерации надежной:

Выясним, какой способ лучше выбрать. Если вам нужно быстрое решение без изменения конфигурации — используйте дополнительные сведения. Если вы строите серьезную систему учета договоров — лучше реализовать отдельный документ или включить штатную автонумерацию через расширение. Это обеспечит стабильность и предсказуемость работы системы в будущем.

← На главную