Commit d7e1b87b1bb4322ed67900988423c97448bbe805

Authored by jason
1 parent 7423f9dd

仿钉钉流程设计- 简化多人审批方式

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java
@@ -6,7 +6,7 @@ import lombok.Getter; @@ -6,7 +6,7 @@ import lombok.Getter;
6 6
7 // TODO @芋艿:审批方式的名字,可能要看下; 7 // TODO @芋艿:审批方式的名字,可能要看下;
8 /** 8 /**
9 - * BPM 审批方式的枚举 9 + * BPM 多人审批方式的枚举
10 * 10 *
11 * @author jason 11 * @author jason
12 */ 12 */
@@ -14,12 +14,10 @@ import lombok.Getter; @@ -14,12 +14,10 @@ import lombok.Getter;
14 @AllArgsConstructor 14 @AllArgsConstructor
15 public enum BpmApproveMethodEnum { 15 public enum BpmApproveMethodEnum {
16 16
17 - SINGLE_PERSON_APPROVE(1, "单人审批"),  
18 - ALL_APPROVE(2, "多人会签(需所有审批人同意)"), // 会签  
19 - APPROVE_BY_RATIO(3, "多人会签(按通过比例)"), // 会签(按通过比例)  
20 - ANY_APPROVE_ALL_REJECT(4, "多人会签(通过只需一人,拒绝需要全员)"), // 会签(通过只需一人,拒绝需要全员)  
21 - ANY_APPROVE(5, "多人或签(一名审批人通过即可)"), // 或签(通过只需一人,拒绝只需一人)  
22 - SEQUENTIAL_APPROVE(6, "依次审批"); // 依次审批 17 + RANDOM_SELECT_ONE_APPROVE(1, "随机挑选一人审批"),
  18 + APPROVE_BY_RATIO(2, "多人会签(按通过比例)"), // 会签(按通过比例)
  19 + ANY_APPROVE(3, "多人或签(一人通过或拒绝)"), // 或签(通过只需一人,拒绝只需一人)
  20 + SEQUENTIAL_APPROVE(4, "依次审批"); // 依次审批
23 21
24 /** 22 /**
25 * 审批方式 23 * 审批方式
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/custom/expression/CompleteByRejectCountExpression.java
@@ -15,7 +15,6 @@ import org.springframework.stereotype.Component; @@ -15,7 +15,6 @@ import org.springframework.stereotype.Component;
15 import java.util.Objects; 15 import java.util.Objects;
16 16
17 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 17 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
18 -import static cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum.ANY_APPROVE_ALL_REJECT;  
19 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum.APPROVE_BY_RATIO; 18 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum.APPROVE_BY_RATIO;
20 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_APPROVE_METHOD; 19 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_APPROVE_METHOD;
21 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_APPROVE_RATIO; 20 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_APPROVE_RATIO;
@@ -41,46 +40,46 @@ public class CompleteByRejectCountExpression { @@ -41,46 +40,46 @@ public class CompleteByRejectCountExpression {
41 // 审批方式 40 // 审批方式
42 Integer approveMethod = NumberUtils.parseInt(BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_APPROVE_METHOD)); 41 Integer approveMethod = NumberUtils.parseInt(BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_APPROVE_METHOD));
43 Assert.notNull(approveMethod, "审批方式不能空"); 42 Assert.notNull(approveMethod, "审批方式不能空");
44 - // 计算拒绝的人数  
45 - // TODO @jason:CollUtil.filter().size();貌似可以更简洁 43 + if (!Objects.equals(APPROVE_BY_RATIO.getMethod(), approveMethod)) {
  44 + log.error("[completionCondition] the execution is [{}] 审批方式[{}] 不匹配", execution, approveMethod);
  45 + throw exception(GlobalErrorCodeConstants.ERROR_CONFIGURATION);
  46 + }
  47 + // 获取拒绝人数
  48 + // TODO @jason:CollUtil.filter().size();貌似可以更简洁 @芋艿 CollUtil.filter().size() 使用这个会报错,好坑了.
46 Integer rejectCount = CollectionUtils.getSumValue(execution.getExecutions(), 49 Integer rejectCount = CollectionUtils.getSumValue(execution.getExecutions(),
47 item -> Objects.equals(BpmTaskStatusEnum.REJECT.getStatus(), item.getVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, Integer.class)) ? 1 : 0, 50 item -> Objects.equals(BpmTaskStatusEnum.REJECT.getStatus(), item.getVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, Integer.class)) ? 1 : 0,
48 Integer::sum, 0); 51 Integer::sum, 0);
49 - // 同意的人数为 完成人数 - 拒绝人数 52 + // 同意人数: 完成人数 - 拒绝人数
50 int agreeCount = nrOfCompletedInstances - rejectCount; 53 int agreeCount = nrOfCompletedInstances - rejectCount;
51 - // 1. 多人会签(通过只需一人,拒绝需要全员)  
52 - if (Objects.equals(ANY_APPROVE_ALL_REJECT.getMethod(), approveMethod)) {  
53 - // 1.1 一人同意. 会签任务完成  
54 - if (agreeCount > 0) { 54 + // 多人会签(按通过比例)
  55 + Integer approveRatio = NumberUtils.parseInt(BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_APPROVE_RATIO));
  56 + Assert.notNull(approveRatio, "通过比例不能空");
  57 + if (Objects.equals(100, approveRatio)) {
  58 + // 所有人都同意
  59 + if (agreeCount == nrOfInstances) {
55 return true; 60 return true;
56 - } else {  
57 - // 1.2 所有人都拒绝了。设置任务拒绝变量, 会签任务完成。 后续终止流程在 ServiceTask【MultiInstanceServiceTaskExpression】处理  
58 - if (Objects.equals(nrOfInstances, rejectCount)) {  
59 - execution.setVariable(String.format("%s_reject", flowElement.getId()), Boolean.TRUE);  
60 - return true;  
61 - }  
62 - return false;  
63 } 61 }
64 - } else if (Objects.equals(APPROVE_BY_RATIO.getMethod(), approveMethod)) {  
65 - Integer approveRatio = NumberUtils.parseInt(BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_APPROVE_RATIO));  
66 - Assert.notNull(approveRatio, "通过比例不能空");  
67 - double approvePct = approveRatio / (double) 100;  
68 - double realApprovePct = (double) agreeCount / nrOfInstances; 62 + // 一个人拒绝了
  63 + if (rejectCount > 0) {
  64 + execution.setVariable(String.format("%s_reject", flowElement.getId()), Boolean.TRUE);
  65 + return true;
  66 + }
  67 + } else {
69 // 判断通过比例 68 // 判断通过比例
  69 + double approvePct = approveRatio / (double) 100;
  70 + double realApprovePct = (double) agreeCount / nrOfInstances;
70 if (realApprovePct >= approvePct) { 71 if (realApprovePct >= approvePct) {
71 return true; 72 return true;
72 } 73 }
73 - double rejectPct = (100 - approveRatio) / (double) 100; 74 + double rejectPct = (100 - approveRatio) / (double) 100;
74 double realRejectPct = (double) rejectCount / nrOfInstances; 75 double realRejectPct = (double) rejectCount / nrOfInstances;
75 // 判断拒绝比例 76 // 判断拒绝比例
76 if (realRejectPct >= rejectPct) { 77 if (realRejectPct >= rejectPct) {
77 execution.setVariable(String.format("%s_reject", flowElement.getId()), Boolean.TRUE); 78 execution.setVariable(String.format("%s_reject", flowElement.getId()), Boolean.TRUE);
78 return true; 79 return true;
79 } 80 }
80 - return false;  
81 } 81 }
82 - log.error("[completionCondition] 按拒绝人数计算会签的完成条件的审批方式[{}],配置有误", approveMethod);  
83 - throw exception(GlobalErrorCodeConstants.ERROR_CONFIGURATION); 82 + return false;
84 } 83 }
85 84
86 } 85 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
@@ -506,7 +506,7 @@ public class SimpleModelUtils { @@ -506,7 +506,7 @@ public class SimpleModelUtils {
506 506
507 private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, Integer approveRatio, UserTask userTask) { 507 private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, Integer approveRatio, UserTask userTask) {
508 BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod); 508 BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod);
509 - if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) { 509 + if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.RANDOM_SELECT_ONE_APPROVE) {
510 return; 510 return;
511 } 511 }
512 // 添加审批方式的扩展属性 512 // 添加审批方式的扩展属性
@@ -515,10 +515,7 @@ public class SimpleModelUtils { @@ -515,10 +515,7 @@ public class SimpleModelUtils {
515 MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics(); 515 MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics();
516 // 设置 collectionVariable。本系统用不到。会在 仅仅为了校验。 516 // 设置 collectionVariable。本系统用不到。会在 仅仅为了校验。
517 multiInstanceCharacteristics.setInputDataItem("${coll_userList}"); 517 multiInstanceCharacteristics.setInputDataItem("${coll_userList}");
518 - if (bpmApproveMethodEnum == BpmApproveMethodEnum.ALL_APPROVE) {  
519 - multiInstanceCharacteristics.setCompletionCondition(ALL_APPROVE_COMPLETE_EXPRESSION);  
520 - multiInstanceCharacteristics.setSequential(false);  
521 - } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY_APPROVE) { 518 + if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY_APPROVE) {
522 multiInstanceCharacteristics.setCompletionCondition(ANY_OF_APPROVE_COMPLETE_EXPRESSION); 519 multiInstanceCharacteristics.setCompletionCondition(ANY_OF_APPROVE_COMPLETE_EXPRESSION);
523 multiInstanceCharacteristics.setSequential(false); 520 multiInstanceCharacteristics.setSequential(false);
524 userTask.setLoopCharacteristics(multiInstanceCharacteristics); 521 userTask.setLoopCharacteristics(multiInstanceCharacteristics);
@@ -527,9 +524,6 @@ public class SimpleModelUtils { @@ -527,9 +524,6 @@ public class SimpleModelUtils {
527 multiInstanceCharacteristics.setSequential(true); 524 multiInstanceCharacteristics.setSequential(true);
528 multiInstanceCharacteristics.setLoopCardinality("1"); 525 multiInstanceCharacteristics.setLoopCardinality("1");
529 userTask.setLoopCharacteristics(multiInstanceCharacteristics); 526 userTask.setLoopCharacteristics(multiInstanceCharacteristics);
530 - } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY_APPROVE_ALL_REJECT ){  
531 - multiInstanceCharacteristics.setCompletionCondition(COMPLETE_BY_REJECT_COUNT_EXPRESSION);  
532 - multiInstanceCharacteristics.setSequential(false);  
533 } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.APPROVE_BY_RATIO) { 527 } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.APPROVE_BY_RATIO) {
534 multiInstanceCharacteristics.setCompletionCondition(COMPLETE_BY_REJECT_COUNT_EXPRESSION); 528 multiInstanceCharacteristics.setCompletionCondition(COMPLETE_BY_REJECT_COUNT_EXPRESSION);
535 multiInstanceCharacteristics.setSequential(false); 529 multiInstanceCharacteristics.setSequential(false);