Как в КД 3 настроить правила регистрации объектов при проверке данных после записи?

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

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

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

Почему правила регистрации типовым образом выполняются перед записью

Выясним причину, почему разработчики БСП заложили подписку именно на событие ПередЗаписью, а не на последующие события жизненного цикла объекта:

  1. Анализ модифицированности данных. В момент выполнения ПередЗаписью объект в оперативной памяти уже содержит измененные реквизиты, но в базе данных еще хранится его исходное состояние. Механизм БСП может прочитать текущее состояние из базы данных и сравнить его с новыми значениями в памяти. Это позволяет избежать ложной регистрации, если реквизиты, значимые для правил обмена, не изменялись. В событии ПриЗаписи старая версия данных в базе уже перезаписана.
  2. Последовательность событий в транзакции. Если запись движений или наборов регистра сведений инициируется в коде обработчика ПриЗаписи справочника, цепочка событий выглядит следующим образом:
    1. Событие ПередЗаписью справочника — здесь запускается ПРО справочника (записей регистра в базе еще нет).
    2. Фиксация справочника в базе данных.
    3. Событие ПриЗаписи справочника — формирование и вызов записи набора записей регистра сведений.
    4. Событие ПередЗаписью набора записей регистра — выполнение ПРО регистра.
    5. Запись набора записей в базу.
    6. Событие ПослеЗаписи справочника.

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

Способ 1. Регистрация справочника через ПРО регистра сведений

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

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

Разберем по шагам, как настроить такую схему:

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

Способ 2. Отложенная фильтрация на этапе выгрузки данных (флаг Выгрузка)

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

Обработчики ПРО вызываются повторно перед отправкой данных на конкретный узел. В этот момент транзакция записи объекта и его движений давно завершена, а все данные надежно зафиксированы в таблицах базы данных. При повторном вызове контекстная переменная Выгрузка принимает значение Истина.

Посмотрим на пример кода в обработчике ПРО справочника:


Если Выгрузка Тогда
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |	Т.ФлагВыгрузки КАК ФлагВыгрузки
        |ИЗ
        |	РегистрСведений.ДополнительныеСвойстваТоваров КАК Т
        |ГДЕ
        |	Т.Номенклатура = &Номенклатура";
    Запрос.УстановитьПараметр("Номенклатура", Объект.Ссылка);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Если Не Выборка.ФлагВыгрузки Тогда
            Отказ = Истина;
        КонецЕсли;
    Иначе
        Отказ = Истина;
    КонецЕсли;
КонецЕсли;

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

Аналогичную логику можно реализовать и в правилах обработки данных (ПОД) на стороне базы-источника в обработчике ПриОбработке, анализируя объект ДанныеИБ. Однако фильтрация через ПРО предпочтительнее, так как ПОД выполняется на более позднем этапе выгрузки.

Способ 3. Использование собственной подписки на события

Если перенос логики в правила конвертации нежелателен или логика привязки слишком сложна для правил регистрации, задачу можно решить на уровне конфигурации или расширения:

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

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

← На главную