В типовой конфигурации «1С:Управление торговлей», редакция 11.4, справочник ДоговорыКонтрагентов имеет свои особенности. В отличие от большинства документов, где автонумерация включена на уровне платформы, в договорах реквизиты Номер и Дата часто заполняются пользователями вручную. Это связано с тем, что номер договора обычно соответствует бумажному оригиналу, который может прийти от клиента.
Однако для наведения порядка в базе данных и автоматизации работы менеджеров часто требуется настроить систему так, чтобы она сама предлагала следующий порядковый номер и проставляла текущую дату. Разберем подробно, как это реализовать с помощью программной доработки.
Проанализируем структуру справочника. В 1С автоматическая нумерация обычно привязана к стандартному реквизиту Код. В справочнике ДоговорыКонтрагентов для хранения номера договора используется отдельный строковый реквизит Номер, а для даты — Дата. Поскольку это пользовательские реквизиты, платформа не умеет увеличивать их значение автоматически при создании нового элемента. Для решения задачи нам потребуется вмешаться в логику записи объекта.
Чтобы не снимать основную конфигурацию с поддержки, мы рекомендуем использовать механизм расширений. Создадим расширение и добавим в него справочник ДоговорыКонтрагентов. Нам необходимо перехватить событие ПередЗаписью на стороне сервера в модуле объекта.
Рассмотрим алгоритм, который должен выполняться при записи договора:
Номер и Дата.Выясним, как правильно найти «последний» номер. Наиболее эффективный способ — использование запроса к базе данных. Если мы хотим нумерацию в разрезе контрагентов (как часто требуют бизнес-процессы), запрос должен обязательно содержать фильтр по владельцу или реквизиту Контрагент.
Рассмотрим пример кода, который можно разместить в модуле объекта расширения:
&После("ПередЗаписью")
Процедура Расш_ПередЗаписью(Отказ, ПараметрыЗаписи)
// Работаем только с новыми объектами
Если ЭтоНовый() Тогда
// Автозаполнение даты, если она пустая
Если Не ЗначениеЗаполнено(ЭтотОбъект.Дата) Тогда
ЭтотОбъект.Дата = ТекущаяДатаСеанса();
КонецЕсли;
// Если номер еще не присвоен вручную
Если ПустаяСтрока(ЭтотОбъект.Номер) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МАКСИМУМ(ДоговорыКонтрагентов.Номер) КАК МаксНомер
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
|ГДЕ
| ДоговорыКонтрагентов.Контрагент = &Контрагент";
Запрос.УстановитьПараметр("Контрагент", ЭтотОбъект.Контрагент);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() И ЗначениеЗаполнено(Выборка.МаксНомер) Тогда
// Извлекаем число из строки и увеличиваем на 1
ПоследнийНомер = Выборка.МаксНомер;
// Простейшая логика инкремента для числовых строк
Попытка
НовыйЧисловойНомер = Число(ПоследнийНомер) + 1;
ЭтотОбъект.Номер = Формат(НовыйЧисловойНомер, "ЧГ=0");
Исключение
// Если в номере были префиксы или буквы, нужна более сложная обработка
ЭтотОбъект.Номер = "1";
КонецПопытки;
Иначе
// Если договоров у контрагента еще нет
ЭтотОбъект.Номер = "1";
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию, возникшую в обсуждении на форуме. Одна из главных ошибок при реализации такой логики — расчет номера в переменной без его последующего присвоения реквизиту объекта. После того как вы вычислили НовыйНомер, обязательно должна следовать строка ЭтотОбъект.Номер = НовыйНомер;, иначе данные не попадут в базу данных.
Также важно помнить о типах данных. Реквизит Номер — это строка. Если вы просто прибавите 1 к строке "00001", 1С может выдать ошибку или некорректный результат. Рекомендуется использовать функции преобразования типов или специализированные функции платформы для работы с префиксами.
Для корректной сортировки договоров в списке (чтобы договор №10 не шел перед договором №2) профессиональные разработчики рекомендуют использовать лидирующие нули (например, "0000001").
Рассмотрим вариант функции, которая корректно увеличивает номер, сохраняя его длину:
Функция ПолучитьСледующийНомер(ТекущийНомер)
// Удаляем лишние пробелы
ЧистыйНомер = СокрЛП(ТекущийНомер);
ДлинаНомера = СтрДлина(ЧистыйНомер);
// Преобразуем в число и увеличиваем
НовоеЧисло = Число(ЧистыйНомер) + 1;
// Форматируем обратно в строку с сохранением длины (дополняем нулями слева)
ФорматнаяСтрока = "ЧЦ=" + ДлинаНомера + "; ЧВН=; ЧГ=0";
Возврат Формат(НовоеЧисло, ФорматнаяСтрока);
КонецФункции
Этот подход гарантирует, что структура номера останется единообразной для всех документов одного контрагента.
Мы выяснили, что автоматизация нумерации договоров в УТ 11.4 требует программного вмешательства, так как типовой функционал ориентирован на ручной ввод. Наилучшим местом для размещения кода является подписка на событие или расширение модуля объекта (обработчик ПередЗаписью).
При внедрении данного решения обратите внимание на следующие моменты:
Организации в запрос, чтобы нумерация не перемешивалась.ПрефиксацияОбъектов.ПолучитьНомерНаОснованииВышестоящего).Использование предложенных методов позволит значительно сократить время на оформление документов и исключить ошибки «человеческого фактора» при заполнении карточки договора.