Как настроить отбор в правилах регистрации объектов по данным табличной части?

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

При настройке планов обмена на базе Библиотеки стандартных подсистем (БСП) разработчики часто сталкиваются с задачей выборочной регистрации документов. Типичный сценарий: документ должен регистрироваться на узле плана обмена, если он либо действует глобально (установлен признак в шапке), либо предназначен для конкретного магазина или подразделения, список которых указан в табличной части.

В типовом визуальном конструкторе Правил Регистрации Объектов (ПРО) отборы по свойствам объекта (ПРОБ) и свойствам плана обмена (ПРОП) работают только с реквизитами шапки. Сопоставить строки табличной части с реквизитами узла плана обмена в интерактивном режиме невозможно. Разберем, как обойти это ограничение платформы и правильно настроить регистрацию объектов с помощью обработчиков событий.

Особенности контекста обработчиков событий ПРО

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

  1. Обработчик ПередОбработкой: вызывается до вычисления узлов-получателей. В этот момент конкретный узел еще не определен, а переменные отборов плана обмена недоступны. Установка флага Отказ = Истина в этом событии полностью отменяет регистрацию объекта для всех узлов информационной базы.
  2. Обработчик ПриОбработке: предназначен для предварительного анализа и переопределения стандартной логики сопоставления.
  3. Обработчик ПослеОбработки: вызывается, когда базовые отборы уже отработали. Здесь становится доступна коллекция Получатели — массив ссылок на узлы плана обмена, для которых будет зарегистрировано изменение объекта. Именно этот массив мы можем программно перезаполнить или отфильтровать.

Способ 1. Программное заполнение массива узлов-получателей в обработчике «ПослеОбработки»

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

Разберем логику по шагам:

  1. В конструкторе ПРО оставляем стандартную выгрузку или базовые проверки шапки.
  2. В обработчике ПослеОбработки проверяем флаг действия акции по всем магазинам.
  3. Если акция действует не везде, очищаем коллекцию Получатели и заполняем её запросом, сопоставляя магазины из табличной части документа со значением реквизита узлов плана обмена.

Посмотрим на пример реализации данного обработчика:


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

КонецЕсли;

Способ 2. Разделение одного правила на два взаимоисключающих ПРО

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

Разберем структуру такой настройки:

  1. Правило №1 (Общие акции):

    В обработчике ПередОбработкой прописываем проверку:

    Отказ = Не Объект.ПоВсемМагазинам;

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

  2. Правило №2 (Адресные акции):

    В обработчике ПередОбработкой устанавливаем обратное условие:

    Отказ = Объект.ПоВсемМагазинам;

    В обработчике ПослеОбработки формируем список узлов запросом по табличной части документа (как показано в первом способе).

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

Способ 3. Определение получателей через типовые механизмы БСП

Если в конфигурации используется БСП, выясним возможность применения экспортных методов подсистемы обмена данными. Например, если список получателей объекта зависит от связанного документа или распоряжения, можно переиспользовать правила регистрации связанных объектов:


// Переопределение узлов по правилам связанного объекта
Получатели = ОпределитьПолучателей(Объект.Распоряжение.ПолучитьОбъект(), "ОбменСМагазинами");

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

Рекомендации по производительности

При реализации программных отборов в ПРО важно помнить следующие правила:

  1. Минимизация обращений к базе данных: обработчики ПРО выполняются синхронно в момент записи объекта в транзакции. Сложные запросы и соединения в обработчиках увеличивают время блокировок данных при оперативном проведении документов.
  2. Проверка на ЭтотУзел: при выборке узлов плана обмена запросом всегда исключайте текущий узел с помощью условия Ссылка <> &ЭтотУзел.
  3. Контроль пометок удаления: обязательно добавляйте условие ПометкаУдаления = Ложь, чтобы избежать регистрации изменений для неактивных узлов обмена.
← На главную