浏览代码

仿钉钉流程设计- 会签按通过比率

jason 1 年之前
父节点
当前提交
5c2fcdce15

+ 1 - 1
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, "依次审批"); // 依次审批

+ 5 - 0
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
      */

+ 21 - 3
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);
     }

+ 6 - 1
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<Map<String,String>> fieldsPermission;
 
     /**
-     * 审批方式
+     * 审批方式 {@link BpmApproveMethodEnum }
      */
     private  Integer approveMethod;
 
+    /**
+     * 通过比例  当审批方式为 多人会签(按通过比例) 需设置
+     */
+    private Integer approveRatio;
     /**
      * 超时处理
      */

+ 9 - 4
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);
     }