Commit 2cf5e17f4b3da37fbfe2ea51a9b577aa019a4326

Authored by 芋道源码
Committed by Gitee
2 parents 4fbe9fa4 c9a85489

!1303 子流程优化

Merge pull request !1303 from Lesan/feature/bpm-子流程
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
@@ -42,6 +42,7 @@ public interface ErrorCodeConstants { @@ -42,6 +42,7 @@ public interface ErrorCodeConstants {
42 ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消"); 42 ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消");
43 ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败"); 43 ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败");
44 ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置"); 44 ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置");
  45 + ErrorCode CHILD_PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消");
45 46
46 // ========== 流程任务 1-009-005-000 ========== 47 // ========== 流程任务 1-009-005-000 ==========
47 ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你"); 48 ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
@@ -18,6 +18,7 @@ public enum BpmReasonEnum { @@ -18,6 +18,7 @@ public enum BpmReasonEnum {
18 REJECT_TASK("审批不通过任务,原因:{}"), // 场景:用户审批不通过任务。修改文案时,需要注意 isRejectReason 方法 18 REJECT_TASK("审批不通过任务,原因:{}"), // 场景:用户审批不通过任务。修改文案时,需要注意 isRejectReason 方法
19 CANCEL_PROCESS_INSTANCE_BY_START_USER("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程 19 CANCEL_PROCESS_INSTANCE_BY_START_USER("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程
20 CANCEL_PROCESS_INSTANCE_BY_ADMIN("管理员【{}】取消流程,原因:{}"), // 场景:管理员取消流程 20 CANCEL_PROCESS_INSTANCE_BY_ADMIN("管理员【{}】取消流程,原因:{}"), // 场景:管理员取消流程
  21 + CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS("子流程自动取消,原因:主流程已取消"),
21 22
22 // ========== 流程任务的独有原因 ========== 23 // ========== 流程任务的独有原因 ==========
23 24
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
@@ -148,7 +148,6 @@ public class BpmProcessInstanceController { @@ -148,7 +148,6 @@ public class BpmProcessInstanceController {
148 processDefinition, processDefinitionInfo, startUser, dept)); 148 processDefinition, processDefinitionInfo, startUser, dept));
149 } 149 }
150 150
151 - // TODO @lesan:【子流程】子流程如果取消,主流程应该是通过、还是不通过哈?还是禁用掉子流程的取消?  
152 @DeleteMapping("/cancel-by-start-user") 151 @DeleteMapping("/cancel-by-start-user")
153 @Operation(summary = "用户取消流程实例", description = "取消发起的流程") 152 @Operation(summary = "用户取消流程实例", description = "取消发起的流程")
154 @PreAuthorize("@ss.hasPermission('bpm:process-instance:cancel')") 153 @PreAuthorize("@ss.hasPermission('bpm:process-instance:cancel')")
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java
@@ -72,6 +72,9 @@ public class BpmApprovalDetailRespVO { @@ -72,6 +72,9 @@ public class BpmApprovalDetailRespVO {
72 @Schema(description = "候选人用户列表") 72 @Schema(description = "候选人用户列表")
73 private List<UserSimpleBaseVO> candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表 73 private List<UserSimpleBaseVO> candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表
74 74
  75 + @Schema(description = "流程编号", example = "8761d8e0-0922-11f0-bd37-00ff1db677bf")
  76 + private String processInstanceId;
  77 +
75 } 78 }
76 79
77 @Schema(description = "活动节点的任务信息") 80 @Schema(description = "活动节点的任务信息")
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
@@ -813,7 +813,6 @@ public class SimpleModelUtils { @@ -813,7 +813,6 @@ public class SimpleModelUtils {
813 callActivity.setCalledElementType("key"); 813 callActivity.setCalledElementType("key");
814 // 1. 是否异步 814 // 1. 是否异步
815 if (node.getChildProcessSetting().getAsync()) { 815 if (node.getChildProcessSetting().getAsync()) {
816 - // TODO @lesan: 这里目前测试没有跳过执行call activity 后面的节点  
817 callActivity.setAsynchronous(true); 816 callActivity.setAsynchronous(true);
818 } 817 }
819 818
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -387,8 +387,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -387,8 +387,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
387 List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) { 387 List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) {
388 // 遍历 tasks 列表,只处理已结束的 UserTask 388 // 遍历 tasks 列表,只处理已结束的 UserTask
389 // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 的话,它无法成为一个节点 389 // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 的话,它无法成为一个节点
390 - // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程;  
391 - // TODO @lesan:【子流程】基于 activities 查询出 usertask、callactivity,然后拼接?如果是子流程,就是可以点击过去?  
392 List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null); 390 List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null);
393 List<ActivityNode> approvalNodes = convertList(endTasks, task -> { 391 List<ActivityNode> approvalNodes = convertList(endTasks, task -> {
394 FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); 392 FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
@@ -410,7 +408,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -410,7 +408,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
410 408
411 // 遍历 activities,只处理已结束的 StartEvent、EndEvent 409 // 遍历 activities,只处理已结束的 StartEvent、EndEvent
412 List<HistoricActivityInstance> endActivities = filterList(activities, activity -> activity.getEndTime() != null 410 List<HistoricActivityInstance> endActivities = filterList(activities, activity -> activity.getEndTime() != null
413 - && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_EVENT_START, ELEMENT_EVENT_END))); 411 + && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_EVENT_START, ELEMENT_CALL_ACTIVITY, ELEMENT_EVENT_END)));
414 endActivities.forEach(activity -> { 412 endActivities.forEach(activity -> {
415 // StartEvent:只处理 BPMN 的场景。因为,SIMPLE 情况下,已经有 START_USER_NODE 节点 413 // StartEvent:只处理 BPMN 的场景。因为,SIMPLE 情况下,已经有 START_USER_NODE 节点
416 if (ELEMENT_EVENT_START.equals(activity.getActivityType()) 414 if (ELEMENT_EVENT_START.equals(activity.getActivityType())
@@ -444,7 +442,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -444,7 +442,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
444 } 442 }
445 approvalNodes.add(endNode); 443 approvalNodes.add(endNode);
446 } 444 }
  445 + // CallActivity
  446 + if (ELEMENT_CALL_ACTIVITY.equals(activity.getActivityType())) {
  447 + ActivityNode callActivity = new ActivityNode().setId(activity.getId())
  448 + .setName(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getName())
  449 + .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus)
  450 + .setStartTime(DateUtils.of(activity.getStartTime()))
  451 + .setEndTime(DateUtils.of(activity.getEndTime()))
  452 + .setProcessInstanceId(activity.getProcessInstanceId());
  453 + approvalNodes.add(callActivity);
  454 + }
447 }); 455 });
  456 + approvalNodes.sort(Comparator.comparing(ActivityNode::getStartTime));
