В процессе разработки в системе «1С:Предприятие» часто возникает задача организовать нумерацию документов таким образом, чтобы она была независимой для разных подразделений, складов или организаций. Стандартная нумерация подразумевает сквозной порядок, но бизнес-логика нередко требует, чтобы для каждого склада, например, существовала своя последовательность: Склад №1 имеет номера 01, 02, 03, а Склад №2 — свои 01, 02 и так далее.
В этой статье мы подробно разберем, как реализовать такую задачу максимально эффективно, используя возможности встроенного языка 1С, проанализируем различные подходы и выясним, почему использование стандартного механизма префиксов является наиболее правильным решением.
Для управления процессом присвоения номера в платформе 1С предусмотрено стандартное событие — ПриУстановкеНовогоНомера. Это событие вызывается в тот момент, когда объект (документ) запрашивает новый номер. Обычно это происходит при первом открытии формы нового документа или при его первой записи.
Рассмотрим структуру этой процедуры. Она имеет два важных параметра:
Ложь, платформа не будет автоматически генерировать номер, и вам придется присвоить его вручную. Если оставить Истина, платформа сгенерирует номер сама, учитывая значение второго параметра.Когда мы передаем в параметр Префикс уникальную строку, соответствующую складу, платформа автоматически ищет в базе данных максимальный номер, который начинается с этого же префикса, и увеличивает его на единицу. Таким образом, решается проблема разделения потоков нумерации без написания сложных запросов.
Проанализируем ситуацию, когда нам нужно разделять номера по реквизиту Склад. Рассмотрим алгоритм действий программиста.
Прежде всего, нам нужно место, где будут храниться префиксы для каждого склада. Не стоит жестко прописывать коды или наименования складов прямо в программном коде — это сделает систему негибкой.
Рекомендуется добавить в справочник Склады новый реквизит, например, ПрефиксНомера (тип: Строка, длина 2-3 символа). Это позволит пользователям самостоятельно определять, какой префикс будет у документов данного склада.
Теперь перейдем в модуль объекта документа, для которого нужно настроить нумерацию. Найдем или создадим обработчик события ПриУстановкеНовогоНомера. Проанализируем пример кода:
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Проверим, заполнен ли склад в документе
Если ЗначениеЗаполнено(Склад) Тогда
// Получаем префикс из справочника Склады
ПрефиксСклада = СокрЛП(Склад.ПрефиксНомера);
// Если префикс у склада задан, добавляем его к общему префиксу
Если ЗначениеЗаполнено(ПрефиксСклада) Тогда
Префикс = ПрефиксСклада + Префикс;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В данном примере мы берем префикс из реквизита склада и объединяем его со стандартным префиксом (например, префиксом организации или информационной базы). Платформа возьмет итоговую строку (например, "ОС1-") и найдет последний номер именно для этой комбинации.
Если вам нужно реализовать такую логику сразу для десятка различных видов документов, копирование кода в каждый модуль — плохая практика. Вместо этого рассмотрим использование Подписки на событие.
1. Создадим новый объект метаданных ПодпискаНаСобытие.
2. В качестве источника выберем нужные типы документов (или ДокументОбъект для всех документов).
3. Событие — ПриУстановкеНовогоНомера.
4. В обработчике в общем модуле пропишем аналогичную логику. Важно помнить, что в подписке первым параметром всегда идет Источник (сам объект документа).
Процедура НумерацияПоСкладуПриУстановкеНовогоНомера(Источник, СтандартнаяОбработка, Префикс) Экспорт
// Проверяем наличие реквизита Склад у документа динамически
МетаданныеДокумента = Источник.Метаданные();
Если МетаданныеДокумента.Реквизиты.Найти("Склад") <> Неопределено Тогда
Если ЗначениеЗаполнено(Источник.Склад) И ЗначениеЗаполнено(Источник.Склад.ПрефиксНомера) Тогда
Префикс = СокрЛП(Источник.Склад.ПрефиксНомера) + Префикс;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Выясним важный нюанс: что произойдет, если пользователь создаст документ для "Склада 1" (получит номер С1-001), а затем передумает и выберет "Склад 2"?
Стандартно номер документа не меняется при изменении реквизитов. Это может привести к тому, что на "Складе 2" окажется документ с префиксом "С1". Рассмотрим варианты решения:
Склад.ПриИзменении склада на форме можно вызывать метод Объект.УстановитьНовыйНомер(). Однако будьте осторожны: это может привести к пропускам в нумерации (дырам), так как старый номер уже "засветился" в базе.При реализации нумерации в разрезе реквизита важно учитывать следующие моменты:
Нумератор в 1С предназначен для создания сквозной нумерации между разными типами документов (например, чтобы у "Реализации" и "Счета-фактуры" была общая очередь номеров). Для разделения номеров внутри одного типа по реквизиту нумератор не используется.ПриУстановкеНовогоНомера работает внутри транзакции записи и использует оптимистические или пессимистические блокировки платформы, что гарантирует отсутствие дублей даже при одновременной работе сотен пользователей. Самописные решения в ПередЗаписью часто лишены этой надежности, если программист не установил блокировку номера вручную.Таким образом, мы выяснили, что использование параметра Префикс в событии ПриУстановкеНовогоНомера — это самый простой, надежный и производительный способ реализации нумерации в разрезе любого ссылочного реквизита. Проанализируйте свои требования к длине номера и политику изменения документов, и вы сможете создать надежную систему учета, отвечающую всем требованиям вашего бизнеса.