Commit 17c7fa44c1223af8cba36cb28c7a0ac95eacc420

Authored by YunaiV
1 parent 0d738fa3

【功能新增】工作流:审批类型,区分人工审批、自动通过、自动拒绝

Showing 13 changed files with 127 additions and 41 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java
@@ -14,7 +14,7 @@ import java.util.Arrays; @@ -14,7 +14,7 @@ import java.util.Arrays;
14 */ 14 */
15 @Getter 15 @Getter
16 @AllArgsConstructor 16 @AllArgsConstructor
17 -public enum BpmApproveMethodEnum implements IntArrayValuable { 17 +public enum BpmUserTaskApproveMethodEnum implements IntArrayValuable {
18 18
19 RANDOM(1, "随机挑选一人审批"), 19 RANDOM(1, "随机挑选一人审批"),
20 RATIO(2, "多人会签(按通过比例)"), // 会签(按通过比例) 20 RATIO(2, "多人会签(按通过比例)"), // 会签(按通过比例)
@@ -31,9 +31,9 @@ public enum BpmApproveMethodEnum implements IntArrayValuable { @@ -31,9 +31,9 @@ public enum BpmApproveMethodEnum implements IntArrayValuable {
31 */ 31 */
32 private final String name; 32 private final String name;
33 33
34 - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmApproveMethodEnum::getMethod).toArray(); 34 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskApproveMethodEnum::getMethod).toArray();
35 35
36 - public static BpmApproveMethodEnum valueOf(Integer method) { 36 + public static BpmUserTaskApproveMethodEnum valueOf(Integer method) {
37 return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values()); 37 return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values());
38 } 38 }
39 39
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * 用户任务的审批类型枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum BpmUserTaskApproveTypeEnum implements IntArrayValuable {
  17 +
  18 + USER(1), // 人工审批
  19 + AUTO_APPROVE(2), // 自动通过
  20 + AUTO_REJECT(3); // 自动拒绝
  21 +
  22 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskApproveTypeEnum::getType).toArray();
  23 +
  24 + private final Integer type;
  25 +
  26 + @Override
  27 + public int[] array() {
  28 + return ARRAYS;
  29 + }
  30 +
  31 +}
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java
@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.core.IntArrayValuable; @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 import lombok.Getter; 4 import lombok.Getter;
5 import lombok.RequiredArgsConstructor; 5 import lombok.RequiredArgsConstructor;
6 6
  7 +import java.util.Arrays;
  8 +
