Как программно зарегистрировать документ на узле обмена при его загрузке?

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

В процессе разработки механизмов синхронизации данных в 1С часто возникает задача: документ приходит из одной базы (например, Бухгалтерия предприятия), дозаполняется в текущей базе (например, УНФ) и должен быть немедленно отправлен обратно для обновления данных в источнике. Однако стандартные механизмы Библиотеки стандартных подсистем (БСП) блокируют так называемую «эхо-регистрацию» — автоматическую регистрацию объекта на том же узле, с которого он только что был получен. Это сделано для предотвращения бесконечного цикла обмена одними и теми же данными.

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

Для начала проанализируем ситуацию: когда в 1С происходит загрузка данных, у объекта устанавливается флаг ОбменДанными.Загрузка = Истина. Типовые подписки на события в современных конфигурациях (УНФ, БП 3.0, ERP) проверяют этот флаг и, если он установлен, отключают стандартный механизм регистрации изменений. Просто вызвать метод ПланыОбмена.ЗарегистрироватьИзменения() внутри процедуры загрузки часто бывает недостаточно, так как транзакция может завершиться очисткой таблицы регистраций со стороны БСП. Если требуется принудительно отправить данные без доработки конфигурации, можно использовать инструмент для массовой регистрации объектов к обмену.

Способ 1. Использование ДополнительныхСвойств в событии ПередЗаписью

Самый корректный и безопасный путь в рамках типовых конфигураций на БСП — это использование специального флага в дополнительных свойствах объекта. Разберем этот механизм по шагам. Нам необходимо создать подписку на событие ПередЗаписью для нужного типа документа (или использовать существующую в модуле объекта).

Рассмотрим пример кода, который позволит системе «понять», что этот объект является исключением из правил:


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

Почему это работает? Модуль ОбменДаннымиСобытия при выполнении регистрации проверяет наличие свойства РегистрироватьОбъектНаУзлеОтправителе. Если оно установлено в Истина, типовой код игнорирует статус Загрузка = Истина и позволяет объекту попасть в очередь выгрузки.

Способ 2. Использование коллекции ОбменДанными.Получатели

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

Проанализируем пример использования этого метода в процедуре ПриЗаписи:


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

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

Типичные ошибки при программной регистрации

Разберем основные причины, по которым регистрация может «не взлететь», даже если вы написали код:

  1. Регистрация незаписанного объекта: Нельзя вызвать ЗарегистрироватьИзменения() для нового документа, у которого еще нет ссылки. Сначала документ должен быть записан в базу.
  2. Неправильный выбор события: Попытки регистрации в ОбработкаПроверкиЗаполнения или ОбработкаЗаполнения обречены на провал. Эти процедуры могут вызываться вне транзакции записи или до того, как объекту будет присвоена ссылка. Рекомендуется использовать ПередЗаписью (с установкой свойств) или ПриЗаписи (с наполнением коллекции получателей).
  3. Правила регистрации объектов (ПРО): В конфигурациях, использующих «Конвертацию данных 2.0», часто настроены внешние правила регистрации. Даже если вы принудительно добавили объект в таблицу регистрации, при запуске обмена система может «пересчитать» регистрации по правилам и удалить вашу запись, если документ не соответствует фильтрам правил.
  4. Отладка в фоновом задании: Обмен данными обычно выполняется в фоне. Чтобы увидеть, почему код не срабатывает, необходимо включить «Отладку фоновых заданий» в конфигураторе, иначе точки останова в модулях обмена просто не сработают.

Выясним причину через отладку

Если регистрация всё равно не происходит, выясним причину с помощью исследования общих модулей БСП. Рекомендуем поставить точку останова в общем модуле ОбменДаннымиСобытия, в процедурах, чье имя начинается с ОпределитьМассивУзловДляРегистрации. Именно там формируется окончательный список узлов, для которых будет зарегистрирован объект. Посмотрев на содержимое массива узлов перед выходом из процедуры, вы поймете, на каком этапе ваш узел «вылетает» из списка регистрации. Для проверки фактического наличия документов в целевой базе и контроля выгрузки подойдёт обработка для сверки выгрузки документов между базами.

Резюме: Для реализации надежной обратной отправки документов при обмене используйте установку свойства РегистрироватьОбъектНаУзлеОтправителе в событии ПередЗаписью. Это «чистый» способ, предусмотренный архитектурой 1С, который не нарушает логику работы типовых механизмов.

← На главную