Как отменить загрузку документа из подчиненного узла РИБ, если в главном узле установлен запрет на изменение

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

При работе в распределенной информационной базе (РИБ) часто возникает необходимость ограничить перезапись данных на главном узле. Разберем типичную задачу: из подчиненного узла выгружается документ, однако на главном узле у этого же документа реквизит НеИзменять имеет значение Истина. В таком случае входящий документ не должен загружаться и затирать актуальные данные главного узла.

Рассмотрим по шагам, как правильно реализовать такое условие при приеме данных, а также разберем технические нюансы работы платформы 1С.

Решение через обработчик модуля плана обмена

Основным и наиболее корректным способом фильтрации данных при загрузке в распределенной информационной базе является использование событийно-ориентированного обработчика в модуле плана обмена.

Найдем в конфигурации нужный план обмена и откроем его модуль. Нам потребуется обработчик события ПриПолученииДанныхОтПодчиненного.

Проанализируем сигнатуру этого метода:


Процедура ПриПолученииДанныхОтПодчиненного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад)
    
    // Проверяем, что обрабатываемый элемент — это нужный тип документа
    Если ТипЗнч(ЭлементДанных) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда
        
        // ВНИМАНИЕ: ЭлементДанных содержит версию объекта из подчиненного узла!
        // Чтобы узнать значение реквизита в главном узле, делаем запрос или обращение к БД по ссылке.
        Если ЗначениеЗаполнено(ЭлементДанных.Ссылка) Тогда
            
            ФлагНеИзменять = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЭлементДанных.Ссылка, "НеИзменять");
            
            Если ФлагНеИзменять = Истина Тогда
                // Отменяем загрузку документа
                ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
                
                // Регистрируем документ на отправку назад в подчиненный узел, 
                // чтобы синхронизировать данные
                ОтправкаНазад = Истина;
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;

КонецПроцедуры

Разберем важные особенности этого кода:

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

Почему не стоит использовать подписку "ПередЗаписью"

Иногда возникает идея написать проверку в подписке на событие ПередЗаписью для документа. Посмотрим, почему этот подход некорректен при обмене данными.

При загрузке сообщения обмена у записываемого объекта платформой автоматически устанавливается флаг ОбменДанными.Загрузка = Истина. Если попытаться заблокировать запись через установку Отказ = Истина в подписке на событие ПередЗаписью, платформа отменит всю текущую транзакцию загрузки данных (порцию элементов). В результате загрузка всего пакета обмена прервется с ошибкой, вместо того чтобы просто пропустить один документ.

Настройка через правила конвертации данных (КД / БСП)

Если обмен выполняется не через стандартный механизм РИБ без правил, а с использованием Библиотеки Стандартных Подсистем (БСП) и правил конвертации данных (КД2 или КД3), алгоритм фильтрации задается непосредственно в правилах обмена.

В обработчиках правил (например, ПередЗаписьюОбъекта или ПриЗагрузке) отказ от записи конкретного объекта выполняется путем установки переменной Отказ = Истина. Механизмы БСП корректно обрабатывают отказ от записи отдельного объекта в правилах, не срывая общую транзакцию загрузки всего пакета.

← На главную