package com.hotent.project.manager.impl; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.hotent.base.manager.impl.BaseManagerImpl; import com.hotent.base.util.StringUtil; import com.hotent.baseInfo.req.CostTaskSearchReq; import com.hotent.constant.BaseConstant; import com.hotent.constant.NodeConstant; import com.hotent.constant.TaskStatusConstant; import com.hotent.enterpriseDeclare.req.CostTaskPageReq; import com.hotent.enterpriseDeclare.req.CostTaskReviewPageReq; import com.hotent.project.dao.CostProjectTaskDao; import com.hotent.project.manager.*; import com.hotent.project.model.CostProjectApproval; import com.hotent.project.model.CostProjectTask; import com.hotent.project.model.CostProjectTaskPreliminaryOpinion; import com.hotent.project.model.CostProjectTaskProccess; import com.hotent.uc.api.model.IUser; import com.hotent.uc.util.ContextUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * 项目任务表 服务实现类 * * @author 超级管理员 * @company 山西清众科技股份有限公司 * @since 2025-10-03 */ @Service public class CostProjectTaskManagerImpl extends BaseManagerImpl implements CostProjectTaskManager { @Autowired private CostProjectTaskProccessManager costProjectTaskProccessManager; @Autowired private CostProjectTaskManager costProjectTaskManager; @Autowired private CostNoticeManager costNoticeManager; @Autowired private CostProjectApprovalManager costProjectApprovalManager; @Autowired private CostProjectTaskPreliminaryOpinionManager preliminaryOpinionManager; @Override public List getTaskList(CostTaskSearchReq req) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); if (ObjectUtil.isNotEmpty(req.getYear())) { queryWrapper.eq(CostProjectTask::getYear, req.getYear()); } if (ObjectUtil.isNotEmpty(req.getProjectName())) { queryWrapper.like(CostProjectTask::getProjectName, req.getProjectName()); } queryWrapper.eq(CostProjectTask::getIsDeleted, BaseConstant.NORMAL_STATUS); return this.list(queryWrapper); } @Override public IPage pageListForReviewTask(CostTaskReviewPageReq req) { // 获取当前用户 IUser currentUser = ContextUtil.getCurrentUser(); String currentUserId = currentUser.getUserId(); // 1. 先查询当前用户有权限的立项(负责人或项目组成员) LambdaQueryWrapper approvalQueryWrapper = new LambdaQueryWrapper<>(); approvalQueryWrapper.eq(CostProjectApproval::getIsDeleted, "0"); approvalQueryWrapper.and(wrapper -> wrapper .eq(CostProjectApproval::getLeaderId, currentUserId) .or(projectMembersWrapper -> { projectMembersWrapper.like(CostProjectApproval::getProjectMembers, currentUserId); }) ); List accessibleApprovals = costProjectApprovalManager.list(approvalQueryWrapper); // 如果没有权限的立项,返回空结果 if (accessibleApprovals.isEmpty()) { return new Page<>(req.getPageNum(), req.getPageSize()); } // 提取有权限的立项ID列表 List accessibleProjectIds = accessibleApprovals.stream() .map(CostProjectApproval::getProjectId) .distinct() .collect(java.util.stream.Collectors.toList()); // 2. 构建任务查询条件 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); // 查询未删除的记录 queryWrapper.eq(CostProjectTask::getIsDeleted, "0"); // 查询根任务(pid为0) queryWrapper.eq(CostProjectTask::getPid, "0"); // 只查询当前用户有权限的立项对应的任务 queryWrapper.in(CostProjectTask::getProjectId, accessibleProjectIds); // 根据请求参数添加查询条件 if (StringUtil.isNotEmpty(req.getProjectName())) { queryWrapper.like(CostProjectTask::getProjectName, req.getProjectName()); } if (StringUtil.isNotEmpty(req.getStatus())) { queryWrapper.eq(CostProjectTask::getStatus, req.getStatus()); } if (StringUtil.isNotEmpty(req.getCurrentNode())) { queryWrapper.eq(CostProjectTask::getCurrentNode, req.getCurrentNode()); } // 按创建时间倒序排列 queryWrapper.orderByDesc(CostProjectTask::getCreateTime); // 创建分页对象并执行查询 Page page = new Page<>(req.getPageNum(), req.getPageSize()); IPage result = costProjectTaskManager.page(page, queryWrapper); // 填充根任务的子任务列表和流程信息 for (CostProjectTask rootTask : result.getRecords()) { // 查询子任务列表 LambdaQueryWrapper childQueryWrapper = new LambdaQueryWrapper<>(); childQueryWrapper.eq(CostProjectTask::getPid, rootTask.getId()) .eq(CostProjectTask::getIsDeleted, "0") .orderByAsc(CostProjectTask::getOrderNum); List childTasks = costProjectTaskManager.list(childQueryWrapper); for (CostProjectTask childTask : childTasks) { childTask.setStatus(TaskStatusConstant.getStatusNameByCode(childTask.getStatus())); } rootTask.setChildTasks(childTasks); rootTask.setCurrentNodeName(NodeConstant.getNodeValueByKey(rootTask.getCurrentNode())); } return result; } @Override @Transactional public void createOrUpdate(CostProjectTask costProjectTask) { //新建或更新 this.saveOrUpdate(costProjectTask); } @Override @Transactional public String saveTask(CostTaskPageReq costTaskPageReq) { // 1.校验内容是否填写完毕!todo // 2. 流程阶段变为资料初审 CostProjectTaskProccess taskProccess = costProjectTaskProccessManager.getOne( new QueryWrapper() .eq("task_id", costTaskPageReq.getTaskId()) ); taskProccess.setCurrentNode(NodeConstant.clcs.getNodeKey()); costProjectTaskProccessManager.updateById(taskProccess); // 3. 子流程状态改为审核中 CostProjectTask task = this.getById(costTaskPageReq.getTaskId()); task.setCurrentNode(NodeConstant.clcs.getNodeKey()); task.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); this.updateById(task); return "任务提交成功,已进入材料初审阶段"; } @Override public String saveYjTask(CostProjectTaskPreliminaryOpinion costProjectTaskPreliminaryOpinion) { // 1.校验内容是否填写完毕!todo preliminaryOpinionManager.createOrUpdate(costProjectTaskPreliminaryOpinion); // 3. 子流程状态改为已反馈 CostProjectTask task = this.getById(costProjectTaskPreliminaryOpinion.getTaskId()); task.setStatus(TaskStatusConstant.FEEDBACKED.getStatusCode()); this.updateById(task); return "意见反馈完成"; } @Override public String doProcessBtn(CostTaskPageReq req) { CostProjectTask task = costProjectTaskManager.getById(req.getTaskId()); String resultMessage = ""; switch (req.getKey()) { case "1": // 补充材料 resultMessage = supplementMaterial(task, req); break; case "2": // 中止 resultMessage = suspendTask(task,req); break; case "3": // 通过 resultMessage = completeTask(task); break; case "4": // 退回 resultMessage = returnToSubmit(task,req); break; default: return "未知的操作类型"; } return resultMessage; } /** * 通过,只修改状态,节点变化需要等待所有子任务完成。 */ private String completeTask(CostProjectTask task) { NodeConstant nextNode = NodeConstant.getNextNode(task.getCurrentNode()); if (nextNode == null){ return "当前节点无法通过"; } // 将当前任务置为办结 String nextNodeStatus = nextNode.getNodeKey(); task.setStatus(TaskStatusConstant.COMPLETED.getStatusCode()); task.setCurrentNode(nextNodeStatus); costProjectTaskManager.updateById(task); // 如果下一个节点是"意见告知",生成空的初步意见数据 if (NodeConstant.yjfk.getNodeKey().equals(nextNodeStatus)) { // 检查是否已存在初步意见 CostProjectTaskPreliminaryOpinion existingOpinion = preliminaryOpinionManager.getByTaskId(task.getId()); if (existingOpinion == null) { // 创建空的初步意见记录 CostProjectTaskPreliminaryOpinion preliminaryOpinion = new CostProjectTaskPreliminaryOpinion(); preliminaryOpinion.setTaskId(task.getId()); preliminaryOpinion.setStatus("draft"); preliminaryOpinion.setIsDeleted(BaseConstant.NORMAL_STATUS); preliminaryOpinionManager.createOrUpdate(preliminaryOpinion); } } // 发送通知 String title = nextNodeStatus+"通过"; String auditedUnit = task.getAuditedUnitName() == null ? "" : task.getAuditedUnitName(); String projectName = task.getProjectName() == null ? "" : task.getProjectName(); String year = task.getYear() == null ? "" : task.getYear(); String content = String.format("%s%s%s%s。", year, projectName, auditedUnit,title); String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String noticeSource = "系统"; String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), "1", title, content, enterpriseId, noticeSource, sendTarget); // 检查同一父任务下是否所有子任务均已办结;若是,父任务节点流转 List siblingTasks = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, task.getPid()) .eq(CostProjectTask::getIsDeleted, "0") ); boolean allSiblingsCompleted = siblingTasks.stream() .allMatch(s -> TaskStatusConstant.COMPLETED.getStatusCode().equals(s.getStatus())); if (allSiblingsCompleted) { CostProjectTask parentTask = costProjectTaskManager.getById(task.getPid()); if (parentTask != null) { CostProjectTask parentProccess = costProjectTaskManager.getOne( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, parentTask.getId()) ); // 将父任务流转到下一步 重置所有子任务状态 parentTask.setCurrentNode(nextNodeStatus); costProjectTaskManager.updateById(parentTask); if (parentProccess != null) { parentProccess.setCurrentNode(nextNodeStatus); costProjectTaskManager.updateById(parentProccess); } List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, parentTask.getId()) .eq(CostProjectTask::getIsDeleted, "0") ); boolean c = nextNodeStatus.equals(NodeConstant.yjfk.getNodeKey()); for (CostProjectTask child : children) { child.setStatus(c?TaskStatusConstant.WAIT_FEEDBACK.getStatusCode():TaskStatusConstant.AUDITING.getStatusCode()); costProjectTaskManager.updateById(child); } } } return title; } /** * 退回,填写退回原因 修改状态 */ private String returnToSubmit(CostProjectTask task,CostTaskPageReq req) { NodeConstant nextNode = NodeConstant.getNextNode(task.getCurrentNode()); if (nextNode == null){ return "当前节点无法通过"; } // 将当前任务置为办结 String nextNodeStatus = nextNode.getNodeKey(); // 通知内容组装 String title = nextNodeStatus+"退回"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String noticeSource = "系统"; String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), "1", title, req.getContent(), enterpriseId, noticeSource, sendTarget); // 更新任务的当前节点和状态 task.setCurrentNode(nextNodeStatus); task.setStatus(TaskStatusConstant.WAIT_SUBMIT.getStatusCode()); costProjectTaskManager.updateById(task); return title; } /** * 中止,填写中止原因 只修改状态 */ private String suspendTask(CostProjectTask task,CostTaskPageReq req) { NodeConstant nextNode = NodeConstant.getNextNode(task.getCurrentNode()); if (nextNode == null){ return "当前节点无法通过"; } // 将当前任务置为办结 String nextNodeStatus = nextNode.getNodeKey(); // 更新任务状态为中止 task.setStatus(TaskStatusConstant.SUSPENDED.getStatusCode()); costProjectTaskManager.updateById(task); // 通知内容组装 String title = nextNodeStatus+"中止"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String noticeSource = "系统"; String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), "1", title, req.getContent(), enterpriseId, noticeSource, sendTarget); // 更新流程阶段为中止 CostProjectTaskProccess taskProccess = costProjectTaskProccessManager.getOne( new LambdaQueryWrapper() .eq(CostProjectTaskProccess::getTaskId, task.getId()) ); if (taskProccess != null) { costProjectTaskProccessManager.updateById(taskProccess); } return title; } /** * 补充材料,仅发送通知,不修改任务状态或节点 */ private String supplementMaterial(CostProjectTask task, CostTaskPageReq req) { // 通知内容组装 String title = "补充材料通知"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String noticeSource = "系统"; String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), "1", title, req.getContent(), enterpriseId, noticeSource, sendTarget); return "补充材料通知已发送"; } }