Commit 2cf5e17f4b3da37fbfe2ea51a9b577aa019a4326
Committed by
Gitee
!1303 子流程优化
Merge pull request !1303 from Lesan/feature/bpm-子流程
Showing
6 changed files
with
34 additions
and
7 deletions
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 |