Механизм бизнес-событий на конкретном примере

Публикация № 1005623

Управление - Бизнес-процессы

Документооборот бизнес-процесс бизнес-событие

23
Есть в системе 1С:Документооборот механизм бизнес-событий. Когда мне понадобилось решить конкретную задачу, гугление ни к чему конкретному не привело. Хотелось так «вжух» и всё понять про данный механизм, но в итоге пришлось лезть в код 1С и смотреть реализацию данного механизма. В данной публикации поделюсь результатами исследований, может, кому-то это поможет быстро и легко во всём разобраться.

На днях попросили меня сделать одну на первый взгляд простую и полезную настройку в 1С:Документооборот: если новый входящий документ пришёл в ответ на исходящий, то автора исходящего необходимо оповестить о новом документе не дожидаясь резолюции руководства.

Вроде всё просто: отлавливаем создание вида связи «В ответ на» и запускаем бизнес-процесс «Ознакомление» с нужными параметрами. Но, зайдя в справочник «Виды бизнес-событий» ничего похожего на создание связи не обнаруживаем. Нам подходит только бизнес событие «Изменение входящего документа», в котором мы уже ручками будем отслеживать создание связи и запускать бизнес процесс.

Как механизм бизнес-событий работает в 1С:Документооборот? Рассмотрим на примере «Изменения входящего документа»:

  1. В модуле объекта процедурой «При записи» проверяется новый ли это документ. Если новый, то регистрируется бизнес событие «СозданиеВходящегоДокумента», если нет, то «ИзменениеВходящегоДокумента». Событие регистрируется процедурой БизнесСобытияВызовСервера.ЗарегистрироватьСобытие, где первым параметром указывается ссылка на объект.
  2. Процедура регистрации бизнес-событий создаёт событию уникальный идентификатор и пишет все данные в регистр сведений «ПроизошедшиеБизнесСобытия». На этом обработка в контексте объекта прекращается.
  3. Дальше с действие вступает регламентное задание «Обработка произошедших бизнес-событий», по умолчанию запускаемое каждые 59 секунд. Оно запускает процедуру «ОбработкаПроизошедшихБизнесСобытий», которая выбирает из регистра сведений «ПроизошедшиеБизнесСобытия» все не обработанные события и начинает их обрабатывать.
  4. Программа проверяет кто является потребителем данного бизнес-события (автозапуск бизнес-процесса, пользовательский обработчик или рассылка уведомлений) и запускает соответствующую процедуру. Дальше по коду идёт обработка исключений и очистка регистра «ПроизошедшиеБизнесСобытия».
  5. Выполнение пользовательского обработчика осуществляется в процедуре «ОбработатьСобытиеПользовательскаяОбработкаСобытий», которая выбирает все пользовательские обработчики, связанные с данным видом бизнес-события и выполняет их код. В качестве параметра «Событие» передаётся строка регистра сведений «ПроизошедшиеБизнесСобытия».

Вот такой несложный механизм.

Получается, что нам нужно всю логику разместить в дополнительном обработчике бизнес события для вида бизнес события «Изменение входящего документа» и «Создание входящего документа» т. к. при создании входящего документа на основании исходящего предварительной записи карточки документа перед созданием связи не производится.

Итак, начнём.

 
 Код дополнительного обработчика бизнес-события
Отладка = Ложь;
	
Если Отладка Тогда
	ЗаписьЖурналаРегистрации("Обработка создания связи входящего документа", УровеньЖурналаРегистрации.Информация,,,
	"Процесс запущен");
КонецЕсли;	
// (1)
СвязьДокумента = Справочники.ТипыСвязей.ПолученВОтветНа;
// ищем связанные документы (2)
Запрос = Новый Запрос;
Запрос.Текст = 
	"ВЫБРАТЬ
	|	СвязиДокументов.СвязанныйДокумент
	|ИЗ
	|	РегистрСведений.СвязиДокументов КАК СвязиДокументов
	|ГДЕ
	|	СвязиДокументов.Документ = &Документ
	|	И СвязиДокументов.ТипСвязи = &ТипСвязи
	|
	|УПОРЯДОЧИТЬ ПО
	|	СвязиДокументов.ДатаУстановки";

Запрос.УстановитьПараметр("Документ", Событие.Источник);
Запрос.УстановитьПараметр("ТипСвязи", СвязьДокумента);

РезультатЗапроса = Запрос.Выполнить();

Если РезультатЗапроса.Пустой() И Отладка Тогда
	ЗаписьЖурналаРегистрации("Обработка создания связи входящего документа", УровеньЖурналаРегистрации.Информация,
			Метаданные.Справочники.ВнутренниеДокументы, Событие.Источник,
			"У документа не обнаружено нужного типа связи");