448 return approvalNodes; 457 return approvalNodes;
449 } 458 }
450 459
@@ -464,7 +473,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -464,7 +473,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
464 HistoricActivityInstance::getActivityId); 473 HistoricActivityInstance::getActivityId);
465 474
466 // 按照 activityId 分组,构建 ApprovalNodeInfo 节点 475 // 按照 activityId 分组,构建 ApprovalNodeInfo 节点
467 - // TODO @lesan:【子流程】在子流程进行审批的时候,HistoricActivityInstance 里面可以拿到 runActivities.get(0).getCalledProcessInstanceId()。要不要支持跳转???  
468 Map<String, HistoricTaskInstance> taskMap = convertMap(tasks, HistoricTaskInstance::getId); 476 Map<String, HistoricTaskInstance> taskMap = convertMap(tasks, HistoricTaskInstance::getId);
469 return convertList(runningTaskMap.entrySet(), entry -> { 477 return convertList(runningTaskMap.entrySet(), entry -> {
470 String activityId = entry.getKey(); 478 String activityId = entry.getKey();
@@ -510,6 +518,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -510,6 +518,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
510 approvalTaskInfo.getAssignee())); // 委派或者向前加签情况,需要先比较 owner 518 approvalTaskInfo.getAssignee())); // 委派或者向前加签情况,需要先比较 owner
511 activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); 519 activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size()));
512 } 520 }
  521 + if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) {
  522 + activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId());
  523 + }
513 return activityNode; 524 return activityNode;
514 }); 525 });
515 } 526 }
@@ -823,6 +834,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -823,6 +834,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
823 && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { 834 && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) {
824 throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); 835 throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
825 } 836 }
  837 + // 1.4 子流程不允许取消
  838 + if (StrUtil.isNotBlank(instance.getSuperExecutionId())) {
  839 + throw exception(CHILD_PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
  840 + }
826 841
827 // 2. 取消流程 842 // 2. 取消流程
828 updateProcessInstanceCancel(cancelReqVO.getId(), 843 updateProcessInstanceCancel(cancelReqVO.getId(),
@@ -849,7 +864,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -849,7 +864,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
849 BpmProcessInstanceStatusEnum.CANCEL.getStatus()); 864 BpmProcessInstanceStatusEnum.CANCEL.getStatus());
850 runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, reason); 865 runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, reason);
851 866
852 - // 2. 结束流程 867 + // 2. 取消所有子流程
  868 + List<ProcessInstance> subProcessInstances = runtimeService.createProcessInstanceQuery()
  869 + .superProcessInstanceId(id)
  870 + .list();
  871 + subProcessInstances.forEach(processInstance -> {
  872 + updateProcessInstanceCancel(processInstance.getProcessInstanceId(),
  873 + BpmReasonEnum.CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS.getReason());
  874 + });
  875 +
  876 + // 3. 结束流程
853 taskService.moveTaskToEnd(id, reason); 877 taskService.moveTaskToEnd(id, reason);
854 } 878 }
855 879