Commit d7e1b87b1bb4322ed67900988423c97448bbe805
1 parent
7423f9dd
仿钉钉流程设计- 简化多人审批方式
Showing
3 changed files
with
30 additions
and
39 deletions
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); |