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