| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void startProject(Long projectId) { |
| | | requireProject(projectId); |
| | | String currentPhase = jdbc.queryForObject(""" |
| | | select current_phase from project_management_info |
| | | where id=:projectId and is_delete=0 for update |
| | | """, Map.of("projectId", projectId), String.class); |
| | | if (!"未开始".equals(currentPhase)) { |
| | | throw new ServiceException("只有未开始的项目可以开始,当前阶段为“" + currentPhase + "”"); |
| | | } |
| | | Integer basicReady = jdbc.queryForObject(""" |
| | | select count(*) from project_management_info |
| | | where id=:projectId and is_delete=0 and project_classification is not null |
| | | and project_classification<>'' and plan_start_time is not null and plan_end_time is not null |
| | | where id=:projectId and is_delete=0 and project_category_id is not null |
| | | and plan_start_time is not null and plan_end_time is not null |
| | | and plan_end_time>=plan_start_time |
| | | and project_leader_id is not null and project_manager_ids is not null |
| | | and json_length(project_manager_ids)>0 and follow_cycle is not null and follow_cycle<>'' |
| | | """, Map.of("projectId", projectId), Integer.class); |
| | |
| | | from project_management_module where project_id=:projectId and is_deleted=0 |
| | | """, Map.of("projectId", projectId)); |
| | | if (modules.isEmpty()) throw new ServiceException("项目开始前请至少添加一个项目模块"); |
| | | Integer invalidModuleDates = jdbc.queryForObject(""" |
| | | select count(*) from project_management_module m |
| | | join project_management_info p on p.id=m.project_id and p.is_delete=0 |
| | | where m.project_id=:projectId and m.is_deleted=0 |
| | | and (m.planned_start_date<p.plan_start_time or m.planned_start_date>p.plan_end_time) |
| | | """, Map.of("projectId", projectId), Integer.class); |
| | | if (invalidModuleDates != null && invalidModuleDates > 0) { |
| | | throw new ServiceException("模块预计开始时间必须在项目计划开始和结束日期之间"); |
| | | } |
| | | BigDecimal total = BigDecimal.ZERO; |
| | | for (Map<String, Object> module : modules) { |
| | | if (isBlank(Objects.toString(module.get("moduleName"), "")) || module.get("plannedStartDate") == null |
| | |
| | | public void transitionStage(ProjectWorkflowDtos.StageTransitionRequest request) { |
| | | requireProject(request.getProjectId()); |
| | | ensurePhases(request.getProjectId()); |
| | | String current = jdbc.queryForObject("select current_phase from project_management_info where id=:id and is_delete=0", |
| | | String current = jdbc.queryForObject("select current_phase from project_management_info where id=:id and is_delete=0 for update", |
| | | Map.of("id", request.getProjectId()), String.class); |
| | | if ("立项".equals(current)) current = "开发"; |
| | | Map<String, String> nextStages = Map.of( |
| | | "开发", "申报", |
| | | "申报", "申报结果", |
| | |
| | | if (expected == null || !expected.equals(request.getTargetStage())) { |
| | | throw new ServiceException("项目阶段只能按开发、申报、申报结果、验收、已完成的顺序推进"); |
| | | } |
| | | validateTransitionForm(current, request.getFormData()); |
| | | if ("开发".equals(current)) { |
| | | Integer unfinished = jdbc.queryForObject(""" |
| | | select count(*) from project_management_module |
| | |
| | | int index = PHASE_CODES.indexOf(Objects.toString(request.getPhaseCode(), "")); |
| | | if (index < 0) throw new ServiceException("项目阶段不正确"); |
| | | String status = Objects.toString(request.getStatus(), "IN_PROGRESS").toUpperCase(); |
| | | if (!List.of("NOT_STARTED", "IN_PROGRESS", "COMPLETED").contains(status)) { |
| | | throw new ServiceException("阶段状态不正确"); |
| | | if (!"IN_PROGRESS".equals(status)) throw new ServiceException("阶段补充办理只能保持进行中状态"); |
| | | String currentPhase = jdbc.queryForObject(""" |
| | | select current_phase from project_management_info |
| | | where id=:id and is_delete=0 for update |
| | | """, Map.of("id", request.getProjectId()), String.class); |
| | | String expectedCode = phaseCodeForName(currentPhase); |
| | | if (!Objects.equals(expectedCode, request.getPhaseCode())) { |
| | | throw new ServiceException("只能维护当前阶段“" + currentPhase + "”,不能跳转或倒退阶段"); |
| | | } |
| | | if (index > 0 && !"NOT_STARTED".equals(status)) { |
| | | Integer previousDone = jdbc.queryForObject(""" |
| | | select count(*) from project_management_phase |
| | | where project_id=:projectId and phase_code=:phaseCode and status='COMPLETED' and is_deleted=0 |
| | | """, new MapSqlParameterSource().addValue("projectId", request.getProjectId()) |
| | | .addValue("phaseCode", PHASE_CODES.get(index - 1)), Integer.class); |
| | | if (previousDone == null || previousDone == 0) { |
| | | String projectPhase = jdbc.queryForObject("select current_phase from project_management_info where id=:id and is_delete=0", |
| | | Map.of("id", request.getProjectId()), String.class); |
| | | if (lifecyclePhaseRank(projectPhase) < index) { |
| | | throw new ServiceException("请先完成上一阶段“" + PHASE_NAMES.get(index - 1) + "”"); |
| | | } |
| | | jdbc.update(""" |
| | | update project_management_phase set status='COMPLETED',completed_time=coalesce(completed_time,now()), |
| | | update_time=now() where project_id=:projectId and phase_code=:phaseCode and is_deleted=0 |
| | | """, new MapSqlParameterSource().addValue("projectId", request.getProjectId()) |
| | | .addValue("phaseCode", PHASE_CODES.get(index - 1))); |
| | | } |
| | | } |
| | | validateSupplementalPhase(currentPhase, request.getFormData()); |
| | | MapSqlParameterSource p = new MapSqlParameterSource() |
| | | .addValue("projectId", request.getProjectId()).addValue("phaseCode", request.getPhaseCode()) |
| | | .addValue("status", status).addValue("formData", jsonObject(request.getFormData())) |
| | |
| | | stageHistoryAction(PHASE_NAMES.get(index), request.getFormData(), false), |
| | | stageHistoryLabel(PHASE_NAMES.get(index), request.getFormData(), false), |
| | | request.getFormData(), request.getRemark(), request.getAttachments()); |
| | | String currentPhase = "COMPLETED".equals(status) && index == PHASE_CODES.size() - 1 |
| | | ? "已完成" : PHASE_NAMES.get(index); |
| | | jdbc.update(""" |
| | | update project_management_info set current_phase=:phase, |
| | | actual_end_time=case when :phase='已完成' then coalesce(actual_end_time,current_date) else actual_end_time end, |
| | | update_time=now() where id=:projectId |
| | | """, new MapSqlParameterSource().addValue("phase", currentPhase).addValue("projectId", request.getProjectId())); |
| | | return jdbc.queryForObject("select id from project_management_phase where project_id=:projectId and phase_code=:phaseCode and is_deleted=0", |
| | | p, Long.class); |
| | | } |
| | |
| | | validateMembers(request.getMembers()); |
| | | |
| | | boolean started = isProjectStarted(request.getProjectId()); |
| | | if (!started) { |
| | | Integer dateInProjectRange = jdbc.queryForObject(""" |
| | | select count(*) from project_management_info |
| | | where id=:projectId and is_delete=0 and plan_start_time is not null and plan_end_time is not null |
| | | and :plannedStartDate between plan_start_time and plan_end_time |
| | | """, new MapSqlParameterSource().addValue("projectId", request.getProjectId()) |
| | | .addValue("plannedStartDate", request.getPlannedStartDate()), Integer.class); |
| | | if (dateInProjectRange == null || dateInProjectRange == 0) { |
| | | throw new ServiceException("模块预计开始时间必须在项目计划开始和结束日期之间"); |
| | | } |
| | | } |
| | | if (started && request.getId() == null) { |
| | | throw new ServiceException("项目开始后不能新增模块,仅可管理模块执行人"); |
| | | } |
| | |
| | | public Long saveFollowUp(ProjectWorkflowDtos.FollowUpRequest request) { |
| | | requireProject(request.getProjectId()); |
| | | ensureProjectMaintenanceEditable(request.getProjectId()); |
| | | Long leaderId = jdbc.queryForObject("select project_leader_id from project_management_info where id=:id", |
| | | Map.of("id", request.getProjectId()), Long.class); |
| | | if (leaderId == null || !leaderId.equals(SecurityUtils.getUserId())) { |
| | | throw new ServiceException("只有项目负责人可以填写项目跟进"); |
| | | } |
| | | ensureProjectLeader(request.getProjectId()); |
| | | if (request.getFollowDate() == null || isBlank(request.getDetail())) { |
| | | throw new ServiceException("请填写跟进日期和跟进详情"); |
| | | } |
| | | validateFollowWindow(request.getProjectId(), request.getFollowDate(), request.getId()); |
| | | if (request.getFollowDate().isAfter(LocalDate.now())) throw new ServiceException("跟进日期不能晚于今天"); |
| | | if (request.getId() == null) { |
| | | validateFollowWindow(request.getProjectId(), request.getFollowDate(), null); |
| | | } else { |
| | | LocalDate oldDate = jdbc.query(""" |
| | | select follow_date from project_management_follow_up |
| | | where id=:id and project_id=:projectId and is_deleted=0 |
| | | """, new MapSqlParameterSource().addValue("id", request.getId()) |
| | | .addValue("projectId", request.getProjectId()), |
| | | rs -> rs.next() ? rs.getDate(1).toLocalDate() : null); |
| | | if (oldDate == null) throw new ServiceException("跟进记录不存在"); |
| | | if (!oldDate.equals(request.getFollowDate())) throw new ServiceException("已有跟进记录不能修改跟进日期"); |
| | | } |
| | | MapSqlParameterSource p = new MapSqlParameterSource() |
| | | .addValue("id", request.getId()).addValue("projectId", request.getProjectId()) |
| | | .addValue("followDate", request.getFollowDate()).addValue("detail", request.getDetail()) |
| | |
| | | """, p, keys, new String[]{"id"}); |
| | | return Objects.requireNonNull(keys.getKey()).longValue(); |
| | | } |
| | | jdbc.update(""" |
| | | int updated = jdbc.update(""" |
| | | update project_management_follow_up set follow_date=:followDate,detail=:detail, |
| | | attachments=:attachments,update_time=now() where id=:id and project_id=:projectId and is_deleted=0 |
| | | """, p); |
| | | if (updated == 0) throw new ServiceException("跟进记录不存在"); |
| | | return request.getId(); |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteFollowUp(Long id) { |
| | | Long projectId = jdbc.query(""" |
| | | select project_id from project_management_follow_up where id=:id and is_deleted=0 |
| | | """, Map.of("id", id), rs -> rs.next() ? rs.getLong(1) : null); |
| | | if (projectId == null) throw new ServiceException("跟进记录不存在"); |
| | | ensureProjectMaintenanceEditable(projectId); |
| | | ensureProjectLeader(projectId); |
| | | jdbc.update("update project_management_follow_up set is_deleted=1,update_time=now() where id=:id", Map.of("id", id)); |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | if (request.getModuleId() == null || request.getReportDate() == null) { |
| | | throw new ServiceException("请选择项目模块和汇报时间"); |
| | | } |
| | | if (request.getReportDate().isAfter(LocalDate.now())) { |
| | | throw new ServiceException("汇报时间不能晚于今天"); |
| | | } |
| | | BigDecimal increment = percent(request.getIncrementProgress(), "本次进度"); |
| | | if (increment.compareTo(BigDecimal.ZERO) <= 0) throw new ServiceException("本次进度必须大于0"); |
| | | BigDecimal current = jdbc.queryForObject(""" |
| | | select current_progress from project_management_module |
| | | where id=:moduleId and project_id=:projectId and is_deleted=0 |
| | | for update |
| | | """, new MapSqlParameterSource().addValue("moduleId", request.getModuleId()).addValue("projectId", request.getProjectId()), BigDecimal.class); |
| | | if (current == null) throw new ServiceException("项目模块不存在"); |
| | | List<ProjectWorkflowDtos.MemberRequest> reporterShares = normalizeReporterShares(request); |
| | |
| | | if (reporterShares.stream().anyMatch(member -> !moduleMemberIds.contains(member.getUserId()))) { |
| | | throw new ServiceException("汇报人员只能选择该模块执行人"); |
| | | } |
| | | if (reporterShares.stream().noneMatch(member -> Objects.equals(member.getUserId(), SecurityUtils.getUserId()))) { |
| | | throw new ServiceException("当前办理人必须包含在本次汇报人员中"); |
| | | } |
| | | request.setReporterIds(reporterShares.stream().map(ProjectWorkflowDtos.MemberRequest::getUserId).toList()); |
| | | request.setReporterNames(reporterShares.stream().map(ProjectWorkflowDtos.MemberRequest::getUserName).toList()); |
| | | Long reportId = request.getId(); |
| | | BigDecimal progress; |
| | | BigDecimal progressAdjustment = BigDecimal.ZERO; |
| | | if (reportId == null) { |
| | | progress = current.add(increment); |
| | | if (progress.compareTo(BigDecimal.valueOf(100)) > 0) { |
| | | BigDecimal finalProgress = current.add(increment); |
| | | if (finalProgress.compareTo(BigDecimal.valueOf(100)) > 0) { |
| | | throw new ServiceException("模块当前进度为" + current.stripTrailingZeros().toPlainString() |
| | | + "% ,本次进度最多可填写" + BigDecimal.valueOf(100).subtract(current).stripTrailingZeros().toPlainString() + "%"); |
| | | } |
| | | progress = previousReportProgress(request.getModuleId(), request.getReportDate(), Long.MAX_VALUE).add(increment); |
| | | } else { |
| | | Map<String, Object> oldReport = query(""" |
| | | select id,module_id as moduleId,report_date as reportDate,progress |
| | | select id,module_id as moduleId,report_date as reportDate,progress,reporter_ids as reporterIds |
| | | from project_management_progress_report |
| | | where id=:id and project_id=:projectId and is_deleted=0 |
| | | """, new MapSqlParameterSource().addValue("id", reportId).addValue("projectId", request.getProjectId())) |
| | | .stream().findFirst().orElseThrow(() -> new ServiceException("进度汇报不存在")); |
| | | if (!Objects.equals(asLong(oldReport.get("moduleId")), request.getModuleId())) { |
| | | throw new ServiceException("已有进度汇报不能更换项目模块"); |
| | | } |
| | | if (!parseLongList(oldReport.get("reporterIds")).contains(SecurityUtils.getUserId())) { |
| | | throw new ServiceException("只有原汇报办理人可以编辑该进度汇报"); |
| | | } |
| | | LocalDate oldDate = oldReport.get("reportDate") instanceof java.sql.Date date ? date.toLocalDate() : request.getReportDate(); |
| | | if (!Objects.equals(oldDate, request.getReportDate())) throw new ServiceException("已有进度汇报不能修改汇报时间"); |
| | |
| | | values (:projectId,:moduleId,:reporterIds,:reporterNames,:reporterShares,:progress,:reportDate,:remark,:attachments,0,now(),now()) |
| | | """, p, keys, new String[]{"id"}); |
| | | reportId = Objects.requireNonNull(keys.getKey()).longValue(); |
| | | jdbc.update(""" |
| | | update project_management_progress_report set progress=progress+:increment,update_time=now() |
| | | where module_id=:moduleId and is_deleted=0 and report_date>:reportDate |
| | | """, new MapSqlParameterSource().addValue("increment", increment) |
| | | .addValue("moduleId", request.getModuleId()).addValue("reportDate", request.getReportDate())); |
| | | } else { |
| | | jdbc.update(""" |
| | | update project_management_progress_report set module_id=:moduleId,reporter_ids=:reporterIds, |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteReport(Long id) { |
| | | Map<String, Object> report = query(""" |
| | | select id,project_id as projectId,module_id as moduleId,report_date as reportDate,progress |
| | | select id,project_id as projectId,module_id as moduleId,report_date as reportDate,progress, |
| | | reporter_ids as reporterIds |
| | | from project_management_progress_report where id=:id and is_deleted=0 |
| | | """, Map.of("id", id)).stream().findFirst().orElseThrow(() -> new ServiceException("进度汇报不存在")); |
| | | ensureProjectMaintenanceEditable(asLong(report.get("projectId"))); |
| | | Long moduleId = asLong(report.get("moduleId")); |
| | | List<Long> moduleMemberIds = query(""" |
| | | select user_id as userId from project_management_module_member |
| | | where module_id=:moduleId and is_deleted=0 |
| | | """, Map.of("moduleId", moduleId)).stream().map(row -> asLong(row.get("userId"))).toList(); |
| | | if (!moduleMemberIds.contains(SecurityUtils.getUserId())) throw new ServiceException("只有该模块执行人可以删除进度汇报"); |
| | | if (!parseLongList(report.get("reporterIds")).contains(SecurityUtils.getUserId())) { |
| | | throw new ServiceException("只有原汇报办理人可以删除该进度汇报"); |
| | | } |
| | | BigDecimal lockedProgress = jdbc.queryForObject(""" |
| | | select current_progress from project_management_module where id=:moduleId and is_deleted=0 for update |
| | | """, Map.of("moduleId", moduleId), BigDecimal.class); |
| | | if (lockedProgress == null) throw new ServiceException("项目模块不存在"); |
| | | LocalDate reportDate = report.get("reportDate") instanceof java.sql.Date date ? date.toLocalDate() : null; |
| | | BigDecimal previous = previousReportProgress(moduleId, reportDate, id); |
| | | BigDecimal increment = nvl((BigDecimal) report.get("progress")).subtract(previous).max(BigDecimal.ZERO); |
| | |
| | | requireProject(request.getProjectId()); |
| | | ensureProjectMaintenanceEditable(request.getProjectId()); |
| | | if (isBlank(request.getMaterialName())) throw new ServiceException("请输入资料名称"); |
| | | if (request.getAttachments() == null || request.getAttachments().isEmpty()) { |
| | | throw new ServiceException("请上传至少一个项目资料文件"); |
| | | } |
| | | MapSqlParameterSource p = new MapSqlParameterSource() |
| | | .addValue("id", request.getId()).addValue("projectId", request.getProjectId()) |
| | | .addValue("materialName", request.getMaterialName()).addValue("materialType", request.getMaterialType()) |
| | |
| | | """, p, keys, new String[]{"id"}); |
| | | return Objects.requireNonNull(keys.getKey()).longValue(); |
| | | } |
| | | jdbc.update(""" |
| | | int updated = jdbc.update(""" |
| | | update project_management_material set material_name=:materialName,material_type=:materialType, |
| | | remark=:remark,attachments=:attachments,update_time=now() |
| | | where id=:id and project_id=:projectId and is_deleted=0 |
| | | """, p); |
| | | if (updated == 0) throw new ServiceException("项目资料不存在"); |
| | | return request.getId(); |
| | | } |
| | | |
| | |
| | | if (projectId == null) throw new ServiceException("记录不存在"); |
| | | ensureProjectMaintenanceEditable(projectId); |
| | | } |
| | | jdbc.getJdbcTemplate().update("update " + table + " set is_deleted=1,update_time=now() where id=?", id); |
| | | int updated = jdbc.getJdbcTemplate().update("update " + table + " set is_deleted=1,update_time=now() where id=? and is_deleted=0", id); |
| | | if (updated == 0) throw new ServiceException("记录不存在"); |
| | | } |
| | | |
| | | public List<Map<String, Object>> listCategories() { |
| | |
| | | if (isBlank(request.getCategoryName())) throw new ServiceException("请输入分类名称"); |
| | | Long parentId = request.getParentId() == null ? 0L : request.getParentId(); |
| | | if (request.getId() != null && request.getId().equals(parentId)) throw new ServiceException("上级分类不能选择自己"); |
| | | validateCategoryParent(request.getId(), parentId); |
| | | Integer duplicate = jdbc.queryForObject(""" |
| | | select count(*) from project_management_category |
| | | where coalesce(parent_id,0)=:parentId and category_name=:categoryName and is_deleted=0 |
| | | and (:id is null or id<>:id) |
| | | """, new MapSqlParameterSource().addValue("parentId", parentId) |
| | | .addValue("categoryName", request.getCategoryName().trim()).addValue("id", request.getId()), Integer.class); |
| | | if (duplicate != null && duplicate > 0) throw new ServiceException("同一上级下已存在同名分类"); |
| | | MapSqlParameterSource p = new MapSqlParameterSource().addValue("id", request.getId()) |
| | | .addValue("parentId", parentId).addValue("categoryName", request.getCategoryName().trim()) |
| | | .addValue("sort", request.getSort() == null ? 0 : request.getSort()).addValue("remark", request.getRemark()); |
| | |
| | | """, p, keys, new String[]{"id"}); |
| | | return Objects.requireNonNull(keys.getKey()).longValue(); |
| | | } |
| | | jdbc.update(""" |
| | | int updated = jdbc.update(""" |
| | | update project_management_category set parent_id=:parentId,category_name=:categoryName, |
| | | sort=:sort,remark=:remark,update_time=now() where id=:id and is_deleted=0 |
| | | """, p); |
| | | if (updated == 0) throw new ServiceException("项目分类不存在或已删除"); |
| | | return request.getId(); |
| | | } |
| | | |
| | | public void deleteCategory(Long id) { |
| | | int children = jdbc.queryForObject("select count(*) from project_management_category where parent_id=:id and is_deleted=0", Map.of("id", id), Integer.class); |
| | | if (children > 0) throw new ServiceException("请先删除下级分类"); |
| | | String categoryName = jdbc.query("select category_name from project_management_category where id=:id and is_deleted=0", |
| | | Map.of("id", id), rs -> rs.next() ? rs.getString(1) : null); |
| | | if (categoryName == null) throw new ServiceException("项目分类不存在"); |
| | | Integer used = jdbc.queryForObject(""" |
| | | select count(*) from project_management_info |
| | | where is_delete=0 and (project_category_id=:id or |
| | | (project_category_id is null and project_classification=:categoryName)) |
| | | """, new MapSqlParameterSource().addValue("id", id).addValue("categoryName", categoryName), Integer.class); |
| | | if (used != null && used > 0) throw new ServiceException("该分类已被项目使用,不能删除"); |
| | | jdbc.update("update project_management_category set is_deleted=1,update_time=now() where id=:id", Map.of("id", id)); |
| | | } |
| | | |
| | | private void validateCategoryParent(Long categoryId, Long parentId) { |
| | | if (parentId == null || parentId == 0L) return; |
| | | Set<Long> visited = new HashSet<>(); |
| | | Long current = parentId; |
| | | while (current != null && current != 0L) { |
| | | if (Objects.equals(current, categoryId)) throw new ServiceException("上级分类不能选择当前分类或其下级分类"); |
| | | if (!visited.add(current)) throw new ServiceException("分类数据已存在循环,请先修复分类关系"); |
| | | current = jdbc.query(""" |
| | | select parent_id from project_management_category where id=:id and is_deleted=0 |
| | | """, Map.of("id", current), rs -> rs.next() ? rs.getLong(1) : null); |
| | | if (current == null) throw new ServiceException("上级分类不存在或已删除"); |
| | | } |
| | | } |
| | | |
| | | public List<Map<String, Object>> listPolicies(String keyword) { |
| | |
| | | """, p, keys, new String[]{"id"}); |
| | | return Objects.requireNonNull(keys.getKey()).longValue(); |
| | | } |
| | | jdbc.update(""" |
| | | int updated = jdbc.update(""" |
| | | update government_policy_file set policy_name=:policyName,publish_date=:publishDate, |
| | | policy_url=:policyUrl,attachments=:attachments,maintainer_name=:maintainer, |
| | | remark=:remark,update_time=now() where id=:id and is_deleted=0 |
| | | """, p); |
| | | if (updated == 0) throw new ServiceException("政策文件不存在或已删除"); |
| | | return request.getId(); |
| | | } |
| | | |
| | |
| | | return val.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | private void validateTransitionForm(String currentPhase, Map<String, Object> formData) { |
| | | switch (currentPhase) { |
| | | case "开发" -> { |
| | | requireDate(formData, "applicationDate", "申报日期"); |
| | | requireText(formData, "applicationType", "申报类型"); |
| | | requireText(formData, "applicationName", "申报名称"); |
| | | requireText(formData, "description", "申报说明"); |
| | | } |
| | | case "申报" -> { |
| | | requireDate(formData, "resultDate", "结果日期"); |
| | | requireValue(formData, "resultStatus", "PASS", "只有申报通过后才能进入申报结果阶段"); |
| | | requireText(formData, "resultDescription", "结果说明"); |
| | | } |
| | | case "申报结果" -> { |
| | | requireDate(formData, "acceptancePlanDate", "计划验收日期"); |
| | | requireText(formData, "acceptor", "验收人/客户"); |
| | | requireText(formData, "acceptanceStandard", "验收标准"); |
| | | } |
| | | case "验收" -> { |
| | | requireDate(formData, "acceptanceDate", "验收日期"); |
| | | requireText(formData, "acceptor", "验收人/客户"); |
| | | requireValue(formData, "acceptanceResult", "PASS", "只有验收通过后才能完成项目"); |
| | | requireText(formData, "acceptanceDescription", "验收说明"); |
| | | } |
| | | default -> throw new ServiceException("当前阶段不能办理流转"); |
| | | } |
| | | } |
| | | |
| | | private void validateSupplementalPhase(String currentPhase, Map<String, Object> formData) { |
| | | if ("申报".equals(currentPhase)) { |
| | | requireDate(formData, "resultDate", "结果日期"); |
| | | String result = requireText(formData, "resultStatus", "申报结果"); |
| | | if (!List.of("SUPPLEMENT", "REJECTED").contains(result)) { |
| | | throw new ServiceException("申报通过必须使用阶段推进操作"); |
| | | } |
| | | requireText(formData, "resultDescription", "结果说明"); |
| | | return; |
| | | } |
| | | if ("验收".equals(currentPhase)) { |
| | | requireDate(formData, "acceptanceDate", "验收日期"); |
| | | requireText(formData, "acceptor", "验收人/客户"); |
| | | requireValue(formData, "acceptanceResult", "RECTIFY", "验收通过必须使用完成项目操作"); |
| | | requireText(formData, "acceptanceDescription", "验收说明"); |
| | | return; |
| | | } |
| | | throw new ServiceException("当前阶段不支持补充办理,只能按流程推进"); |
| | | } |
| | | |
| | | private String phaseCodeForName(String phaseName) { |
| | | return switch (Objects.toString(phaseName, "")) { |
| | | case "立项" -> "INITIATION"; |
| | | case "开发" -> "DEVELOPMENT"; |
| | | case "申报" -> "APPLICATION"; |
| | | case "申报结果" -> "RESULT"; |
| | | case "验收" -> "ACCEPTANCE"; |
| | | default -> null; |
| | | }; |
| | | } |
| | | |
| | | private String requireText(Map<String, Object> formData, String key, String label) { |
| | | String value = Objects.toString(formData == null ? null : formData.get(key), "").trim(); |
| | | if (value.isEmpty()) throw new ServiceException("请填写" + label); |
| | | return value; |
| | | } |
| | | |
| | | private void requireDate(Map<String, Object> formData, String key, String label) { |
| | | String value = requireText(formData, key, label); |
| | | try { |
| | | LocalDate.parse(value); |
| | | } catch (Exception e) { |
| | | throw new ServiceException(label + "格式不正确"); |
| | | } |
| | | } |
| | | |
| | | private void requireValue(Map<String, Object> formData, String key, String expected, String message) { |
| | | if (!expected.equals(requireText(formData, key, key))) throw new ServiceException(message); |
| | | } |
| | | |
| | | private void requireProject(Long projectId) { |
| | | if (projectId == null) throw new ServiceException("项目不能为空"); |
| | | Integer count = jdbc.queryForObject("select count(*) from project_management_info where id=:id and is_delete=0", Map.of("id", projectId), Integer.class); |
| | |
| | | } |
| | | } |
| | | |
| | | private void ensureProjectLeader(Long projectId) { |
| | | Long leaderId = jdbc.query("select project_leader_id from project_management_info where id=:id and is_delete=0", |
| | | Map.of("id", projectId), rs -> rs.next() ? rs.getLong(1) : null); |
| | | if (leaderId == null || !leaderId.equals(SecurityUtils.getUserId())) { |
| | | throw new ServiceException("只有项目负责人可以维护项目跟进"); |
| | | } |
| | | } |
| | | |
| | | private List<Map<String, Object>> query(String sql, Map<String, ?> params) { |
| | | return jdbc.queryForList(sql, params); |
| | | } |