| | |
| | | |
| | | 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} 的调用者,用于调用对应的策略,实现任务的候选人的计算 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Slf4j |
| | | public class BpmTaskCandidateInvoker { |
| | |
| | | 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)) { |
| | |
| | | } |
| | | |
| | | // 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; |
| | | }); |
| | | } |
| | |
| | | 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)) { |
| | |
| | | |
| | | @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 跳过,则移除发起人 |
| | | * |
| | | * 注意:如果只有一个候选人,则不处理,避免无法审批 |