7 /** 9 /**
8 * BPM 用户任务的审批人为空时,处理类型枚举 10 * BPM 用户任务的审批人为空时,处理类型枚举
9 * 11 *
@@ -19,11 +21,13 @@ public enum BpmUserTaskAssignEmptyHandlerTypeEnum implements IntArrayValuable { @@ -19,11 +21,13 @@ public enum BpmUserTaskAssignEmptyHandlerTypeEnum implements IntArrayValuable {
19 ASSIGN_ADMIN(4), // 转交给流程管理员 21 ASSIGN_ADMIN(4), // 转交给流程管理员
20 ; 22 ;
21 23
  24 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskAssignEmptyHandlerTypeEnum::getType).toArray();
  25 +
22 private final Integer type; 26 private final Integer type;
23 27
24 @Override 28 @Override
25 public int[] array() { 29 public int[] array() {
26 - return new int[0]; 30 + return ARRAYS;
27 } 31 }
28 32
29 } 33 }
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java
@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.core.IntArrayValuable; @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 import lombok.Getter; 4 import lombok.Getter;
5 import lombok.RequiredArgsConstructor; 5 import lombok.RequiredArgsConstructor;
6 6
  7 +import java.util.Arrays;
  8 +
7 /** 9 /**
8 * BPM 用户任务的审批人与发起人相同时,处理类型枚举 10 * BPM 用户任务的审批人与发起人相同时,处理类型枚举
9 * 11 *
@@ -17,11 +19,13 @@ public enum BpmUserTaskAssignStartUserHandlerTypeEnum implements IntArrayValuabl @@ -17,11 +19,13 @@ public enum BpmUserTaskAssignStartUserHandlerTypeEnum implements IntArrayValuabl
17 SKIP(2), // 自动跳过【参考飞书】:1)如果当前节点还有其他审批人,则交由其他审批人进行审批;2)如果当前节点没有其他审批人,则该节点自动通过 19 SKIP(2), // 自动跳过【参考飞书】:1)如果当前节点还有其他审批人,则交由其他审批人进行审批;2)如果当前节点没有其他审批人,则该节点自动通过
18 TRANSFER_DEPT_LEADER(3); // 转交给部门负责人审批【参考飞书】:若部门负责人为空,则自动通过 20 TRANSFER_DEPT_LEADER(3); // 转交给部门负责人审批【参考飞书】:若部门负责人为空,则自动通过
19 21
  22 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskAssignStartUserHandlerTypeEnum::getType).toArray();
  23 +
20 private final Integer type; 24 private final Integer type;
21 25
22 @Override 26 @Override
23 public int[] array() { 27 public int[] array() {
24 - return new int[0]; 28 + return ARRAYS;
25 } 29 }
26 30
27 } 31 }
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
@@ -30,6 +30,8 @@ public enum BpmReasonEnum { @@ -30,6 +30,8 @@ public enum BpmReasonEnum {
30 ASSIGN_START_USER_TRANSFER_DEPT_LEADER("审批人与提交人为同一人时,转交给部门负责人审批"), 30 ASSIGN_START_USER_TRANSFER_DEPT_LEADER("审批人与提交人为同一人时,转交给部门负责人审批"),
31 ASSIGN_EMPTY_APPROVE("审批人为空,自动通过"), 31 ASSIGN_EMPTY_APPROVE("审批人为空,自动通过"),
32 ASSIGN_EMPTY_REJECT("审批人为空,自动不通过"), 32 ASSIGN_EMPTY_REJECT("审批人为空,自动不通过"),
  33 + APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"),
  34 + APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"),
33 ; 35 ;
34 36
35 private final String reason; 37 private final String reason;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
@@ -59,8 +59,12 @@ public class BpmSimpleModelNodeVO { @@ -59,8 +59,12 @@ public class BpmSimpleModelNodeVO {
59 @Schema(description = "候选人参数") 59 @Schema(description = "候选人参数")
60 private String candidateParam; // 用于审批,抄送节点 60 private String candidateParam; // 用于审批,抄送节点
61 61
  62 + @Schema(description = "审批节点类型", example = "1")
  63 + @InEnum(BpmUserTaskApproveTypeEnum.class)
  64 + private Integer approveType; // 用于审批节点
  65 +
62 @Schema(description = "多人审批方式", example = "1") 66 @Schema(description = "多人审批方式", example = "1")
63 - @InEnum(BpmApproveMethodEnum.class) 67 + @InEnum(BpmUserTaskApproveMethodEnum.class)
64 private Integer approveMethod; // 用于审批节点 68 private Integer approveMethod; // 用于审批节点
65 69
66 @Schema(description = "通过比例", example = "100") 70 @Schema(description = "通过比例", example = "100")
@@ -155,8 +159,6 @@ public class BpmSimpleModelNodeVO { @@ -155,8 +159,6 @@ public class BpmSimpleModelNodeVO {
155 private Boolean enable; 159 private Boolean enable;
156 } 160 }
157 161
158 - // Map<String, Integer> formPermissions; 表单权限;仅发起、审批、抄送节点会使用  
159 - // TODO @芋艿:⑥ 没有人的策略?  
160 // TODO @芋艿:条件;建议可以固化的一些选项;然后有个表达式兜底;要支持 162 // TODO @芋艿:条件;建议可以固化的一些选项;然后有个表达式兜底;要支持
161 163
162 } 164 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
5 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;  
6 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; 5 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
  6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
7 import lombok.Setter; 7 import lombok.Setter;
8 import org.flowable.bpmn.model.Activity; 8 import org.flowable.bpmn.model.Activity;
9 import org.flowable.engine.delegate.DelegateExecution; 9 import org.flowable.engine.delegate.DelegateExecution;
@@ -52,7 +52,9 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav @@ -52,7 +52,9 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav
52 // 第二步,获取任务的所有处理人 52 // 第二步,获取任务的所有处理人
53 Set<Long> assigneeUserIds = taskCandidateInvoker.calculateUsers(execution); 53 Set<Long> assigneeUserIds = taskCandidateInvoker.calculateUsers(execution);
54 if (CollUtil.isEmpty(assigneeUserIds)) { 54 if (CollUtil.isEmpty(assigneeUserIds)) {
55 - // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务,避免自动通过! 55 + // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过!
  56 + // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务
  57 + // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时
56 assigneeUserIds = SetUtils.asSet((Long) null); 58 assigneeUserIds = SetUtils.asSet((Long) null);
57 } 59 }
58 execution.setVariable(super.collectionVariable, assigneeUserIds); 60 execution.setVariable(super.collectionVariable, assigneeUserIds);
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java
@@ -2,15 +2,14 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; @@ -2,15 +2,14 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
5 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;  
6 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; 5 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
  6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
7 import lombok.Setter; 7 import lombok.Setter;
8 import org.flowable.bpmn.model.Activity; 8 import org.flowable.bpmn.model.Activity;
9 import org.flowable.engine.delegate.DelegateExecution; 9 import org.flowable.engine.delegate.DelegateExecution;
10 import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; 10 import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
11 import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; 11 import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
12 12
13 -import java.util.LinkedHashSet;  
14 import java.util.Set; 13 import java.util.Set;
15 14
16 /** 15 /**
@@ -44,9 +43,11 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB @@ -44,9 +43,11 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
44 super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); 43 super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
45 44
46 // 第二步,获取任务的所有处理人 45 // 第二步,获取任务的所有处理人
47 - Set<Long> assigneeUserIds = new LinkedHashSet<>(taskCandidateInvoker.calculateUsers(execution)); // 保证有序!!! 46 + Set<Long> assigneeUserIds = taskCandidateInvoker.calculateUsers(execution);
48 if (CollUtil.isEmpty(assigneeUserIds)) { 47 if (CollUtil.isEmpty(assigneeUserIds)) {
49 - // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务,避免自动通过! 48 + // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过!
  49 + // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务
  50 + // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时
50 assigneeUserIds = SetUtils.asSet((Long) null); 51 assigneeUserIds = SetUtils.asSet((Long) null);
51 } 52 }
52 execution.setVariable(super.collectionVariable, assigneeUserIds); 53 execution.setVariable(super.collectionVariable, assigneeUserIds);
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
@@ -6,6 +6,7 @@ import cn.hutool.core.util.RandomUtil; @@ -6,6 +6,7 @@ import cn.hutool.core.util.RandomUtil;
6 import cn.hutool.extra.spring.SpringUtil; 6 import cn.hutool.extra.spring.SpringUtil;
7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO; 7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRejectReqVO; 8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRejectReqVO;
  9 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveTypeEnum;
9 import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignEmptyHandlerTypeEnum; 10 import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignEmptyHandlerTypeEnum;
10 import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum; 11 import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
11 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; 12 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
@@ -56,18 +57,31 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @@ -56,18 +57,31 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
56 return; 57 return;
57 } 58 }
58 59
59 - // 特殊:审批人为空,根据配置是否要自动通过、自动拒绝 60 + // 特殊:处理需要自动通过、不通过的情况
  61 + Integer approveType = BpmnModelUtils.parseApproveType(userTask);
60 Integer assignEmptyHandlerType = BpmnModelUtils.parseAssignEmptyHandlerType(userTask); 62 Integer assignEmptyHandlerType = BpmnModelUtils.parseAssignEmptyHandlerType(userTask);
61 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { 63 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
62 64
63 @Override 65 @Override
64 public void afterCommit() { 66 public void afterCommit() {
65 - if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {  
66 - SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()  
67 - .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));  
68 - } else if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.REJECT.getType())) {  
69 - SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()  
70 - .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_REJECT.getReason())); 67 + // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝
  68 + if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) {
  69 + if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {
  70 + SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
  71 + .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));
  72 + } else if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.REJECT.getType())) {
  73 + SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
  74 + .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_REJECT.getReason()));
  75 + }
  76 + // 特殊情况二:【自动审核】审批类型为自动通过、不通过
  77 + } else {
  78 + if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType())) {
  79 + SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
  80 + .setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_APPROVE.getReason()));
  81 + } else if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) {
  82 + SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
  83 + .setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_REJECT.getReason()));
  84 + }
71 } 85 }
72 86
73 } 87 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java
@@ -6,7 +6,9 @@ import cn.hutool.core.util.ObjectUtil; @@ -6,7 +6,9 @@ import cn.hutool.core.util.ObjectUtil;
6 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
7 import cn.hutool.extra.spring.SpringUtil; 7 import cn.hutool.extra.spring.SpringUtil;
8 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 8 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  9 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
9 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; 10 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
  11 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveTypeEnum;
10 import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignStartUserHandlerTypeEnum; 12 import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignStartUserHandlerTypeEnum;
11 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; 13 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
12 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; 14 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
@@ -20,10 +22,7 @@ import org.flowable.bpmn.model.UserTask; @@ -20,10 +22,7 @@ import org.flowable.bpmn.model.UserTask;
20 import org.flowable.engine.delegate.DelegateExecution; 22 import org.flowable.engine.delegate.DelegateExecution;
21 import org.flowable.engine.runtime.ProcessInstance; 23 import org.flowable.engine.runtime.ProcessInstance;
22 24
23 -import java.util.HashMap;  
24 -import java.util.List;  
25 -import java.util.Map;  
26 -import java.util.Set; 25 +import java.util.*;
27 26
28 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
29 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG; 28 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG;
@@ -61,7 +60,14 @@ public class BpmTaskCandidateInvoker { @@ -61,7 +60,14 @@ public class BpmTaskCandidateInvoker {
61 List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class); 60 List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
62 // 遍历所有的 UserTask,校验审批人配置 61 // 遍历所有的 UserTask,校验审批人配置
63 userTaskList.forEach(userTask -> { 62 userTaskList.forEach(userTask -> {
64 - // 1. 非空校验 63 + // 1.1 非人工审批,无需校验审批人配置
  64 + Integer approveType = BpmnModelUtils.parseApproveType(userTask);
  65 + if (ObjectUtils.equalsAny(approveType,
  66 + BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType(),
  67 + BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) {
  68 + return;
  69 + }
  70 + // 1.2 非空校验
65 Integer strategy = BpmnModelUtils.parseCandidateStrategy(userTask); 71 Integer strategy = BpmnModelUtils.parseCandidateStrategy(userTask);
66 String param = BpmnModelUtils.parseCandidateParam(userTask); 72 String param = BpmnModelUtils.parseCandidateParam(userTask);
67 if (strategy == null) { 73 if (strategy == null) {
@@ -84,6 +90,14 @@ public class BpmTaskCandidateInvoker { @@ -84,6 +90,14 @@ public class BpmTaskCandidateInvoker {
84 */ 90 */
85 @DataPermission(enable = false) // 忽略数据权限,避免因为过滤,导致找不到候选人 91 @DataPermission(enable = false) // 忽略数据权限,避免因为过滤,导致找不到候选人
86 public Set<Long> calculateUsers(DelegateExecution execution) { 92 public Set<Long> calculateUsers(DelegateExecution execution) {
  93 + // 审批类型非人工审核时,不进行计算候选人。原因是:后续会自动通过、不通过
  94 + Integer approveType = BpmnModelUtils.parseApproveType(execution.getCurrentFlowElement());
  95 + if (ObjectUtils.equalsAny(approveType,
  96 + BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType(),
  97 + BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) {
  98 + return new HashSet<>();
  99 + }
  100 +
87 Integer strategy = BpmnModelUtils.parseCandidateStrategy(execution.getCurrentFlowElement()); 101 Integer strategy = BpmnModelUtils.parseCandidateStrategy(execution.getCurrentFlowElement());
88 String param = BpmnModelUtils.parseCandidateParam(execution.getCurrentFlowElement()); 102 String param = BpmnModelUtils.parseCandidateParam(execution.getCurrentFlowElement());
89 // 1.1 计算任务的候选人 103 // 1.1 计算任务的候选人
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
@@ -57,11 +57,15 @@ public interface BpmnModelConstants { @@ -57,11 +57,15 @@ public interface BpmnModelConstants {
57 String USER_TASK_REJECT_RETURN_TASK_ID = "rejectReturnTaskId"; 57 String USER_TASK_REJECT_RETURN_TASK_ID = "rejectReturnTaskId";
58 58
59 /** 59 /**
  60 + * BPMN UserTask 的扩展属性,用于标记用户任务的审批类型
  61 + */
  62 + String USER_TASK_APPROVE_TYPE = "approveType";
  63 +
  64 + /**
60 * BPMN UserTask 的扩展属性,用于标记用户任务的审批方式 65 * BPMN UserTask 的扩展属性,用于标记用户任务的审批方式
61 */ 66 */
62 String USER_TASK_APPROVE_METHOD = "approveMethod"; 67 String USER_TASK_APPROVE_METHOD = "approveMethod";
63 68
64 - // TODO @jason:这个命名,可能有个 fieldsPermissions 更合适点。可能 formPermissions 会更更合适。  
65 /** 69 /**
66 * BPMN ExtensionElement 流程表单字段权限元素, 用于标记字段权限 70 * BPMN ExtensionElement 流程表单字段权限元素, 用于标记字段权限
67 */ 71 */
@@ -76,6 +80,7 @@ public interface BpmnModelConstants { @@ -76,6 +80,7 @@ public interface BpmnModelConstants {
76 */ 80 */
77 String FORM_FIELD_PERMISSION_ELEMENT_PERMISSION_ATTRIBUTE = "permission"; 81 String FORM_FIELD_PERMISSION_ELEMENT_PERMISSION_ATTRIBUTE = "permission";
78 82
  83 + // TODO @jason:上面是 fieldsPermission,然后这里是 buttonsSettings;感觉有点不统一。然后 BpmSimpleModelNodeVO 里面是 fieldsPermission、buttonsSetting;
79 /** 84 /**
80 * BPMN ExtensionElement 操作按钮设置元素, 用于审批节点操作按钮设置 85 * BPMN ExtensionElement 操作按钮设置元素, 用于审批节点操作按钮设置
81 */ 86 */
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
@@ -45,6 +45,10 @@ public class BpmnModelUtils { @@ -45,6 +45,10 @@ public class BpmnModelUtils {
45 return candidateParam; 45 return candidateParam;
46 } 46 }
47 47
  48 + public static Integer parseApproveType(FlowElement userTask) {
  49 + return NumberUtils.parseInt(parseExtensionElement(userTask, BpmnModelConstants.USER_TASK_APPROVE_TYPE));
  50 + }
  51 +
48 public static BpmUserTaskRejectHandlerType parseRejectHandlerType(FlowElement userTask) { 52 public static BpmUserTaskRejectHandlerType parseRejectHandlerType(FlowElement userTask) {
49 Integer rejectHandlerType = NumberUtils.parseInt(parseExtensionElement(userTask, USER_TASK_REJECT_HANDLER_TYPE)); 53 Integer rejectHandlerType = NumberUtils.parseInt(parseExtensionElement(userTask, USER_TASK_REJECT_HANDLER_TYPE));
50 return BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType); 54 return BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
@@ -9,10 +9,7 @@ import cn.hutool.core.util.*; @@ -9,10 +9,7 @@ import cn.hutool.core.util.*;
9 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 9 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; 10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.RejectHandler; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.RejectHandler;
12 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum;  
13 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;  
14 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModeConditionType;  
15 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType; 12 +import cn.iocoder.yudao.module.bpm.enums.definition.*;
16 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; 13 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
17 import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelConditionGroups; 14 import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelConditionGroups;
18 import org.flowable.bpmn.BpmnAutoLayout; 15 import org.flowable.bpmn.BpmnAutoLayout;
@@ -448,9 +445,11 @@ public class SimpleModelUtils { @@ -448,9 +445,11 @@ public class SimpleModelUtils {
448 UserTask userTask = new UserTask(); 445 UserTask userTask = new UserTask();
449 userTask.setId(node.getId()); 446 userTask.setId(node.getId());
450 userTask.setName(node.getName()); 447 userTask.setName(node.getName());
451 - // 设置审批任务的截止时间  
452 - if (node.getTimeoutHandler() != null && node.getTimeoutHandler().getEnable()) {  
453 - userTask.setDueDate(node.getTimeoutHandler().getTimeDuration()); 448 +
  449 + // 如果不是审批人节点,则直接返回
  450 + addExtensionElement(userTask, USER_TASK_APPROVE_TYPE, StrUtil.toStringOrNull(node.getApproveType()));
  451 + if (ObjectUtil.notEqual(node.getApproveType(), BpmUserTaskApproveTypeEnum.USER.getType())) {
  452 + return userTask;
454 } 453 }
455 454
456 // 添加候选人元素 455 // 添加候选人元素
@@ -467,6 +466,10 @@ public class SimpleModelUtils { @@ -467,6 +466,10 @@ public class SimpleModelUtils {
467 addAssignStartUserHandlerType(node.getAssignStartUserHandlerType(), userTask); 466 addAssignStartUserHandlerType(node.getAssignStartUserHandlerType(), userTask);
468 // 添加用户任务的空处理元素 467 // 添加用户任务的空处理元素
469 addAssignEmptyHandlerType(node.getAssignEmptyHandler(), userTask); 468 addAssignEmptyHandlerType(node.getAssignEmptyHandler(), userTask);
  469 + // 设置审批任务的截止时间
  470 + if (node.getTimeoutHandler() != null && node.getTimeoutHandler().getEnable()) {
  471 + userTask.setDueDate(node.getTimeoutHandler().getTimeDuration());
  472 + }
470 return userTask; 473 return userTask;
471 } 474 }
472 475
@@ -494,8 +497,8 @@ public class SimpleModelUtils { @@ -494,8 +497,8 @@ public class SimpleModelUtils {
494 } 497 }
495 498
496 private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, Integer approveRatio, UserTask userTask) { 499 private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, Integer approveRatio, UserTask userTask) {
497 - BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod);  
498 - if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.RANDOM) { 500 + BpmUserTaskApproveMethodEnum approveMethodEnum = BpmUserTaskApproveMethodEnum.valueOf(approveMethod);
  501 + if (approveMethodEnum == null || approveMethodEnum == BpmUserTaskApproveMethodEnum.RANDOM) {
499 return; 502 return;
500 } 503 }
501 // 添加审批方式的扩展属性 504 // 添加审批方式的扩展属性
@@ -504,19 +507,19 @@ public class SimpleModelUtils { @@ -504,19 +507,19 @@ public class SimpleModelUtils {
504 MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics(); 507 MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics();
505 // 设置 collectionVariable。本系统用不到。仅仅为了 Flowable 校验不报错。 508 // 设置 collectionVariable。本系统用不到。仅仅为了 Flowable 校验不报错。
506 multiInstanceCharacteristics.setInputDataItem("${coll_userList}"); 509 multiInstanceCharacteristics.setInputDataItem("${coll_userList}");
507 - if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY) { 510 + if (approveMethodEnum == BpmUserTaskApproveMethodEnum.ANY) {
508 multiInstanceCharacteristics.setCompletionCondition(ANY_OF_APPROVE_COMPLETE_EXPRESSION); 511 multiInstanceCharacteristics.setCompletionCondition(ANY_OF_APPROVE_COMPLETE_EXPRESSION);
509 multiInstanceCharacteristics.setSequential(false); 512 multiInstanceCharacteristics.setSequential(false);
510 userTask.setLoopCharacteristics(multiInstanceCharacteristics); 513 userTask.setLoopCharacteristics(multiInstanceCharacteristics);
511 - } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.SEQUENTIAL) { 514 + } else if (approveMethodEnum == BpmUserTaskApproveMethodEnum.SEQUENTIAL) {
512 multiInstanceCharacteristics.setCompletionCondition(ALL_APPROVE_COMPLETE_EXPRESSION); 515 multiInstanceCharacteristics.setCompletionCondition(ALL_APPROVE_COMPLETE_EXPRESSION);
513 multiInstanceCharacteristics.setSequential(true); 516 multiInstanceCharacteristics.setSequential(true);
514 multiInstanceCharacteristics.setLoopCardinality("1"); 517 multiInstanceCharacteristics.setLoopCardinality("1");
515 userTask.setLoopCharacteristics(multiInstanceCharacteristics); 518 userTask.setLoopCharacteristics(multiInstanceCharacteristics);
516 - } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.RATIO) { 519 + } else if (approveMethodEnum == BpmUserTaskApproveMethodEnum.RATIO) {
517 Assert.notNull(approveRatio, "通过比例不能为空"); 520 Assert.notNull(approveRatio, "通过比例不能为空");
518 - double approvePct = approveRatio / (double) 100;  
519 - multiInstanceCharacteristics.setCompletionCondition(String.format(APPROVE_BY_RATIO_COMPLETE_EXPRESSION, String.format("%.2f", approvePct))); 521 + multiInstanceCharacteristics.setCompletionCondition(
  522 + String.format(APPROVE_BY_RATIO_COMPLETE_EXPRESSION, String.format("%.2f", approveRatio / (double) 100)));
520 multiInstanceCharacteristics.setSequential(false); 523 multiInstanceCharacteristics.setSequential(false);
521 } 524 }
522 userTask.setLoopCharacteristics(multiInstanceCharacteristics); 525 userTask.setLoopCharacteristics(multiInstanceCharacteristics);