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