From f651ad5716aa86afafc16e8abe342ed7ddd9d986 Mon Sep 17 00:00:00 2001
From: zzw <228544128@qq.com>
Date: 星期二, 06 十月 2026 18:10:57 +0800
Subject: [PATCH] fix: show full date range separator in log filters

---
 emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java |  307 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 264 insertions(+), 43 deletions(-)

diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java b/emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java
index 15bdcf8..f2c5329 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java
@@ -4,22 +4,24 @@
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.emergencyrepair.business.dto.Requests;
+import com.emergencyrepair.business.dto.CompletionFaultQueryItem;
 import com.emergencyrepair.business.entity.Acceptance;
 import com.emergencyrepair.business.entity.CompletionInfo;
-import com.emergencyrepair.business.entity.Contractor;
 import com.emergencyrepair.business.entity.Fault;
 import com.emergencyrepair.business.entity.TeamMajor;
 import com.emergencyrepair.business.entity.WorkOrder;
 import com.emergencyrepair.business.mapper.AcceptanceMapper;
 import com.emergencyrepair.business.mapper.CompletionInfoMapper;
-import com.emergencyrepair.business.mapper.ContractorMapper;
 import com.emergencyrepair.business.mapper.FaultMapper;
 import com.emergencyrepair.business.mapper.TeamMajorMapper;
 import com.emergencyrepair.business.mapper.WorkOrderMapper;
 import com.emergencyrepair.common.BusinessException;
 import com.emergencyrepair.common.StatusConstants;
