Как сравнить реквизиты документа из обмена с текущими данными в базе в не-РИБ обмене?

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

При организации обмена данными в среде 1С, особенно в конфигурациях на обычных формах (таких как УТ 10.3), часто возникает задача выборочной загрузки документов. Например, если в базе-приемнике документ уже имеет определенный «финальный» статус, мы можем захотеть проигнорировать изменения, пришедшие из базы-источника, чтобы не нарушить бизнес-логику. Рассмотрим подробнее, как реализовать сравнение реквизитов объекта «в пути» с данными, уже записанными в информационной базе.

Вариант 1. Использование модуля объекта и свойства ОбменДанными.Загрузка

Самый очевидный, но требующий осторожности способ — внедрить проверку непосредственно в модуль документа. Когда данные поступают через механизмы обмена, платформа устанавливает свойству ОбменДанными.Загрузка значение Истина. Это наш главный маркер того, что объект записывается программно в процессе импорта.

Разберем, как написать код в обработчике ПередЗаписью модуля объекта:


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

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

Вариант 2. Программное управление в модуле Плана Обмена

Для не-РИБ обменов на платформе 1С 8.x существует специализированный механизм в модуле ПланаОбмена. Речь идет о процедуре ПриПолученииДанных. Этот метод позволяет перехватить каждый объект еще до того, как он начнет записываться в базу.

Посмотрим на пример реализации этой логики:


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

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

Вариант 3. Использование правил конвертации данных (КД 2.1)

Если ваш обмен построен на «Универсальном обмене данными в формате XML», то логику сравнения лучше вынести в правила (ПКО). В КД 2.1 есть обработчик «Перед загрузкой» для объекта.

Проанализируем шаги настройки в конфигурации «Конвертация данных»:

  1. Откройте нужное ПКО (Правило Конвертации Объекта).
  2. Перейдите на закладку «Обработчики событий».
  3. Вставьте код в событие «Перед загрузкой».

// В обработчике доступны параметры: Объект, Ссылка, Отказ
Если Ссылка <> Неопределено Тогда
    // Ссылка — это объект, уже найденный в базе-приемнике
    Если Ссылка.Статус = Справочники.СтатусыЗаказов.Завершен Тогда
        // Отменяем загрузку только этого конкретного объекта
        Отказ = Истина;
    КонецЕсли;
КонецЕсли;

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

Проблема рассинхронизации данных в регистрах

В процессе обсуждения часто всплывает проблема: статус в документе обновился, а в связанном Регистре Сведений (например, «История статусов») — нет. Рассмотрим, почему это происходит. При установленном флаге ОбменДанными.Загрузка = Истина подписки на события и код в ПриЗаписи, который обычно отвечает за движение по регистрам, часто обходятся проверкой:


Если ОбменДанными.Загрузка Тогда
    Возврат;
КонецЕсли;

Выясним причину: это сделано для того, чтобы движения документа, пришедшие из другой базы как самостоятельные объекты (наборы записей), не затирались повторным проведением в приемнике. Если вы блокируете запись документа по условию статуса, убедитесь, что вы также блокируете или корректно обрабатываете приходящие наборы записей регистров, иначе вы получите ситуацию, когда в документе статус «Новый», а в регистре сведений уже «Завершен».

Рекомендации по архитектуре

Для надежной работы двустороннего обмена рекомендуется придерживаться следующих правил:

Таким образом, мы рассмотрели три основных способа контроля данных при обмене. Выбор конкретного метода зависит от используемой технологии (самописный обмен через планы обмена или стандартный через XML-правила) и критичности производительности системы.

← На главную