КонецЕсли;	

ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
	СвязанныйДокумент = ВыборкаДетальныеЗаписи.СвязанныйДокумент;
	// проверяем наличие процесса ознакомление у нового документа
	// он может быть завершён, но главное, чтобы он был (3)
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
				   |	ОзнакомлениеПредметы.Ссылка КАК Ссылка
				   |ИЗ
				   |	БизнесПроцесс.Ознакомление.Предметы КАК ОзнакомлениеПредметы
				   |ГДЕ
				   |	НЕ ОзнакомлениеПредметы.Ссылка.ПометкаУдаления
				   |	И ОзнакомлениеПредметы.Предмет = &Предмет
				   |	И ОзнакомлениеПредметы.РольПредмета = ЗНАЧЕНИЕ(Перечисление.РолиПредметов.Основной)";
	
	Запрос.УстановитьПараметр("Предмет", Событие.Источник);
	РезультатЗапроса = Запрос.Выполнить();
	// если это только что внесённый документ, то по нему нет ознакомлений
	НоваяСвязь = РезультатЗапроса.Пустой();
	
	Если НоваяСвязь Тогда							
		// создаём бизнес процесс Ознакомление (4)
		БизнесПроцесс = БизнесПроцессы.Ознакомление.СоздатьБизнесПроцесс();
		БизнесПроцесс.Автор = Событие.Автор;
		БизнесПроцесс.Наименование = НСтр("ru='Ознакомиться с входящим документом ""'") + Строка(Событие.Источник) + """";
		БизнесПроцесс.Описание = НСтр("ru = 'На Ваш исходящий документ '")
			+ Строка(СвязанныйДокумент) + НСтр("ru = ', был получен ответ, Вам рекомендовано ознакомиться с ним.'");
		Мультипредметность.ДобавитьПредмет(БизнесПроцесс, Событие.Источник);
		БизнесПроцесс.Дата = ТекущаяДата();
		БизнесПроцесс.СрокИсполненияПроцесса = БизнесПроцесс.Дата + 3 * 86400;
		БизнесПроцесс.Состояние =  Перечисления.СостоянияБизнесПроцессов.Активен;
		
		НоваяСтрока = БизнесПроцесс.Исполнители.Добавить();
		НоваяСтрока.Исполнитель = СвязанныйДокумент.Подготовил;
		
		Попытка
			БизнесПроцесс.Записать();
			БизнесПроцесс.Старт();
			
			ЗаписьЖурналаРегистрации("Обработка создания связи входящего документа", УровеньЖурналаРегистрации.Информация,
				Метаданные.БизнесПроцессы.Исполнение, БизнесПроцесс.Ссылка,
					"Создан процесс ознакомления на основе связи с документом " + Строка(СвязанныйДокумент));
		Исключение
			ЗаписьЖурналаРегистрации("Обработка создания связи входящего документа", УровеньЖурналаРегистрации.Ошибка,,,
				"Процесс ознакомления не был создан, ошибка " + ОписаниеОшибки());
		КонецПопытки;					
	Иначе	
		Если Отладка Тогда
			ЗаписьЖурналаРегистрации("Обработка создания связи входящего документа", УровеньЖурналаРегистрации.Информация,
				Метаданные.Справочники.ВнутренниеДокументы, Событие.Источник,
				"Установлено, что связь уже была обработана");
		КонецЕсли;		
	КонецЕсли;			
КонецЦикла;		


Если Отладка Тогда
	ЗаписьЖурналаРегистрации("Обработка создания связи входящего документа", УровеньЖурналаРегистрации.Информация,,,
		"Процесс завершён");
КонецЕсли;

 

Первым делом получим ссылку на нужный тип связи (1).

Дальше проверим установлена ли эта связь у данного документа (2).

А дальше нам необходимо установить, что данная связь является новой, чтобы не генерировать оповещения каждый раз при сохранении карточки документа.

Алгоритм, который я предлагаю не самый точный, но рабочий.  Мы проверяем не было ли по новому документу когда-либо сформировано бизнес-процессов «Ознакомление» (3). Этот подход будет верным если при создании входящих документов автоматически не стартуют иные процессы «Ознакомление».

Ну и наконец создаём новый бизнес-процесс «Ознакомление», прикрепляем в качестве основного предмета новый документ и стартуем его выбрав в качестве исполнителя автора документа.

И всё, все счастливы, особенно исполнители исходящих запросов.

23

См. также

Специальные предложения

Избранное Подписка Сортировка: Древо
В этой теме еще нет сообщений.
Оставьте свое сообщение