+import com.emergencyrepair.common.audit.CurrentUserContext;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
@@ -30,24 +32,27 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Objects;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Service
 @RequiredArgsConstructor
 public class BusinessService {
     private static final DateTimeFormatter FAULT_DATE_FORMAT = DateTimeFormatter.ofPattern("yyMMdd");
-    private static final String FAULT_CODE_PREFIX = "\u6f5c1\u57fa-";
     private static final Object FAULT_CODE_LOCK = new Object();
+    @Value("${fault-code.prefix:\u6f5c1\u57fa-}")
+    private String faultCodePrefix;
     private final FaultMapper faultMapper;
+    private final JdbcTemplate jdbcTemplate;
     private final TeamMajorMapper teamMajorMapper;
     private final WorkOrderMapper workOrderMapper;
-    private final ContractorMapper contractorMapper;
     private final CompletionInfoMapper completionInfoMapper;
     private final AcceptanceMapper acceptanceMapper;
     private final ObjectMapper objectMapper;
@@ -168,26 +173,30 @@
     private String generateFaultCode(Fault fault) {
         String xNo = normalizeXNo(fault.getXNo());
         if (xNo == null) {
-            throw new BusinessException("璇烽�夋嫨X鍙凤紝鏍煎紡涓�3浣嶆暟瀛�");
+            throw new BusinessException("璇烽�夋嫨rk_X鍙凤紝鏍煎紡涓�3浣嶆暟瀛�");
         }
         if (!StringUtils.hasText(fault.getTeamMajor())) {
-            throw new BusinessException("璇烽�夋嫨T闃熶笓涓�");
+            throw new BusinessException("璇烽�夋嫨rk_T闃熶笓涓�");
         }
         TeamMajor teamMajor = teamMajorMapper.selectOne(Wrappers.<TeamMajor>lambdaQuery()
                 .eq(TeamMajor::getName, fault.getTeamMajor().trim())
                 .last("LIMIT 1"));
         if (teamMajor == null) {
-            throw new BusinessException("T闃熶笓涓氭湭閰嶇疆锛岃鍏堝湪绯荤粺绠$悊 > T闃熶笓涓氶厤缃腑缁存姢锛�" + fault.getTeamMajor());
+            throw new BusinessException("rk_T闃熶笓涓氭湭閰嶇疆锛岃鍏堝湪绯荤粺绠$悊 > rk_T闃熶笓涓氶厤缃腑缁存姢锛�" + fault.getTeamMajor());
         }
         String category = teamMajor.getCategory() == null ? "" : teamMajor.getCategory().trim().toUpperCase();
         if (!"A".equals(category) && !"B".equals(category)) {
-            throw new BusinessException("T闃熶笓涓氬垎绫诲彧鑳戒负A鎴朆锛�" + fault.getTeamMajor());
+            throw new BusinessException("rk_T闃熶笓涓氬垎绫诲彧鑳戒负A鎴朆锛�" + fault.getTeamMajor());
         }
-        String prefix = FAULT_CODE_PREFIX + xNo + "/" + category + "-" + fault.getReportDate().format(FAULT_DATE_FORMAT) + "-";
+        String prefix = faultCodePrefix + xNo + "/" + category + "-" + fault.getReportDate().format(FAULT_DATE_FORMAT) + "-";
         int next = 1;
-        for (Fault item : faultMapper.selectList(Wrappers.<Fault>lambdaQuery()
-                .likeRight(Fault::getFaultCode, prefix))) {
-            next = Math.max(next, parseFaultSequence(item.getFaultCode(), prefix) + 1);
+        // Include logically deleted rows so a generated code never collides with
+        // the unique index on FAULT_CODE.
+        List<String> existingCodes = jdbcTemplate.query(
+                "SELECT FAULT_CODE FROM LX.T_FAULT WHERE FAULT_CODE LIKE ?",
+                new Object[]{prefix + "%"}, (rs, rowNum) -> rs.getString(1));
+        for (String existingCode : existingCodes) {
+            next = Math.max(next, parseFaultSequence(existingCode, prefix) + 1);
         }
         return prefix + String.format("%03d", next);
     }
@@ -244,7 +253,7 @@
             throw new BusinessException("璇峰~鍐欓攢椤圭悊鐢�");
         }
         String cancelledBy = StringUtils.hasText(request.getCancelledBy())
-                ? request.getCancelledBy().trim() : "XCB鍔╃悊";
+                ? request.getCancelledBy().trim() : "rk_XCB鍔╃悊";
         for (Long id : request.getIds()) {
             Fault fault = requireFault(id);
             if (!StatusConstants.Task.REPORTED_XCB.equals(fault.getTaskStatus())
@@ -281,16 +290,16 @@
         if (request.getContractorIds() == null || request.getContractorIds().isEmpty()) {
             throw new BusinessException("鑷冲皯鍒嗛厤涓�涓壙淇崟浣�");
         }
-        List<Contractor> contractors = contractorMapper.selectBatchIds(request.getContractorIds());
-        Map<Long, Contractor> contractorMap = contractors.stream()
-                .collect(Collectors.toMap(Contractor::getId, Function.identity()));
+        Map<Long, String> contractorMap = contractorNamesByIds(request.getContractorIds());
+        if (contractorMap.isEmpty()) {
+            throw new BusinessException("鎵夸慨鍗曚綅涓嶅瓨鍦ㄦ垨鏈湪閮ㄩ棬琛ㄤ腑閰嶇疆");
+        }
         String contractorIds = request.getContractorIds().stream()
                 .map(String::valueOf)
                 .collect(Collectors.joining(","));
         String contractorNames = request.getContractorIds().stream()
                 .map(contractorMap::get)
-                .filter(item -> item != null)
-                .map(Contractor::getName)
+                .filter(Objects::nonNull)
                 .collect(Collectors.joining("銆�"));
 
         int index = 0;
@@ -298,7 +307,7 @@
             Fault fault = requireFault(id);
             if (!StatusConstants.Task.REPORTED_XCB.equals(fault.getTaskStatus())
                     && !StatusConstants.Task.RETURNED.equals(fault.getTaskStatus())) {
-                throw new BusinessException("鏁呴殰 " + fault.getFaultCode() + " 褰撳墠鐘舵�佷笉鍏佽XCB鍔╃悊瀹℃牳");
+                throw new BusinessException("鏁呴殰 " + fault.getFaultCode() + " 褰撳墠鐘舵�佷笉鍏佽rk_XCB鍔╃悊瀹℃牳");
             }
             index++;
             fault.setContractorIds(contractorIds);
@@ -325,21 +334,21 @@
             LocalDateTime now = LocalDateTime.now();
             switch (request.getStage()) {
                 case "CMB":
-                    requireStatus(fault, StatusConstants.Task.XCB_REVIEWED, "CMB棰嗗瀹℃壒");
+                    requireStatus(fault, StatusConstants.Task.XCB_REVIEWED, "rk_CMB棰嗗瀹℃壒");
                     fault.setCmbOpinion(request.getOpinion());
                     fault.setCmbResult(pass ? "閫氳繃" : "涓嶉�氳繃");
                     fault.setCmbTime(now);
                     fault.setTaskStatus(pass ? StatusConstants.Task.CMB_APPROVED : StatusConstants.Task.RETURNED);
                     break;
                 case "JCC_ASSISTANT":
-                    requireStatus(fault, StatusConstants.Task.CMB_APPROVED, "JCC鍔╃悊瀹℃壒");
+                    requireStatus(fault, StatusConstants.Task.CMB_APPROVED, "rk_JCC鍔╃悊瀹℃壒");
                     fault.setJccAssistantOpinion(request.getOpinion());
                     fault.setJccAssistantResult(pass ? "閫氳繃" : "涓嶉�氳繃");
                     fault.setJccAssistantTime(now);
                     fault.setTaskStatus(pass ? StatusConstants.Task.JCC_ASSISTANT_APPROVED : StatusConstants.Task.RETURNED);
                     break;
                 case "JCC_DIRECTOR":
-                    requireStatus(fault, StatusConstants.Task.JCC_ASSISTANT_APPROVED, "JCC澶勯暱瀹℃壒");
+                    requireStatus(fault, StatusConstants.Task.JCC_ASSISTANT_APPROVED, "rk_JCC澶勯暱瀹℃壒");
                     fault.setJccDirectorOpinion(request.getOpinion());
                     fault.setJccDirectorResult(pass ? "閫氳繃" : "涓嶉�氳繃");
                     fault.setJccDirectorTime(now);
@@ -373,19 +382,17 @@
             if (exists > 0) {
                 throw new BusinessException("鏁呴殰 " + fault.getFaultCode() + " 宸茬粡娲惧崟");
             }
-            List<Contractor> contractors = contractorMapper.selectBatchIds(contractorIds);
-            Map<Long, Contractor> contractorMap = contractors.stream()
-                    .collect(Collectors.toMap(Contractor::getId, Function.identity()));
+            Map<Long, String> contractorMap = contractorNamesByIds(contractorIds);
             int sequence = 1;
             for (Long contractorId : contractorIds) {
-                Contractor contractor = contractorMap.get(contractorId);
-                if (contractor == null) {
+                String contractorName = contractorMap.get(contractorId);
+                if (contractorName == null) {
                     continue;
                 }
                 WorkOrder workOrder = workOrderFromFault(fault);
                 workOrder.setWorkOrderNo(fault.getFaultCode() + "/" + String.format("%02d", sequence++));
-                workOrder.setContractorId(contractor.getId());
-                workOrder.setContractorName(contractor.getName());
+                workOrder.setContractorId(contractorId);
+                workOrder.setContractorName(contractorName);
                 workOrder.setCompletionStatus(StatusConstants.Completion.UNFINISHED);
                 workOrder.setDispatchTime(LocalDateTime.now());
                 workOrder.setCreateTime(LocalDateTime.now());
@@ -401,9 +408,172 @@
         return created;
     }
 
-    public List<WorkOrder> listWorkOrders(String status, String keyword) {
+    public List<CompletionFaultQueryItem> listCompletionQueries(String keyword, String completionStatus,
+                                                               String contractorName, LocalDate startDate,
+                                                               LocalDate endDate) {
+        List<CompletionInfo> completions = completionInfoMapper.selectList(Wrappers.<CompletionInfo>lambdaQuery()
+                .orderByDesc(CompletionInfo::getSubmitTime).orderByDesc(CompletionInfo::getUpdateTime));
+        if (completions.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        Set<Long> workOrderIds = completions.stream().map(CompletionInfo::getWorkOrderId)
+                .filter(Objects::nonNull).collect(Collectors.toSet());
+        if (workOrderIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+        Map<Long, WorkOrder> workOrderMap = workOrderMapper.selectBatchIds(workOrderIds).stream()
+                .collect(Collectors.toMap(WorkOrder::getId, item -> item));
+        Set<Long> faultIds = workOrderMap.values().stream().map(WorkOrder::getFaultId)
+                .filter(Objects::nonNull).collect(Collectors.toSet());
+        if (faultIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+        Map<Long, Fault> faultMap = faultMapper.selectBatchIds(faultIds).stream()
+                .collect(Collectors.toMap(Fault::getId, item -> item));
+
+        String normalizedKeyword = StringUtils.hasText(keyword) ? keyword.trim().toLowerCase() : null;
+        String normalizedContractor = StringUtils.hasText(contractorName) ? contractorName.trim().toLowerCase() : null;
+        Map<Long, CompletionFaultQueryItem> grouped = new LinkedHashMap<>();
+        for (CompletionInfo completion : completions) {
+            WorkOrder workOrder = workOrderMap.get(completion.getWorkOrderId());
+            if (workOrder == null) {
+                continue;
+            }
+            if (StringUtils.hasText(completionStatus)
+                    && !completionStatus.equalsIgnoreCase(workOrder.getCompletionStatus())) {
+                continue;
+            }
+            if (normalizedContractor != null && !containsIgnoreCase(workOrder.getContractorName(), normalizedContractor)) {
+                continue;
+            }
+            LocalDate completionDate = completion.getFinishDate() != null
+                    ? completion.getFinishDate()
+                    : (completion.getSubmitTime() == null ? null : completion.getSubmitTime().toLocalDate());
+            if (startDate != null && (completionDate == null || completionDate.isBefore(startDate))) {
+                continue;
+            }
+            if (endDate != null && (completionDate == null || completionDate.isAfter(endDate))) {
+                continue;
+            }
+
+            Fault fault = faultMap.get(workOrder.getFaultId());
+            if (fault == null) {
+                continue;
+            }
+            CompletionFaultQueryItem.WorkOrderCompletionItem workOrderItem = buildCompletionWorkOrderItem(workOrder, completion);
+            if (normalizedKeyword != null && !matchesCompletionKeyword(fault, workOrderItem, normalizedKeyword)) {
+                continue;
+            }
+
+            CompletionFaultQueryItem item = grouped.get(fault.getId());
+            if (item == null) {
+                item = new CompletionFaultQueryItem();
+                item.setFaultId(String.valueOf(fault.getId()));
+                item.setFaultCode(fault.getFaultCode());
+                item.setXNo(fault.getXNo());
+                item.setEquipmentName(fault.getEquipmentName());
+                item.setParentSystem(fault.getParentSystem());
+                item.setEngineeringMajor(fault.getEngineeringMajor());
+                item.setTeamMajor(fault.getTeamMajor());
+                item.setReportUnit(fault.getReportUnit());
+                item.setReportDate(fault.getReportDate());
+                item.setOwner(fault.getOwner());
+                item.setEngineeringNameDesc(fault.getEngineeringNameDesc());
+                item.setTaskStatus(fault.getTaskStatus());
+                grouped.put(fault.getId(), item);
+            }
+            item.getWorkOrders().add(workOrderItem);
+        }
+
+        List<CompletionFaultQueryItem> result = new ArrayList<>(grouped.values());
+        result.forEach(item -> item.getWorkOrders().sort(Comparator.comparing(
+                CompletionFaultQueryItem.WorkOrderCompletionItem::getWorkOrderNo,
+                Comparator.nullsLast(String::compareTo))));
+        result.sort(Comparator.comparing(CompletionFaultQueryItem::getReportDate,
+                Comparator.nullsLast(Comparator.reverseOrder())));
+        return result;
+    }
+
+    private CompletionFaultQueryItem.WorkOrderCompletionItem buildCompletionWorkOrderItem(
+            WorkOrder workOrder, CompletionInfo completion) {
+        CompletionFaultQueryItem.WorkOrderCompletionItem item = new CompletionFaultQueryItem.WorkOrderCompletionItem();
+        item.setWorkOrderId(String.valueOf(workOrder.getId()));
+        item.setWorkOrderNo(workOrder.getWorkOrderNo());
+        item.setContractorName(workOrder.getContractorName());
+        item.setCompletionStatus(workOrder.getCompletionStatus());
+        item.setEngineeringNo(completion.getEngineeringNo());
+        item.setStartDate(completion.getStartDate());
+        item.setFinishDate(completion.getFinishDate());
+        item.setContractorPerson(completion.getContractorPerson());
+        item.setTInternalConstruction(completion.getTInternalConstruction());
+        item.setRelatedProject(completion.getRelatedProject());
+        item.setDurationDays(completion.getDurationDays());
+        item.setPersonCount(completion.getPersonCount());
+        item.setAcceptanceMode(completion.getAcceptanceMode());
+        item.setQualityInfo(completion.getQualityInfo());
+        item.setReasonAnalysis(completion.getReasonAnalysis());
+        item.setFaultDescription(completion.getFaultDescription());
+        item.setItemName(completion.getItemName());
+        item.setSubmitTime(completion.getSubmitTime());
+        List<Requests.SolutionItem> solutions = parseJsonList(completion.getSolutionsJson(), Requests.SolutionItem.class);
+        if (solutions.isEmpty() && StringUtils.hasText(completion.getSolution())) {
+            Requests.SolutionItem legacy = new Requests.SolutionItem();
+            legacy.setContent(completion.getSolution());
+            solutions.add(legacy);
+        }
+        item.setSolutions(solutions);
+        item.setMaterials(parseJsonList(completion.getConsumablesJson(), Requests.MaterialItem.class));
+        return item;
+    }
+
+    private boolean matchesCompletionKeyword(Fault fault, CompletionFaultQueryItem.WorkOrderCompletionItem item,
+                                             String keyword) {
+        if (containsIgnoreCase(fault.getFaultCode(), keyword)
+                || containsIgnoreCase(fault.getXNo(), keyword)
+                || containsIgnoreCase(fault.getEquipmentName(), keyword)
+                || containsIgnoreCase(fault.getEngineeringNameDesc(), keyword)
+                || containsIgnoreCase(fault.getReportUnit(), keyword)
+                || containsIgnoreCase(item.getWorkOrderNo(), keyword)
+                || containsIgnoreCase(item.getContractorName(), keyword)
+                || containsIgnoreCase(item.getEngineeringNo(), keyword)
+                || containsIgnoreCase(item.getItemName(), keyword)
+                || containsIgnoreCase(item.getContractorPerson(), keyword)) {
+            return true;
+        }
+        return item.getSolutions().stream().anyMatch(solution -> containsIgnoreCase(solution.getContent(), keyword))
+                || item.getMaterials().stream().anyMatch(material -> containsIgnoreCase(material.getName(), keyword)
+                || containsIgnoreCase(material.getSpecification(), keyword));
+    }
+
+    private boolean containsIgnoreCase(String value, String keyword) {
+        return StringUtils.hasText(value) && value.toLowerCase().contains(keyword);
+    }
+
+    private <T> List<T> parseJsonList(String json, Class<T> type) {
+        if (!StringUtils.hasText(json)) {
+            return new ArrayList<>();
+        }
+        try {
+            return objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, type));
+        } catch (Exception exception) {
+            return new ArrayList<>();
+        }
+    }
+
+    public List<WorkOrder> listWorkOrders(String status, String keyword, boolean completionReportable) {
         LambdaQueryWrapper<WorkOrder> query = Wrappers.lambdaQuery();
-        if (StringUtils.hasText(status)) {
+        if (completionReportable) {
+            query.eq(WorkOrder::getCompletionStatus, StatusConstants.Completion.COMPLETED)
+                    .notInSql(WorkOrder::getId, "SELECT WORK_ORDER_ID FROM LX.T_COMPLETION_INFO WHERE DEL_FLAG = 0 OR DEL_FLAG IS NULL");
+            List<String> unitNames = currentUserContractorNames();
+            if (unitNames != null) {
+                if (unitNames.isEmpty()) {
+                    return Collections.emptyList();
+                }
+                query.in(WorkOrder::getContractorName, unitNames);
+            }
+        } else if (StringUtils.hasText(status)) {
             query.in(WorkOrder::getCompletionStatus, Arrays.asList(status.split(",")));
         }
         if (StringUtils.hasText(keyword)) {
@@ -417,6 +587,54 @@
         return workOrderMapper.selectList(query);
     }
 
+    /**
+     * Returns null when the current user sees every unit (system administrator).
+     * Otherwise returns the contractor names matching the logged-in user's department.
+     */
+    private List<String> currentUserContractorNames() {
+        String username = CurrentUserContext.get();
+        if (!StringUtils.hasText(username) || "admin".equalsIgnoreCase(username)) {
+            return null;
+        }
+        List<Map<String, Object>> rows = jdbcTemplate.query(
+                "SELECT d.DEPT_NAME, d.DEPT_TYPE FROM CSICZB_ZB.SYS_USER u "
+                        + "LEFT JOIN CSICZB_ZB.SYS_DEPT d ON d.DEPT_ID = u.DEPT_ID "
+                        + "WHERE u.USER_NAME = ? AND (u.DEL_FLAG = '0' OR u.DEL_FLAG IS NULL)",
+                new Object[]{username}, (rs, rowNum) -> {
+                    Map<String, Object> row = new LinkedHashMap<>();
+                    row.put("deptName", rs.getString("DEPT_NAME"));
+                    row.put("deptType", rs.getString("DEPT_TYPE"));
+                    return row;
+                });
+        if (rows.isEmpty() || !StringUtils.hasText((String) rows.get(0).get("deptName"))) {
+            return Collections.emptyList();
+        }
+        Map<String, Object> dept = rows.get(0);
+        if (!"cj".equalsIgnoreCase(String.valueOf(dept.get("deptType")))) {
+            return Collections.emptyList();
+        }
+        return Collections.singletonList(((String) dept.get("deptName")).trim());
+    }
+
+    private Map<Long, String> contractorNamesByIds(Collection<Long> ids) {
+        Map<Long, String> result = new LinkedHashMap<>();
+        if (ids == null || ids.isEmpty()) {
+            return result;
+        }
+        String placeholders = ids.stream().map(item -> "?").collect(Collectors.joining(","));
+        List<Object> args = new ArrayList<>(ids);
+        return jdbcTemplate.query(
+                "SELECT DEPT_ID, DEPT_NAME FROM CSICZB_ZB.SYS_DEPT "
+                        + "WHERE DEPT_TYPE = 'cj' AND (DEL_FLAG = '0' OR DEL_FLAG IS NULL) "
+                        + "AND DEPT_ID IN (" + placeholders + ")",
+                args.toArray(), rs -> {
+                    while (rs.next()) {
+                        result.put(rs.getLong("DEPT_ID"), rs.getString("DEPT_NAME"));
+                    }
+                    return result;
+                });
+    }
+
     public WorkOrder getWorkOrder(Long id) {
         return workOrderMapper.selectById(id);
     }
@@ -424,13 +642,15 @@
     @Transactional
     public void updateCompletionStatus(Requests.StatusRequest request) {
         WorkOrder workOrder = requireWorkOrder(request.getId());
-        if (StatusConstants.Completion.COMPLETED.equals(workOrder.getCompletionStatus())) {
+        if (StatusConstants.Completion.COMPLETED.equals(workOrder.getCompletionStatus())
+                && !StatusConstants.Completion.COMPLETED.equals(request.getStatus())) {
             throw new BusinessException("宸插畬宸ユ淳宸ュ崟涓嶈兘閫�鍥炴櫘閫氬畬宸ョ姸鎬�");
         }
         if (!Arrays.asList(
                 StatusConstants.Completion.UNFINISHED,
                 StatusConstants.Completion.WAIT_PARTS,
-                StatusConstants.Completion.WAIT_TEST).contains(request.getStatus())) {
+                StatusConstants.Completion.WAIT_TEST,
+                StatusConstants.Completion.COMPLETED).contains(request.getStatus())) {
             throw new BusinessException("瀹屽伐鐘舵�佷笉鍚堟硶");
         }
         workOrder.setCompletionStatus(request.getStatus());
@@ -453,21 +673,22 @@
     @Transactional
     public CompletionInfo submitCompletion(Requests.CompletionRequest request) {
         WorkOrder workOrder = requireWorkOrder(request.getWorkOrderId());
-        if (StatusConstants.Completion.COMPLETED.equals(workOrder.getCompletionStatus())) {
+        CompletionInfo info = completionInfoMapper.selectOne(Wrappers.<CompletionInfo>lambdaQuery()
+                .eq(CompletionInfo::getWorkOrderId, workOrder.getId()).last("LIMIT 1"));
+        if (info != null) {
             throw new BusinessException("璇ユ淳宸ュ崟宸插畬宸ヤ笂鎶ワ紝涓嶈兘閲嶅鎻愪氦");
+        }
+        if (!StatusConstants.Completion.COMPLETED.equals(workOrder.getCompletionStatus())) {
+            throw new BusinessException("璇ユ淳宸ュ崟灏氭湭鍦ㄥ畬宸ユ儏鍐靛鐞嗕腑纭瀹屽伐锛屼笉鑳藉~鎶ュ畬宸ヤ俊鎭�");
         }
         LocalDateTime now = LocalDateTime.now();
         workOrder.setCompletionStatus(StatusConstants.Completion.COMPLETED);
         workOrder.setUpdateTime(now);
         workOrderMapper.updateById(workOrder);
 
-        CompletionInfo info = completionInfoMapper.selectOne(Wrappers.<CompletionInfo>lambdaQuery()
-                .eq(CompletionInfo::getWorkOrderId, workOrder.getId()).last("LIMIT 1"));
-        if (info == null) {
-            info = new CompletionInfo();
-            info.setWorkOrderId(workOrder.getId());
-            info.setCreateTime(now);
-        }
+        info = new CompletionInfo();
+        info.setWorkOrderId(workOrder.getId());
+        info.setCreateTime(now);
         info.setWorkOrderNo(workOrder.getWorkOrderNo());
         info.setXNo(workOrder.getXNo());
         info.setContractorName(workOrder.getContractorName());
@@ -713,7 +934,7 @@
             ids.add(fault.getEquipmentId());
         }
         if (ids.isEmpty()) {
-            throw new BusinessException("璇烽�夋嫨瑁呭鍚嶇О");
+            throw new BusinessException("璇烽�夋嫨璁惧鍚嶇О");
         }
         List<Long> normalized = new ArrayList<>(ids);
         fault.setEquipmentIds(normalized.stream().map(String::valueOf).collect(Collectors.joining(",")));

--
Gitblit v1.9.1