Скажу сразу, ранее практически не попадалось задач по бизнес-процессам. А тут пришлось с нуля в также не знакомой мне области создавать подсистему "Претензионно-исковая деятельность".
Проект сдан, теперь началась работа пользователей и появилась потребность администрирования их работы. Всё, что находилось в 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)