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