From 1332cc511936d7dbe804921bc733c83d5e4d1400 Mon Sep 17 00:00:00 2001
From: zzw <228544128@qq.com>
Date: 星期二, 06 十月 2026 17:17:49 +0800
Subject: [PATCH] feat: add completion query and configurable system identity

---
 emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 155 insertions(+), 0 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 b36be6c..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,6 +4,7 @@
 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.Fault;
@@ -32,6 +33,7 @@
 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;
@@ -406,6 +408,159 @@
         return created;
     }
 
+    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 (completionReportable) {

--
Gitblit v1.9.1