Почему не срабатывают обработчики выгрузки и фильтрация в Конвертации данных 2.x?

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

При настройке обмена данными через конфигурацию «1С:Конвертация данных 2.x» часто возникает задача ограничить выгрузку документов и справочников определенным подразделением организации. Однако разработчики нередко сталкиваются с ситуацией, когда фильтр не отрабатывает, свойство Отказ = Истина не выставляется, и лишние объекты все равно переносятся в базу-приемник. Разберем по шагам, почему это происходит и как правильно организовать алгоритм проверки реквизитов.

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

Причина 1. Логическая ошибка в ветвлении условий «Если ... ИначеЕсли»

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

Посмотрим на пример ошибочной логики:


Если Объект.Метаданные().Реквизиты.Найти("бит_аэро_Подразделение") <> Неопределено Тогда 
    // Если этот реквизит есть у объекта, но он пустой, ветка завершится, 
    // а до проверки обычного реквизита "Подразделение" управление вообще не дойдет!
    Если ЗначениеЗаполнено(Объект.бит_аэро_Подразделение) Тогда
        Если НЕ (Объект.бит_аэро_Подразделение = ПодразделениеФильтр) Тогда
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
ИначеЕсли Объект.Метаданные().Реквизиты.Найти("Подразделение") <> Неопределено Тогда
    // До этого блока код не доходит при наличии предыдущего реквизита
    Если ЗначениеЗаполнено(Объект.Подразделение) Тогда
        Если НЕ (Объект.Подразделение = ПодразделениеФильтр) Тогда
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

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

Причина 2. Путаница между переменными «Объект» и «Источник»

В различных обработчиках правил конвертации данных контекстные переменные инициализируются по-разному:

  1. В обработчике «Перед выгрузкой объекта» (ПВО) на уровне Правил выгрузки данных (ПВД) проверяемый элемент доступен через переменную Объект.
  2. В обработчиках «Перед выгрузкой» и «Перед конвертацией объекта» на уровне Правил конвертации объектов (ПКО) выгружаемый элемент передается в переменную Источник.

Если в коде ПКО обратиться к Объект, произойдет ошибка выполнения или условие вернет Неопределено, из-за чего проверка реквизитов не выполнится.

Причина 3. Выгрузка объектов по ссылке в обход ПВД

Выясним причину, по которой отключение правил в ПВД или фильтрация в ПВО не предотвращают выгрузку документов. Обработчики ПВД срабатывают исключительно для тех объектов, которые инициированы непосредственно выборкой данных самого правила. Если же документ или справочник оказывается связан по ссылке с другим разрешенным к выгрузке объектом, он выгружается по правилам ПКО напрямую, полностью минуя ПВД и обработчик «Перед выгрузкой объекта».

Для гарантированной фильтрации связанных данных условие отказа необходимо дублировать в обработчик ПКО «Перед выгрузкой», используя переменную Источник.

Оптимальная реализация фильтрации по подразделению

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

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

Посмотрим на пример готового кода для обработчика «Перед выгрузкой объекта» (ПВО) в ПВД:


ПодразделениеФильтр = Параметры.ПодразделениеФильтр;

// Проверка реквизита "Подразделение"
Если Объект.Метаданные().Реквизиты.Найти("Подразделение") <> Неопределено Тогда
    Если ЗначениеЗаполнено(Объект.Подразделение) Тогда
        Если НЕ (Объект.Подразделение = ПодразделениеФильтр 
            ИЛИ Объект.Подразделение.ПринадлежитЭлементу(ПодразделениеФильтр)) Тогда
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

// Проверка реквизита "ПодразделениеОрганизации"
Если Объект.Метаданные().Реквизиты.Найти("ПодразделениеОрганизации") <> Неопределено Тогда
    Если ЗначениеЗаполнено(Объект.ПодразделениеОрганизации) Тогда
        Если НЕ (Объект.ПодразделениеОрганизации = ПодразделениеФильтр 
            ИЛИ Объект.ПодразделениеОрганизации.ПринадлежитЭлементу(ПодразделениеФильтр)) Тогда
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

Для обработчика «Перед выгрузкой» в ПКО аналогичный код будет выглядеть следующим образом:


ПодразделениеФильтр = Параметры.ПодразделениеФильтр;

Если Источник <> Неопределено И НЕ Отказ Тогда
    Если Источник.Метаданные().Реквизиты.Найти("Подразделение") <> Неопределено Тогда
        Если ЗначениеЗаполнено(Источник.Подразделение) Тогда
            Если НЕ (Источник.Подразделение = ПодразделениеФильтр 
                ИЛИ Источник.Подразделение.ПринадлежитЭлементу(ПодразделениеФильтр)) Тогда
                Отказ = Истина;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

Важное замечание: Метод Метаданные().Реквизиты.Найти() выполняет поиск только по дополнительным реквизитам. Если реквизит является стандартным (например, Организация), к нему следует обращаться через коллекцию СтандартныеРеквизиты.

← На главную