Commit 17c7fa44c1223af8cba36cb28c7a0ac95eacc420
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); |