| | |
| | | package com.ruoyi.approve.utils; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.ruoyi.approve.pojo.ApprovalInstance; |
| | | import com.ruoyi.approve.pojo.ApprovalInstanceNode; |
| | | import com.ruoyi.approve.pojo.ApprovalRecord; |
| | | import com.ruoyi.approve.pojo.ApprovalTask; |
| | | import com.ruoyi.approve.pojo.ApprovalTemplateNode; |
| | | import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover; |
| | | import com.ruoyi.approve.service.ApprovalInstanceNodeService; |
| | | import com.ruoyi.approve.service.ApprovalRecordService; |
| | | import com.ruoyi.approve.service.ApprovalTaskService; |
| | | import com.ruoyi.approve.service.ApprovalTemplateNodeApproverService; |
| | | import com.ruoyi.approve.service.ApprovalTemplateNodeService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 审批流程节点工具类 |
| | | */ |
| | | @Component |
| | | @RequiredArgsConstructor |
| | | public class ApproveProcessConfigNodeUtils { |
| | | |
| | | private final ApprovalInstanceNodeService instanceNodeService; |
| | | private final ApprovalTaskService approvalTaskService; |
| | | private final ApprovalRecordService approvalRecordService; |
| | | private final ApprovalTemplateNodeService approvalTemplateNodeService; |
| | | private final ApprovalTemplateNodeApproverService approvalTemplateNodeApproverService; |
| | | |
| | | } |
| | | /** |
| | | * 按当前层级创建审批节点和审批任务。 |
| | | * 该重载会同时写入一条发起审批记录。 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ApprovalInstanceNode createCurrentNodeAndTasks(ApprovalInstance instance) { |
| | | return createCurrentNodeAndTasks(instance, true); |
| | | } |
| | | |
| | | /** |
| | | * 按当前层级创建审批节点和审批任务。 |
| | | * |
| | | * @param instance 审批实例 |
| | | * @param createSubmitRecord 是否创建发起审批记录 |
| | | * @return 创建出的当前节点实例 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ApprovalInstanceNode createCurrentNodeAndTasks(ApprovalInstance instance, boolean createSubmitRecord) { |
| | | if (instance == null || instance.getId() == null) { |
| | | throw new RuntimeException("审批实例不能为空"); |
| | | } |
| | | if (instance.getTemplateId() == null) { |
| | | throw new RuntimeException("审批模板不能为空"); |
| | | } |
| | | |
| | | Integer currentLevel = instance.getCurrentLevel() == null ? 1 : instance.getCurrentLevel(); |
| | | |
| | | ApprovalInstanceNode existsNode = instanceNodeService.getOne( |
| | | new LambdaQueryWrapper<ApprovalInstanceNode>() |
| | | .eq(ApprovalInstanceNode::getInstanceId, instance.getId()) |
| | | .eq(ApprovalInstanceNode::getLevelNo, currentLevel) |
| | | .eq(ApprovalInstanceNode::getDeleted, 0) |
| | | .last("LIMIT 1") |
| | | ); |
| | | if (existsNode != null) { |
| | | return existsNode; |
| | | } |
| | | |
| | | ApprovalTemplateNode templateNode = approvalTemplateNodeService.getOne( |
| | | new LambdaQueryWrapper<ApprovalTemplateNode>() |
| | | .eq(ApprovalTemplateNode::getTemplateId, instance.getTemplateId()) |
| | | .eq(ApprovalTemplateNode::getLevelNo, currentLevel) |
| | | .orderByAsc(ApprovalTemplateNode::getId) |
| | | .last("LIMIT 1") |
| | | ); |
| | | if (templateNode == null) { |
| | | throw new RuntimeException("未找到当前层级对应的审批模板节点"); |
| | | } |
| | | |
| | | List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverService.list( |
| | | new LambdaQueryWrapper<ApprovalTemplateNodeApprover>() |
| | | .eq(ApprovalTemplateNodeApprover::getTemplateId, instance.getTemplateId()) |
| | | .eq(ApprovalTemplateNodeApprover::getNodeId, templateNode.getId()) |
| | | .eq(ApprovalTemplateNodeApprover::getDeleted, 0L) |
| | | .orderByAsc(ApprovalTemplateNodeApprover::getSortNo) |
| | | ); |
| | | if (approvers == null || approvers.isEmpty()) { |
| | | throw new RuntimeException("当前审批节点未配置审批人"); |
| | | } |
| | | |
| | | ApprovalInstanceNode instanceNode = new ApprovalInstanceNode(); |
| | | instanceNode.setInstanceId(instance.getId()); |
| | | instanceNode.setLevelNo(templateNode.getLevelNo()); |
| | | instanceNode.setApproveType(templateNode.getApproveType()); |
| | | instanceNode.setStatus("PENDING"); |
| | | instanceNode.setStartTime(LocalDateTime.now()); |
| | | instanceNode.setDeleted((byte) 0); |
| | | instanceNodeService.save(instanceNode); |
| | | |
| | | List<ApprovalTask> taskList = new ArrayList<>(approvers.size()); |
| | | for (ApprovalTemplateNodeApprover approver : approvers) { |
| | | ApprovalTask task = new ApprovalTask(); |
| | | task.setInstanceId(instance.getId()); |
| | | task.setNodeId(instanceNode.getId()); |
| | | task.setLevelNo(instanceNode.getLevelNo()); |
| | | task.setApproverId(approver.getApproverId()); |
| | | task.setApproverName(approver.getApproverName()); |
| | | task.setTaskStatus("PENDING"); |
| | | task.setIsRead((byte) 0); |
| | | task.setDeleted((byte) 0); |
| | | taskList.add(task); |
| | | } |
| | | approvalTaskService.saveBatch(taskList); |
| | | |
| | | if (createSubmitRecord) { |
| | | ApprovalRecord record = new ApprovalRecord(); |
| | | record.setInstanceId(instance.getId()); |
| | | record.setNodeId(instanceNode.getId()); |
| | | record.setOperatorId(instance.getApplicantId()); |
| | | record.setOperatorName(instance.getApplicantName()); |
| | | record.setAction("SUBMIT"); |
| | | record.setComment("发起审批"); |
| | | record.setDeleted((byte) 0); |
| | | approvalRecordService.save(record); |
| | | } |
| | | |
| | | return instanceNode; |
| | | } |
| | | |
| | | /** |
| | | * 查询当前待处理节点。 |
| | | */ |
| | | public ApprovalInstanceNode getCurrentNode(Long instanceId) { |
| | | if (instanceId == null) { |
| | | return null; |
| | | } |
| | | |
| | | return instanceNodeService.getOne( |
| | | new LambdaQueryWrapper<ApprovalInstanceNode>() |
| | | .eq(ApprovalInstanceNode::getInstanceId, instanceId) |
| | | .eq(ApprovalInstanceNode::getStatus, "PENDING") |
| | | .eq(ApprovalInstanceNode::getDeleted, 0) |
| | | .orderByAsc(ApprovalInstanceNode::getLevelNo) |
| | | .last("LIMIT 1") |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前审批层级。 |
| | | */ |
| | | public Integer getCurrentLevel(Long instanceId) { |
| | | ApprovalInstanceNode currentNode = getCurrentNode(instanceId); |
| | | return currentNode != null ? currentNode.getLevelNo() : null; |
| | | } |
| | | |
| | | /** |
| | | * 查询当前节点下的待审批任务。 |
| | | */ |
| | | public List<ApprovalTask> getCurrentPendingTasks(Long instanceId) { |
| | | if (instanceId == null) { |
| | | return List.of(); |
| | | } |
| | | |
| | | ApprovalInstanceNode currentNode = getCurrentNode(instanceId); |
| | | if (currentNode == null) { |
| | | return List.of(); |
| | | } |
| | | |
| | | return approvalTaskService.list( |
| | | new LambdaQueryWrapper<ApprovalTask>() |
| | | .eq(ApprovalTask::getInstanceId, instanceId) |
| | | .eq(ApprovalTask::getNodeId, currentNode.getId()) |
| | | .eq(ApprovalTask::getTaskStatus, "PENDING") |
| | | .eq(ApprovalTask::getDeleted, 0) |
| | | .orderByAsc(ApprovalTask::getLevelNo) |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前用户在当前节点上的待审批任务。 |
| | | */ |
| | | public ApprovalTask getCurrentUserTask(Long instanceId, Long userId) { |
| | | if (instanceId == null || userId == null) { |
| | | return null; |
| | | } |
| | | |
| | | ApprovalInstanceNode currentNode = getCurrentNode(instanceId); |
| | | if (currentNode == null) { |
| | | return null; |
| | | } |
| | | |
| | | return approvalTaskService.getOne( |
| | | new LambdaQueryWrapper<ApprovalTask>() |
| | | .eq(ApprovalTask::getInstanceId, instanceId) |
| | | .eq(ApprovalTask::getNodeId, currentNode.getId()) |
| | | .eq(ApprovalTask::getApproverId, userId) |
| | | .eq(ApprovalTask::getTaskStatus, "PENDING") |
| | | .eq(ApprovalTask::getDeleted, 0) |
| | | .last("LIMIT 1") |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * 判断当前用户是否是当前审批人。 |
| | | */ |
| | | public boolean isCurrentApprover(Long instanceId, Long userId) { |
| | | return getCurrentUserTask(instanceId, userId) != null; |
| | | } |
| | | |
| | | /** |
| | | * 查询当前节点的审批人 ID 列表。 |
| | | */ |
| | | public List<Long> getCurrentNodeApproverIds(Long instanceId) { |
| | | return getCurrentPendingTasks(instanceId).stream() |
| | | .map(ApprovalTask::getApproverId) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前节点剩余待审批人数。 |
| | | */ |
| | | public int getRemainingApproverCount(Long instanceId) { |
| | | return getCurrentPendingTasks(instanceId).size(); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前节点已同意人数。 |
| | | */ |
| | | public int getApprovedCount(Long instanceId) { |
| | | if (instanceId == null) { |
| | | return 0; |
| | | } |
| | | |
| | | ApprovalInstanceNode currentNode = getCurrentNode(instanceId); |
| | | if (currentNode == null) { |
| | | return 0; |
| | | } |
| | | |
| | | return Math.toIntExact(approvalTaskService.count( |
| | | new LambdaQueryWrapper<ApprovalTask>() |
| | | .eq(ApprovalTask::getInstanceId, instanceId) |
| | | .eq(ApprovalTask::getNodeId, currentNode.getId()) |
| | | .eq(ApprovalTask::getTaskStatus, "APPROVED") |
| | | .eq(ApprovalTask::getDeleted, 0) |
| | | )); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前节点已拒绝人数。 |
| | | */ |
| | | public int getRejectedCount(Long instanceId) { |
| | | if (instanceId == null) { |
| | | return 0; |
| | | } |
| | | |
| | | ApprovalInstanceNode currentNode = getCurrentNode(instanceId); |
| | | if (currentNode == null) { |
| | | return 0; |
| | | } |
| | | |
| | | return Math.toIntExact(approvalTaskService.count( |
| | | new LambdaQueryWrapper<ApprovalTask>() |
| | | .eq(ApprovalTask::getInstanceId, instanceId) |
| | | .eq(ApprovalTask::getNodeId, currentNode.getId()) |
| | | .eq(ApprovalTask::getTaskStatus, "REJECTED") |
| | | .eq(ApprovalTask::getDeleted, 0) |
| | | )); |
| | | } |
| | | |
| | | /** |
| | | * 判断当前节点是否可以流转到下一层。 |
| | | */ |
| | | public boolean canProceedToNextLevel(Long instanceId, String approveType) { |
| | | if (instanceId == null || approveType == null) { |
| | | return false; |
| | | } |
| | | |
| | | if (getRejectedCount(instanceId) > 0) { |
| | | return false; |
| | | } |
| | | |
| | | int totalApproverCount = getCurrentPendingTasks(instanceId).size() + getApprovedCount(instanceId); |
| | | int approvedCount = getApprovedCount(instanceId); |
| | | |
| | | if ("AND".equalsIgnoreCase(approveType)) { |
| | | return approvedCount > 0 && approvedCount == totalApproverCount; |
| | | } |
| | | if ("OR".equalsIgnoreCase(approveType)) { |
| | | return approvedCount > 0; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 查询当前用户在当前节点上的任务状态。 |
| | | */ |
| | | public String getUserTaskStatus(Long instanceId, Long userId) { |
| | | if (instanceId == null || userId == null) { |
| | | return null; |
| | | } |
| | | |
| | | ApprovalInstanceNode currentNode = getCurrentNode(instanceId); |
| | | if (currentNode == null) { |
| | | return null; |
| | | } |
| | | |
| | | ApprovalTask task = approvalTaskService.getOne( |
| | | new LambdaQueryWrapper<ApprovalTask>() |
| | | .eq(ApprovalTask::getInstanceId, instanceId) |
| | | .eq(ApprovalTask::getNodeId, currentNode.getId()) |
| | | .eq(ApprovalTask::getApproverId, userId) |
| | | .eq(ApprovalTask::getDeleted, 0) |
| | | .last("LIMIT 1") |
| | | ); |
| | | |
| | | return task != null ? task.getTaskStatus() : null; |
| | | } |
| | | |
| | | /** |
| | | * 查询指定用户的全部待审批任务。 |
| | | */ |
| | | public List<ApprovalTask> getUserAllPendingTasks(Long userId) { |
| | | if (userId == null) { |
| | | return List.of(); |
| | | } |
| | | |
| | | return approvalTaskService.list( |
| | | new LambdaQueryWrapper<ApprovalTask>() |
| | | .eq(ApprovalTask::getApproverId, userId) |
| | | .eq(ApprovalTask::getTaskStatus, "PENDING") |
| | | .eq(ApprovalTask::getDeleted, 0) |
| | | .orderByDesc(ApprovalTask::getCreateTime) |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * 查询审批实例的进度摘要。 |
| | | */ |
| | | public String getApprovalProgress(Long instanceId) { |
| | | if (instanceId == null) { |
| | | return "无效的审批实例"; |
| | | } |
| | | |
| | | ApprovalInstanceNode currentNode = getCurrentNode(instanceId); |
| | | if (currentNode == null) { |
| | | return "审批已完成或尚未开始"; |
| | | } |
| | | |
| | | int approvedCount = getApprovedCount(instanceId); |
| | | int rejectedCount = getRejectedCount(instanceId); |
| | | int pendingCount = getRemainingApproverCount(instanceId); |
| | | int totalCount = approvedCount + rejectedCount + pendingCount; |
| | | |
| | | return String.format( |
| | | "第%d级审批:总人数=%d,已同意=%d,已拒绝=%d,待审批=%d", |
| | | currentNode.getLevelNo(), |
| | | totalCount, |
| | | approvedCount, |
| | | rejectedCount, |
| | | pendingCount |
| | | ); |
| | | } |
| | | } |