From ed8fc5f674544d3af63c6f68093ffc038385c493 Mon Sep 17 00:00:00 2001 From: dongyukun <1208714201@qq.com> Date: 星期一, 16 十二月 2024 09:30:04 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- iailab-module-bpm/iailab-module-bpm-biz/src/main/java/com/iailab/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java | 107 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 93 insertions(+), 14 deletions(-) diff --git a/iailab-module-bpm/iailab-module-bpm-biz/src/main/java/com/iailab/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java b/iailab-module-bpm/iailab-module-bpm-biz/src/main/java/com/iailab/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java index d70f332..b1a364f 100644 --- a/iailab-module-bpm/iailab-module-bpm-biz/src/main/java/com/iailab/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java +++ b/iailab-module-bpm/iailab-module-bpm-biz/src/main/java/com/iailab/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java @@ -2,23 +2,28 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; import com.iailab.framework.common.enums.CommonStatusEnum; +import com.iailab.framework.common.util.object.ObjectUtils; import com.iailab.framework.datapermission.core.annotation.DataPermission; +import com.iailab.module.bpm.enums.definition.BpmUserTaskApproveTypeEnum; +import com.iailab.module.bpm.enums.definition.BpmUserTaskAssignStartUserHandlerTypeEnum; import com.iailab.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; import com.iailab.module.bpm.framework.flowable.core.util.BpmnModelUtils; +import com.iailab.module.bpm.service.task.BpmProcessInstanceService; import com.iailab.module.system.api.user.AdminUserApi; import com.iailab.module.system.api.user.dto.AdminUserRespDTO; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.model.BpmnModel; +import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.UserTask; import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.runtime.ProcessInstance; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.iailab.module.bpm.enums.ErrorCodeConstants.MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG; @@ -57,7 +62,14 @@ List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class); // 遍历所有的 UserTask,校验审批人配置 userTaskList.forEach(userTask -> { - // 1. 非空校验 + // 1.1 非人工审批,无需校验审批人配置 + Integer approveType = BpmnModelUtils.parseApproveType(userTask); + if (ObjectUtils.equalsAny(approveType, + BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType(), + BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) { + return; + } + // 1.2 非空校验 Integer strategy = BpmnModelUtils.parseCandidateStrategy(userTask); String param = BpmnModelUtils.parseCandidateParam(userTask); if (strategy == null) { @@ -79,20 +91,66 @@ * @return 用户编号集合 */ @DataPermission(enable = false) // 忽略数据权限,避免因为过滤,导致找不到候选人 - public Set<Long> calculateUsers(DelegateExecution execution) { - Integer strategy = BpmnModelUtils.parseCandidateStrategy(execution.getCurrentFlowElement()); - String param = BpmnModelUtils.parseCandidateParam(execution.getCurrentFlowElement()); + public Set<Long> calculateUsersByTask(DelegateExecution execution) { + // 审批类型非人工审核时,不进行计算候选人。原因是:后续会自动通过、不通过 + FlowElement flowElement = execution.getCurrentFlowElement(); + Integer approveType = BpmnModelUtils.parseApproveType(flowElement); + if (ObjectUtils.equalsAny(approveType, + BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType(), + BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) { + return new HashSet<>(); + } + // 1.1 计算任务的候选人 - Set<Long> userIds = getCandidateStrategy(strategy).calculateUsers(execution, param); + Integer strategy = BpmnModelUtils.parseCandidateStrategy(flowElement); + String param = BpmnModelUtils.parseCandidateParam(flowElement); + Set<Long> userIds = getCandidateStrategy(strategy).calculateUsersByTask(execution, param); // 1.2 移除被禁用的用户 removeDisableUsers(userIds); - // 2. 校验是否有候选人 + // 2. 候选人为空时,根据“审批人为空”的配置补充 if (CollUtil.isEmpty(userIds)) { - log.error("[calculateUsers][流程任务({}/{}/{}) 任务规则({}/{}) 找不到候选人]", execution.getId(), - execution.getProcessDefinitionId(), execution.getCurrentActivityId(), strategy, param); - throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER); + userIds = getCandidateStrategy(BpmTaskCandidateStrategyEnum.ASSIGN_EMPTY.getStrategy()) + .calculateUsersByTask(execution, param); + // ASSIGN_EMPTY 策略,不需要移除被禁用的用户。原因是,再移除,可能会出现更没审批人了!!! } + + // 3. 移除发起人的用户 + ProcessInstance processInstance = SpringUtil.getBean(BpmProcessInstanceService.class) + .getProcessInstance(execution.getProcessInstanceId()); + Assert.notNull(processInstance, "流程实例({}) 不存在", execution.getProcessInstanceId()); + removeStartUserIfSkip(userIds, flowElement, Long.valueOf(processInstance.getStartUserId())); + return userIds; + } + + public Set<Long> calculateUsersByActivity(BpmnModel bpmnModel, String activityId, + Long startUserId, String processDefinitionId, Map<String, Object> processVariables) { + // 审批类型非人工审核时,不进行计算候选人。原因是:后续会自动通过、不通过 + FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, activityId); + Integer approveType = BpmnModelUtils.parseApproveType(flowElement); + if (ObjectUtils.equalsAny(approveType, + BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType(), + BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) { + return new HashSet<>(); + } + + // 1.1 计算任务的候选人 + Integer strategy = BpmnModelUtils.parseCandidateStrategy(flowElement); + String param = BpmnModelUtils.parseCandidateParam(flowElement); + Set<Long> userIds = getCandidateStrategy(strategy).calculateUsersByActivity(bpmnModel, activityId, param, + startUserId, processDefinitionId, processVariables); + // 1.2 移除被禁用的用户 + removeDisableUsers(userIds); + + // 2. 候选人为空时,根据“审批人为空”的配置补充 + if (CollUtil.isEmpty(userIds)) { + userIds = getCandidateStrategy(BpmTaskCandidateStrategyEnum.ASSIGN_EMPTY.getStrategy()) + .calculateUsersByActivity(bpmnModel, activityId, param, startUserId, processDefinitionId, processVariables); + // ASSIGN_EMPTY 策略,不需要移除被禁用的用户。原因是,再移除,可能会出现更没审批人了!!! + } + + // 3. 移除发起人的用户 + removeStartUserIfSkip(userIds, flowElement, startUserId); return userIds; } @@ -104,10 +162,31 @@ Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds); assigneeUserIds.removeIf(id -> { AdminUserRespDTO user = userMap.get(id); - return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus()); + return user == null || CommonStatusEnum.isDisable(user.getStatus()); }); } + /** + * 如果“审批人与发起人相同时”,配置了 SKIP 跳过,则移除发起人 + * + * 注意:如果只有一个候选人,则不处理,避免无法审批 + * + * @param assigneeUserIds 当前分配的候选人 + * @param flowElement 当前节点 + * @param startUserId 发起人 + */ + @VisibleForTesting + void removeStartUserIfSkip(Set<Long> assigneeUserIds, FlowElement flowElement, Long startUserId) { + if (CollUtil.size(assigneeUserIds) <= 1) { + return; + } + Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(flowElement); + if (ObjectUtil.notEqual(assignStartUserHandlerType, BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP.getType())) { + return; + } + assigneeUserIds.remove(startUserId); + } + private BpmTaskCandidateStrategy getCandidateStrategy(Integer strategy) { BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy); Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy); -- Gitblit v1.9.3