gaoluyang
5 天以前 321564177399931273e63647f37cdddd268fa5a5
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java
@@ -26,6 +26,7 @@
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID;
/**
 * {@link BpmTaskCandidateStrategy} 的调用者,用于调用对应的策略,实现任务的候选人的计算
@@ -106,8 +107,13 @@
            Integer strategy = BpmnModelUtils.parseCandidateStrategy(flowElement);
            String param = BpmnModelUtils.parseCandidateParam(flowElement);
            Set<Long> userIds = getCandidateStrategy(strategy).calculateUsersByTask(execution, param);
            // 1.2 移除被禁用的用户
            removeDisableUsers(userIds);
            ProcessInstance processInstance = SpringUtil.getBean(BpmProcessInstanceService.class)
                    .getProcessInstance(execution.getProcessInstanceId());
            Assert.notNull(processInstance, "流程实例({}) 不存在", execution.getProcessInstanceId());
            Long startUserId = Long.valueOf(processInstance.getStartUserId());
            // 1.2 移除被禁用的用户;发起人节点必须保留发起人,
            //     否则发起人账号被禁用时该节点无人可审,流程会一直停在「发起人」节点
            removeDisableUsers(userIds, isStartUserNode(flowElement) ? startUserId : null);
            // 2. 候选人为空时,根据“审批人为空”的配置补充
            if (CollUtil.isEmpty(userIds)) {
@@ -117,10 +123,7 @@
            }
            // 3. 移除发起人的用户
            ProcessInstance processInstance = SpringUtil.getBean(BpmProcessInstanceService.class)
                    .getProcessInstance(execution.getProcessInstanceId());
            Assert.notNull(processInstance, "流程实例({}) 不存在", execution.getProcessInstanceId());
            removeStartUserIfSkip(userIds, flowElement, Long.valueOf(processInstance.getStartUserId()));
            removeStartUserIfSkip(userIds, flowElement, startUserId);
            return userIds;
        });
    }
@@ -146,8 +149,8 @@
        String param = BpmnModelUtils.parseCandidateParam(flowElement);
        Set<Long> userIds = getCandidateStrategy(strategy).calculateUsersByActivity(bpmnModel, activityId, param,
                startUserId, processDefinitionId, processVariables);
        // 1.2 移除被禁用的用户
        removeDisableUsers(userIds);
        // 1.2 移除被禁用的用户;发起人节点必须保留发起人,避免发起人禁用后流程停在「发起人」节点
        removeDisableUsers(userIds, START_USER_NODE_ID.equals(activityId) ? startUserId : null);
        // 2. 候选人为空时,根据“审批人为空”的配置补充
        if (CollUtil.isEmpty(userIds)) {
@@ -163,17 +166,38 @@
    @VisibleForTesting
    void removeDisableUsers(Set<Long> assigneeUserIds) {
        removeDisableUsers(assigneeUserIds, null);
    }
    /**
     * 移除被禁用的用户
     *
     * @param assigneeUserIds 候选人
     * @param keepUserId      需要保留的用户(发起人节点保留发起人),可为空
     */
    @VisibleForTesting
    void removeDisableUsers(Set<Long> assigneeUserIds, Long keepUserId) {
        if (CollUtil.isEmpty(assigneeUserIds)) {
            return;
        }
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);
        assigneeUserIds.removeIf(id -> {
            if (ObjectUtil.equal(id, keepUserId)) {
                return false;
            }
            AdminUserRespDTO user = userMap.get(id);
            return user == null || CommonStatusEnum.isDisable(user.getStatus());
        });
    }
    /**
     * 是否为「发起人」节点
     */
    private static boolean isStartUserNode(FlowElement flowElement) {
        return flowElement != null && START_USER_NODE_ID.equals(flowElement.getId());
    }
    /**
     * 如果“审批人与发起人相同时”,配置了 SKIP 跳过,则移除发起人
     *
     * 注意:如果只有一个候选人,则不处理,避免无法审批