Commit 08f7c33cd4effaaf20fad9eaf9e49109627cda53

Authored by YunaiV
1 parent 0075d19f

fix(bpm): 优化回退逻辑健壮性与连续审批可读性

1. returnTask 在 moveExecutionsToSingleActivityId 前校验 runExecutionIds 非空,
   避免传入空集合导致 Flowable 内部报错
2. approveTask 清理退回标记变量改为先判断存在再删除,避免每次完成任务产生无谓的
   DB delete,并补充 info 日志便于排查
3. processTaskAssigned 中 sameAssigneeQuery 重命名为 approvedTaskQuery,
   贴合其「已审批通过历史任务查询」的实际语义
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -618,8 +618,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -618,8 +618,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
618 runtimeService.setVariable(task.getProcessInstanceId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskIdsByReturn); 618 runtimeService.setVariable(task.getProcessInstanceId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskIdsByReturn);
619 } 619 }
620 620
621 - // 6. 清理退回设置的不自动通过的变量。  
622 - runtimeService.removeVariable(task.getProcessInstanceId(), String.format(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey())); 621 + // 6. 清理退回设置的不自动通过的变量。仅在该标记存在时才删除,避免每次完成任务都产生无谓的 DB delete
  622 + String returnFlagKey = String.format(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey());
  623 + if (runtimeService.hasVariable(task.getProcessInstanceId(), returnFlagKey)) {
  624 + log.info("[approveTask][taskId({}) 清理退回标记变量({})]", task.getId(), returnFlagKey);
  625 + runtimeService.removeVariable(task.getProcessInstanceId(), returnFlagKey);
  626 + }
623 627
624 // 7. 调用 BPM complete 去完成任务 628 // 7. 调用 BPM complete 去完成任务
625 taskService.complete(task.getId(), variables, true); 629 taskService.complete(task.getId(), variables, true);
@@ -951,6 +955,11 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -951,6 +955,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
951 Set<String> needSimulateTaskDefinitionKeys = getNeedSimulateTaskDefinitionKeys(bpmnModel, currentTask, targetElement); 955 Set<String> needSimulateTaskDefinitionKeys = getNeedSimulateTaskDefinitionKeys(bpmnModel, currentTask, targetElement);
952 956
953 // 4. 执行驳回 957 // 4. 执行驳回
  958 + // 4.1 校验是否有可回撤的 execution,避免 moveExecutionsToSingleActivityId 传入空集合时 Flowable 内部报错
  959 + if (CollUtil.isEmpty(runExecutionIds)) {
  960 + throw exception(TASK_RETURN_FAIL_SOURCE_TARGET_ERROR);
  961 + }
  962 + // 4.2 执行驳回
954 // ① 使用 moveExecutionsToSingleActivityId 替换 moveActivityIdsToSingleActivityId。原因:当多实例任务回退的时候有问题。 963 // ① 使用 moveExecutionsToSingleActivityId 替换 moveActivityIdsToSingleActivityId。原因:当多实例任务回退的时候有问题。
955 // 相关 issue: https://github.com/flowable/flowable-engine/issues/3944 964 // 相关 issue: https://github.com/flowable/flowable-engine/issues/3944
956 // ② flowable 7.2.0 版本后,继续使用 moveActivityIdsToSingleActivityId 方法。原因:flowable 7.2.0 版本修复了该问题。 965 // ② flowable 7.2.0 版本后,继续使用 moveActivityIdsToSingleActivityId 方法。原因:flowable 7.2.0 版本修复了该问题。
@@ -1480,12 +1489,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -1480,12 +1489,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
1480 return; 1489 return;
1481 } 1490 }
1482 if (processDefinitionInfo.getAutoApprovalType() != null) { 1491 if (processDefinitionInfo.getAutoApprovalType() != null) {
1483 - HistoricTaskInstanceQuery sameAssigneeQuery = historyService.createHistoricTaskInstanceQuery() 1492 + HistoricTaskInstanceQuery approvedTaskQuery = historyService.createHistoricTaskInstanceQuery()
1484 .processInstanceId(task.getProcessInstanceId()) 1493 .processInstanceId(task.getProcessInstanceId())
1485 .taskVariableValueEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS, BpmTaskStatusEnum.APPROVE.getStatus()) 1494 .taskVariableValueEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS, BpmTaskStatusEnum.APPROVE.getStatus())
1486 .finished(); 1495 .finished();
1487 if (BpmAutoApproveTypeEnum.APPROVE_ALL.getType().equals(processDefinitionInfo.getAutoApprovalType()) 1496 if (BpmAutoApproveTypeEnum.APPROVE_ALL.getType().equals(processDefinitionInfo.getAutoApprovalType())
1488 - && sameAssigneeQuery.taskAssignee(task.getAssignee()).count() > 0) { 1497 + && approvedTaskQuery.taskAssignee(task.getAssignee()).count() > 0) {
1489 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) 1498 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
1490 .setReason(BpmAutoApproveTypeEnum.APPROVE_ALL.getName())); 1499 .setReason(BpmAutoApproveTypeEnum.APPROVE_ALL.getName()));
1491 return; 1500 return;
@@ -1500,8 +1509,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -1500,8 +1509,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
1500 List<String> sourceTaskIds = convertList(BpmnModelUtils.getElementIncomingUserTaskFlows( // 获取所有的上一个 UserTask 节点连线 1509 List<String> sourceTaskIds = convertList(BpmnModelUtils.getElementIncomingUserTaskFlows( // 获取所有的上一个 UserTask 节点连线
1501 BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey())), 1510 BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey())),
1502 SequenceFlow::getSourceRef); 1511 SequenceFlow::getSourceRef);
1503 - sameAssigneeQuery.taskDefinitionKeys(sourceTaskIds).orderByTaskCreateTime().desc(); // 设置 taskIds, 并按创建时间倒序排序  
1504 - HistoricTaskInstance firstHisTask = CollUtil.getFirst(sameAssigneeQuery.list()); 1512 + approvedTaskQuery.taskDefinitionKeys(sourceTaskIds).orderByTaskCreateTime().desc(); // 设置 taskIds, 并按创建时间倒序排序
  1513 + HistoricTaskInstance firstHisTask = CollUtil.getFirst(approvedTaskQuery.list());
1505 if (firstHisTask != null && StrUtil.equals(firstHisTask.getAssignee(), task.getAssignee())) { 1514 if (firstHisTask != null && StrUtil.equals(firstHisTask.getAssignee(), task.getAssignee())) {
1506 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) 1515 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
1507 .setReason(BpmAutoApproveTypeEnum.APPROVE_SEQUENT.getName())); 1516 .setReason(BpmAutoApproveTypeEnum.APPROVE_SEQUENT.getName()));