From b30f4c40c77a940a2a749a676e901787f55040b0 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期五, 06 十一月 2026 11:48:25 +0800
Subject: [PATCH] 流程优化
---
src/main/java/com/ruoyi/projectManagement/service/ProjectWorkflowService.java | 276 ++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 224 insertions(+), 52 deletions(-)
diff --git a/src/main/java/com/ruoyi/projectManagement/service/ProjectWorkflowService.java b/src/main/java/com/ruoyi/projectManagement/service/ProjectWorkflowService.java
index f2e9b48..85b60ad 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/ProjectWorkflowService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/ProjectWorkflowService.java
@@ -155,10 +155,18 @@
@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);
@@ -169,6 +177,15 @@
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
@@ -208,9 +225,8 @@
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(
"寮�鍙�", "鐢虫姤",
"鐢虫姤", "鐢虫姤缁撴灉",
@@ -221,6 +237,7 @@
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
@@ -283,28 +300,16 @@
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("闃舵鐘舵�佷笉姝g‘");
+ 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()))
@@ -320,13 +325,6 @@
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);
}
@@ -402,6 +400,17 @@
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("椤圭洰寮�濮嬪悗涓嶈兘鏂板妯″潡锛屼粎鍙鐞嗘ā鍧楁墽琛屼汉");
}
@@ -534,15 +543,23 @@
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())
@@ -557,11 +574,23 @@
""", 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)
@@ -571,11 +600,15 @@
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);
@@ -588,26 +621,33 @@
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("宸叉湁杩涘害姹囨姤涓嶈兘淇敼姹囨姤鏃堕棿");
@@ -636,6 +676,11 @@
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,
@@ -659,16 +704,19 @@
@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);
@@ -689,6 +737,9 @@
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())
@@ -703,11 +754,12 @@
""", 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();
}
@@ -721,7 +773,8 @@
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() {
@@ -736,6 +789,14 @@
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());
@@ -747,17 +808,41 @@
""", 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) {
@@ -790,11 +875,12 @@
""", 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();
}
@@ -1160,6 +1246,84 @@
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);
@@ -1174,6 +1338,14 @@
}
}
+ 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);
}
--
Gitblit v1.9.3