Почему в многоуровневом РИБ движения регистрируются без документов и как это исправить

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием IT и автоматизация бизнеса
← На главную

При построении сложных многоуровневых (каскадных) распределенных информационных баз (РИБ) с фильтрацией по организациям разработчики часто сталкиваются с ситуацией, когда при передаче данных через промежуточные узлы (например, Уровень 1 → Уровень 2 → Уровень 3 → Уровень 4) документы приходят на конечные узлы без движений по регистрам. Проанализируем, почему возникает эта проблема на уровне платформы 1С:Предприятие, и подробно разберем проверенные способы её устранения.

Причина возникновения проблемы при каскадном обмене

Рассмотрим механизм работы обмена данными в промежуточных базах:

  1. Порядок сериализации метаданных в XML-файл обмена: платформа формирует XML-сообщение обмена по внутреннему порядку типов метаданных и таблиц регистрации изменений (_ChngRec), а не по логической иерархии объектов. Из-за этого наборы записей регистров сведений и накоплений могут записываться в базу промежуточного узла раньше, чем сам документ-регистратор.
  2. Неразрешенные ссылки при считывании набора записей: когда в промежуточный узел загружается набор записей подчиненного регистра, поле Регистратор содержит объект ДокументСсылка (созданный по GUID). Физически сам документ в таблицах базы данных еще отсутствует. Если в коде подписки на событие перед записью регистра происходит обращение к реквизитам через точку (например, НаборЗаписей.Отбор.Регистратор.Значение.Организация), платформа возвращает пустую ссылку или Null. В результате алгоритм определения узлов-получателей не может определить организацию и не регистрирует набор записей для нижестоящего узла.
  3. Режим загрузки данных: промежуточные узлы работают с флагом ОбменДанными.Загрузка = Истина, что отключает типовые обработчики бизнес-логики объектов и переносит всю ответственность за повторную фиксацию изменений на подписки на события и правила регистрации объектов (ПРО).

Когда следом за движениями в базу наконец записывается сам документ, он успешно считывает свою организацию и регистрируется на отправку дальше, но связанные с ним движения уже пропущены и утеряны для следующего уровня обмена.

Способ 1. Принудительная регистрация наборов записей при записи документа

Разберем наиболее надежный и распространенный подход: регистрацию подчиненных движений перенести на момент записи самого документа-регистратора.

Когда документ записывается в промежуточную базу, он уже содержит все свои реквизиты (включая организацию). В подписке на событие ПриЗаписи документа или в правилах регистрации объектов (ПРО) мы регистрируем не только сам документ, но и все подчиненные ему наборы записей по нужным регистрам.

Посмотрим на пример реализации программной регистрации движений через объект документа:


Для Каждого Движение Из РегистраторОбъект.Движения Цикл
    Набор = Движение.СоздатьНаборЗаписей();
    Набор.Отбор.Регистратор.Установить(РегистраторОбъект.Ссылка);
    ПланыОбмена.ЗарегистрироватьИзменения(УзелПолучатель, Набор);
КонецЦикла;

Важный нюанс: при реализации этого подхода необходимо отключить независимую регистрацию для самих наборов подчиненных регистров по отбору регистратора в правилах регистрации, чтобы исключить холостые и некорректные срабатывания до появления документа.

Способ 2. Получение организации напрямую из данных набора записей

Проанализируем альтернативный вариант, когда в регистре сведений или накоплений уже присутствует измерение или реквизит Организация.

Вместо разыменования реквизита через регистратор (Отбор.Регистратор.Значение.Организация), настроим чтение организации непосредственно из строк набора записей. Это позволяет корректно определить узел-получатель даже при отсутствии документа в базе.


Если НаборЗаписей.Количество() > 0 Тогда
    ЗначениеОрганизации = НаборЗаписей[0].Организация;
    // Определяем узел обмена по значению организации и регистрируем набор
    Если ЗначениеЗаполнено(ЗначениеОрганизации) Тогда
        УзелПолучатель = ПолучитьУзелПоОрганизации(ЗначениеОрганизации);
        ПланыОбмена.ЗарегистрироватьИзменения(УзелПолучатель, НаборЗаписей);
    КонецЕсли;
КонецЕсли;

Ограничение способа: если документ был отменен в проведении или очищен, в промежуточную базу придет пустой набор записей. В пустом наборе записей строк нет, поэтому извлечь организацию из измерений не получится. В таких случаях очистку движений на подчиненных узлах все равно необходимо инициировать через событие регистрации документа.

Способ 3. Пакетная регистрация после завершения загрузки сообщения

Если структура регистров сложная и включает множество зависимостей, разберем решение с отложенной перерегистрацией объектов после полной обработки входящего пакета данных.

  1. В процессе загрузки данных во временную таблицу или массив накапливаются ссылки на поступившие документы и наборы записей.
  2. В обработчике ПослеЗагрузкиДанных (или в соответствующей завершающей процедуре регламентного задания обмена), когда абсолютно все объекты пакета гарантированно физически записаны в базу данных, запускается процедура актуализации регистрации.
  3. Процедура считывает уже существующие в базе реквизиты документов-регистраторов и без ошибок регистрирует связанные с ними движения на нижестоящие узлы плана обмена.

Этот способ исключает зависимость от порядка следования тегов в XML-сообщении и обеспечивает полную целостность передаваемых данных по всей цепочке каскадного РИБ.

← На главную