Развертывание распределенной информационной базы (РИБ) в полностью самописной конфигурации, лишенной БСП (Библиотеки стандартных подсистем), всегда ставит перед разработчиком ряд нетривиальных задач. Одной из самых острых проблем является обеспечение уникальности номеров документов и кодов справочников. Когда мы добавляем РИБ в систему, где изначально не была предусмотрена префиксация, мы неизбежно сталкиваемся с коллизиями. Документ, созданный в периферийной базе с номером 000001, при синхронизации встретится с документом с точно таким же номером 000001, созданным в главном узле.
В этой статье мы подробно разберем, как победить эту проблему. Мы рассмотрим несколько эффективных стратегий — от классической автоматической префиксации до продвинутых методов динамического распределения диапазонов и интеграции через веб-сервисы.
Давайте проанализируем, почему нельзя просто проигнорировать эту проблему или отключить контроль уникальности номеров в свойствах объектов метаданных. Если мы отключим проверку уникальности, в системе действительно смогут существовать два документа разных узлов с номером 000001. Однако это влечет за собой крайне неприятные последствия для учета:
Поэтому решать проблему уникальности необходимо на системном уровне. Выясним, какие варианты у нас есть.
Рассмотрим самый распространенный и надежный способ — внедрение префиксации на основе кодов узлов планов обмена. Платформа 1С предоставляет для этого все необходимые механизмы. Нам не потребуется БСП, достаточно создать подписки на события.
Разберем реализацию по шагам:
ПриУстановкеНовогоНомера для всех необходимых документов.ОбменДанными.Загрузка.Посмотрим на пример кода для обработчика подписки документов:
Процедура ПодпискаНаСобытиеУстановкаНовогоНомераПриУстановкеНовогоНомера(Источник, СтандартнаяОбработка, Префикс) Экспорт
// Если документ загружается в процессе обмена РИБ, префикс менять нельзя!
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Получаем код текущего узла плана обмена
ТекущийУзел = ПланыОбмена.ПочтовыеУзлы.ЭтотУзел();
КодУзла = СокрЛП(ТекущийУзел.Код);
// Используем код узла в качестве префикса
Если Не ПустаяСтрока(КодУзла) Тогда
Префикс = КодУзла + "-";
КонецЕсли;
// Платформа автоматически добавит префикс и сгенерирует уникальный номер внутри этого префикса
КонецПроцедуры
Аналогичным образом настроим подписку для справочников на событие ПриУстановкеНовогоКода:
Процедура ПодпискаНаСобытиеПриУстановкеНовогоКода(Источник, СтандартнаяОбработка, Префикс) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
ТекущийУзел = ПланыОбмена.ПочтовыеУзлы.ЭтотУзел();
КодУзла = СокрЛП(ТекущийУзел.Код);
Если Не ПустаяСтрока(КодУзла) Тогда
Префикс = КодУзла + "-";
КонецЕсли;
КонецПроцедуры
Этот метод красив своей простотой. Платформа 1С самостоятельно анализирует существующие номера с данным префиксом и инкрементирует числовую часть, полностью исключая пересечения с номерами других узлов.
Что делать, если заказчик категорически требует сквозную строго последовательную нумерацию без каких-либо буквенных или цифирных префиксов в номере документа? В таком случае мы можем использовать веб-сервис или HTTP-сервис, развернутый в главном узле.
Разберем этот алгоритм. При создании документа в периферийной базе система делает синхронный вызов веб-сервиса центрального узла. Центральный узел генерирует очередной свободный номер, фиксирует его у себя и возвращает периферийному узлу.
Проанализируем плюсы и минусы этого подхода:
Если мы не хотим использовать префиксы и при этом не можем гарантировать постоянный интернет для работы веб-сервисов, рассмотрим метод отложенной перенумерации в главном узле.
При этом методе в подчиненных базах документы создаются локально (с возможным дублированием номеров). При загрузке пакета данных в главный узел система проверяет, нет ли уже документа с таким номером.
Если дубль обнаружен, главный узел:
Важно: У этого метода есть критический недостаток. Если пользователи в периферийном узле уже успели распечатать бумажный документ и отдать его контрагенту, а затем в главном узле номер изменился, это приведет к расхождению бумажного носителя и данных в базе. Для официальных первичных документов (таких как счета-фактуры или накладные) этот метод использовать нельзя.
Проанализируем еще один мощный архитектурный подход — выделение диапазонов (пулов) номеров для каждого узла. Это позволяет сохранить полностью числовую нумерацию без префиксов и при этом обеспечить абсолютную автономность работы баз.
Мы можем создать регистр сведений ДиапазоныНомерации со следующей структурой:
УзелПланаОбмена, ТипДокумента.МинимальноеЗначение, МаксимальноеЗначение, ТекущееЗначение.При создании документа в периферийном узле система обращается к этому регистру и берет значение из ресурса ТекущееЗначение, увеличивая его на единицу. Например:
Чтобы не прописывать эти диапазоны вручную на десятилетия вперед, мы можем реализовать автоматический запрос новых пулов из центра через веб-сервис, когда текущий пул узла исчерпан более чем на 90%.
Иногда разработчики жестко привязывают технические префиксы к кодам узлов планов обмена. Но что произойдет, если базу подчиненного узла придется пересоздать или переименовать? Привязка может сломаться, и начнется путаница в номерах.
Гораздо надежнее использовать бизнес-префиксы, привязанные к реальным сущностям учета, например, к справочнику Организации, Подразделения или Склады. Добавим в справочник Организации реквизит Префикс (тип: Строка, длина 2-3 символа).
Тогда в подписке на событие ПриУстановкеНовогоНомера мы будем динамически считывать этот префикс:
Процедура ПодпискаНаСобытиеПриУстановкеНовогоНомераБизнес(Источник, СтандартнаяОбработка, Префикс) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Предположим, у документа есть реквизит Организация
Если ОбщегоНазначения.ЕстьРеквизитОбъекта("Организация", Источник.Метаданные()) Тогда
ПрефиксОрганизации = СокрЛП(Источник.Организация.Префикс);
Если Не ПустаяСтрока(ПрефиксОрганизации) Тогда
Префикс = ПрефиксОрганизации;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Это гарантирует, что документы, создаваемые в разных филиалах по разным организациям или складам, никогда не пересекутся по номерам.
Давайте рассмотрим концепцию двухэтапной нумерации. Она отлично подходит, когда в периферийных точках документы создаются очень быстро и хаотично, но в центре они должны выстраиваться в красивую хронологическую цепочку.
При создании документа в периферийном узле ему присваивается временный номер с префиксом "ВРЕМ-" (или даже GUID в качестве номера). Документ проводится и печатается во внутреннем контуре как временный. После отправки в центральный узел, специальный обработчик в модуле обмена сбрасывает временный номер и присваивает документу финальный красивый сквозной номер центральной базы. Измененный документ отправляется обратно в периферию при следующем сеансе связи.
Подводя итог, можно сказать, что выбор метода зависит исключительно от требований бизнеса к внешнему виду номеров документов. Самым стабильным, простым в реализации и надежным способом является классическая префиксация через подписки на события 1С с использованием кодов узлов или бизнес-префиксов организаций. Это решение внедряется буквально за пару часов даже в полностью самописную конфигурацию без БСП и гарантирует полное отсутствие коллизий в РИБ.