package com.hotent.project.manager.impl; 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.core.toolkit.StringUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.hotent.base.manager.impl.BaseManagerImpl; import com.hotent.base.query.PageList; import com.hotent.base.query.QueryFilter; import com.hotent.base.util.AuthenticationUtil; import com.hotent.base.util.StringUtil; import com.hotent.baseInfo.manager.AuditedUnitManager; import com.hotent.baseInfo.manager.CostCatalogManager; import com.hotent.baseInfo.manager.CostDictDataManager; import com.hotent.baseInfo.manager.CostDistrictManager; import com.hotent.baseInfo.model.AuditedUnit; import com.hotent.baseInfo.model.CostCatalog; import com.hotent.baseInfo.model.CostDictData; import com.hotent.baseInfo.model.CostDistrict; import com.hotent.baseInfo.req.CostTaskSearchReq; 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.*; import com.hotent.project.resp.CostProjectApprovalDetailResp; import com.hotent.surveyinfo.manager.CostSurveyTemplateUploadManager; import com.hotent.surveyinfo.model.CostSurveyTemplateUpload; import com.hotent.sys.persistence.manager.DataDictManager; import com.hotent.sys.persistence.model.DataDict; import com.hotent.uc.api.model.IUser; import com.hotent.uc.manager.OrgManager; import com.hotent.uc.manager.UserManager; import com.hotent.uc.model.Org; import com.hotent.uc.model.User; import com.hotent.uc.util.ContextUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; import static com.hotent.base.util.AuthenticationUtil.getCurrentUserMainOrgId; /** * 项目任务表 服务实现类 * * @author 超级管理员 * @company 山西清众科技股份有限公司 * @since 2025-10-03 */ @Service public class CostProjectTaskManagerImpl extends BaseManagerImpl implements CostProjectTaskManager { @Autowired private CostDistrictManager costDistrictManager; @Autowired private CostProjectTaskProccessManager costProjectTaskProccessManager; @Autowired private CostProjectTaskManager costProjectTaskManager; @Autowired private CostNoticeManager costNoticeManager; @Resource DataDictManager dataDictManager; @Autowired UserManager userService; @Autowired private CostProjectApprovalManager costProjectApprovalManager; @Autowired private CostProjectTaskPreliminaryOpinionManager preliminaryOpinionManager; @Autowired private CostProjectTaskApprovalManager costProjectTaskApprovalManager; @Autowired private CostProjectProccessNodeManager costProjectProccessNodeManager; @Autowired private CostProjectProccessManager costProjectProccessManager; @Autowired private CostProjectTaskMaterialManager costProjectTaskMaterialManager; @Autowired private CostSurveyTemplateUploadManager costSurveyTemplateUploadManager; @Autowired private CostProjectTaskNodeManager costProjectTaskNodeManager; @Autowired private OrgManager orgManager; @Autowired private CostCatalogManager costCatalogManager; @Autowired private AuditedUnitManager auditedUnitManager; @Autowired private CostProjectTaskMaterialSummaryManager costProjectTaskMaterialSummaryManager; @Autowired private com.hotent.project.service.AsyncMaterialSummaryService asyncMaterialSummaryService; @Override public List getTaskList(CostTaskSearchReq req) throws Exception { // 获取当前用户 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 ArrayList<>(); } // 提取有权限的立项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"); // 只查询当前用户有权限的立项对应的任务 queryWrapper.in(CostProjectTask::getProjectId, accessibleProjectIds); // 按创建时间倒序排列 queryWrapper.orderByDesc(CostProjectTask::getCreateTime); return costProjectTaskManager.list(queryWrapper); } /** * 计算任务预警状态 * * @param task 任务对象 * @return 预警状态:green-绿色预警(在办理期限内) yellow-黄色预警(超过环节期限但没超过流程期限) red-红色预警(超过流程期限) */ private String calculateWarningStatus(CostProjectTask task) { // 获取任务对应的流程信息 CostProjectTaskProccess process = costProjectTaskProccessManager.getOne( new LambdaQueryWrapper() .eq(CostProjectTaskProccess::getTaskId, task.getId()) ); if (process == null) { return "green"; // 默认绿色预警 } // 获取当前环节的节点信息 CostProjectTaskNode currentNode = costProjectTaskNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectTaskNode::getTaskId, task.getId()) .eq(CostProjectTaskNode::getProcessNodeKey, task.getCurrentNode()) ); // 获取当前时间 LocalDateTime now = LocalDateTime.now(); // 1. 如果超过流程期限,红色预警 if (process.getPlannedAuditEndDate() != null && now.toLocalDate().isAfter(process.getPlannedAuditEndDate())) { return "red"; } // 2. 如果当前环节有截止时间且已超过,但未超过流程期限,黄色预警 if (currentNode != null && currentNode.getEndTime() != null && now.isAfter(currentNode.getEndTime())) { // 检查是否超过流程期限 if (process.getPlannedAuditEndDate() != null && now.toLocalDate().isAfter(process.getPlannedAuditEndDate())) { return "red"; // 超过流程期限,红色预警 } else { return "yellow"; // 超过环节期限但未超过流程期限,黄色预警 } } // 3. 默认绿色预警(在办理期限内) return "green"; } @Override public IPage pageListForReviewTask(CostTaskReviewPageReq req) throws Exception { // 获取当前用户 IUser currentUser = ContextUtil.getCurrentUser(); String currentUserId = currentUser.getUserId(); LambdaQueryWrapper approvalQueryWrapper = new LambdaQueryWrapper<>(); if (req.getType().equals(1)) { String userId = currentUser.getUserId(); User user = userService.getById(userId); Integer dataScope = user.getDataScope(); // 只能查自己和自己下属的 if(dataScope != null && dataScope != 0){ Set areaSet = new HashSet<>(); if(dataScope == 1){ String cityCode = user.getCityCode(); String codeSub = cityCode.substring(0, 4); QueryWrapper districtQueryWrapper = new QueryWrapper<>(); districtQueryWrapper.like("code", codeSub); List costDistricts = costDistrictManager.list(districtQueryWrapper); for (CostDistrict costDistrict1 : costDistricts) { areaSet.add(costDistrict1.getCode()); } } if(dataScope == 2){ String code = user.getCountyCode(); areaSet.add(code); } approvalQueryWrapper.in(CostProjectApproval::getAreaCode,areaSet); //queryWrapper.in("area_code", areaSet); } }else { // 1. 先查询当前用户有权限的立项(负责人或项目组成员) approvalQueryWrapper.eq(CostProjectApproval::getIsDeleted, "0"); approvalQueryWrapper.and(wrapper -> wrapper .eq(CostProjectApproval::getLeaderId, currentUserId) .or(projectMembersWrapper -> { projectMembersWrapper.like(CostProjectApproval::getProjectMembers, currentUserId); }) ); } if (StringUtil.isNotEmpty(req.getAuditedUnitName())) { approvalQueryWrapper.like(CostProjectApproval::getAuditedUnitName,req.getAuditedUnitName()); } if (StringUtil.isNotEmpty(req.getAuditedUnitId())) { approvalQueryWrapper.like(CostProjectApproval::getAuditedUnitId,req.getAuditedUnitId()); } if (StringUtil.isNotEmpty(req.getProjectName())) { approvalQueryWrapper.like(CostProjectApproval::getProjectName,req.getProjectName()); } if (StringUtil.isNotEmpty(req.getEndYear()) && StringUtil.isNotEmpty(req.getStartYear())) { List years = new ArrayList<>(); int startYear =Integer.parseInt(req.getStartYear()); int endYear =Integer.parseInt(req.getEndYear()); for (int year = startYear; year <=endYear; year++) { years.add(String.valueOf(year)); } String sql = "(" + years.stream() .map(y -> "FIND_IN_SET('" + y + "', audit_period) > 0") .collect(Collectors.joining(" OR ")) + ")"; approvalQueryWrapper.apply(sql); } 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()); if (StringUtil.isNotEmpty(req.getAreaCode())) { List list = costProjectTaskApprovalManager.list( new LambdaQueryWrapper().eq(CostProjectTaskApproval::getAreaCode, req.getAreaCode()) ); if (list.isEmpty()) { return new Page<>(req.getPageNum(), req.getPageSize()); } List projectIds = list.stream().map(CostProjectTaskApproval::getProjectId).collect(Collectors.toList()); accessibleProjectIds.addAll(projectIds); } // 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.getAuditedUnitName())) { queryWrapper.like(CostProjectTask::getAuditedUnitName, req.getAuditedUnitName()); } if (StringUtil.isNotEmpty(req.getStatus())) { queryWrapper.eq(CostProjectTask::getStatus, req.getStatus()); } if (StringUtil.isNotEmpty(req.getYear())) { queryWrapper.eq(CostProjectTask::getYear, req.getYear()); } if (StringUtil.isNotEmpty(req.getIsGd())) { queryWrapper.eq(CostProjectTask::getIsGd, req.getIsGd()); } if (StringUtil.isNotEmpty(req.getArchiveNo())) { queryWrapper.eq(CostProjectTask::getArchiveNo, req.getArchiveNo()); } if (StringUtil.isNotEmpty(req.getCurrentNode())) { queryWrapper.eq(CostProjectTask::getCurrentNode, req.getCurrentNode()); } if (StringUtil.isNotEmpty(req.getNCurrentNode())) { queryWrapper.ne(CostProjectTask::getCurrentNode, req.getNCurrentNode()); } if (StringUtil.isNotEmpty(req.getNStatus())) { queryWrapper.ne(CostProjectTask::getStatus, req.getNStatus()); } // 按创建时间倒序排列 queryWrapper.orderByDesc(CostProjectTask::getCreateTime); Page page = new Page<>(req.getPageNum(), req.getPageSize()); IPage result = costProjectTaskManager.page(page, queryWrapper); List rootList = result.getRecords(); if (rootList == null || rootList.isEmpty()) { return result; } List rootIds = rootList.stream() .map(CostProjectTask::getId) .collect(Collectors.toList()); List allChildTasks = costProjectTaskManager.list( new LambdaQueryWrapper() .in(CostProjectTask::getPid, rootIds) .eq(CostProjectTask::getIsDeleted, "0") .orderByAsc(CostProjectTask::getOrderNum) ); Map> childGroup = allChildTasks.stream() .collect(Collectors.groupingBy(CostProjectTask::getPid)); Set allProjectIds = new HashSet<>(); rootList.forEach(t -> allProjectIds.add(t.getProjectId())); allChildTasks.forEach(t -> allProjectIds.add(t.getProjectId())); List approvalList = costProjectApprovalManager.list( new LambdaQueryWrapper() .in(CostProjectApproval::getProjectId, allProjectIds) ); Map approvalMap = approvalList.stream().collect( Collectors.toMap(CostProjectApproval::getProjectId, v -> v) ); List list = rootList.stream().map(CostProjectTask::getAuditType).distinct().collect(Collectors.toList()); //List costDictDatas= costDictDataManager.getValueByDictType(list,null,"sys_audit_type"); QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("TYPE_ID_","1970328589832323072"); wrapper.in("KEY_",list); List costDictDatas= dataDictManager.list(wrapper); List collect = accessibleApprovals.stream().map(CostProjectApproval::getOrgId).distinct().collect(Collectors.toList()); List orgs = orgManager.getOrgByIds(collect); for (CostProjectTask rootTask : rootList) { costDictDatas.stream() .filter(c -> rootTask.getAuditType() != null && rootTask.getAuditType().equals(String.valueOf(c.getKey()))) .findAny().ifPresent(costDictData -> rootTask.setAuditTypeName(costDictData.getName())); // 根任务状态 rootTask.setStatusName(TaskStatusConstant.getStatusNameByCode(rootTask.getStatus())); rootTask.setCurrentNodeName(NodeConstant.getNodeValueByKey(rootTask.getCurrentNode())); rootTask.setWarningStatus(calculateWarningStatus(rootTask)); // 设置目录 CostProjectApproval rootDetail = approvalMap.get(rootTask.getProjectId()); if (rootDetail != null) { orgs.stream() .filter(c -> rootDetail.getOrgId() != null && rootDetail.getOrgId().equals(c.getId())) .findAny().ifPresent(costDictData -> rootTask.setOrgName(costDictData.getName())); rootTask.setCatalogId(rootDetail.getCatalogId()); if (StringUtil.isNotEmpty(rootDetail.getAreaCode())) { CostDistrict district = costDistrictManager.getOne( new LambdaQueryWrapper() .eq(CostDistrict::getCode, rootDetail.getAreaCode()) ); rootTask.setAreaName(district != null ? district.getName() : "山西省"); } } // 子任务 List childTasks = childGroup.getOrDefault(rootTask.getId(), Collections.emptyList()); for (CostProjectTask childTask : childTasks) { childTask.setStatusName(TaskStatusConstant.getStatusNameByCode(childTask.getStatus())); CostProjectApproval detail = approvalMap.get(childTask.getProjectId()); if (detail != null) { childTask.setCatalogId(detail.getCatalogId()); } } rootTask.setChildTasks(childTasks); } return result; } @Override @Transactional public void createOrUpdate(CostProjectTask costProjectTask) { //新建或更新 this.saveOrUpdate(costProjectTask); } @Override @Transactional public String saveTask(CostTaskPageReq costTaskPageReq) { // 1.校验内容是否填写完毕!t List costProjectTaskMaterials = costProjectTaskMaterialManager.listByTaskId(costTaskPageReq.getTaskId()); boolean c = costProjectTaskMaterials.stream() .filter(item -> "1".equals(item.getIsRequired())) .allMatch( item -> "1".equals(item.getIsUpload()) ); if (!c) { throw new RuntimeException("报送资料必填文件未全部填写完成!"); } List costSurveyTemplateUploads = costSurveyTemplateUploadManager.listByTaskId(costTaskPageReq.getTaskId()); boolean d = costSurveyTemplateUploads.stream() .filter(item -> "1".equals(item.getIsRequired())) .allMatch( item -> "1".equals(item.getIsUpload()) ); if (!d) { throw new RuntimeException("成本调查必填文件未全部填写完成!"); } // 2. 子流程状态改为审核中 CostProjectTask task = this.getById(costTaskPageReq.getTaskId()); String currentNode = task.getCurrentNode(); // 如果当前节点不是tjcl,则保持当前节点不变,只修改状态 if (!"tjcl".equals(currentNode)) { task.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); } else { task.setCurrentNode(NodeConstant.clcs.getNodeKey()); task.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); CostProjectTask parentTask = this.getById(task.getPid()); String parentCurrentNode = parentTask.getCurrentNode(); parentTask.setCurrentNode(NodeConstant.clcs.getNodeKey()); parentTask.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); this.updateById(parentTask); } this.updateById(task); // 发送通知 String title = NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "材料已提交"; // 操作人 String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "材料已提交" + task.getAuditedUnitName() + "的项目(" + task.getProjectName() + ")"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return "任务提交成功"; } @Override public String saveYjTask(CostProjectTaskPreliminaryOpinion costProjectTaskPreliminaryOpinion) { // 1.校验内容是否填写完毕!todo preliminaryOpinionManager.createOrUpdate(costProjectTaskPreliminaryOpinion); // 2. 子流程状态改为已反馈 CostProjectTask task = this.getById(costProjectTaskPreliminaryOpinion.getTaskId()); task.setStatus(TaskStatusConstant.FEEDBACKED.getStatusCode()); this.updateById(task); // 发送通知 String title = NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "意见已反馈"; // 操作人 String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "意见已反馈" + task.getAuditedUnitName() + "的项目(" + task.getProjectName() + ")"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return "意见反馈完成"; } @Override public String doProcessBtn(CostTaskPageReq req) { CostProjectTask task = costProjectTaskManager.getById(req.getTaskId()); // 检查任务是否已办结,只允许恢复操作 if (TaskStatusConstant.COMPLETED.getStatusCode().equals(task.getStatus())) { if (!"2".equals(req.getKey())) { throw new RuntimeException("任务已办结,仅支持恢复操作"); } } 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; case "5": // 催办 resultMessage = remindTask(task, req); break; case "6": // 退回上一步 resultMessage = backPreToSubmit(task, req); break; case "7": // 扭转下一步 resultMessage = toNextSubmit(task, req); break; case "8": // 复核 resultMessage = reviewTask(task, req); break; case "10": // 催报 resultMessage = remindUnitTask(task, req); break; case "9": // 归档(没有这个东西) resultMessage = archiveTask(task, req); break; default: return "未知的操作类型"; } return resultMessage; } /** * 通过,填写原因 修改状态 */ private String completeTask(CostProjectTask task) { CostProjectTask nTask = costProjectTaskManager.getById(task.getId()); if (!"0".equals(task.getPid())) { // 子任务 所有“是否必填”为“是”的资料“初审结果”均为“通过”. List costProjectTaskMaterials = costProjectTaskMaterialManager.listByTaskId(nTask.getId()); boolean c = costProjectTaskMaterials.stream() .filter(item -> "1".equals(item.getIsRequired()) && "1".equals(item.getIsUpload())) .allMatch( item -> "1".equals(item.getAuditedStatus()) ); if (!c) { throw new RuntimeException("报送资料未全部通过!"); } List costSurveyTemplateUploads = costSurveyTemplateUploadManager.listByTaskId(nTask.getId()); boolean d = costSurveyTemplateUploads.stream() .filter(item -> "1".equals(item.getIsRequired()) && "1".equals(item.getIsUpload())) .allMatch( item -> "1".equals(item.getAuditedStatus()) ); if (!d) { throw new RuntimeException("成本调查表未全部通过!"); } } else { List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, nTask.getId()) ); // 主任务:检查所有非中止的子任务是否都已办结 boolean allChildrenCompleted = children.stream() .filter(child -> !TaskStatusConstant.SUSPENDED.getStatusCode().equals(child.getStatus())) .allMatch(child -> TaskStatusConstant.COMPLETED.getStatusCode().equals(child.getStatus())); if (!allChildrenCompleted) { throw new RuntimeException("子任务未全部办结,主任务无法办结"); } } task.setStatus(TaskStatusConstant.COMPLETED.getStatusCode()); costProjectTaskManager.updateById(task); // 发送通知 String title = NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "通过"; // 操作人 String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "已通过" + task.getAuditedUnitName() + "的项目(" + task.getProjectName() + ")"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return title; } /** * 退回,只修改状态为不通过,不修改节点(子任务操作) */ private String returnToSubmit(CostProjectTask task, CostTaskPageReq req) { if ("0".equals(task.getPid())) { return "仅支持子任务进行此操作!"; } // 通知内容组装 String title = NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "退回"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "已退回" + task.getAuditedUnitName() + "的项目(" + task.getProjectName() + ")"; if (StringUtil.isNotEmpty(req.getContent())) { content += ",原因:" + req.getContent(); } costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); task.setStatus(TaskStatusConstant.NOT_PASSED.getStatusCode()); costProjectTaskManager.updateById(task); return title; } /** * 中止/恢复,如果是主任务中止,所有子任务同步中止;如果是主任务恢复,所有子任务同步恢复 */ private String suspendTask(CostProjectTask task, CostTaskPageReq req) { // 恢复操作只支持主任务 if (!"0".equals(task.getPid())) { throw new RuntimeException("仅支持主任务进行此操作"); } // 判断是中止还是恢复 String status = req.getStatus() == null || TaskStatusConstant.SUSPENDED.getStatusCode().equals(req.getStatus()) ? TaskStatusConstant.SUSPENDED.getStatusCode() : TaskStatusConstant.AUDITING.getStatusCode(); // 中止操作:保存中止前的状态 if (TaskStatusConstant.SUSPENDED.getStatusCode().equals(status)) { task.setPreSuspendStatus(task.getStatus()); List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, task.getId()) .eq(CostProjectTask::getIsDeleted, "0") ); for (CostProjectTask child : children) { child.setPreSuspendStatus(child.getStatus()); child.setStatus(status); costProjectTaskManager.updateById(child); } } else { // 恢复操作:恢复到中止前的状态 String preStatus = task.getPreSuspendStatus(); task.setStatus(StringUtil.isNotEmpty(preStatus) ? preStatus : TaskStatusConstant.AUDITING.getStatusCode()); task.setPreSuspendStatus(null); List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, task.getId()) .eq(CostProjectTask::getIsDeleted, "0") ); for (CostProjectTask child : children) { String childPreStatus = child.getPreSuspendStatus(); child.setStatus(StringUtil.isNotEmpty(childPreStatus) ? childPreStatus : TaskStatusConstant.AUDITING.getStatusCode()); child.setPreSuspendStatus(null); costProjectTaskManager.updateById(child); } } task.setStatus(status); costProjectTaskManager.updateById(task); // 通知内容组装 String title = NodeConstant.getNodeValueByKey(task.getCurrentNode()) + TaskStatusConstant.getStatusNameByCode(status); String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "已" + TaskStatusConstant.getStatusNameByCode(status) + task.getAuditedUnitName() + "的项目(" + task.getProjectName() + ")"; if (StringUtil.isNotEmpty(req.getContent())) { content += ",原因:" + req.getContent(); } String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return title; } /** * 补充材料,发送通知+修改任务状态 */ private String supplementMaterial(CostProjectTask task, CostTaskPageReq req) { String currentNode = task.getCurrentNode(); String title = NodeConstant.getNodeValueByKey(currentNode) + TaskStatusConstant.BCCL.getStatusName(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); switch (currentNode) { // 集体审议节点:支持指定多个子任务补充材料 case "jtsy": if (StringUtil.isNotEmpty(req.getAuditedUnitIds())) { String[] childUnitIds = req.getAuditedUnitIds().split(","); List unitNames = new java.util.ArrayList<>(); for (String auditedUnitId : childUnitIds) { CostProjectTask childTask = costProjectTaskManager.getOne( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, task.getId()) .eq(CostProjectTask::getAuditedUnitId, auditedUnitId) ); if (childTask == null) { throw new RuntimeException("未知的子任务"); } // 检查子任务是否已中止 if (TaskStatusConstant.SUSPENDED.getStatusCode().equals(childTask.getStatus())) { throw new RuntimeException("子任务已中止,无法补充材料:" + childTask.getAuditedUnitName()); } // 更新子任务状态为补充材料 childTask.setStatus(TaskStatusConstant.BCCL.getStatusCode()); costProjectTaskManager.updateById(childTask); // 通知内容组装(针对子任务对应的单位) String childContent = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "要求" + childTask.getAuditedUnitName() + "补充材料,项目(" + task.getProjectName() + ")"; String childEnterpriseId = childTask.getAuditedUnitId() == null ? "" : childTask.getAuditedUnitId(); String childSendTarget = childTask.getCreateBy() == null ? "" : childTask.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, childContent, childEnterpriseId, noticeSource, childSendTarget); // 收集单位名称 if (StringUtil.isNotEmpty(childTask.getAuditedUnitName())) { unitNames.add(childTask.getAuditedUnitName()); } } // 返回结果,包含所有单位名称 String unitNamesStr = unitNames.isEmpty() ? "" : String.join("、", unitNames); return title + "(单位:" + unitNamesStr + ")"; } default: // 检查任务是否已中止 if (TaskStatusConstant.SUSPENDED.getStatusCode().equals(task.getStatus())) { throw new RuntimeException("任务已中止,无法补充材料"); } task.setStatus(TaskStatusConstant.BCCL.getStatusCode()); costProjectTaskManager.updateById(task); String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "要求" + task.getAuditedUnitName() + "补充材料,项目(" + task.getProjectName() + ")"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return title; } } /** * 退回上一步,修改状态和节点(主任务操作,子任务同步节点流转) */ private String backPreToSubmit(CostProjectTask task, CostTaskPageReq req) { CostProjectTask nTask = costProjectTaskManager.getById(task.getId()); if (!"0".equals(task.getPid())) { return "仅支持主任务进行此操作"; } // 获取退回后的上一节点 NodeConstant prevNode = NodeConstant.getPrevNode(nTask.getCurrentNode()); if (prevNode == null) { throw new RuntimeException("当前节点已是第一步,无法退回"); } String prevNodeStatus = prevNode.getNodeKey(); // 更新流程节点时间:清空当前节点的结束时间,重置上一节点的开始时间 CostProjectProccess proccess = costProjectProccessManager.getOne( new LambdaQueryWrapper().eq(CostProjectProccess::getProjectId, task.getProjectId()) ); // 清空当前节点的实际结束时间和操作信息 CostProjectProccessNode currentNode = costProjectProccessNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectProccessNode::getProcessId, proccess.getProcessId()) .eq(CostProjectProccessNode::getProcessNodeKey, task.getCurrentNode()) ); if (currentNode != null) { currentNode.setActEndTime(null); currentNode.setActUserIds(null); currentNode.setActUserNames(null); currentNode.setActRemarks(null); costProjectProccessNodeManager.updateById(currentNode); } // 重置上一节点的开始时间 CostProjectProccessNode prevNodeObj = costProjectProccessNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectProccessNode::getProcessId, proccess.getProcessId()) .eq(CostProjectProccessNode::getProcessNodeKey, prevNodeStatus) ); if (prevNodeObj != null) { prevNodeObj.setActStartTime(LocalDateTime.now()); costProjectProccessNodeManager.updateById(prevNodeObj); } // 主任务退回上一步,重置归档状态 nTask.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); nTask.setCurrentNode(prevNodeStatus); nTask.setIsGd("0"); costProjectTaskManager.updateById(nTask); // 子任务同步节点流转,并根据退回后的节点设置正确的状态 List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, nTask.getId()) .eq(CostProjectTask::getIsDeleted, "0") ); // 根据退回后的节点,设置子任务状态 String childStatus = ""; switch (prevNodeStatus) { case "yjfk": childStatus = TaskStatusConstant.WAIT_FEEDBACK.getStatusCode(); break; case "jtsy": case "cjbg": case "gd": childStatus = TaskStatusConstant.COMPLETED.getStatusCode(); break; default: childStatus = TaskStatusConstant.AUDITING.getStatusCode(); break; } // 同步所有非中止状态的子任务 for (CostProjectTask child : children) { if (!child.getStatus().equals(TaskStatusConstant.SUSPENDED.getStatusCode())) { child.setStatus(childStatus); child.setCurrentNode(prevNodeStatus); costProjectTaskManager.updateById(child); // 如果退回到意见反馈节点,通知企业 if ("yjfk".equals(prevNodeStatus) && StringUtil.isNotEmpty(child.getAuditedUnitId())) { AuditedUnit auditedUnit = auditedUnitManager.getOne( new LambdaQueryWrapper() .eq(AuditedUnit::getUnitId, child.getAuditedUnitId()) .eq(AuditedUnit::getIsDeleted, "0") ); if (auditedUnit != null && StringUtil.isNotEmpty(auditedUnit.getAccount())) { String noticeTitle = "意见反馈通知"; String noticeContent = "您的项目(" + child.getProjectName() + ")需要反馈意见,请及时处理"; String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org != null ? org.getName() : "系统") + " " + AuthenticationUtil.getCurrentUserFullname(); costNoticeManager.sendNotice( child.getProjectId(), child.getId(), "1", noticeTitle, noticeContent, child.getAuditedUnitId(), noticeSource, auditedUnit.getAccount() ); } } } } // 通知内容组装 String title = "已退回至" + NodeConstant.getNodeValueByKey(prevNodeStatus); String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]已退回至[" + NodeConstant.getNodeValueByKey(prevNodeStatus) + "]," + task.getProjectName(); if (StringUtil.isNotEmpty(req.getContent())) { content += ",原因:" + req.getContent(); } costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return title; } /** * 扭转下一步,修改状态和节点(主任务操作,子任务同步节点流转) * 自动完成办结操作并扭转到下一步 */ private String toNextSubmit(CostProjectTask task, CostTaskPageReq req) { CostProjectTask nTask = costProjectTaskManager.getById(task.getId()); if (!"0".equals(task.getPid())) { return "仅支持主任务进行此操作"; } // 获取下一节点 NodeConstant nextNode = NodeConstant.getNextNode(nTask.getCurrentNode()); if (nextNode == null) { throw new RuntimeException("当前节点已是最后一步,无法扭转"); } String nextNodeStatus = nextNode.getNodeKey(); // 获取所有子任务 List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, nTask.getId()) .eq(CostProjectTask::getIsDeleted, "0") ); // 检查所有非中止的子任务是否都已办结 boolean allChildrenCompleted = children.stream() .filter(child -> !TaskStatusConstant.SUSPENDED.getStatusCode().equals(child.getStatus())) .allMatch(child -> TaskStatusConstant.COMPLETED.getStatusCode().equals(child.getStatus())); if (!allChildrenCompleted) { throw new RuntimeException("子任务未全部办结,主任务无法扭转"); } // 先完成当前节点的办结操作(如果未办结) if (!nTask.getStatus().equals(TaskStatusConstant.COMPLETED.getStatusCode())) { nTask.setStatus(TaskStatusConstant.COMPLETED.getStatusCode()); costProjectTaskManager.updateById(nTask); } // 修改当前节点的结束时间 CostProjectProccess proccess = costProjectProccessManager.getOne( new LambdaQueryWrapper().eq(CostProjectProccess::getProjectId, task.getProjectId()) ); CostProjectProccessNode one = costProjectProccessNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectProccessNode::getProcessId, proccess.getProcessId()) .eq(CostProjectProccessNode::getProcessNodeKey, task.getCurrentNode()) ); one.setActUserIds(req.getUserIds()); one.setActUserNames(req.getUserIdNames()); one.setActRemarks(req.getContent()); one.setActEndTime(LocalDateTime.now()); costProjectProccessNodeManager.updateById(one); // 主任务扭转到下一节点 nTask.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); nTask.setCurrentNode(nextNodeStatus); nTask.setIsGd("0"); costProjectTaskManager.updateById(nTask); // 设置下一节点的开始时间 CostProjectProccessNode two = costProjectProccessNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectProccessNode::getProcessId, proccess.getProcessId()) .eq(CostProjectProccessNode::getProcessNodeKey, nextNodeStatus) ); two.setActStartTime(LocalDateTime.now()); costProjectProccessNodeManager.updateById(two); // 子任务同步节点流转,根据节点设置对应状态 String childStatus = ""; switch (nextNodeStatus) { case "yjfk": childStatus = TaskStatusConstant.WAIT_FEEDBACK.getStatusCode(); break; case "jtsy": case "cjbg": case "gd": childStatus = TaskStatusConstant.COMPLETED.getStatusCode(); break; default: childStatus = TaskStatusConstant.AUDITING.getStatusCode(); break; } // 同步所有非中止状态的子任务 for (CostProjectTask child : children) { if (!child.getStatus().equals(TaskStatusConstant.SUSPENDED.getStatusCode())) { child.setStatus(childStatus); child.setCurrentNode(nextNodeStatus); costProjectTaskManager.updateById(child); // 如果扭转到意见反馈节点,通知企业 if ("yjfk".equals(nextNodeStatus) && StringUtil.isNotEmpty(child.getAuditedUnitId())) { AuditedUnit auditedUnit = auditedUnitManager.getOne( new LambdaQueryWrapper() .eq(AuditedUnit::getUnitId, child.getAuditedUnitId()) .eq(AuditedUnit::getIsDeleted, "0") ); if (auditedUnit != null && StringUtil.isNotEmpty(auditedUnit.getAccount())) { String noticeTitle = "意见反馈通知"; String noticeContent = "您的项目(" + child.getProjectName() + ")需要反馈意见,请及时处理"; String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org != null ? org.getName() : "系统") + " " + AuthenticationUtil.getCurrentUserFullname(); costNoticeManager.sendNotice( child.getProjectId(), child.getId(), "1", noticeTitle, noticeContent, child.getAuditedUnitId(), noticeSource, auditedUnit.getAccount() ); } } } } // 通知内容组装 String title = NodeConstant.getNodeValueByKey(nextNodeStatus) + "已开始"; String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]已办结并扭转至[" + NodeConstant.getNodeValueByKey(nextNodeStatus) + "]," + task.getProjectName(); if (StringUtil.isNotEmpty(req.getContent())) { content += ",备注:" + req.getContent(); } costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return title; } @Override public List getDoList(String projectId) { // 获取当前用户 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 ArrayList<>(); } // 提取有权限的立项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"); // 查询子任务 queryWrapper.ne(CostProjectTask::getPid, "0"); // 只查询当前用户有权限的立项对应的任务 queryWrapper.in(CostProjectTask::getProjectId, accessibleProjectIds); // 根据请求参数添加查询条件 queryWrapper.eq(projectId != null, CostProjectTask::getProjectId, projectId); // 按创建时间倒序排列 queryWrapper.orderByDesc(CostProjectTask::getCreateTime); List list = costProjectTaskManager.list(queryWrapper); for (CostProjectTask rootTask : list) { rootTask.setStatusName(TaskStatusConstant.getStatusNameByCode(rootTask.getStatus())); rootTask.setCurrentNodeName(NodeConstant.getNodeValueByKey(rootTask.getCurrentNode())); } return list; } @Override public List> getDoChartList(String year, String region) { List list = costCatalogManager.list( new LambdaQueryWrapper().eq(CostCatalog::getParentId, "1969351600934948833") ); List> maps = new ArrayList<>(); for (CostCatalog costCatalog : list) { // 递归获取所有下级目录ID List allCatalogIds = getAllChildCatalogIds(costCatalog.getCatalogId()); // 通过项目立项表关联查询目录 List approvals = costProjectApprovalManager.list( new LambdaQueryWrapper() .in(CostProjectApproval::getCatalogId, allCatalogIds) .eq(CostProjectApproval::getIsDeleted, "0") ); if (approvals.isEmpty()) { Map map = new HashMap<>(); map.put("name", costCatalog.getCatalogName()); map.put("finish", 0); map.put("nFinish", 0); maps.add(map); continue; } List projectIds = approvals.stream() .map(CostProjectApproval::getProjectId) .collect(Collectors.toList()); // 查询子任务 LambdaQueryWrapper taskQuery = new LambdaQueryWrapper<>(); taskQuery.eq(CostProjectTask::getIsDeleted, "0") .ne(CostProjectTask::getPid, "0") .in(CostProjectTask::getProjectId, projectIds); if (StringUtil.isNotEmpty(year)) { taskQuery.eq(CostProjectTask::getYear, year); } List tasks = this.list(taskQuery); // 统计完成和未完成的任务 long finishCount = tasks.stream() .filter(task -> TaskStatusConstant.COMPLETED.getStatusCode().equals(task.getStatus())) .count(); long nFinishCount = tasks.size() - finishCount; Map map = new HashMap<>(); map.put("name", costCatalog.getCatalogName()); map.put("finish", finishCount); map.put("nFinish", nFinishCount); maps.add(map); } return maps; } @Override public List getDoMsgList() { IUser currentUser = ContextUtil.getCurrentUser(); String currentUserId = currentUser.getUserId(); AuditedUnit unit = auditedUnitManager.getOne( new LambdaQueryWrapper() .eq(AuditedUnit::getAccount, currentUserId) .last("limit 1") ); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(CostNotice::getIsDeleted, "0"); if (unit != null) { queryWrapper.and(q -> q.eq(CostNotice::getEnterpriseId, unit.getUnitId()) .or() .eq(CostNotice::getSendTarget, currentUserId)); } else { // unit 为空时,只看是否发给当前用户 queryWrapper.eq(CostNotice::getSendTarget, currentUserId); } queryWrapper.orderByDesc(CostNotice::getCreateTime) .last("limit 8"); return costNoticeManager.list(queryWrapper); } @Override public IPage pageListForReviewTaskChild(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()); if (req.getAreaCode() != null) { List list = costProjectTaskApprovalManager.list( new LambdaQueryWrapper().eq(CostProjectTaskApproval::getAreaCode, req.getAreaCode()) ); if (list.isEmpty()) { return new Page<>(req.getPageNum(), req.getPageSize()); } List projectIds = list.stream().map(CostProjectTaskApproval::getProjectId).collect(Collectors.toList()); accessibleProjectIds.addAll(projectIds); } // 2. 构建任务查询条件 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); // 查询未删除的记录 queryWrapper.eq(CostProjectTask::getIsDeleted, "0"); // 查询根任务(pid为0) queryWrapper.ne(CostProjectTask::getPid, "0"); // 只查询当前用户有权限的立项对应的任务 queryWrapper.in(CostProjectTask::getProjectId, accessibleProjectIds); // 根据请求参数添加查询条件 if (StringUtil.isNotEmpty(req.getProjectName())) { queryWrapper.like(CostProjectTask::getProjectName, req.getProjectName()); } if (StringUtil.isNotEmpty(req.getAuditedUnitName())) { queryWrapper.like(CostProjectTask::getAuditedUnitName, req.getAuditedUnitName()); } if (StringUtil.isNotEmpty(req.getStatus())) { queryWrapper.eq(CostProjectTask::getStatus, req.getStatus()); } if (StringUtil.isNotEmpty(req.getYear())) { queryWrapper.eq(CostProjectTask::getYear, req.getYear()); } queryWrapper.eq(req.getCurrentNode() != null, CostProjectTask::getCurrentNode, req.getCurrentNode()); queryWrapper.ne(req.getNCurrentNode() != null, CostProjectTask::getCurrentNode, req.getNCurrentNode()); queryWrapper.ne(req.getNStatus() != null, CostProjectTask::getStatus, req.getNStatus()); // 按创建时间倒序排列 queryWrapper.orderByDesc(CostProjectTask::getCreateTime); Page page = new Page<>(req.getPageNum(), req.getPageSize()); IPage result = costProjectTaskManager.page(page, queryWrapper); List rootList = result.getRecords(); if (rootList == null || rootList.isEmpty()) { return result; } Set allProjectIds = new HashSet<>(); rootList.forEach(t -> allProjectIds.add(t.getProjectId())); List approvalList = costProjectApprovalManager.list( new LambdaQueryWrapper() .in(CostProjectApproval::getProjectId, allProjectIds) ); Map approvalMap = approvalList.stream().collect( Collectors.toMap(CostProjectApproval::getProjectId, v -> v) ); for (CostProjectTask rootTask : rootList) { // 任务状态 rootTask.setStatusName(TaskStatusConstant.getStatusNameByCode(rootTask.getStatus())); rootTask.setCurrentNodeName(NodeConstant.getNodeValueByKey(rootTask.getCurrentNode())); rootTask.setWarningStatus(calculateWarningStatus(rootTask)); // 找根任务 String pid = rootTask.getPid(); if (StringUtils.isNotBlank(pid)) { CostProjectTask rrootTask = this.getById(pid); if (rrootTask != null) { rootTask.setAuditPeriod(rrootTask.getAuditPeriod()); } } // 设置目录 CostProjectApproval rootDetail = approvalMap.get(rootTask.getProjectId()); if (rootDetail != null) { rootTask.setCatalogId(rootDetail.getCatalogId()); if (StringUtil.isNotEmpty(rootDetail.getAreaCode())) { CostDistrict district = costDistrictManager.getOne( new LambdaQueryWrapper() .eq(CostDistrict::getCode, rootDetail.getAreaCode()) ); rootTask.setAreaName(district != null ? district.getName() : "山西省"); } } } return result; } @Override public List findTaskByProjectId(String projectId, String enterpriseId) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("project_id",projectId); wrapper.eq("audited_unit_id",enterpriseId); return this.list(wrapper); } private List getAllChildCatalogIds(String catalogId) { List result = new ArrayList<>(); result.add(catalogId); List children = costCatalogManager.list( new LambdaQueryWrapper().eq(CostCatalog::getParentId, catalogId) ); for (CostCatalog child : children) { result.addAll(getAllChildCatalogIds(child.getCatalogId())); } return result; } /** * 催办任务,仅记录消息 * * @param task 任务对象 * @param req 请求参数 * @return 催办结果消息 */ private String remindTask(CostProjectTask task, CostTaskPageReq req) { // 检查是否提供了用户ID if (StringUtil.isEmpty(req.getUserIds())) { throw new RuntimeException("未指定催办人员"); } String title = NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "催办"; // 分割用户ID并逐个发送通知 for (String userId : req.getUserIds().split(",")) { // 发送催办通知 String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "催办" + task.getAuditedUnitName() + "的项目(" + task.getProjectName() + ")"; if (StringUtil.isNotEmpty(req.getContent())) { content += ",原因:" + req.getContent(); } String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); // 使用传入的用户ID作为发送目标 costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); } return title; } /** * 催办任务,仅记录消息 * * @param task 任务对象 * @param req 请求参数 * @return 催办结果消息 */ private String remindUnitTask(CostProjectTask task, CostTaskPageReq req) { // 检查是否提供了用户ID if (StringUtil.isEmpty(req.getAuditedUnitIds())) { throw new RuntimeException("未指定催报企业"); } String title = NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "催办"; // 分割用户ID并逐个发送通知 for (String unitId : req.getAuditedUnitIds().split(",")) { // 发送催办通知 String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "催报" + task.getAuditedUnitName() + "的项目(" + task.getProjectName() + ")"; if (StringUtil.isNotEmpty(req.getContent())) { content += ",原因:" + req.getContent(); } String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); // 使用传入的用户ID作为发送目标 costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); } return title; } /** * 复核,主任务退回到实地审核节点,子任务恢复到流程初始状态 * * @param task 任务对象 * @param req 请求参数 * @return 复核结果消息 */ private String reviewTask(CostProjectTask task, CostTaskPageReq req) { CostProjectTask nTask = costProjectTaskManager.getById(task.getId()); if (!"0".equals(task.getPid())) { return "仅支持主任务进行此操作"; } // 获取实地审核节点 String reviewNodeKey = NodeConstant.sdshenhe.getNodeKey(); // 更新流程节点时间:清空当前节点及之后节点的时间,重置实地审核节点的开始时间 CostProjectProccess proccess = costProjectProccessManager.getOne( new LambdaQueryWrapper().eq(CostProjectProccess::getProjectId, task.getProjectId()) ); if (proccess != null) { // 清空当前节点的实际结束时间和操作信息 CostProjectProccessNode currentNode = costProjectProccessNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectProccessNode::getProcessId, proccess.getProcessId()) .eq(CostProjectProccessNode::getProcessNodeKey, task.getCurrentNode()) ); if (currentNode != null) { currentNode.setActEndTime(null); currentNode.setActUserIds(null); currentNode.setActUserNames(null); currentNode.setActRemarks(null); costProjectProccessNodeManager.updateById(currentNode); } // 清空实地审核之后所有节点的时间和操作信息 boolean foundReviewNode = false; for (NodeConstant nodeConstant : NodeConstant.values()) { if (nodeConstant.getNodeKey().equals(reviewNodeKey)) { foundReviewNode = true; continue; } if (foundReviewNode) { CostProjectProccessNode node = costProjectProccessNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectProccessNode::getProcessId, proccess.getProcessId()) .eq(CostProjectProccessNode::getProcessNodeKey, nodeConstant.getNodeKey()) ); if (node != null) { node.setActStartTime(null); node.setActEndTime(null); node.setActUserIds(null); node.setActUserNames(null); node.setActRemarks(null); costProjectProccessNodeManager.updateById(node); } } } // 重置实地审核节点的开始时间 CostProjectProccessNode reviewNode = costProjectProccessNodeManager.getOne( new LambdaQueryWrapper() .eq(CostProjectProccessNode::getProcessId, proccess.getProcessId()) .eq(CostProjectProccessNode::getProcessNodeKey, reviewNodeKey) ); if (reviewNode != null) { reviewNode.setActStartTime(LocalDateTime.now()); costProjectProccessNodeManager.updateById(reviewNode); } } // 主任务退回到实地审核节点 nTask.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); nTask.setCurrentNode(reviewNodeKey); nTask.setIsGd("0"); costProjectTaskManager.updateById(nTask); // 子任务恢复到流程初始状态(实地审核节点,审核中状态) List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, nTask.getId()) .eq(CostProjectTask::getIsDeleted, "0") ); String initialNodeKey = NodeConstant.sdshenhe.getNodeKey(); for (CostProjectTask child : children) { // 非中止状态的子任务恢复到初始状态 if (!child.getStatus().equals(TaskStatusConstant.SUSPENDED.getStatusCode())) { child.setStatus(TaskStatusConstant.AUDITING.getStatusCode()); child.setCurrentNode(initialNodeKey); costProjectTaskManager.updateById(child); } } // 发送通知 String title = "复核-已退回至" + NodeConstant.getNodeValueByKey(reviewNodeKey); String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "要求复核,已退回至[" + NodeConstant.getNodeValueByKey(reviewNodeKey) + "]," + task.getProjectName(); if (StringUtil.isNotEmpty(req.getContent())) { content += ",原因:" + req.getContent(); } costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return title; } /** * 归档任务,修改任务归档状态并异步生成资料归纳主表 * * @param task 任务对象 * @param req 请求参数 * @return 归档结果消息 */ private String archiveTask(CostProjectTask task, CostTaskPageReq req) { CostProjectTask nTask = costProjectTaskManager.getById(task.getId()); if (!"0".equals(task.getPid())) { return "仅支持主任务进行归档操作"; } // 检查任务是否已办结 if (!TaskStatusConstant.COMPLETED.getStatusCode().equals(nTask.getStatus())) { throw new RuntimeException("任务未办结,无法归档"); } // 检查所有子任务是否都已办结 List children = costProjectTaskManager.list( new LambdaQueryWrapper() .eq(CostProjectTask::getPid, nTask.getId()) .eq(CostProjectTask::getIsDeleted, "0") ); boolean allChildrenCompleted = children.stream() .filter(child -> !TaskStatusConstant.SUSPENDED.getStatusCode().equals(child.getStatus())) .allMatch(child -> TaskStatusConstant.COMPLETED.getStatusCode().equals(child.getStatus())); if (!allChildrenCompleted) { throw new RuntimeException("子任务未全部办结,主任务无法归档"); } // 更新主任务归档状态 nTask.setIsGd("1"); costProjectTaskManager.updateById(nTask); // 发送通知 String title = "任务已归档"; String content = "[" + NodeConstant.getNodeValueByKey(task.getCurrentNode()) + "]" + AuthenticationUtil.getCurrentUserFullname() + "已归档" + task.getProjectName(); if (StringUtil.isNotEmpty(req.getContent())) { content += ",备注:" + req.getContent(); } String enterpriseId = task.getAuditedUnitId() == null ? "" : task.getAuditedUnitId(); String orgId = getCurrentUserMainOrgId(); Org org = orgManager.getById(orgId); String noticeSource = (org.getName()) + " " + AuthenticationUtil.getCurrentUserFullname(); String sendTarget = task.getCreateBy() == null ? "" : task.getCreateBy(); costNoticeManager.sendNotice(task.getProjectId(), task.getId(), "1", title, content, enterpriseId, noticeSource, sendTarget); return title; } }