Создан параллельный шлюз, последующие узлы не могут быть отклонены
Все системы, связанные с этой ошибкой
ruoyi-flowable
Чем подробнее, тем легче определить проблему
Создан параллельный шлюз, последующие узлы не могут быть отклонены
Желательно иметь возможность выбирать соответствующие узлы для отклонения
### Шаги воспроизведения
! Введите описание изображения
@Transactional(rollbackFor = Exception.class)
@Override
public void taskReturn(WfTaskBo bo) {
// Текущий узел задачи task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
if (ObjectUtil.isNull(task)) {
throw new RuntimeException("Ошибка получения информации о задаче!");
}
if (task.isSuspended()) {
throw new RuntimeException("Задача находится в состоянии приостановки");
}
// Получение информации о определении процесса
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// Получение информации о модели процесса
BpmnModel bpmnModel = repositoryService.```java
getBpmnModel(processDefinition.getId());
// Получение текущего узла задачи
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
// Получение узла перехода
FlowElement target = ModelUtils.getFlowElementById(bpmnModel, bo.getTargetKey());
// Отсканировать от текущего узла вперед, чтобы определить, является ли текущий узел и узел перехода последовательными. Если узел перехода находится на параллельном шлюзе или не на одной и той же линии, переход невозможен
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
if (!isSequential) {
throw new RuntimeException("Текущий узел относительно узла перехода не является последовательным, отклонение невозможно");
}
// Получение всех узлов задачи, которые находятся в нормальном состоянии, эти узлы не могут быть использованы напрямую, необходимо найти среди них узлы, которые нужно отклонить
List runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// Список задач, которые нужно вернуть
List currentIds = new ArrayList<>();
// Используя выходные соединения родительского шлюза, сравнивая с runTaskList, получаем задачи, которые нужно откатить
List currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// Цикл для получения ID узлов, которые нужно откатить, для установки причины отката
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
// Установка причин отката
for (String currentTaskId : currentTaskIds) {
taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), bo.getComment());
}
try {
// 1 к 1 или много к 1, currentIds — список узлов, которые нужно перейти (1 или много), targetKey — узел, к которому нужно перейти (1)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(currentIds, bo.getTargetKey()).changeState();
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("Не удалось найти экземпляр процесса, возможно, процесс изменился");
} catch (FlowableException e) {
throw new RuntimeException("Не удалось отменить или начать активность");
}
// Установка имени узла задачи
bo.setTaskName(task.getName());
// Обработка копирования пользователей
if (!copyService.makeCopy(bo)) {
throw new RuntimeException("Не удалось скопировать задачу");
}
}
@Override
public List<FlowElement> findReturnTaskList(WfTaskBo bo) {
// Текущая задача task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
// Получение информации о процессе
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// Получаем модель процесса
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
// Запрашиваем исторические узлы List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.activityType(BpmnXMLConstants.ELEMENT_TASK_USER)
.finished()
.orderByHistoricActivityInstanceEndTime().asc()
.list();
List<String> activityIdList = activityInstanceList.stream()
.map(HistoricActivityInstance::getActivityId)
.filter(activityId -> !StringUtils.equals(activityId, task.getTaskDefinitionKey()))
.distinct()
.collect(Collectors.toList());
// Получаем текущий узел задачи
FlowElement source = ModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
List<FlowElement> elementList = new ArrayList<>();
for (String activityId : activityIdList) {
FlowElement target = ModelUtils.getFlowElementById(bpmnModel, activityId);
boolean isSequential = ModelUtils.isSequentialReachable(source, target, new HashSet<>());
if (isSequential) {
elementList.add(target);
}
}
return elementList;
}