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