diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java index 32d7cb088..f2b61dbbe 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java @@ -16,7 +16,7 @@ public enum BpmApproveMethodEnum { SINGLE_PERSON_APPROVE(1, "单人审批"), ALL_APPROVE(2, "多人会签(需所有审批人同意)"), // 会签 - APPROVE_BY_RATIO(3, "多人会签(按比例投票)"), // 会签(按比例投票) + APPROVE_BY_RATIO(3, "多人会签(按通过比例)"), // 会签(按通过比例) ANY_APPROVE_ALL_REJECT(4, "多人会签(通过只需一人,拒绝需要全员)"), // 会签(通过只需一人,拒绝需要全员) ANY_APPROVE(5, "多人或签(一名审批人通过即可)"), // 或签(通过只需一人,拒绝只需一人) SEQUENTIAL_APPROVE(6, "依次审批"); // 依次审批 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java index ada89443d..9c9176dd8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java @@ -55,6 +55,11 @@ public interface BpmnModelConstants { */ String USER_TASK_APPROVE_METHOD = "approveMethod"; + /** + * BPMN UserTask 的扩展属性,当审批方式为按通过比例时, 标记会签通过比例 + */ + String USER_TASK_APPROVE_RATIO = "approveRatio"; + /** * BPMN ExtensionElement 的扩展属性,用于标记 服务任务附属的用户任务 Id */ diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/expression/CompleteByRejectCountExpression.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/expression/CompleteByRejectCountExpression.java index 99d121b95..027a950a1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/expression/CompleteByRejectCountExpression.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/expression/CompleteByRejectCountExpression.java @@ -16,7 +16,9 @@ import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum.ANY_APPROVE_ALL_REJECT; +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum.APPROVE_BY_RATIO; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_APPROVE_METHOD; +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_APPROVE_RATIO; /** * 按拒绝人数计算会签的完成条件的流程表达式实现 @@ -28,7 +30,7 @@ import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnMode public class CompleteByRejectCountExpression { /** - * 会签的完成条件 + * 会签的完成条件 */ public boolean completionCondition(DelegateExecution execution) { FlowElement flowElement = execution.getCurrentFlowElement(); @@ -53,13 +55,29 @@ public class CompleteByRejectCountExpression { } else { // 1.2 所有人都拒绝了。设置任务拒绝变量, 会签任务完成。 后续终止流程在 ServiceTask【MultiInstanceServiceTaskExpression】处理 if (Objects.equals(nrOfInstances, rejectCount)) { - execution.setVariable(String.format("%s_reject",flowElement.getId()), Boolean.TRUE); + execution.setVariable(String.format("%s_reject", flowElement.getId()), Boolean.TRUE); return true; } return false; } + } else if (Objects.equals(APPROVE_BY_RATIO.getMethod(), approveMethod)) { + Integer approveRatio = NumberUtils.parseInt(BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_APPROVE_RATIO)); + Assert.notNull(approveRatio, "通过比例不能空"); + double approvePct = approveRatio / (double) 100; + double realApprovePct = (double) agreeCount / nrOfInstances; + // 判断通过比例 + if (realApprovePct >= approvePct) { + return true; + } + double rejectPct = (100 - approveRatio) / (double) 100; + double realRejectPct = (double) rejectCount / nrOfInstances; + // 判断拒绝比例 + if (realRejectPct >= rejectPct) { + execution.setVariable(String.format("%s_reject", flowElement.getId()), Boolean.TRUE); + return true; + } + return false; } - // TODO 多人会签(按比例投票) log.error("[completionCondition] 按拒绝人数计算会签的完成条件的审批方式[{}],配置有误", approveMethod); throw exception(GlobalErrorCodeConstants.ERROR_CONFIGURATION); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/simple/SimpleModelUserTaskConfig.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/simple/SimpleModelUserTaskConfig.java index 1ff3dd714..7523fd8b0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/simple/SimpleModelUserTaskConfig.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/simple/SimpleModelUserTaskConfig.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.simple; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType; import lombok.Data; @@ -30,10 +31,14 @@ public class SimpleModelUserTaskConfig { private List> fieldsPermission; /** - * 审批方式 + * 审批方式 {@link BpmApproveMethodEnum } */ private Integer approveMethod; + /** + * 通过比例 当审批方式为 多人会签(按通过比例) 需设置 + */ + private Integer approveRatio; /** * 超时处理 */ diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 4ad525ca1..a28eca0fa 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -493,7 +493,7 @@ public class SimpleModelUtils { // 添加表单字段权限属性元素 addFormFieldsPermission(userTaskConfig.getFieldsPermission(), userTask); // 处理多实例 - processMultiInstanceLoopCharacteristics(userTaskConfig.getApproveMethod(), userTask); + processMultiInstanceLoopCharacteristics(userTaskConfig.getApproveMethod(), userTaskConfig.getApproveRatio(), userTask); // 添加任务被拒绝的处理元素 addTaskRejectElements(userTaskConfig.getRejectHandler(), userTask); return userTask; @@ -507,7 +507,7 @@ public class SimpleModelUtils { addExtensionElement(userTask, USER_TASK_REJECT_RETURN_TASK_ID, rejectHandler.getReturnNodeId()); } - private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, UserTask userTask) { + private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, Integer approveRatio, UserTask userTask) { BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod); if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) { return; @@ -530,11 +530,16 @@ public class SimpleModelUtils { multiInstanceCharacteristics.setSequential(true); multiInstanceCharacteristics.setLoopCardinality("1"); userTask.setLoopCharacteristics(multiInstanceCharacteristics); - } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY_APPROVE_ALL_REJECT) { + } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY_APPROVE_ALL_REJECT ){ multiInstanceCharacteristics.setCompletionCondition(COMPLETE_BY_REJECT_COUNT_EXPRESSION); multiInstanceCharacteristics.setSequential(false); + } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.APPROVE_BY_RATIO) { + multiInstanceCharacteristics.setCompletionCondition(COMPLETE_BY_REJECT_COUNT_EXPRESSION); + multiInstanceCharacteristics.setSequential(false); + Assert.notNull(approveRatio, "通过比例不能为空"); + // 添加通过比例的扩展属性 + addExtensionElement(userTask, BpmnModelConstants.USER_TASK_APPROVE_RATIO, approveRatio.toString()); } - // TODO 会签(按比例投票 ) userTask.setLoopCharacteristics(multiInstanceCharacteristics); }