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