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 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 628 // 7. 调用 BPM complete 去完成任务
625 629 taskService.complete(task.getId(), variables, true);
... ... @@ -951,6 +955,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
951 955 Set<String> needSimulateTaskDefinitionKeys = getNeedSimulateTaskDefinitionKeys(bpmnModel, currentTask, targetElement);
952 956  
953 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 963 // ① 使用 moveExecutionsToSingleActivityId 替换 moveActivityIdsToSingleActivityId。原因:当多实例任务回退的时候有问题。
955 964 // 相关 issue: https://github.com/flowable/flowable-engine/issues/3944
956 965 // ② flowable 7.2.0 版本后,继续使用 moveActivityIdsToSingleActivityId 方法。原因:flowable 7.2.0 版本修复了该问题。
... ... @@ -1480,12 +1489,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
1480 1489 return;
1481 1490 }
1482 1491 if (processDefinitionInfo.getAutoApprovalType() != null) {
1483   - HistoricTaskInstanceQuery sameAssigneeQuery = historyService.createHistoricTaskInstanceQuery()
  1492 + HistoricTaskInstanceQuery approvedTaskQuery = historyService.createHistoricTaskInstanceQuery()
1484 1493 .processInstanceId(task.getProcessInstanceId())
1485 1494 .taskVariableValueEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS, BpmTaskStatusEnum.APPROVE.getStatus())
1486 1495 .finished();
1487 1496 if (BpmAutoApproveTypeEnum.APPROVE_ALL.getType().equals(processDefinitionInfo.getAutoApprovalType())
1488   - && sameAssigneeQuery.taskAssignee(task.getAssignee()).count() > 0) {
  1497 + && approvedTaskQuery.taskAssignee(task.getAssignee()).count() > 0) {
1489 1498 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
1490 1499 .setReason(BpmAutoApproveTypeEnum.APPROVE_ALL.getName()));
1491 1500 return;
... ... @@ -1500,8 +1509,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
1500 1509 List<String> sourceTaskIds = convertList(BpmnModelUtils.getElementIncomingUserTaskFlows( // 获取所有的上一个 UserTask 节点连线
1501 1510 BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey())),
1502 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 1514 if (firstHisTask != null && StrUtil.equals(firstHisTask.getAssignee(), task.getAssignee())) {
1506 1515 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
1507 1516 .setReason(BpmAutoApproveTypeEnum.APPROVE_SEQUENT.getName()));
... ...