From 2a64b537e8e3bce9ce030585a3da17d48379c0ad Mon Sep 17 00:00:00 2001
From: sfd <sun.sunshine@163.com>
Date: 星期一, 26 五月 2025 15:04:45 +0800
Subject: [PATCH] 修改json类型转换错误

---
 aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java | 1857 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 1,716 insertions(+), 141 deletions(-)

diff --git a/aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java b/aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java
index 0522a73..42c418c 100644
--- a/aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java
+++ b/aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java
@@ -1,16 +1,17 @@
 package com.aps.core.service.impl;
 
-import com.alibaba.fastjson2.JSONArray;
+import cn.hutool.core.util.IdUtil;
 import com.alibaba.fastjson2.JSONObject;
 import com.aps.common.core.utils.DateUtils;
 import com.aps.common.core.utils.uuid.IdUtils;
 import com.aps.common.security.utils.SecurityUtils;
 import com.aps.core.domain.*;
-import com.aps.core.mapper.ApsGasPipelineCapacityPlanMapper;
-import com.aps.core.mapper.ApsGasPipingPlanMapper;
-import com.aps.core.mapper.ApsGasPipingRouteStatMapper;
+import com.aps.core.domain.ApsPlate.ApsPlateStandardRequireError;
+import com.aps.core.mapper.*;
 import com.aps.core.service.IApsGasMaterialUsageService;
 import com.aps.core.service.IApsGasPipingRouteStatService;
+import com.aps.core.service.IApsStandardProcessService;
+import com.aps.core.mapper.ApsPlateStandardRequireErrorMapper;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.ss.usermodel.*;
@@ -20,18 +21,20 @@
 import org.apache.poi.xssf.streaming.SXSSFRow;
 import org.apache.poi.xssf.streaming.SXSSFSheet;
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.sql.Timestamp;
+import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.YearMonth;
-import java.time.ZoneId;
+import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.stream.Collectors;
+
+import static java.util.stream.Collectors.groupingBy;
 
 /**
  * 姘斾綋绠¤矾浜ц兘璐熻浇缁熻Service涓氬姟灞傚鐞�
@@ -54,6 +57,12 @@
 
     @Autowired
     private IApsGasMaterialUsageService apsGasMaterialUsageService;
+
+    @Autowired
+    private IApsStandardProcessService apsStandardProcessService;
+
+    @Autowired
+    private ApsPlateStandardRequireErrorMapper apsPlateStandardRequireErrorMapper;
 
     /**
      * 鏌ヨ姘斾綋绠¤矾浜ц兘璐熻浇缁熻
@@ -142,9 +151,11 @@
             apsGasPipingPlans.forEach(apsGasPipingPlan -> {
                 List<ApsProcessRoute> apsProcessRoutes = apsGasPipingPlan.getApsProcessRoutes();
                 //鎸夌収宸ュ簭搴忓彿鍗囧簭鎺掑簭
-                apsProcessRoutes.sort((a, b)->a.getProcessNumber().compareTo(b.getProcessNumber()));
+                apsProcessRoutes.sort((a, b)->b.getProcessNumber().compareTo(a.getProcessNumber()));
                 //鏄惁鎵惧埌褰撳墠宸ュ簭
-                boolean isFind = false;
+                boolean isCurrentProcess = false;
+                boolean lastProcessStartTimeIsBeforeNow = false;
+                ApsGasPipingRouteStat preApsProcessRoute = null;
                 for (int i=0;i<apsProcessRoutes.size();i++){
                     ApsProcessRoute apsProcessRoute = apsProcessRoutes.get(i);
                     ApsGasPipingRouteStat apsGasPipingRouteStat = new ApsGasPipingRouteStat();
@@ -153,40 +164,52 @@
                     //鏂欏彿
                     apsGasPipingRouteStat.setItemNumber(apsGasPipingPlan.getItemNumber());
                     //褰撳墠宸ュ簭鍙�
-                    apsGasPipingRouteStat.setCurrentProcessNumber(apsGasPipingPlan.getProcessNumber());
+                    apsGasPipingRouteStat.setCurrentProcessNumber(new BigDecimal(apsGasPipingPlan.getProcessNumber()));
                     //鐢熶骇鏁伴噺
                     apsGasPipingRouteStat.setProductionQuantity(apsGasPipingPlan.getProductionQuantity());
                     //宸ュ簭鍚嶇О
                     apsGasPipingRouteStat.setProcessName(apsProcessRoute.getProcessName());
                     //宸ュ簭鍙�
-                    apsGasPipingRouteStat.setRoadProcessNumber(apsProcessRoute.getProcessNumber());
+                    apsGasPipingRouteStat.setRoadProcessNumber( new BigDecimal(apsProcessRoute.getProcessNumber()) );
                     //鏍囧噯宸ユ椂
                     apsGasPipingRouteStat.setStandardTime(apsProcessRoute.getStandardTime());
                     //涓撲笟
                     apsGasPipingRouteStat.setMajor(apsGasPipingPlan.getPlanType());
                     //宸ュ簭鎬诲伐鏃� 绛変簬 鏍囧噯宸ユ椂*鐢熶骇鏁伴噺
                     apsGasPipingRouteStat.setProcessTotalTime(apsProcessRoute.getStandardTime().multiply(apsGasPipingPlan.getProductionQuantity()));
-                    //璁″垝寮�宸ユ棩
-                    if(apsGasPipingRouteStat.getCurrentProcessNumber().equals(apsGasPipingRouteStat.getRoadProcessNumber())) {
-                        /* 瀵� stat.getProcessPlanStartDay() 鍜屽綋鍓嶆棩鏈� 杩涜瀵规瘮锛屽彧瀵规瘮鍒版棩锛屼笉鐢ㄧ鍗佸垎绉�*/
-                        LocalDate startLocalDate = LocalDate.ofInstant(apsProcessRoute.getProcessPlanStartDay().toInstant(), ZoneId.systemDefault());
-                        LocalDate nowLocalDate = LocalDate.now();
-                        if (startLocalDate.isBefore(nowLocalDate)) {
-                            apsGasPipingRouteStat.setProcessPlanStartDay(new Date());
-                        }else{
-                            apsGasPipingRouteStat.setProcessPlanStartDay(apsProcessRoute.getProcessPlanStartDay());
-                        }
-                        isFind = true;
-                    }
-                    if(!isFind){
-                        continue;
+                    //璁″垝寮�宸ユ棩 濡傛灉鏄綋鍓嶅簭
+                    if(apsGasPipingPlan.getProcessNumber().equals(apsProcessRoute.getProcessNumber())) {
+                        isCurrentProcess = true;
                     }
                     // 涓婁竴閬撳伐搴忕殑缁撴潫鏃堕棿 = 涓婁竴閬撳伐搴忕殑寮�濮嬫椂闂� + 涓婁竴閬撳伐搴忕殑鎬诲伐鏃�
-                    if(apsGasPipingRouteStat.getProcessPlanStartDay()==null){
-                        LocalDateTime previousProcessPlanStartDay = apsProcessRoutes.get(i - 1).getProcessPlanStartDay().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
-                        long previousProcessTotalTime = apsGasPipingRouteStatList.get(i - 1).getProcessTotalTime().longValue();
-                        LocalDateTime currentProcessPlanStartDay = previousProcessPlanStartDay.plusHours(previousProcessTotalTime);
-                        apsGasPipingRouteStat.setProcessPlanStartDay(Date.from(Timestamp.valueOf(currentProcessPlanStartDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).toInstant()));
+                    if(i==0){
+                        LocalDate endLocalDate = LocalDate.ofInstant(apsGasPipingPlan.getPlanEndDay().toInstant(), ZoneId.systemDefault());
+                        LocalDate nowLocalDate = LocalDate.now();
+                        LocalDateTime planEndDay;
+                        if(endLocalDate.isBefore(nowLocalDate)){
+                            planEndDay = LocalDateTime.now();
+                        }else{
+                            planEndDay = apsGasPipingPlan.getPlanEndDay().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+                        }
+                        apsGasPipingRouteStat.setProcessPlanEndDay(Date.from(planEndDay.atZone(ZoneId.systemDefault()).toInstant()));
+                        long seconds = apsProcessRoute.getStandardTime().multiply(apsGasPipingPlan.getProductionQuantity()).multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
+                        LocalDateTime planStartDay = planEndDay.plusSeconds(-seconds);
+                        apsGasPipingRouteStat.setProcessPlanStartDay(Date.from(planStartDay.atZone(ZoneId.systemDefault()).toInstant()));
+                        if(planStartDay.isBefore(LocalDateTime.now())){
+                            lastProcessStartTimeIsBeforeNow = true;
+                        }
+                    }else{
+                        if(lastProcessStartTimeIsBeforeNow){
+                            Date now = new Date();
+                            apsGasPipingRouteStat.setProcessPlanStartDay(now);
+                            apsGasPipingRouteStat.setProcessPlanEndDay(now);
+                        }else{
+                            apsGasPipingRouteStat.setProcessPlanEndDay(preApsProcessRoute.getProcessPlanStartDay());
+                            LocalDateTime planEndDay = preApsProcessRoute.getProcessPlanStartDay().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+                            long seconds = apsProcessRoute.getStandardTime().multiply(apsGasPipingPlan.getProductionQuantity()).multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
+                            LocalDateTime planStartDay = planEndDay.plusSeconds(-seconds);
+                            apsGasPipingRouteStat.setProcessPlanStartDay(Date.from(planStartDay.atZone(ZoneId.systemDefault()).toInstant()));
+                        }
                     }
                     //鎻掑叆 骞� 鏈� 鏃�
                     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@@ -200,14 +223,18 @@
 //                    apsGasMaterialUsage.setItemNumber(apsGasPipingPlan.getItemNumber());
 //                    apsGasMaterialUsage.setProcessName(apsProcessRoute.getProcessName());
 //                    List<ApsGasMaterialUsage> apsGasMaterialUsageList = apsGasMaterialUsageService.selectApsGasMaterialUsageList(apsGasMaterialUsage);
-                    apsGasPipingRouteStat.setStandardDosage(apsProcessRoute.getStandardTime().multiply(apsGasPipingPlan.getProductionQuantity()));
+//                    apsGasPipingRouteStat.setStandardDosage(apsProcessRoute.getStandardTime().multiply(apsGasPipingPlan.getProductionQuantity()));
                     //宸ュ簭鎬荤敤閲� = 鏍囧噯鐢ㄩ噺*鐢熶骇鏁伴噺
-                    apsGasPipingRouteStat.setProcessTotalDosage(apsGasPipingRouteStat.getStandardDosage().multiply(apsGasPipingPlan.getProductionQuantity()));
+//                    apsGasPipingRouteStat.setProcessTotalDosage(apsGasPipingRouteStat.getStandardDosage().multiply(apsGasPipingPlan.getProductionQuantity()));
                     apsGasPipingRouteStat.setCreateTime(DateUtils.getNowDate());
                     apsGasPipingRouteStat.setCreateBy("auto");
                     apsGasPipingRouteStat.setBatchNumber(batchNum);
                     apsGasPipingRouteStat.setId(IdUtils.fastSimpleUUID());
                     apsGasPipingRouteStatList.add(apsGasPipingRouteStat);
+                    preApsProcessRoute = apsGasPipingRouteStat;
+                    if(isCurrentProcess){
+                        break;
+                    }
                 }
             });
             List<ApsGasPipingRouteStat> tempInsertList = new ArrayList<>();
@@ -228,24 +255,48 @@
         return true;
     }
 
-    @Override
-    public JSONObject getCapacityPlanData(ApsGasPipingRouteStat apsGasPipingRouteStat) {
+    public JSONObject getCapacityPlanDataBackup(ApsGasPipingRouteStat apsGasPipingRouteStat) {
         JSONObject result = new JSONObject();
-        HashSet<String> startPlanTimeSet = new HashSet<>();
-        JSONArray processData = new JSONArray();
+        YearMonth yearMonth = YearMonth.parse(apsGasPipingRouteStat.getSearchEndDate());
+        int daysInMonth = yearMonth.lengthOfMonth();
+        LinkedHashSet<String> startPlanTimeSet = new LinkedHashSet<>();
+        //宸ュ簭鍒嗙粍缁熻
+        LinkedHashMap<String, List<ApsResourceDateStat>> processMap = new LinkedHashMap<>();
+        List<HashMap<String, List<ApsResourceDateStat>>> processList = new ArrayList<>();
         try {
+            //鑾峰彇鏍囧噯宸ュ簭鍚嶇О
+            ApsStandardProcess apsStandardProcess = new ApsStandardProcess();
+            apsStandardProcess.setMajor(apsGasPipingRouteStat.getMajor().equals("gas")?"姘旀煖":"绠¤矾");
+            List<ApsStandardProcess> apsStandardProcessList = apsStandardProcessService.selectApsStandardProcessList(apsStandardProcess);
+            apsStandardProcessList.sort((a, b)->a.getProcessName().compareTo(b.getProcessName()));
+            for(ApsStandardProcess temp:apsStandardProcessList){
+                processMap.put(temp.getProcessName(), new ArrayList<ApsResourceDateStat>());
+            }
             //鑾峰彇宸ュ簭璁″垝浜ц兘鏁版嵁
             HashMap<String, ApsGasPipelineCapacityPlan> apsGasPipingPlanMap = new HashMap<>();
-            List<ApsGasPipelineCapacityPlan> apsGasPipelineCapacityPlanList = apsGasPipelineCapacityPlanMapper.selectApsGasPipelineCapacityPlanList(new ApsGasPipelineCapacityPlan());
+            ApsGasPipelineCapacityPlan searchCapacityPlan = new ApsGasPipelineCapacityPlan();
+            searchCapacityPlan.setMajor(apsGasPipingRouteStat.getMajor().equals("gas")?"姘旀煖":"绠¤矾");
+            if("day".equals(apsGasPipingRouteStat.getSearchType())){
+                searchCapacityPlan.setYear(yearMonth.getYear()+"");
+                searchCapacityPlan.setMonth(yearMonth.getMonthValue()+"");
+                for(int i=1;i<=daysInMonth;i++){
+                    startPlanTimeSet.add(yearMonth +"-"+ (i<10?"0"+i:i));
+                }
+            }else if("month".equals(apsGasPipingRouteStat.getSearchType())){
+                searchCapacityPlan.setYear(yearMonth.getYear()+"");
+                YearMonth start = YearMonth.of(Integer.parseInt(apsGasPipingRouteStat.getSearchStartDate().split("-")[0]), Integer.parseInt(apsGasPipingRouteStat.getSearchStartDate().split("-")[1]));
+                YearMonth end = YearMonth.of(Integer.parseInt(apsGasPipingRouteStat.getSearchEndDate().split("-")[0]), Integer.parseInt(apsGasPipingRouteStat.getSearchEndDate().split("-")[1]));
+                List<String> yearMonths = getYearMonthsInRange(start, end);
+                startPlanTimeSet.addAll(yearMonths);
+            }
+            List<ApsGasPipelineCapacityPlan> apsGasPipelineCapacityPlanList = apsGasPipelineCapacityPlanMapper.selectApsGasPipelineCapacityPlanList(searchCapacityPlan);
             apsGasPipelineCapacityPlanList.forEach(apsGasPipelineCapacityPlan -> {
-                apsGasPipingPlanMap.put(apsGasPipelineCapacityPlan.getProcessName(),apsGasPipelineCapacityPlan);
+                apsGasPipingPlanMap.put(apsGasPipelineCapacityPlan.getProcessName()+"-"+apsGasPipelineCapacityPlan.getYear()+"-"+(Integer.parseInt(apsGasPipelineCapacityPlan.getMonth())<10?"0"+apsGasPipelineCapacityPlan.getMonth():apsGasPipelineCapacityPlan.getMonth()),apsGasPipelineCapacityPlan);
             });
             //璁$畻鏃ヤ骇鑳芥暟鎹�
             DateTimeFormatter formatter = null;
             List<ApsGasPipingRouteStat> apsGasPipingRouteStats;
             SimpleDateFormat simpleDateFormat = null;
-            YearMonth yearMonth = YearMonth.parse(apsGasPipingRouteStat.getSearchEndDate());
-            int daysInMonth = yearMonth.lengthOfMonth();
             apsGasPipingRouteStat.setSearchStartDate(apsGasPipingRouteStat.getSearchStartDate()+"-01 00:00:00");
             apsGasPipingRouteStat.setSearchEndDate(apsGasPipingRouteStat.getSearchEndDate()+"-"+ daysInMonth +" 23:59:59");
             if("day".equals(apsGasPipingRouteStat.getSearchType())){
@@ -255,120 +306,403 @@
                 formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                 simpleDateFormat = new SimpleDateFormat("yyyy-MM");
             }
-            apsGasPipingRouteStats = apsGasPipingRouteStatMapper.selectApsGasPipingRouteStatList(apsGasPipingRouteStat);
+            ApsGasPipingRouteStat queryStatParam = new ApsGasPipingRouteStat();
+            BeanUtils.copyProperties(apsGasPipingRouteStat,queryStatParam);
+            queryStatParam.setMajor("");
+            apsGasPipingRouteStats = apsGasPipingRouteStatMapper.selectApsGasPipingRouteStatList(queryStatParam);
             //鏍规嵁寮�宸ユ棩杩涜鍗囧簭鎺掑簭
-            apsGasPipingRouteStats.sort((a, b)->a.getPlanStartDay().compareTo(b.getPlanStartDay()));
-            //宸ュ簭鍒嗙粍缁熻
-            HashMap<String, List<ApsResourceDateStat>> processMap = new HashMap<>();
-            List<HashMap<String, List<ApsResourceDateStat>>> processList = new ArrayList<>();
-            HashMap<String, List<ApsResourceDateStat>> processMapMonth = new HashMap<>();
-            List<HashMap<String, List<ApsResourceDateStat>>> processListMonth = new ArrayList<>();
+            apsGasPipingRouteStats.sort((a, b)->a.getProcessPlanStartDay().compareTo(b.getProcessPlanStartDay()));
             //宸ュ簭寮�宸ユ棩鏈�
             String planStartDate = "";
+            //缁熻鎵�鏈夊伐搴忓搴旂殑寮�宸ユ椂闂�
             for (ApsGasPipingRouteStat apsGasPipingRouteStatTemp : apsGasPipingRouteStats) {
-                planStartDate = simpleDateFormat.format(apsGasPipingRouteStatTemp.getProcessPlanStartDay());
-                if("month".equals(apsGasPipingRouteStat.getSearchType())){
-                    planStartDate = planStartDate+"-01";
-                }
-                ApsResourceDateStat apsResourceDateStat = new ApsResourceDateStat();
-                apsResourceDateStat.setPlanDay(LocalDate.parse(planStartDate, formatter));
-                apsResourceDateStat.setResourceName(apsGasPipingRouteStatTemp.getProcessName());
-                //鏌ヨ姘旀煖绠¤矾浜ц兘瑙勫垝琛�
-                apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(apsGasPipingRouteStatTemp.getProcessName())!=null?apsGasPipingPlanMap.get(apsGasPipingRouteStatTemp.getProcessName()).getDayProduceAllNum().intValue():0);
-                //鏌ヨ鏂欏彿宸ュ簭浜ц兘琛�
-                apsResourceDateStat.setRequireTimes(apsGasPipingRouteStatTemp.getProcessTotalTime().intValue());
-                if(apsResourceDateStat.getDesignTimes()!=0){
-                    apsResourceDateStat.setCapacityLoad(BigDecimal.valueOf(apsResourceDateStat.getRequireTimes()/apsResourceDateStat.getDesignTimes()* 100L));
-                }else{
-                    apsResourceDateStat.setCapacityLoad(BigDecimal.valueOf(0));
-                }
-                List<ApsResourceDateStat> apsResourceDateStatList = new ArrayList<>();
                 if(processMap.containsKey(apsGasPipingRouteStatTemp.getProcessName())){
-                    apsResourceDateStatList = processMap.get(apsGasPipingRouteStatTemp.getProcessName());
-                }
-                apsResourceDateStatList.add(apsResourceDateStat);
-                processMap.put(apsGasPipingRouteStatTemp.getProcessName(), apsResourceDateStatList);
-            }
-            processMap.forEach((processName, apsResourceDateStatList) -> {
-                HashMap<String, ApsResourceDateStat> dayMap = new HashMap<>();
-                apsResourceDateStatList.forEach(apsResourceDateStat -> {
-                    startPlanTimeSet.add(apsResourceDateStat.getPlanDay().toString());
+                    planStartDate = simpleDateFormat.format(apsGasPipingRouteStatTemp.getProcessPlanStartDay());
                     if("month".equals(apsGasPipingRouteStat.getSearchType())){
-                        if(dayMap.containsKey(apsResourceDateStat.getPlanDay().toString())){
-                            ApsResourceDateStat apsResourceDateStatTemp = dayMap.get(apsResourceDateStat.getPlanDay().toString());
-                            apsResourceDateStatTemp.setDesignTimes(apsGasPipingPlanMap.get(processName)!=null?apsGasPipingPlanMap.get(processName).getMonthProduceAllNum().intValue():0);
-                            apsResourceDateStatTemp.setRequireTimes(apsResourceDateStatTemp.getRequireTimes()+apsResourceDateStat.getRequireTimes());
-                            if(apsResourceDateStatTemp.getDesignTimes()!=0){
-                                apsResourceDateStatTemp.setCapacityLoad(BigDecimal.valueOf(apsResourceDateStatTemp.getRequireTimes()/apsResourceDateStatTemp.getDesignTimes()* 100L));
+                        planStartDate = planStartDate+"-01";
+                    }
+                    ApsResourceDateStat apsResourceDateStat = new ApsResourceDateStat();
+                    apsResourceDateStat.setPlanDay(LocalDate.parse(planStartDate, formatter));
+                    apsResourceDateStat.setResourceName(apsGasPipingRouteStatTemp.getProcessName());
+                    //鏌ヨ姘旀煖绠¤矾浜ц兘瑙勫垝琛�
+                    apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(apsGasPipingRouteStatTemp.getProcessName()+"-"+planStartDate.substring(0, 7))!=null?apsGasPipingPlanMap.get(apsGasPipingRouteStatTemp.getProcessName()+"-"+planStartDate.substring(0, 7)).getDayProduceAllNum():new BigDecimal(0));
+                    //鏌ヨ鏂欏彿宸ュ簭浜ц兘琛�
+                    apsResourceDateStat.setRequireTimes(apsGasPipingRouteStatTemp.getProcessTotalTime());
+                    if(apsResourceDateStat.getDesignTimes().compareTo(BigDecimal.ZERO)>0){
+                        apsResourceDateStat.setCapacityLoad(apsResourceDateStat.getRequireTimes()
+                                .divide(apsResourceDateStat.getDesignTimes(), 2, RoundingMode.HALF_UP)
+                                .multiply(new BigDecimal(100)));
+                    }else{
+                        apsResourceDateStat.setCapacityLoad(BigDecimal.valueOf(0));
+                    }
+                   // apsResourceDateStatList = new ArrayList<>();
+
+                    List<ApsResourceDateStat>   apsResourceDateStatList = processMap.get(apsGasPipingRouteStatTemp.getProcessName());
+                    apsResourceDateStatList.add(apsResourceDateStat);
+                    processMap.put(apsGasPipingRouteStatTemp.getProcessName(), apsResourceDateStatList);
+                }
+
+            }
+            //鑱氬悎姣忛亾宸ュ簭鐨勫紑宸ユ椂闂村拰浜ц兘
+            processMap.forEach((processName, apsResourceDateStatList) -> {
+                LinkedHashMap<String, ApsResourceDateStat> dayMap = new LinkedHashMap<>();
+                apsResourceDateStatList.forEach(apsResourceDateStat -> {
+//                    startPlanTimeSet.add(apsResourceDateStat.getPlanDay().toString());
+                    if(dayMap.containsKey(apsResourceDateStat.getPlanDay().toString())){
+                        ApsResourceDateStat apsResourceDateStatTemp = dayMap.get(apsResourceDateStat.getPlanDay().toString());
+                        if("month".equals(apsGasPipingRouteStat.getSearchType())){
+                            apsResourceDateStatTemp.setDesignTimes(apsGasPipingPlanMap.get(processName+"-"+apsResourceDateStat.getPlanDay().toString().substring(0,7))!=null?apsGasPipingPlanMap.get(processName+"-"+apsResourceDateStat.getPlanDay().toString().substring(0,7)).getMonthProduceAllNum():new BigDecimal(0));
+                        }else{
+                            apsResourceDateStatTemp.setDesignTimes(apsGasPipingPlanMap.get(processName+"-"+apsResourceDateStat.getPlanDay().toString().substring(0,7))!=null?apsGasPipingPlanMap.get(processName+"-"+apsResourceDateStat.getPlanDay().toString().substring(0,7)).getDayProduceAllNum():new BigDecimal(0));
+                        }
+                        apsResourceDateStatTemp.setRequireTimes(apsResourceDateStatTemp.getRequireTimes().add(apsResourceDateStat.getRequireTimes()));
+                        if(apsResourceDateStatTemp.getDesignTimes().compareTo(BigDecimal.ZERO) > 0){
+                            apsResourceDateStatTemp.setCapacityLoad(apsResourceDateStatTemp.getRequireTimes()
+                                    .divide(apsResourceDateStatTemp.getDesignTimes(), 2, RoundingMode.HALF_UP)
+                                    .multiply(new BigDecimal(100)));
+                        }else{
+                            apsResourceDateStatTemp.setCapacityLoad(new BigDecimal(0));
+                        }
+                        apsResourceDateStatTemp.setResourceGroupName(processName);
+                        apsResourceDateStatTemp.setPlanDay(apsResourceDateStat.getPlanDay());
+                        dayMap.put(apsResourceDateStat.getPlanDay().toString(), apsResourceDateStatTemp);
+                    }else{
+                        dayMap.put(apsResourceDateStat.getPlanDay().toString(), apsResourceDateStat);
+                    }
+                });
+                List<ApsResourceDateStat> tempList = new ArrayList<>();
+                dayMap.forEach((key, value) -> {
+                    tempList.add(value);
+                });
+                HashMap<String, List<ApsResourceDateStat>> temp = new HashMap<>();
+                temp.put(processName, tempList);
+                processList.add(temp);
+            });
+            //鎺掑簭鏃堕棿鏍囬
+            List<String> sortedStartPlanTimeList = new ArrayList<>(startPlanTimeSet);
+            Collections.sort(sortedStartPlanTimeList);
+            for (int i=0;i<processList.size();i++){
+                HashMap<String, List<ApsResourceDateStat>> temp = processList.get(i);
+                for (Map.Entry<String, List<ApsResourceDateStat>> entry : temp.entrySet()){
+                    List<ApsResourceDateStat> apsResourceDateStatList = entry.getValue();
+                    String key = entry.getKey();
+                    List<ApsResourceDateStat> crtList = new ArrayList<>();
+                    for(String tempTime:sortedStartPlanTimeList) {
+                        if("month".equals(apsGasPipingRouteStat.getSearchType())){
+                            tempTime += "-01";
+                        }
+                        LocalDate crtDate = LocalDate.parse(tempTime, formatter);
+                        Optional<ApsResourceDateStat> first = apsResourceDateStatList.stream().filter(x -> x.getPlanDay().equals(crtDate)).findFirst();
+                        if (first.isPresent()) {
+                            ApsResourceDateStat apsResourceDateStat = first.get();
+                            crtList.add(apsResourceDateStat);
+                        } else {
+                            ApsResourceDateStat apsResourceDateStat = new ApsResourceDateStat();
+                            apsResourceDateStat.setPlanDay(LocalDate.parse(tempTime, formatter));
+                            if ("month".equals(apsGasPipingRouteStat.getSearchType())) {
+                                apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(entry.getKey()+"-"+tempTime.substring(0,7)) != null ? apsGasPipingPlanMap.get(entry.getKey()+"-"+tempTime.substring(0,7)).getMonthProduceAllNum() : new BigDecimal(0));
+                            } else {
+                                apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(entry.getKey()+"-"+tempTime.substring(0,7)) != null ? apsGasPipingPlanMap.get(entry.getKey()+"-"+tempTime.substring(0,7)).getDayProduceAllNum() : new BigDecimal(0));
+                            }
+                            apsResourceDateStat.setRequireTimes(new BigDecimal(0));
+                            apsResourceDateStat.setCapacityLoad(new BigDecimal(0));
+                            apsResourceDateStat.setResourceName(entry.getKey());
+                            apsResourceDateStat.setResourceGroupName(entry.getKey());
+                            apsResourceDateStatList.add(apsResourceDateStat);
+                            crtList.add(apsResourceDateStat);
+                        }
+                        temp.put(entry.getKey(), crtList);
+                        processList.set(i, temp);
+                    }
+                }
+            }
+            result.put("planTable", processList);
+            result.put("planTitle", sortedStartPlanTimeList);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    @Override
+    public JSONObject getCapacityPlanData(ApsGasPipingRouteStat apsGasPipingRouteStat) {
+        JSONObject result = new JSONObject();
+        YearMonth yearMonth = YearMonth.parse(apsGasPipingRouteStat.getSearchEndDate());
+        int daysInMonth = yearMonth.lengthOfMonth();
+        LinkedHashSet<String> startPlanTimeSet = new LinkedHashSet<>();
+        //宸ュ簭鍒嗙粍缁熻
+        LinkedHashMap<String, List<ApsResourceDateStat>> processMap = new LinkedHashMap<>();
+        List<HashMap<String, List<ApsResourceDateStat>>> processList = new ArrayList<>();
+        try {
+            //鑾峰彇鏍囧噯宸ュ簭鍚嶇О
+            ApsStandardProcess apsStandardProcess = new ApsStandardProcess();
+            apsStandardProcess.setMajor(apsGasPipingRouteStat.getMajor().equals("gas")?"姘旀煖":"绠¤矾");
+            List<ApsStandardProcess> apsStandardProcessList = apsStandardProcessService.selectApsStandardProcessList(apsStandardProcess);
+            apsStandardProcessList.sort((a, b)->a.getProcessName().compareTo(b.getProcessName()));
+            for(ApsStandardProcess temp:apsStandardProcessList){
+                processMap.put(temp.getProcessName(), new ArrayList<ApsResourceDateStat>());
+            }
+            //鑾峰彇宸ュ簭璁″垝浜ц兘鏁版嵁
+            HashMap<String, ApsGasPipelineCapacityPlan> apsGasPipingPlanMap = new HashMap<>();
+            ApsGasPipelineCapacityPlan searchCapacityPlan = new ApsGasPipelineCapacityPlan();
+            searchCapacityPlan.setMajor(apsGasPipingRouteStat.getMajor().equals("gas")?"姘旀煖":"绠¤矾");
+            if("day".equals(apsGasPipingRouteStat.getSearchType())){
+                searchCapacityPlan.setYear(yearMonth.getYear()+"");
+                searchCapacityPlan.setMonth(yearMonth.getMonthValue()+"");
+                for(int i=1;i<=daysInMonth;i++){
+                    startPlanTimeSet.add(yearMonth +"-"+ (i<10?"0"+i:i));
+                }
+            }else if("month".equals(apsGasPipingRouteStat.getSearchType())){
+                searchCapacityPlan.setYear(yearMonth.getYear()+"");
+                YearMonth start = YearMonth.of(Integer.parseInt(apsGasPipingRouteStat.getSearchStartDate().split("-")[0]), Integer.parseInt(apsGasPipingRouteStat.getSearchStartDate().split("-")[1]));
+                YearMonth end = YearMonth.of(Integer.parseInt(apsGasPipingRouteStat.getSearchEndDate().split("-")[0]), Integer.parseInt(apsGasPipingRouteStat.getSearchEndDate().split("-")[1]));
+                List<String> yearMonths = getYearMonthsInRange(start, end);
+                startPlanTimeSet.addAll(yearMonths);
+            }
+            List<ApsGasPipelineCapacityPlan> apsGasPipelineCapacityPlanList = apsGasPipelineCapacityPlanMapper.selectApsGasPipelineCapacityPlanList(searchCapacityPlan);
+            apsGasPipelineCapacityPlanList.forEach(apsGasPipelineCapacityPlan -> {
+                String key = apsGasPipelineCapacityPlan.getProcessName() + "-" + apsGasPipelineCapacityPlan.getOrgCode() + "-" + apsGasPipelineCapacityPlan.getYear() + "-" + (Integer.parseInt(apsGasPipelineCapacityPlan.getMonth())<10?"0"+apsGasPipelineCapacityPlan.getMonth():apsGasPipelineCapacityPlan.getMonth());
+                apsGasPipingPlanMap.put(key, apsGasPipelineCapacityPlan);
+            });
+            //璁$畻鏃ヤ骇鑳芥暟鎹�
+            DateTimeFormatter formatter = null;
+            List<ApsGasPipingRouteStat> apsGasPipingRouteStats;
+            SimpleDateFormat simpleDateFormat = null;
+            apsGasPipingRouteStat.setSearchStartDate(apsGasPipingRouteStat.getSearchStartDate()+"-01 00:00:00");
+            apsGasPipingRouteStat.setSearchEndDate(apsGasPipingRouteStat.getSearchEndDate()+"-"+ daysInMonth +" 23:59:59");
+            if("day".equals(apsGasPipingRouteStat.getSearchType())){
+                formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+            }else if("month".equals(apsGasPipingRouteStat.getSearchType())){
+                formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                simpleDateFormat = new SimpleDateFormat("yyyy-MM");
+            }
+            ApsGasPipingRouteStat queryStatParam = new ApsGasPipingRouteStat();
+            BeanUtils.copyProperties(apsGasPipingRouteStat,queryStatParam);
+            queryStatParam.setMajor(apsGasPipingRouteStat.getMajor());
+            queryStatParam.setPlant(apsGasPipingRouteStat.getPlant());
+            apsGasPipingRouteStats = apsGasPipingRouteStatMapper.selectApsGasPipingRouteStatList(queryStatParam);
+            //鏍规嵁寮�宸ユ棩杩涜鍗囧簭鎺掑簭
+            apsGasPipingRouteStats.sort((a, b)->a.getProcessPlanStartDay().compareTo(b.getProcessPlanStartDay()));
+            //宸ュ簭寮�宸ユ棩鏈�
+            String planStartDate = "";
+            //缁熻鎵�鏈夊伐搴忓搴旂殑寮�宸ユ椂闂�
+            for (ApsGasPipingRouteStat apsGasPipingRouteStatTemp : apsGasPipingRouteStats) {
+                if(processMap.containsKey(apsGasPipingRouteStatTemp.getProcessName())){
+                    planStartDate = simpleDateFormat.format(apsGasPipingRouteStatTemp.getProcessPlanStartDay());
+                    if("month".equals(apsGasPipingRouteStat.getSearchType())){
+                        planStartDate = planStartDate+"-01";
+                    }
+                    ApsResourceDateStat apsResourceDateStat = new ApsResourceDateStat();
+                    apsResourceDateStat.setPlanDay(LocalDate.parse(planStartDate, formatter));
+                    apsResourceDateStat.setResourceName(apsGasPipingRouteStatTemp.getProcessName());
+                    apsResourceDateStat.setPlant(apsGasPipingRouteStatTemp.getPlant());
+                    //鏌ヨ姘旀煖绠¤矾浜ц兘瑙勫垝琛�
+                    String capacityKey = apsGasPipingRouteStatTemp.getProcessName() + "-" + apsGasPipingRouteStatTemp.getPlant() + "-" + planStartDate.substring(0, 7);
+                    apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(capacityKey)!=null?apsGasPipingPlanMap.get(capacityKey).getDayProduceAllNum():new BigDecimal(0));
+                    //鏌ヨ鏂欏彿宸ュ簭浜ц兘琛�
+                    apsResourceDateStat.setRequireTimes(apsGasPipingRouteStatTemp.getProcessTotalTime());
+                    if(apsResourceDateStat.getDesignTimes().compareTo(BigDecimal.ZERO)>0){
+                        apsResourceDateStat.setCapacityLoad(apsResourceDateStat.getRequireTimes()
+                                .divide(apsResourceDateStat.getDesignTimes(), 2, RoundingMode.HALF_UP)
+                                .multiply(new BigDecimal(100)));
+                    }else{
+                        apsResourceDateStat.setCapacityLoad(BigDecimal.valueOf(0));
+                    }
+
+                    List<ApsResourceDateStat> apsResourceDateStatList = processMap.get(apsGasPipingRouteStatTemp.getProcessName());
+                    apsResourceDateStatList.add(apsResourceDateStat);
+                    processMap.put(apsGasPipingRouteStatTemp.getProcessName(), apsResourceDateStatList);
+                }
+            }
+            //鑱氬悎姣忛亾宸ュ簭鐨勫紑宸ユ椂闂村拰浜ц兘
+            for (Map.Entry<String, List<ApsResourceDateStat>> entry : processMap.entrySet()) {
+                String processName = entry.getKey();
+                List<ApsResourceDateStat> apsResourceDateStatList = entry.getValue();
+
+                if("day".equals(apsGasPipingRouteStat.getSearchType())) {
+                    // 鎸夊ぉ缁熻鏃朵繚鎸佸師鏈夐�昏緫锛屼笉鎸夊伐鍘傚垎缁�
+                    LinkedHashMap<String, ApsResourceDateStat> dayMap = new LinkedHashMap<>();
+
+                    // 棣栧厛锛屼负鎵�鏈夋棩鏈熷垱寤哄垵濮嬭褰�
+                    for(String date : startPlanTimeSet) {
+                        ApsResourceDateStat initStat = new ApsResourceDateStat();
+                        initStat.setPlanDay(LocalDate.parse(date, formatter));
+                        initStat.setResourceName(processName);
+                        initStat.setResourceGroupName(processName);
+                        initStat.setRequireTimes(new BigDecimal(0));
+                        String capacityKey = processName + "-" + date.substring(0,7);
+                        initStat.setDesignTimes(apsGasPipingPlanMap.get(capacityKey)!=null?apsGasPipingPlanMap.get(capacityKey).getDayProduceAllNum():new BigDecimal(0));
+                        initStat.setCapacityLoad(new BigDecimal(0));
+                        dayMap.put(date, initStat);
+                    }
+
+                    // 鐒跺悗澶勭悊瀹為檯鏁版嵁
+                    for (ApsResourceDateStat apsResourceDateStat : apsResourceDateStatList) {
+                        String dateKey = apsResourceDateStat.getPlanDay().toString();
+                        if(dayMap.containsKey(dateKey)){
+                            ApsResourceDateStat apsResourceDateStatTemp = dayMap.get(dateKey);
+                            String capacityKey = processName + "-"+ apsResourceDateStat.getPlant() + "-" + dateKey.substring(0,7);
+                            apsResourceDateStatTemp.setDesignTimes(apsGasPipingPlanMap.get(capacityKey)!=null?apsGasPipingPlanMap.get(capacityKey).getDayProduceAllNum():new BigDecimal(0));
+                            apsResourceDateStatTemp.setRequireTimes(apsResourceDateStatTemp.getRequireTimes().add(apsResourceDateStat.getRequireTimes()));
+                            if(apsResourceDateStatTemp.getDesignTimes().compareTo(BigDecimal.ZERO) > 0){
+                                apsResourceDateStatTemp.setCapacityLoad(apsResourceDateStatTemp.getRequireTimes()
+                                        .divide(apsResourceDateStatTemp.getDesignTimes(), 2, RoundingMode.HALF_UP)
+                                        .multiply(new BigDecimal(100)));
                             }else{
-                                apsResourceDateStatTemp.setCapacityLoad(BigDecimal.valueOf(0));
+                                apsResourceDateStatTemp.setCapacityLoad(new BigDecimal(0));
                             }
                             apsResourceDateStatTemp.setResourceGroupName(processName);
                             apsResourceDateStatTemp.setPlanDay(apsResourceDateStat.getPlanDay());
-                            dayMap.put(apsResourceDateStat.getPlanDay().toString(), apsResourceDateStatTemp);
-                        }else{
-                            dayMap.put(apsResourceDateStat.getPlanDay().toString(), apsResourceDateStat);
+                            dayMap.put(dateKey, apsResourceDateStatTemp);
                         }
                     }
-                });
-                if("month".equals(apsGasPipingRouteStat.getSearchType())){
-                    List<ApsResourceDateStat> tempList = new ArrayList<>();
-                    dayMap.forEach((key, value) -> {
-                        tempList.add(value);
-                    });
-                    processMapMonth.put(processName, tempList);
+
+                    List<ApsResourceDateStat> tempList = new ArrayList<>(dayMap.values());
+                    HashMap<String, List<ApsResourceDateStat>> temp = new HashMap<>();
+                    temp.put(processName, tempList);
+                    processList.add(temp);
+                } else {
+                    // 鎸夋湀缁熻鏃舵墠鎸夊伐鍘傚垎缁�
+                    if (apsResourceDateStatList.isEmpty()) {
+                        // 浠庝骇鑳借鍒掓暟鎹腑鑾峰彇鎵�鏈夌殑宸ュ巶
+                        Set<String> plants = apsGasPipelineCapacityPlanList.stream()
+                                .filter(plan -> plan.getProcessName().equals(processName))
+                                .map(ApsGasPipelineCapacityPlan::getOrgCode)
+                                .filter(orgCode -> orgCode != null && !orgCode.trim().isEmpty())
+                                .collect(Collectors.toSet());
+
+                        // 濡傛灉娌℃湁鎵惧埌浠讳綍鏈夋晥宸ュ巶锛岃烦杩囪繖涓伐搴�
+                        if (plants.isEmpty()) {
+                            continue;
+                        }
+
+                        // 涓烘瘡涓伐鍘傚垱寤虹┖璁板綍
+                        for (String plant : plants) {
+                            LinkedHashMap<String, ApsResourceDateStat> dayMap = new LinkedHashMap<>();
+                            // 涓烘瘡涓湀浠藉垱寤鸿褰�
+                            for(String monthDate : startPlanTimeSet) {
+                                String tempTime = monthDate + "-01";
+                                ApsResourceDateStat apsResourceDateStat = new ApsResourceDateStat();
+                                apsResourceDateStat.setPlanDay(LocalDate.parse(tempTime, formatter));
+                                apsResourceDateStat.setResourceName(processName);
+                                apsResourceDateStat.setResourceGroupName(processName + "-" + plant);
+                                apsResourceDateStat.setPlant(plant);
+                                apsResourceDateStat.setRequireTimes(new BigDecimal(0));
+                                String capacityKey = processName + "-" + plant + "-" + monthDate;
+                                apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(capacityKey)!=null?apsGasPipingPlanMap.get(capacityKey).getMonthProduceAllNum():new BigDecimal(0));
+                                apsResourceDateStat.setCapacityLoad(new BigDecimal(0));
+                                dayMap.put(monthDate, apsResourceDateStat);
+                            }
+                            List<ApsResourceDateStat> tempList = new ArrayList<>(dayMap.values());
+                            HashMap<String, List<ApsResourceDateStat>> temp = new HashMap<>();
+                            temp.put(processName + "_" + plant, tempList);
+                            processList.add(temp);
+                        }
+                    } else {
+                        // 鎸夊伐鍘傚垎缁勶紝骞惰繃婊ゆ帀plant涓簄ull鎴栫┖瀛楃涓茬殑璁板綍
+                        Map<String, List<ApsResourceDateStat>> plantGroups = apsResourceDateStatList.stream()
+                                .filter(stat -> stat.getPlant() != null && !stat.getPlant().trim().isEmpty())
+                                .collect(groupingBy(ApsResourceDateStat::getPlant));
+
+                        // 濡傛灉杩囨护鍚庢病鏈夋湁鏁堢殑宸ュ巶鏁版嵁锛岃烦杩囪繖涓伐搴�
+                        if (plantGroups.isEmpty()) {
+                            continue;
+                        }
+
+                        // 瀵规瘡涓伐鍘傜殑鏁版嵁杩涜澶勭悊
+                        for (Map.Entry<String, List<ApsResourceDateStat>> plantEntry : plantGroups.entrySet()) {
+                            String plant = plantEntry.getKey();
+                            // 鍐嶆纭plant涓嶄负绌�
+                            if (plant == null || plant.trim().isEmpty()) {
+                                continue;
+                            }
+                            List<ApsResourceDateStat> plantStats = plantEntry.getValue();
+                            LinkedHashMap<String, ApsResourceDateStat> dayMap = new LinkedHashMap<>();
+
+                            // 棣栧厛涓烘墍鏈夋湀浠藉垱寤哄垵濮嬭褰�
+                            for(String monthDate : startPlanTimeSet) {
+                                String tempTime = monthDate + "-01";
+                                ApsResourceDateStat initStat = new ApsResourceDateStat();
+                                initStat.setPlanDay(LocalDate.parse(tempTime, formatter));
+                                initStat.setResourceName(processName);
+                                initStat.setResourceGroupName(processName + "-" + plant);
+                                initStat.setPlant(plant);
+                                initStat.setRequireTimes(new BigDecimal(0));
+                                String capacityKey = processName + "-" + plant + "-" + monthDate;
+                                initStat.setDesignTimes(apsGasPipingPlanMap.get(capacityKey)!=null?apsGasPipingPlanMap.get(capacityKey).getMonthProduceAllNum():new BigDecimal(0));
+                                initStat.setCapacityLoad(new BigDecimal(0));
+                                dayMap.put(monthDate, initStat);
+                            }
+
+                            // 鐒跺悗澶勭悊瀹為檯鏁版嵁
+                            for (ApsResourceDateStat stat : plantStats) {
+                                String monthKey = stat.getPlanDay().toString().substring(0, 7);
+                                if (dayMap.containsKey(monthKey)) {
+                                    ApsResourceDateStat existingStat = dayMap.get(monthKey);
+                                    String capacityKey = processName + "-" + plant + "-" + monthKey;
+                                    existingStat.setDesignTimes(apsGasPipingPlanMap.get(capacityKey)!=null?apsGasPipingPlanMap.get(capacityKey).getMonthProduceAllNum():new BigDecimal(0));
+                                    existingStat.setRequireTimes(existingStat.getRequireTimes().add(stat.getRequireTimes()));
+                                    if(existingStat.getDesignTimes().compareTo(BigDecimal.ZERO) > 0){
+                                        existingStat.setCapacityLoad(existingStat.getRequireTimes()
+                                                .divide(existingStat.getDesignTimes(), 2, RoundingMode.HALF_UP)
+                                                .multiply(new BigDecimal(100)));
+                                    }
+                                }
+                            }
+
+                            List<ApsResourceDateStat> tempList = new ArrayList<>(dayMap.values());
+                            HashMap<String, List<ApsResourceDateStat>> temp = new HashMap<>();
+                            temp.put(processName + "_" + plant, tempList);
+                            processList.add(temp);
+                        }
+                    }
                 }
-            });
+            }
+            //鎺掑簭鏃堕棿鏍囬
             List<String> sortedStartPlanTimeList = new ArrayList<>(startPlanTimeSet);
             Collections.sort(sortedStartPlanTimeList);
-//            processMap.forEach((processName, apsResourceDateStatList) -> {
-//                HashMap<String, ApsResourceDateStat> dayMap = new HashMap<>();
-//                apsResourceDateStatList.forEach(apsResourceDateStat -> {
-//                    startPlanTimeSet.add(apsResourceDateStat.getPlanDay().toString());
-//                    if(dayMap.containsKey(apsResourceDateStat.getPlanDay().toString())){
-//                        ApsResourceDateStat apsResourceDateStatTemp = dayMap.get(apsResourceDateStat.getPlanDay().toString());
-//                        if("day".equals(apsGasPipingRouteStat.getSearchType())){
-//                            apsResourceDateStatTemp.setDesignTimes(apsResourceDateStatTemp.getDesignTimes()+apsResourceDateStat.getDesignTimes());
-//                        }else if("month".equals(apsGasPipingRouteStat.getSearchType())){
-//                            apsResourceDateStatTemp.setDesignTimes(apsGasPipingPlanMap.get(processName)!=null?apsGasPipingPlanMap.get(processName).getMonthProduceAllNum().intValue():0);
-//                        }
-//                        apsResourceDateStatTemp.setRequireTimes(apsResourceDateStatTemp.getRequireTimes()+apsResourceDateStat.getRequireTimes());
-//                        if(apsResourceDateStatTemp.getDesignTimes()!=0){
-//                            apsResourceDateStatTemp.setCapacityLoad(BigDecimal.valueOf(apsResourceDateStatTemp.getRequireTimes()/apsResourceDateStatTemp.getDesignTimes()* 100L));
-//                        }
-//                        apsResourceDateStatTemp.setResourceGroupName(processName);
-//                        dayMap.put(apsResourceDateStat.getPlanDay().toString(), apsResourceDateStatTemp);
-//                    }else{
-//                        dayMap.put(apsResourceDateStat.getPlanDay().toString(), apsResourceDateStat);
-//                    }
-//                });
-//                JSONArray tempList = new JSONArray();
-//                dayMap.forEach((key, value) -> {
-//                    JSONObject temp = new JSONObject();
-//                    temp.put("planDay", key);
-//                    temp.put("designTimes", value.getDesignTimes());
-//                    temp.put("requireTimes", value.getRequireTimes());
-//                    temp.put("capacityLoad", value.getCapacityLoad());
-//                    temp.put("resourceGroupName", value.getResourceGroupName());
-//                    tempList.add(temp);
-//                });
-//                processData.add(new JSONObject().put(processName, tempList));
-//            });
-            if("month".equals(apsGasPipingRouteStat.getSearchType())){
-                for (String key : processMapMonth.keySet()) {
-                    HashMap<String, List<ApsResourceDateStat>> temp = new HashMap<>();
-                    temp.put(key, processMapMonth.get(key));
-                    processListMonth.add(temp);
+            for (int i=0;i<processList.size();i++){
+                HashMap<String, List<ApsResourceDateStat>> temp = processList.get(i);
+                for (Map.Entry<String, List<ApsResourceDateStat>> entry : temp.entrySet()){
+                    List<ApsResourceDateStat> apsResourceDateStatList = entry.getValue();
+                    String key = entry.getKey();
+                    List<ApsResourceDateStat> crtList = new ArrayList<>();
+                    for(String tempTime:sortedStartPlanTimeList) {
+                        if("month".equals(apsGasPipingRouteStat.getSearchType())){
+                            tempTime += "-01";
+                        }
+                        LocalDate crtDate = LocalDate.parse(tempTime, formatter);
+                        Optional<ApsResourceDateStat> first = apsResourceDateStatList.stream().filter(x -> x.getPlanDay().equals(crtDate)).findFirst();
+                        if (first.isPresent()) {
+                            ApsResourceDateStat apsResourceDateStat = first.get();
+                            crtList.add(apsResourceDateStat);
+                        } else {
+                            ApsResourceDateStat apsResourceDateStat = new ApsResourceDateStat();
+                            apsResourceDateStat.setPlanDay(LocalDate.parse(tempTime, formatter));
+                            String[] keyParts = key.split("-");
+                            String processNamePart = keyParts[0];
+                            String plantPart = keyParts[1];
+                            String capacityKey = processNamePart + "-" + plantPart + "-" + tempTime.substring(0,7);
+                            if ("month".equals(apsGasPipingRouteStat.getSearchType())) {
+                                apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(capacityKey) != null ? apsGasPipingPlanMap.get(capacityKey).getMonthProduceAllNum() : new BigDecimal(0));
+                            } else {
+                                apsResourceDateStat.setDesignTimes(apsGasPipingPlanMap.get(capacityKey) != null ? apsGasPipingPlanMap.get(capacityKey).getDayProduceAllNum() : new BigDecimal(0));
+                            }
+                            apsResourceDateStat.setRequireTimes(new BigDecimal(0));
+                            apsResourceDateStat.setCapacityLoad(new BigDecimal(0));
+                            apsResourceDateStat.setResourceName(processNamePart);
+                            apsResourceDateStat.setResourceGroupName(key);
+                            apsResourceDateStat.setPlant(plantPart);
+                            apsResourceDateStatList.add(apsResourceDateStat);
+                            crtList.add(apsResourceDateStat);
+                        }
+                        temp.put(entry.getKey(), crtList);
+                        processList.set(i, temp);
+                    }
                 }
-                result.put("planTable", processListMonth);
-            }else{
-                for (String key : processMap.keySet()) {
-                    HashMap<String, List<ApsResourceDateStat>> temp = new HashMap<>();
-                    temp.put(key, processMap.get(key));
-                    processList.add(temp);
-                }
-                result.put("planTable", processList);
             }
+            result.put("planTable", processList);
             result.put("planTitle", sortedStartPlanTimeList);
         } catch (Exception e) {
             e.printStackTrace();
@@ -431,8 +765,8 @@
                     dataRow.createCell(0).setCellValue(resourceName);
                     for (int j = 0; j < resourceDateStats.size(); j++) {
                         ApsResourceDateStat apsResourceDateStat = resourceDateStats.get(j);
-                        dataRow.createCell(j*3+1).setCellValue(apsResourceDateStat.getDesignTimes());
-                        dataRow.createCell(j*3+2).setCellValue(apsResourceDateStat.getRequireTimes());
+                        dataRow.createCell(j*3+1).setCellValue(apsResourceDateStat.getDesignTimes().doubleValue());
+                        dataRow.createCell(j*3+2).setCellValue(apsResourceDateStat.getRequireTimes().doubleValue());
                         if(apsResourceDateStat.getCapacityLoad()!=null){
                             dataRow.createCell(j*3+3).setCellValue(apsResourceDateStat.getCapacityLoad().doubleValue()+"%");
                         }else{
@@ -469,4 +803,1245 @@
         styles.put("title", style);
         return styles;
     }
+
+    public static List<String> getYearMonthsInRange(YearMonth start, YearMonth end) {
+        List<String> yearMonths = new ArrayList<>();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
+
+        while (!start.isAfter(end)) {
+            yearMonths.add(start.format(formatter));
+            start = start.plusMonths(1);
+        }
+
+        return yearMonths;
+    }
+
+    @Override
+    public void saveGasPipingProcessStat(){
+        try {
+            String batchNum = IdUtils.fastSimpleUUID();
+            List<ApsGasPipingRouteStat> tempList = apsGasPipingRouteStatMapper.queryTempStat();
+            Map<String, List<ApsGasPipingRouteStat>> groupByOrderNo = tempList.stream().collect(groupingBy(ApsGasPipingRouteStat::getWorkOrderNo));
+            Boolean hasBefore = false;
+            LocalDateTime now = LocalDateTime.now();
+            for (Map.Entry<String, List<ApsGasPipingRouteStat>> entry : groupByOrderNo.entrySet()) {
+                List<ApsGasPipingRouteStat> statPerOrder = entry.getValue();
+                /*num 涓烘牴鎹畬宸ユ椂闂存帓搴忓嚭鐨勫簭鍙凤紝鎸夋鎺掑簭锛屽彲淇濊瘉鏄寜瀹屽伐鏃堕棿鍊掑彊鎺掑垪*/
+                statPerOrder.sort((a, b)->a.getNum().compareTo(b.getNum()));
+                ApsGasPipingRouteStat last=null;
+                for (int i = 0; i <statPerOrder.size(); i++) {
+                    ApsGasPipingRouteStat stat = statPerOrder.get(i);
+                    stat.setId(IdUtils.fastSimpleUUID());
+                    stat.setBatchNumber(batchNum);
+                    stat.setCreateBy(SecurityUtils.getUsername());
+                    stat.setWarning(false);
+                    if(i==0){
+                        Date orderPlanEndDay = stat.getOrderPlanEndDay();
+                        LocalDateTime transLocalDateTime = transLocalDateTime(orderPlanEndDay);
+                        LocalTime endOfDay = LocalTime.of(23, 59, 59);
+                        LocalDateTime orderPlanEndDayLocalDateTime =  LocalDateTime.of( transLocalDateTime.toLocalDate(), endOfDay);
+                        if(orderPlanEndDayLocalDateTime.isBefore(now)){
+                            hasBefore = true;
+                            stat.setWarning(true);
+                            stat.setProcessPlanEndDay(transDate(now));
+                            stat.setProcessPlanStartDay(transDate(now));
+                        }else {
+                            /*璁″垝瀹屽伐鏃�=閽i噾璁″垝宸ュ崟瀹屾垚鏃堕棿*/
+                            stat.setProcessPlanEndDay(transDate(orderPlanEndDayLocalDateTime));
+                            /*璁″垝寮�宸ユ棩=閽i噾璁″垝宸ュ崟瀹屾垚鏃堕棿 -  宸ュ簭鎬诲伐鏃�*/
+                            long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
+                            LocalDateTime lastPlanStartDt = orderPlanEndDayLocalDateTime.minusSeconds(seconds);
+                            if(lastPlanStartDt.isBefore(now)){
+                                hasBefore = true;
+                                stat.setProcessPlanStartDay(transDate(now));
+                            }else {
+                                stat.setProcessPlanStartDay(transDate(lastPlanStartDt));
+                            }
+                        }
+                    }
+                    /*褰撳伐鑹哄伐搴忓彿 >= 宸ュ崟褰撳墠宸ュ簭 浠h〃鏄湭鏉ュ伐搴忥紝鎵嶈繘琛岃鍒掑紑宸ユ棩 鍜岃鍒掑畬宸ユ棩鐨勮绠�
+                     * 褰撳伐鑹哄伐搴忓彿 < 宸ュ崟褰撳墠宸ュ簭  杩囧幓宸ュ簭锛屼笉杩涜璁$畻
+                     * */
+                    if( stat.getRouteProcessNumber().compareTo(stat.getCurrentProcessNumber())>=0){
+                        /*鍊掓帓鏃� 涓嬩竴閬撳伐搴忓瓨鍦� 姣斿綋鍓嶆椂闂村皬鐨勮鍒掓椂闂达紝鍒欏綋鍓嶈鍒掑紑濮嬪拰缁撴潫鏃堕棿閮芥槸褰撳墠鏃堕棿*/
+                        if(hasBefore){
+                            stat.setWarning(true);
+                            stat.setProcessPlanEndDay(transDate(now));
+                            stat.setProcessPlanStartDay(transDate(now));
+                        }else{
+                            /*涓嬩竴閬撳伐搴忚鍒掓椂闂撮兘姝e父鏃讹紝*/
+                            if (last != null) {
+                                /*褰撳墠宸ュ簭缁撴潫鏃堕棿=涓嬩竴閬撳伐搴忕殑寮�濮嬫椂闂�*/
+                                stat.setProcessPlanEndDay(last.getProcessPlanStartDay());
+                                /*寮�濮嬫椂闂�=缁撴潫鏃堕棿-鎬诲伐鏃�*/
+                                long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
+                                LocalDateTime crtStartDt = transLocalDateTime(last.getProcessPlanStartDay()).minusSeconds(seconds);
+                                /*濡傛灉寮�濮嬫椂闂村皬浜庡綋鍓嶆椂闂�*/
+                                if(crtStartDt.isBefore(now)){
+                                    hasBefore=true;
+                                    stat.setWarning(true);
+                                    stat.setProcessPlanStartDay(transDate(now));
+                                }else {
+                                    stat.setProcessPlanStartDay(transDate(crtStartDt));
+                                }
+                            }
+                        }
+                    }
+                    last = stat;
+                    apsGasPipingRouteStatMapper.insertApsGasPipingRouteStat(stat);
+                }
+                hasBefore=false;
+
+            }
+            apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatByBatchNum(batchNum);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    };
+
+    private Date transDate(LocalDateTime localDateTime){
+        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+    }
+
+    private LocalDateTime transLocalDateTime(Date date){
+        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
+    }
+
+    /**
+     * 淇濆瓨閽i噾缁熻鏁版嵁
+     */
+    @Transactional
+    @Override
+    public void saveGasPipingRoutStateList() {
+        String batchNum = IdUtils.fastSimpleUUID();
+        List<ApsGasPipingRouteStat> tempList = apsGasPipingRouteStatMapper.queryTempStat();
+        Map<String, List<ApsGasPipingRouteStat>> groupByOrderNo = tempList.stream().collect(groupingBy(ApsGasPipingRouteStat::getWorkOrderNo));
+
+        LocalDateTime now = LocalDateTime.now();
+        /*寰呬繚瀛樼殑鏁版嵁*/
+        List<ApsGasPipingRouteStat> cptStateList = new ArrayList<>();
+        for (Map.Entry<String, List<ApsGasPipingRouteStat>> entry : groupByOrderNo.entrySet()) {
+            List<ApsGasPipingRouteStat> statPerOrder = entry.getValue();
+            /*num 涓烘牴鎹畬宸ユ椂闂存帓搴忓嚭鐨勫簭鍙凤紝鎸夋鎺掑簭锛屽彲淇濊瘉鏄寜瀹屽伐鏃堕棿鍊掑彊鎺掑垪*/
+            statPerOrder.sort((a, b)->a.getNum().compareTo(b.getNum()));
+            ApsGasPipingRouteStat last=null;
+            /*褰撳墠宸ュ簭鏄惁瀛樺湪 璁″垝寮�宸ユ椂闂� 灏忎簬 褰撳墠鐨勬椂闂达紝濡傛灉瀛樺湪鍚庣画璁剧疆涓哄綋鍓嶆椂闂�*/
+            boolean hasBefore = false;
+            for (int i = 0; i <statPerOrder.size(); i++) {
+                ApsGasPipingRouteStat stat = statPerOrder.get(i);
+                stat.setId(String.valueOf(IdUtil.getSnowflakeNextId()));
+                stat.setBatchNumber(batchNum);
+                stat.setCreateTime(DateUtils.getNowDate());
+                stat.setCreateBy(SecurityUtils.getUsername());
+                stat.setWarning(false);
+                stat.setDelFlag("0");
+                if(i==0){
+                    Date orderPlanEndDay = stat.getOrderPlanEndDay();
+                    LocalDateTime transLocalDateTime = transLocalDateTime(orderPlanEndDay);
+                    LocalTime endOfDay = LocalTime.of(23, 59, 59);
+                    LocalDateTime orderPlanEndDayLocalDateTime =  LocalDateTime.of( transLocalDateTime.toLocalDate(), endOfDay);
+                    if(orderPlanEndDayLocalDateTime.isBefore(now)){
+                        hasBefore = true;
+                        stat.setWarning(true);
+                        stat.setProcessPlanEndDay(transDate(now));
+                        stat.setProcessPlanStartDay(transDate(now));
+                    }else {
+                        /*璁″垝瀹屽伐鏃�=閽i噾璁″垝宸ュ崟瀹屾垚鏃堕棿*/
+                        stat.setProcessPlanEndDay(transDate(orderPlanEndDayLocalDateTime));
+                        /*璁″垝寮�宸ユ棩=閽i噾璁″垝宸ュ崟瀹屾垚鏃堕棿 -  宸ュ簭鎬诲伐鏃�*/
+                        long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
+                        LocalDateTime lastPlanStartDt = orderPlanEndDayLocalDateTime.minusSeconds(seconds);
+                        if(lastPlanStartDt.isBefore(now)){
+                            hasBefore = true;
+                            stat.setProcessPlanStartDay(transDate(now));
+                        }else {
+                            stat.setProcessPlanStartDay(transDate(lastPlanStartDt));
+                        }
+                    }
+                }
+                /*褰撳伐鑹哄伐搴忓彿 >= 宸ュ崟褰撳墠宸ュ簭 浠h〃鏄湭鏉ュ伐搴忥紝鎵嶈繘琛岃鍒掑紑宸ユ棩 鍜岃鍒掑畬宸ユ棩鐨勮绠�
+                 * 褰撳伐鑹哄伐搴忓彿 < 宸ュ崟褰撳墠宸ュ簭  杩囧幓宸ュ簭锛屼笉杩涜璁$畻
+                 * */
+                if( stat.getRoadProcessNumber().compareTo(stat.getCurrentProcessNumber())>=0){
+                    /*鍊掓帓鏃� 涓嬩竴閬撳伐搴忓瓨鍦� 姣斿綋鍓嶆椂闂村皬鐨勮鍒掓椂闂达紝鍒欏綋鍓嶈鍒掑紑濮嬪拰缁撴潫鏃堕棿閮芥槸褰撳墠鏃堕棿*/
+                    if(hasBefore){
+                        stat.setWarning(true);
+                        stat.setProcessPlanEndDay(transDate(now));
+                        stat.setProcessPlanStartDay(transDate(now));
+                    }else{
+                        /*涓嬩竴閬撳伐搴忚鍒掓椂闂撮兘姝e父鏃讹紝*/
+                        if (last != null) {
+                            /*褰撳墠宸ュ簭缁撴潫鏃堕棿=涓嬩竴閬撳伐搴忕殑寮�濮嬫椂闂�*/
+                            stat.setProcessPlanEndDay(last.getProcessPlanStartDay());
+                            /*寮�濮嬫椂闂�=缁撴潫鏃堕棿-鎬诲伐鏃�*/
+                            long seconds = stat.getProcessTotalTime().multiply(new BigDecimal(60)).multiply(new BigDecimal(60)).longValue();
+                            LocalDateTime crtStartDt = transLocalDateTime(last.getProcessPlanStartDay()).minusSeconds(seconds);
+                            /*濡傛灉寮�濮嬫椂闂村皬浜庡綋鍓嶆椂闂�*/
+                            if(crtStartDt.isBefore(now)){
+                                hasBefore=true;
+                                stat.setWarning(true);
+                                stat.setProcessPlanStartDay(transDate(now));
+                            }else {
+                                stat.setProcessPlanStartDay(transDate(crtStartDt));
+                            }
+                        }
+                    }
+                }
+               if(stat.getProcessPlanStartDay()!=null){
+                   String[] strNow = new SimpleDateFormat("yyyy-MM-dd").format(stat.getProcessPlanStartDay()).toString().split("-");
+                   stat.setPlanStartYear(strNow[0]);
+                   stat.setPlanStartMonth(strNow[1]);
+                   stat.setPlanStartDay(strNow[2]);
+               }
+                last = stat;
+                cptStateList.add(stat);
+            }
+        }
+        // 鎵归噺鎻掑叆浠ユ彁楂樻�ц兘
+        if (!cptStateList.isEmpty()) {
+            int batchSize = 1000;
+            int size = cptStateList.size();
+            for (int i = 0; i < size; i += batchSize) {
+                int end = Math.min(i + batchSize, size);
+                List<ApsGasPipingRouteStat> batch = cptStateList.subList(i, end);
+                apsGasPipingRouteStatMapper.insertApsGasPipingRouteStatBatch(batch);
+                log.info("鎵归噺鎻掑叆鏁版嵁锛屽紑濮嬩綅缃細{}锛岀粨鏉熶綅缃細{}", i, end);
+            }
+        }
+        apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatByBatchNum(batchNum);
+        log.info("鎵归噺鎻掑叆鏁版嵁瀹屾垚,batchNum:"+batchNum);
+    }
+
+    /**
+     * 鏍规嵁鎵嬪伐姘斾綋棰勬祴鏁版嵁鍜屾墜宸ユ皵浣撳伐鍗曟暟鎹敓鎴愮粺璁℃暟鎹�
+     * 
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int generateGasPipingRouteStatData() {
+        int count = 0;
+        
+        // 娓呯┖涔嬪墠鐨勬暟鎹�
+        apsGasPipingRouteStatMapper.deleteAll();
+        
+        // 鐢熸垚鎵规鍙�
+        String batchNumber = IdUtils.fastSimpleUUID();
+        List<ApsGasPipingRouteStat> statList = new ArrayList<>();
+        
+        // 澶勭悊鎵嬪伐姘斾綋棰勬祴鏁版嵁 - 浣跨敤鑱斿悎鏌ヨ鑾峰彇鎵�鏈夌浉鍏虫暟鎹�
+        List<Map<String, Object>> predictionDataList = apsGasPipingRouteStatMapper.selectPredictionRouteData();
+        
+        // 鎸夌墿鏂欎唬鐮佸垎缁勶紝渚夸簬澶勭悊鍚屼竴鐗╂枡鐨勪笉鍚屽伐搴�
+        Map<String, List<Map<String, Object>>> predictionGroups = predictionDataList.stream()
+                .collect(Collectors.groupingBy(data -> data.get("material_code").toString()));
+        
+        // 澶勭悊姣忎釜鐗╂枡鐨勫伐鑹鸿矾绾�
+        for (String materialCode : predictionGroups.keySet()) {
+            List<Map<String, Object>> materialData = predictionGroups.get(materialCode);
+            
+            // 鎸夊伐搴忓彿鎺掑簭
+            materialData.sort((a, b) -> {
+                String numA = a.get("process_number").toString();
+                String numB = b.get("process_number").toString();
+                return numA.compareTo(numB);
+            });
+            
+            // 鑾峰彇鎵�鏈夊伐搴忕殑淇℃伅骞跺垱寤虹粺璁¤褰�
+            List<ApsGasPipingRouteStat> processList = new ArrayList<>();
+            for (Map<String, Object> data : materialData) {
+                ApsGasPipingRouteStat stat = new ApsGasPipingRouteStat();
+                stat.setId(IdUtils.fastSimpleUUID());
+                stat.setWorkOrderNo(""); // 棰勬祴鏁版嵁娌℃湁宸ュ崟鍙�
+                stat.setItemNumber(data.get("material_code").toString());
+                stat.setProcessName(data.get("process_name").toString());
+                stat.setRoadProcessNumber(new BigDecimal(data.get("process_number").toString()));
+                
+                // 鐢熶骇鏁伴噺鍜屾爣鍑嗗伐鏃�
+                BigDecimal quantity = new BigDecimal(data.get("predict_quantity").toString()).setScale(4, RoundingMode.HALF_UP);
+                BigDecimal standardTime = new BigDecimal(data.get("standard_time").toString()).setScale(4, RoundingMode.HALF_UP);
+                
+                stat.setProductionQuantity(quantity);
+                stat.setStandardTime(standardTime);
+                stat.setProcessTotalTime(standardTime.multiply(quantity).setScale(4, RoundingMode.HALF_UP));
+                
+                // 宸ュ巶銆佷笓涓氬拰杞﹂棿
+                stat.setPlant(data.get("factory").toString());
+                stat.setMajor(data.get("domain") != null ? data.get("domain").toString() : "");
+                stat.setWorkshop(data.get("workshop") != null ? data.get("workshop").toString() : "");
+                
+                // 鎵规鍙峰拰鍒涘缓淇℃伅
+                stat.setBatchNumber(batchNumber);
+                stat.setCreateBy(SecurityUtils.getUsername());
+                stat.setCreateTime(truncateToSeconds(DateUtils.getNowDate()));
+                
+                processList.add(stat);
+            }
+            
+            // 璁$畻璁″垝瀹屽伐鏃ュ拰璁″垝寮�宸ユ棩
+            if (!processList.isEmpty()) {
+                int lastIndex = processList.size() - 1;
+                
+                // 鏈�鍚庝竴閬撳伐搴忕殑璁″垝瀹屽伐鏃ユ湡涓洪娴嬫棩鏈�
+                ApsGasPipingRouteStat lastProcess = processList.get(lastIndex);
+                Date predictDate = (Date) materialData.get(lastIndex).get("predict_date");
+                lastProcess.setProcessPlanEndDay(truncateToSeconds(predictDate));
+                
+                // 鏍囪鏄惁鍑虹幇杩囨椂闂村啿绐佺殑鎯呭喌
+                boolean hasTimeConflict = false;
+                
+                // 璁$畻姣忎釜宸ュ簭鐨勮鍒掑紑宸ユ棩鍜屽畬宸ユ棩 - 浠庢渶鍚庝竴閬撳伐搴忓紑濮嬪�掓帹
+                for (int i = lastIndex; i >= 0; i--) {
+                    ApsGasPipingRouteStat current = processList.get(i);
+                    
+                    // 濡傛灉褰撳墠鏄渶鍚庝竴閬撳伐搴忥紝璁″垝寮�宸ユ棩 = 璁″垝瀹屽伐鏃� - 宸ュ簭鎬诲伐鏃�
+                    if (i == lastIndex) {
+                        hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
+                    } else {
+                        // 闈炴渶鍚庝竴閬撳伐搴忥紝璁″垝瀹屽伐鏃ヤ负涓嬩竴閬撳伐搴忕殑璁″垝寮�宸ユ棩
+                        ApsGasPipingRouteStat next = processList.get(i + 1);
+                        current.setProcessPlanEndDay(next.getProcessPlanStartDay());
+                        
+                        // 濡傛灉宸茬粡鍑虹幇鏃堕棿鍐茬獊锛屽悗缁伐搴忕殑璁″垝寮�宸ユ棩鍜岃鍒掑畬宸ユ棩閮借涓哄綋鍓嶆椂闂�
+                        if (hasTimeConflict) {
+                            current.setProcessPlanStartDay(truncateToSeconds(new Date()));
+                        } else {
+                            // 鍚﹀垯姝e父璁$畻锛屽苟妫�鏌ユ槸鍚﹀嚭鐜版椂闂村啿绐�
+                            hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
+                        }
+                    }
+                    
+                    // 璁剧疆骞淬�佹湀銆佹棩
+                    setDateComponents(current);
+                }
+                
+                statList.addAll(processList);
+            }
+        }
+        
+        // 澶勭悊鎵嬪伐姘斾綋宸ュ崟鏁版嵁 - 浣跨敤鑱斿悎鏌ヨ鑾峰彇鎵�鏈夌浉鍏虫暟鎹�
+        List<Map<String, Object>> moDataList = apsGasPipingRouteStatMapper.selectMoRouteData();
+        
+        // 鑾峰彇鎵�鏈夌殑MO鏁版嵁锛岀敤浜庢鏌ュ摢浜汳O娌℃湁鍏宠仈鍒板伐鑹鸿矾绾�
+        List<Map<String, Object>> allMoData = apsGasPipingRouteStatMapper.selectAllMoData();
+        
+        // 璁板綍宸插叧鑱斿伐鑹鸿矾绾跨殑MO缂栧彿
+        Set<String> processedMoSet = new HashSet<>();
+        
+        // 鎸夊伐鍗曞彿鍒嗙粍锛屼究浜庡鐞嗗悓涓�宸ュ崟鐨勪笉鍚屽伐搴�
+        Map<String, List<Map<String, Object>>> moGroups = moDataList.stream()
+                .collect(Collectors.groupingBy(data -> data.get("work_order_no").toString()));
+        
+        // 澶勭悊姣忎釜宸ュ崟鐨勫伐鑹鸿矾绾�
+        for (String workOrderNo : moGroups.keySet()) {
+            List<Map<String, Object>> workOrderData = moGroups.get(workOrderNo);
+            
+            // 鏍囪璇ュ伐鍗曞凡澶勭悊
+            processedMoSet.add(workOrderNo);
+            
+            // 鎸夊伐搴忓彿鎺掑簭
+            workOrderData.sort((a, b) -> {
+                String numA = a.get("process_number").toString();
+                String numB = b.get("process_number").toString();
+                return numA.compareTo(numB);
+            });
+            
+            // 鑾峰彇鎵�鏈夊伐搴忕殑淇℃伅骞跺垱寤虹粺璁¤褰�
+            List<ApsGasPipingRouteStat> processList = new ArrayList<>();
+            for (Map<String, Object> data : workOrderData) {
+                ApsGasPipingRouteStat stat = new ApsGasPipingRouteStat();
+                stat.setId(IdUtils.fastSimpleUUID());
+                stat.setWorkOrderNo(data.get("work_order_no").toString());
+                stat.setItemNumber(data.get("material_code").toString());
+                stat.setProcessName(data.get("process_name").toString());
+                stat.setRoadProcessNumber(new BigDecimal(data.get("process_number").toString()));
+                
+                // 鐢熶骇鏁伴噺鍜屾爣鍑嗗伐鏃�
+                BigDecimal quantity = new BigDecimal(data.get("quantity").toString()).setScale(4, RoundingMode.HALF_UP);
+                BigDecimal standardTime = new BigDecimal(data.get("standard_time").toString()).setScale(4, RoundingMode.HALF_UP);
+                
+                stat.setProductionQuantity(quantity);
+                stat.setStandardTime(standardTime);
+                stat.setProcessTotalTime(standardTime.multiply(quantity).setScale(4, RoundingMode.HALF_UP));
+                
+                // 宸ュ巶銆佷笓涓氬拰杞﹂棿
+                stat.setPlant(data.get("factory").toString());
+                stat.setMajor(data.get("domain") != null ? data.get("domain").toString() : "");
+                stat.setWorkshop(data.get("workshop") != null ? data.get("workshop").toString() : "");
+                
+                // 鎵规鍙峰拰鍒涘缓淇℃伅
+                stat.setBatchNumber(batchNumber);
+                stat.setCreateBy(SecurityUtils.getUsername());
+                stat.setCreateTime(truncateToSeconds(DateUtils.getNowDate()));
+                
+                processList.add(stat);
+            }
+            
+            // 璁$畻璁″垝瀹屽伐鏃ュ拰璁″垝寮�宸ユ棩
+            if (!processList.isEmpty()) {
+                int lastIndex = processList.size() - 1;
+                
+                // 鏈�鍚庝竴閬撳伐搴忕殑璁″垝瀹屽伐鏃ユ湡涓哄伐鍗曡鍒掑畬宸ユ棩鏈�
+                ApsGasPipingRouteStat lastProcess = processList.get(lastIndex);
+                Date planEnd = (Date) workOrderData.get(0).get("plan_end");
+                lastProcess.setProcessPlanEndDay(truncateToSeconds(planEnd));
+                
+                // 鏍囪鏄惁鍑虹幇杩囨椂闂村啿绐佺殑鎯呭喌
+                boolean hasTimeConflict = false;
+                
+                // 璁$畻姣忎釜宸ュ簭鐨勮鍒掑紑宸ユ棩鍜屽畬宸ユ棩 - 浠庢渶鍚庝竴閬撳伐搴忓紑濮嬪�掓帹
+                for (int i = lastIndex; i >= 0; i--) {
+                    ApsGasPipingRouteStat current = processList.get(i);
+                    
+                    // 濡傛灉褰撳墠鏄渶鍚庝竴閬撳伐搴忥紝璁″垝寮�宸ユ棩 = 璁″垝瀹屽伐鏃� - 宸ュ簭鎬诲伐鏃�
+                    if (i == lastIndex) {
+                        hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
+                    } else {
+                        // 闈炴渶鍚庝竴閬撳伐搴忥紝璁″垝瀹屽伐鏃ヤ负涓嬩竴閬撳伐搴忕殑璁″垝寮�宸ユ棩
+                        ApsGasPipingRouteStat next = processList.get(i + 1);
+                        current.setProcessPlanEndDay(next.getProcessPlanStartDay());
+                        
+                        // 濡傛灉宸茬粡鍑虹幇鏃堕棿鍐茬獊锛屽悗缁伐搴忕殑璁″垝寮�宸ユ棩鍜岃鍒掑畬宸ユ棩閮借涓哄綋鍓嶆椂闂�
+                        if (hasTimeConflict) {
+                            current.setProcessPlanStartDay(truncateToSeconds(new Date()));
+                        } else {
+                            // 鍚﹀垯姝e父璁$畻锛屽苟妫�鏌ユ槸鍚﹀嚭鐜版椂闂村啿绐�
+                            hasTimeConflict = calculateProcessPlanStartDay(current, hasTimeConflict);
+                        }
+                    }
+                    
+                    // 璁剧疆骞淬�佹湀銆佹棩
+                    setDateComponents(current);
+                }
+                
+                statList.addAll(processList);
+            }
+        }
+        
+        // 澶勭悊娌℃湁鍏宠仈鍒板伐鑹鸿矾绾跨殑MO鏁版嵁
+        List<ApsPlateStandardRequireError> errorList = new ArrayList<>();
+        for (Map<String, Object> moData : allMoData) {
+            String workOrderNo = moData.get("mo").toString();
+            // 濡傛灉璇ュ伐鍗曟病鏈夎澶勭悊杩囷紝璇存槑娌℃湁鍏宠仈鍒板伐鑹鸿矾绾�
+            if (!processedMoSet.contains(workOrderNo)) {
+                ApsPlateStandardRequireError error = ApsPlateStandardRequireError.builder()
+                        .id(Long.valueOf(IdUtils.fastSimpleUUID().hashCode()))
+                        .batchNumber(batchNumber)
+                        .requireId(IdUtil.getSnowflakeNextId())
+                        .docNum(workOrderNo)
+                        .itemNum(moData.get("material_code").toString())
+                        .orgCode(moData.get("factory").toString())
+                        .message("鏍囧噯宸ヨ壓璺嚎涓嶅瓨鍦�")
+                        .delFlag("0")
+                        .build();
+                
+                // 璁剧疆鍩虹被灞炴��
+                error.setCreateBy(SecurityUtils.getUsername());
+                error.setCreateTime(truncateToSeconds(DateUtils.getNowDate()));
+                
+                errorList.add(error);
+            }
+        }
+        
+        // 鎵归噺鎻掑叆寮傚父鏁版嵁
+        if (!errorList.isEmpty()) {
+            apsPlateStandardRequireErrorMapper.batchInsert(errorList);
+        }
+        
+        // 鎵归噺鎻掑叆鏁版嵁
+        if (!statList.isEmpty()) {
+            for (int i = 0; i < statList.size(); i += 500) {
+                int endIndex = Math.min(i + 500, statList.size());
+                List<ApsGasPipingRouteStat> batch = statList.subList(i, endIndex);
+                count += apsGasPipingRouteStatMapper.insertApsGasPipingRouteStatBatch(batch);
+            }
+        }
+        
+        return count;
+    }
+
+    /**
+     * 璁$畻宸ュ簭璁″垝寮�宸ユ棩锛屽苟鍒ゆ柇鏄惁鍙戠敓鏃堕棿鍐茬獊
+     * 
+     * @param stat 褰撳墠宸ュ簭缁熻瀵硅薄
+     * @param hasTimeConflict 涔嬪墠鏄惁宸茬粡鍙戠敓鏃堕棿鍐茬獊
+     * @return 鏄惁鍙戠敓鏃堕棿鍐茬獊
+     */
+    private boolean calculateProcessPlanStartDay(ApsGasPipingRouteStat stat, boolean hasTimeConflict) {
+        Date planEndDay = stat.getProcessPlanEndDay();
+        if (planEndDay == null) {
+            return hasTimeConflict;
+        }
+        
+        // 璁$畻宸ュ簭鎬诲伐鏃跺搴旂殑绉掓暟
+        long processTotalTimeSeconds = stat.getProcessTotalTime()
+                .multiply(BigDecimal.valueOf(60 * 60))
+                .longValue();
+        
+        // 鑾峰彇褰撳墠鏃堕棿骞剁簿纭埌绉掔骇鍒�
+        Date now = truncateToSeconds(new Date());
+        
+        // 璁$畻寮�宸ユ棩鏈熷苟绮剧‘鍒扮绾у埆
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(planEndDay);
+        
+        // 鍒嗘壒鍑忓幓绉掓暟锛岄伩鍏峣nt婧㈠嚭
+        long seconds = processTotalTimeSeconds;
+        while (seconds > 0) {
+            int step = (seconds > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) seconds;
+            calendar.add(Calendar.SECOND, -step);
+            seconds -= step;
+        }
+        
+        Date calculatedStartDay = truncateToSeconds(calendar.getTime());
+        
+        // 濡傛灉璁″垝瀹屽伐鏃ユ湡灏忎簬绛変簬褰撳墠鏃堕棿锛屽垯璁″垝寮�宸ユ棩涔熻涓鸿鍒掑畬宸ユ棩锛堝綋鍓嶆椂闂达級
+        if (planEndDay.compareTo(now) <= 0) {
+            stat.setProcessPlanStartDay(truncateToSeconds(planEndDay));
+            return true; // 鍙戠敓鏃堕棿鍐茬獊
+        } 
+        // 濡傛灉璁$畻鍑虹殑璁″垝寮�宸ユ棩灏忎簬绛変簬褰撳墠鏃堕棿锛屽垯璁句负褰撳墠鏃堕棿
+        else if (calculatedStartDay.compareTo(now) <= 0) {
+            stat.setProcessPlanStartDay(now);
+            return true; // 棣栨鍑虹幇鏃堕棿鍐茬獊
+        } 
+        // 鍚﹀垯姝e父璁剧疆璁″垝寮�宸ユ棩
+        else {
+            stat.setProcessPlanStartDay(calculatedStartDay);
+            return hasTimeConflict; // 淇濇寔鍘熸湁鍐茬獊鐘舵��
+        }
+    }
+    
+    /**
+     * 灏嗘棩鏈熺簿纭埌绉掔骇鍒紝鍘婚櫎姣淇℃伅
+     * 
+     * @param date 鍘熷鏃ユ湡
+     * @return 绮剧‘鍒扮鐨勬棩鏈�
+     */
+    private Date truncateToSeconds(Date date) {
+        if (date == null) {
+            return null;
+        }
+        
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime();
+    }
+    
+    /**
+     * 璁剧疆鏃ユ湡鐩稿叧缁勪欢锛堝勾銆佹湀銆佹棩锛�
+     */
+    private void setDateComponents(ApsGasPipingRouteStat stat) {
+        if (stat.getProcessPlanStartDay() != null) {
+            SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
+            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
+            SimpleDateFormat dayFormat = new SimpleDateFormat("dd");
+            
+            stat.setPlanStartYear(yearFormat.format(stat.getProcessPlanStartDay()));
+            stat.setPlanStartMonth(monthFormat.format(stat.getProcessPlanStartDay()));
+            stat.setPlanStartDay(dayFormat.format(stat.getProcessPlanStartDay()));
+        }
+    }
+
+    /**
+     * 鑱氬悎姘斾綋绠¤矾浜ц兘璐熻浇缁熻鏁版嵁
+     * 鍦⊿ervice灞傚畬鎴愯仛鍚堝鐞嗭紝鏀寔澶氱淮搴﹀垎缁�
+     * 
+     * @param params 鑱氬悎鍙傛暟
+     * @return 鑱氬悎缁撴灉
+     */
+    @Override
+    public Map<String, Object> aggregateGasPipingRouteStat(Map<String, Object> params) {
+        Map<String, Object> result = new HashMap<>();
+        List<Map<String, Object>> plantTable = new ArrayList<>();
+        
+        // 鑾峰彇鏃堕棿棰楃矑搴﹀弬鏁�
+        String timeGranularity = params.containsKey("timeGranularity") ? 
+                (String) params.get("timeGranularity") : "day"; // 榛樿涓�"鏃�"绮掑害
+        
+        // 鑾峰彇row缁村害鐨勮仛鍚堝瓧娈� - 榛樿涓哄伐搴忓悕绉�(processName)
+        String rowGroupBy = params.containsKey("rowGroupBy") ? 
+                (String) params.get("rowGroupBy") : "processName";
+        
+        // 纭畾鍒嗙粍缁村害 - 宸ュ巶銆佷笓涓氥�佽溅闂�
+        boolean groupByPlant = params.containsKey("groupByPlant") && Boolean.TRUE.equals(params.get("groupByPlant"));
+        boolean groupByMajor = params.containsKey("groupByMajor") && Boolean.TRUE.equals(params.get("groupByMajor"));
+        boolean groupByWorkshop = params.containsKey("groupByWorkshop") && Boolean.TRUE.equals(params.get("groupByWorkshop"));
+        // 濡傛灉rowGroupBy宸茬粡鏄煇涓淮搴︼紝鍒欒缁村害涓嶉渶瑕佸啀娆″垎缁�
+        if ("plant".equals(rowGroupBy)) groupByPlant = false;
+        if ("major".equals(rowGroupBy)) groupByMajor = false;
+        if ("workshop".equals(rowGroupBy)) groupByWorkshop = false;
+        
+        // 鏋勫缓鏌ヨ鏉′欢
+        Map<String, Object> queryParams = new HashMap<>();
+        
+        // 璁剧疆鏌ヨ鏉′欢 - 鍒嗙被鏉′欢
+        if (params.containsKey("plant")) {
+            Object plantParam = params.get("plant");
+            if (plantParam instanceof List) {
+                queryParams.put("plants", plantParam);
+            } else if (plantParam instanceof String) {
+                // 澶勭悊鍙兘鐨勯�楀彿鍒嗛殧瀛楃涓�
+                String plantStr = (String) plantParam;
+                if (plantStr.contains(",")) {
+                    List<String> plantList = Arrays.asList(plantStr.split(","));
+                    queryParams.put("plants", plantList);
+                } else {
+                    queryParams.put("plant", plantStr);
+                }
+            }
+        }
+        
+        if (params.containsKey("major")) {
+            Object majorParam = params.get("major");
+            if (majorParam instanceof List) {
+                queryParams.put("majors", majorParam);
+            } else if (majorParam instanceof String) {
+                // 澶勭悊鍙兘鐨勯�楀彿鍒嗛殧瀛楃涓�
+                String majorStr = (String) majorParam;
+                if (majorStr.contains(",")) {
+                    List<String> majorList = Arrays.asList(majorStr.split(","));
+                    queryParams.put("majors", majorList);
+                } else {
+                    queryParams.put("major", majorStr);
+                }
+            }
+        }
+        
+        if (params.containsKey("workshop")) {
+            Object workshopParam = params.get("workshop");
+            if (workshopParam instanceof List) {
+                queryParams.put("workshops", workshopParam);
+            } else if (workshopParam instanceof String) {
+                // 澶勭悊鍙兘鐨勯�楀彿鍒嗛殧瀛楃涓�
+                String workshopStr = (String) workshopParam;
+                if (workshopStr.contains(",")) {
+                    List<String> workshopList = Arrays.asList(workshopStr.split(","));
+                    queryParams.put("workshops", workshopList);
+                } else {
+                    queryParams.put("workshop", workshopStr);
+                }
+            }
+        }
+        
+        // 纭畾鏃堕棿鑼冨洿
+        List<String> timePoints = new ArrayList<>();
+        
+        if ("day".equalsIgnoreCase(timeGranularity)) {
+            // "鏃�"绮掑害锛氫紶鍏ヤ竴涓湀浠斤紝鑱氬悎璇ユ湀姣忎竴澶╃殑鏁版嵁
+            if (!params.containsKey("yearMonth")) {
+                result.put("plantTable", plantTable);
+                result.put("message", "鏃ョ矑搴﹁仛鍚堥渶瑕佹寚瀹歽earMonth鍙傛暟");
+                return result;
+            }
+            
+            String yearMonth = (String) params.get("yearMonth");
+            // 鐢熸垚鎸囧畾鏈堜唤涓殑姣忎竴澶�
+            YearMonth ym = YearMonth.parse(yearMonth);
+            int daysInMonth = ym.lengthOfMonth();
+            
+            for (int day = 1; day <= daysInMonth; day++) {
+                String dayStr = String.format("%02d", day);
+                timePoints.add(yearMonth + "-" + dayStr);
+            }
+            
+            // 璁剧疆鏌ヨ鍙傛暟
+            String[] ymParts = yearMonth.split("-");
+            queryParams.put("yearStart", ymParts[0]);
+            queryParams.put("monthStart", ymParts[1]);
+            queryParams.put("yearEnd", ymParts[0]);
+            queryParams.put("monthEnd", ymParts[1]);
+            
+        } else if ("month".equalsIgnoreCase(timeGranularity)) {
+            // "鏈�"绮掑害锛氫紶鍏ヤ竴涓椂闂村尯闂达紝鑱氬悎璇ュ尯闂村唴姣忎釜鏈堢殑鏁版嵁
+            if (!params.containsKey("startDate") || !params.containsKey("endDate")) {
+                result.put("plantTable", plantTable);
+                result.put("message", "鏈堢矑搴﹁仛鍚堥渶瑕佹寚瀹歴tartDate鍜宔ndDate鍙傛暟");
+                return result;
+            }
+            
+            String startDate = (String) params.get("startDate");
+            String endDate = (String) params.get("endDate");
+            
+            // 瑙f瀽寮�濮嬪拰缁撴潫骞存湀
+            YearMonth start = YearMonth.parse(startDate);
+            YearMonth end = YearMonth.parse(endDate);
+            
+            // 鐢熸垚鍖洪棿鍐呯殑姣忎釜鏈�
+            timePoints = getYearMonthsInRange(start, end);
+            
+            // 璁剧疆鏌ヨ鍙傛暟
+            String[] startParts = startDate.split("-");
+            String[] endParts = endDate.split("-");
+            queryParams.put("yearStart", startParts[0]);
+            queryParams.put("monthStart", startParts[1]);
+            queryParams.put("yearEnd", endParts[0]);
+            queryParams.put("monthEnd", endParts[1]);
+        }
+        
+        if (timePoints.isEmpty()) {
+            result.put("plantTable", plantTable);
+            result.put("message", "鏈兘鐢熸垚鏈夋晥鐨勬椂闂寸偣鍒楄〃");
+            return result;
+        }
+        
+        // 鏌ヨ鍘熷鏁版嵁锛堜笉渚濊禆鏁版嵁搴撹仛鍚堬級
+        List<Map<String, Object>> rawData = apsGasPipingRouteStatMapper.selectRawStatData(queryParams);
+        
+        // 濡傛灉娌℃湁鏌ヨ鍒板師濮嬫暟鎹紝浣嗛渶瑕佽繑鍥炴墍鏈夊伐搴�/杞﹂棿鐨勬暟鎹�
+        if (rawData.isEmpty()) {
+            // 鍒涘缓娌℃湁鏃堕棿闄愬埗鐨勫熀纭�鏌ヨ鍙傛暟
+            Map<String, Object> baseParams = new HashMap<>(queryParams);
+            baseParams.remove("yearStart");
+            baseParams.remove("monthStart");
+            baseParams.remove("yearEnd");
+            baseParams.remove("monthEnd");
+            
+            // 鐩存帴浠巃ps_gas_piping_route_stat琛ㄦ煡璇㈡墍鏈夊彲鑳界殑宸ュ簭鍜岃溅闂�
+            List<Map<String, Object>> baseData = apsGasPipingRouteStatMapper.selectBaseStatData(baseParams);
+            
+            // 涓烘瘡涓伐搴�/杞﹂棿鍒涘缓鍩轰簬鏃堕棿鐨勭┖鏁版嵁
+            for (Map<String, Object> data : baseData) {
+                String rowGroupValue = getStringValue(data, rowGroupBy);
+                if (rowGroupValue == null || rowGroupValue.trim().isEmpty()) continue;
+                
+                Map<String, Object> rowEntry = new HashMap<>();
+                Map<String, Object> rowDetail = new HashMap<>();
+                
+                // 娣诲姞鍩烘湰淇℃伅
+                String plant = getStringValue(data, "plant");
+                String major = getStringValue(data, "major");
+                String workshop = getStringValue(data, "workshop");
+                
+                if (groupByPlant) rowDetail.put("plant", plant);
+                if (groupByMajor) rowDetail.put("major", major);
+                if (groupByWorkshop) rowDetail.put("workshop", workshop);
+                
+                // 澶勭悊宸ュ簭鍚嶇О - 濡傛灉rowGroupBy涓簑orkshop锛岄渶瑕佹坊鍔爌rocessName瀛楁
+                if ("workshop".equals(rowGroupBy)) {
+                    String processName = getStringValue(data, "processName");
+                    rowDetail.put("processName", processName != null ? processName : "");
+                }
+                
+                // 涓烘瘡涓椂闂寸偣鍒涘缓闆跺�兼暟鎹�
+                List<Map<String, Object>> timeDataList = new ArrayList<>();
+                for (String timePoint : timePoints) {
+                    Map<String, Object> pointData = new HashMap<>();
+                    pointData.put("planDay", timePoint);
+                    pointData.put("requireTimes", BigDecimal.ZERO);
+                    pointData.put("designTimes", BigDecimal.ZERO); 
+                    pointData.put("capacityLoad", BigDecimal.ZERO);
+                    timeDataList.add(pointData);
+                }
+                
+                rowDetail.put("timeData", timeDataList);
+                rowEntry.put(rowGroupValue, rowDetail);
+                plantTable.add(rowEntry);
+            }
+            
+            // 鏇存柊缁撴灉浣嗕笉鐩存帴杩斿洖锛岀户缁墽琛屽悗缁敞鎰忕偣4鐨勫鐞�
+            result.put("plantTable", plantTable);
+            result.put("timePoints", timePoints);
+            result.put("rowGroupBy", rowGroupBy);
+        } else {
+            // 鍦⊿ervice灞傚畬鎴愯仛鍚�
+            // 浣跨敤缁勫悎key鏉ュ疄鐜板缁村害鍒嗙粍锛堝姩鎬乺owGroupBy瀛楁 + 鍙�夌殑宸ュ巶/涓撲笟/杞﹂棿锛�
+            Map<String, Map<String, Object>> groupInfoMap = new HashMap<>();
+            Map<String, Map<String, BigDecimal>> groupTimeDataMap = new HashMap<>();
+            // 瀛樺偍姣忎釜groupKey瀵瑰簲鐨刾rocessName闆嗗悎
+            Map<String, Set<String>> groupProcessNamesMap = new HashMap<>();
+            
+            // 閬嶅巻鍘熷鏁版嵁锛屾寜澶氱淮搴﹀垎缁勮繘琛岃仛鍚�
+            for (Map<String, Object> data : rawData) {
+                // 鑾峰彇琛屽垎缁勫瓧娈靛��
+                String rowGroupValue = getStringValue(data, rowGroupBy);
+                if (rowGroupValue == null || rowGroupValue.trim().isEmpty()) {
+                    log.warn("璺宠繃澶勭悊锛歿} 瀛楁鍊间负绌�", rowGroupBy);
+                    continue;
+                }
+                
+                // 鑾峰彇宸ュ簭鍚嶇О锛堢敤浜庢棩蹇楀拰鍚庣画澶勭悊锛�
+                String processName = getStringValue(data, "processName");
+                
+                // 澶勭悊寮�宸ユ棩鏈�
+                Date processPlanStartDay = (Date) data.get("processPlanStartDay");
+                if (processPlanStartDay == null) {
+                    log.warn("璺宠繃澶勭悊锛氳鍒掑紑宸ユ棩涓簄ull, {}={}", rowGroupBy, rowGroupValue);
+                    continue;
+                }
+                
+                // 鏋勫缓鍒嗙粍閿� - 鍩轰簬row鍒嗙粍瀛楁鍜屽彲閫夌殑鍏朵粬缁村害
+                String plant = getStringValue(data, "plant");
+                String major = getStringValue(data, "major");
+                String workshop = getStringValue(data, "workshop");
+                
+                StringBuilder groupKeyBuilder = new StringBuilder(rowGroupValue);
+                
+                // 鏍规嵁鐢ㄦ埛閫夋嫨鐨勫垎缁勭淮搴︽坊鍔犲埌鍒嗙粍閿�
+                if (groupByPlant && plant != null) {
+                    groupKeyBuilder.append("_PLANT_").append(plant);
+                }
+                if (groupByMajor && major != null) {
+                    groupKeyBuilder.append("_MAJOR_").append(major);
+                }
+                if (groupByWorkshop && workshop != null) {
+                    groupKeyBuilder.append("_WORKSHOP_").append(workshop);
+                }
+                
+                String groupKey = groupKeyBuilder.toString();
+                
+                // 璁板綍鍒嗙粍鐨勫熀鏈俊鎭紙鍙褰曚竴娆★級
+                if (!groupInfoMap.containsKey(groupKey)) {
+                    Map<String, Object> groupInfo = new HashMap<>();
+                    groupInfo.put(rowGroupBy, rowGroupValue);
+                    groupInfo.put("plant", plant);
+                    groupInfo.put("major", major);
+                    groupInfo.put("workshop", workshop);
+                    groupInfo.put("processName", processName);
+                    groupInfoMap.put(groupKey, groupInfo);
+                }
+                
+                // 鏀堕泦processName
+                if (processName != null && !processName.trim().isEmpty()) {
+                    if (!groupProcessNamesMap.containsKey(groupKey)) {
+                        groupProcessNamesMap.put(groupKey, new HashSet<>());
+                    }
+                    groupProcessNamesMap.get(groupKey).add(processName);
+                }
+                
+                // 璁$畻鏃堕棿鐐筀ey
+                String timeKey;
+                LocalDate planStartLocalDate = processPlanStartDay.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+                
+                if ("day".equalsIgnoreCase(timeGranularity)) {
+                    // 鏃ョ矑搴�: 2025-05-25
+                    timeKey = planStartLocalDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
+                } else {
+                    // 鏈堢矑搴�: 2025-05
+                    timeKey = planStartLocalDate.getYear() + "-" + String.format("%02d", planStartLocalDate.getMonthValue());
+                }
+                
+                // 鑾峰彇璇ュ垎缁勭殑鏃堕棿鐐规槧灏勶紝濡傛灉涓嶅瓨鍦ㄥ垯鍒涘缓
+                if (!groupTimeDataMap.containsKey(groupKey)) {
+                    groupTimeDataMap.put(groupKey, new HashMap<>());
+                }
+                Map<String, BigDecimal> timeMap = groupTimeDataMap.get(groupKey);
+                
+                // 绱姞璇ュ垎缁勫湪璇ユ椂闂寸偣鐨勫伐鏃舵暟鎹�
+                BigDecimal processTotalTime = getBigDecimalValue(data, "processTotalTime");
+                if (processTotalTime != null) {
+                    BigDecimal currentTotal = timeMap.getOrDefault(timeKey, BigDecimal.ZERO);
+                    timeMap.put(timeKey, currentTotal.add(processTotalTime));
+                }
+            }
+            
+            // 鏋勫缓鏈�缁堣繑鍥炵殑鏁版嵁缁撴瀯
+            for (String groupKey : groupInfoMap.keySet()) {
+                Map<String, Object> rowEntry = new HashMap<>();
+                Map<String, Object> rowDetail = new HashMap<>();
+                
+                // 鑾峰彇璇ュ垎缁勭殑鍩烘湰淇℃伅
+                Map<String, Object> groupInfo = groupInfoMap.get(groupKey);
+                String rowGroupValue = (String) groupInfo.get(rowGroupBy);
+                
+                // 娣诲姞鍒嗙粍鍩烘湰淇℃伅
+                if (groupByPlant) {
+                    rowDetail.put("plant", groupInfo.get("plant"));
+                }
+                if (groupByMajor) {
+                    rowDetail.put("major", groupInfo.get("major"));
+                }
+                if (groupByWorkshop) {
+                    rowDetail.put("workshop", groupInfo.get("workshop"));
+                }
+                
+                // 澶勭悊processName - 濡傛灉rowGroupBy涓簑orkshop锛屽垯灏嗘墍鏈塸rocessName鐢ㄥ垎鍙疯繛鎺�
+                if ("workshop".equals(rowGroupBy)) {
+                    Set<String> processNames = groupProcessNamesMap.getOrDefault(groupKey, new HashSet<>());
+                    if (!processNames.isEmpty()) {
+                        String joinedProcessNames = String.join(";", processNames);
+                        rowDetail.put("processName", joinedProcessNames);
+                    } else {
+                        rowDetail.put("processName", groupInfo.get("processName"));
+                    }
+                } else if (!"processName".equals(rowGroupBy)) {
+                    // 淇濈暀宸ュ簭鍚嶇О淇℃伅锛屼互渚垮墠绔睍绀�
+                    rowDetail.put("processName", groupInfo.get("processName"));
+                }
+                
+                // 娣诲姞鏃堕棿鏁版嵁
+                List<Map<String, Object>> timeDataList = new ArrayList<>();
+                Map<String, BigDecimal> timeMap = groupTimeDataMap.getOrDefault(groupKey, new HashMap<>());
+                
+                for (String timePoint : timePoints) {
+                    Map<String, Object> pointData = new HashMap<>();
+                    pointData.put("planDay", timePoint);
+                    
+                    // 鑾峰彇璇ユ椂闂寸偣鐨勯渶姹傚伐鏃讹紝濡傛灉涓嶅瓨鍦ㄥ垯璁句负0
+                    BigDecimal requireTimes = timeMap.getOrDefault(timePoint, BigDecimal.ZERO);
+                    pointData.put("requireTimes", requireTimes);
+                    
+                    // 璁捐宸ユ椂鍜屼骇鑳借礋鑽风◢鍚庤绠�
+                    pointData.put("designTimes", 0);
+                    pointData.put("capacityLoad", 0);
+                    
+                    timeDataList.add(pointData);
+                }
+                
+                rowDetail.put("timeData", timeDataList);
+                rowEntry.put(rowGroupValue, rowDetail);
+                plantTable.add(rowEntry);
+            }
+        }
+
+        // 鍦ㄨ繑鍥炲墠鏌ヨ璁捐浜ц兘鏁版嵁骞惰绠椾骇鑳借礋鑽�
+        for (Map<String, Object> rowEntry : plantTable) {
+            for (String rowKey : rowEntry.keySet()) {
+                Map<String, Object> rowDetail = (Map<String, Object>) rowEntry.get(rowKey);
+                List<Map<String, Object>> timeDataList = (List<Map<String, Object>>) rowDetail.get("timeData");
+                
+                // 鑾峰彇鍩烘湰淇℃伅
+                String plant = rowDetail.containsKey("plant") ? (String) rowDetail.get("plant") : null;
+                String major = rowDetail.containsKey("major") ? (String) rowDetail.get("major") : null;
+                String workshop = rowDetail.containsKey("workshop") ? (String) rowDetail.get("workshop") : null;
+                
+                // 澶勭悊涓嶅悓鐨剅owGroupBy鎯呭喌
+                if ("workshop".equals(rowGroupBy) && rowDetail.containsKey("processName")) {
+                    // 鎯呭喌1: 鎸墂orkshop鑱氬悎锛岄渶瑕佹媶鍒唒rocessName瀛楁
+                    String processNamesStr = (String) rowDetail.get("processName");
+                    String[] processNames = processNamesStr.split(";");
+                    
+                    // 浼樺寲鏌ヨ - 鍒涘缓缂撳瓨锛屾寜鏈堜唤缂撳瓨鏌ヨ缁撴灉
+                    // Key: year-month-processName, Value: 鏌ヨ缁撴灉鍒楄〃
+                    Map<String, List<ApsGasPipelineCapacityPlan>> capacityPlanCache = new HashMap<>();
+                    
+                    // 閬嶅巻姣忎釜鏃堕棿鐐�
+                    for (Map<String, Object> timeData : timeDataList) {
+                        String planDay = (String) timeData.get("planDay");
+                        BigDecimal requireTimes = new BigDecimal(timeData.get("requireTimes").toString());
+                        BigDecimal totalDesignTimes = BigDecimal.ZERO;
+                        
+                        // 鎷嗗垎骞存湀鏃�
+                        String[] dateParts = planDay.split("-");
+                        String year = dateParts[0];
+                        String month = dateParts[1];
+                        // 缁熶竴month鏍煎紡涓烘暣鏁板瓧绗︿覆锛屽幓鎺夊墠瀵奸浂
+                        month = String.valueOf(Integer.parseInt(month));
+                        String yearMonth = year + "-" + month;
+                        
+                        // 绱姞澶氫釜宸ュ簭鐨勮璁′骇鑳�
+                        for (String processName : processNames) {
+                            // 鏋勫缓缂撳瓨閿�
+                            String cacheKey = yearMonth + "-" + processName.trim();
+                            
+                            // 浠庣紦瀛樿幏鍙栨垨鏌ヨ鏁版嵁
+                            List<ApsGasPipelineCapacityPlan> capacityPlans;
+                            if (capacityPlanCache.containsKey(cacheKey)) {
+                                capacityPlans = capacityPlanCache.get(cacheKey);
+                            } else {
+                                // 浣跨敤涓撶敤鏌ヨ鏂规硶鏌ヨ璁捐浜ц兘鏁版嵁
+                                // 鎸夋枃妗h姹傦細鏍规嵁process_name鍜宲lant鍘籥ps_gas_pipeline_capacity_plan琛ㄤ腑鏌ヨ
+                                capacityPlans = apsGasPipelineCapacityPlanMapper.selectDesignCapacityForInterface2(
+                                        processName.trim(), year, month, major, plant);
+                                
+                                // 灏嗙粨鏋滃瓨鍏ョ紦瀛�
+                                capacityPlanCache.put(cacheKey, capacityPlans);
+                            }
+                            
+                            // 绱姞璁捐浜ц兘鍊�
+                            for (ApsGasPipelineCapacityPlan plan : capacityPlans) {
+                                if ("day".equalsIgnoreCase(timeGranularity)) {
+                                    // 鏃ョ矑搴︿娇鐢ㄦ棩浜у嚭鏁伴噺
+                                    if (plan.getDayProduceAllNum() != null) {
+                                        totalDesignTimes = totalDesignTimes.add(plan.getDayProduceAllNum());
+                                    }
+                                } else {
+                                    // 鏈堢矑搴︿娇鐢ㄦ湀浜у嚭鎬绘暟閲�
+                                    if (plan.getMonthProduceAllNum() != null) {
+                                        totalDesignTimes = totalDesignTimes.add(plan.getMonthProduceAllNum());
+                                    }
+                                }
+                            }
+                        }
+                        
+                        // 鏇存柊璁捐宸ユ椂
+                        timeData.put("designTimes", totalDesignTimes);
+                        
+                        // 璁$畻浜ц兘璐熻嵎 = 闇�姹備骇鑳�/璁捐浜ц兘脳100%
+                        if (totalDesignTimes.compareTo(BigDecimal.ZERO) > 0) {
+                            BigDecimal capacityLoad = requireTimes
+                                    .divide(totalDesignTimes, 2, RoundingMode.HALF_UP)
+                                    .multiply(new BigDecimal(100));
+                            timeData.put("capacityLoad", capacityLoad);
+                        } else {
+                            timeData.put("capacityLoad", 0);
+                        }
+                    }
+                } else {
+                    // 鎯呭喌2: 鎸塸rocessName鎴栧叾浠栧瓧娈佃仛鍚�
+                    String processName = rowDetail.containsKey("processName") ? 
+                            (String) rowDetail.get("processName") : rowKey;
+                    
+                    // 浼樺寲鏌ヨ - 鍒涘缓缂撳瓨锛屾寜鏈堜唤缂撳瓨鏌ヨ缁撴灉
+                    Map<String, List<ApsGasPipelineCapacityPlan>> capacityPlanCache = new HashMap<>();
+                    
+                    // 閬嶅巻姣忎釜鏃堕棿鐐�
+                    for (Map<String, Object> timeData : timeDataList) {
+                        String planDay = (String) timeData.get("planDay");
+                        BigDecimal requireTimes = new BigDecimal(timeData.get("requireTimes").toString());
+                        
+                        // 鎷嗗垎骞存湀鏃�
+                        String[] dateParts = planDay.split("-");
+                        String year = dateParts[0];
+                        String month = dateParts[1];
+                        // 缁熶竴month鏍煎紡涓烘暣鏁板瓧绗︿覆锛屽幓鎺夊墠瀵奸浂
+                        month = String.valueOf(Integer.parseInt(month));
+                        String yearMonth = year + "-" + month;
+                        
+                        // 鏋勫缓缂撳瓨閿�
+                        String cacheKey = yearMonth + "-" + processName;
+                        
+                        // 浠庣紦瀛樿幏鍙栨垨鏌ヨ鏁版嵁
+                        List<ApsGasPipelineCapacityPlan> capacityPlans;
+                        if (capacityPlanCache.containsKey(cacheKey)) {
+                            capacityPlans = capacityPlanCache.get(cacheKey);
+                        } else {
+                            // 浣跨敤涓撶敤鏌ヨ鏂规硶鏌ヨ璁捐浜ц兘鏁版嵁
+                            // 鎸夋枃妗h姹傦細鏍规嵁process_name鍜宲lant鍘籥ps_gas_pipeline_capacity_plan琛ㄤ腑鏌ヨ
+                            capacityPlans = apsGasPipelineCapacityPlanMapper.selectDesignCapacityForInterface2(
+                                    processName, year, month, major, plant);
+                            
+                            // 灏嗙粨鏋滃瓨鍏ョ紦瀛�
+                            capacityPlanCache.put(cacheKey, capacityPlans);
+                        }
+                        
+                        // 绱姞璁捐浜ц兘鍊�
+                        BigDecimal totalDesignTimes = BigDecimal.ZERO;
+                        for (ApsGasPipelineCapacityPlan plan : capacityPlans) {
+                            if ("day".equalsIgnoreCase(timeGranularity)) {
+                                // 鏃ョ矑搴︿娇鐢ㄦ棩浜у嚭鏁伴噺
+                                if (plan.getDayProduceAllNum() != null) {
+                                    totalDesignTimes = totalDesignTimes.add(plan.getDayProduceAllNum());
+                                }
+                            } else {
+                                // 鏈堢矑搴︿娇鐢ㄦ湀浜у嚭鎬绘暟閲�
+                                if (plan.getMonthProduceAllNum() != null) {
+                                    totalDesignTimes = totalDesignTimes.add(plan.getMonthProduceAllNum());
+                                }
+                            }
+                        }
+                        
+                        // 鏇存柊璁捐宸ユ椂
+                        timeData.put("designTimes", totalDesignTimes);
+                        
+                        // 璁$畻浜ц兘璐熻嵎 = 闇�姹備骇鑳�/璁捐浜ц兘脳100%
+                        if (totalDesignTimes.compareTo(BigDecimal.ZERO) > 0) {
+                            BigDecimal capacityLoad = requireTimes
+                                    .divide(totalDesignTimes, 2, RoundingMode.HALF_UP)
+                                    .multiply(new BigDecimal(100));
+                            timeData.put("capacityLoad", capacityLoad);
+                        } else {
+                            timeData.put("capacityLoad", 0);
+                        }
+                    }
+                }
+            }
+        }
+
+        result.put("plantTable", plantTable);
+        result.put("timePoints", timePoints);
+        result.put("rowGroupBy", rowGroupBy);
+        
+        // 鏍规嵁鏂囨。娉ㄦ剰鐐�3锛屾坊鍔犳帓搴忛�昏緫
+        if (!plantTable.isEmpty()) {
+            // 瀵硅仛鍚堢粨鏋滆繘琛屾帓搴�
+            Collections.sort(plantTable, (map1, map2) -> {
+                String key1 = map1.keySet().iterator().next();
+                String key2 = map2.keySet().iterator().next();
+                
+                // 棣栧厛鎸塺owGroupBy鎺掑簭锛坧rocessName鎴杦orkshop锛�
+                int result1 = key1.compareTo(key2);
+                if (result1 != 0) {
+                    return result1;
+                }
+                
+                // 濡傛灉rowGroupBy鐩稿悓锛屽啀鎸塸lant鎺掑簭
+                Map<String, Object> detail1 = (Map<String, Object>) map1.get(key1);
+                Map<String, Object> detail2 = (Map<String, Object>) map2.get(key2);
+                
+                String plant1 = detail1.containsKey("plant") ? (String) detail1.get("plant") : "";
+                String plant2 = detail2.containsKey("plant") ? (String) detail2.get("plant") : "";
+                
+                return plant1.compareTo(plant2);
+            });
+        }
+        
+        // 瀹炵幇娉ㄦ剰鐐�4锛氬綋鏃堕棿棰楃矑搴︿负"鏃�"鏃讹紝纭繚娌℃湁鏁版嵁鐨勫伐鍘備篃杩斿洖瀹屾暣缁撴瀯
+        if ("day".equalsIgnoreCase(timeGranularity) && params.containsKey("plant")) {
+            // 鑾峰彇璇锋眰涓殑宸ュ巶鍒楄〃
+            List<String> requestedPlants = new ArrayList<>();
+            Object plantParam = params.get("plant");
+            if (plantParam instanceof List) {
+                requestedPlants.addAll((List<String>) plantParam);
+            } else if (plantParam instanceof String) {
+                String plantStr = (String) plantParam;
+                if (plantStr.contains(",")) {
+                    requestedPlants.addAll(Arrays.asList(plantStr.split(",")));
+                } else {
+                    requestedPlants.add(plantStr);
+                }
+            }
+            
+            if (!requestedPlants.isEmpty()) {
+                // 妫�鏌ュ摢浜涘伐鍘傛病鏈夋暟鎹�
+                Set<String> plantsWithData = new HashSet<>();
+                for (Map<String, Object> rowEntry : plantTable) {
+                    for (String rowKey : rowEntry.keySet()) {
+                        Map<String, Object> rowDetail = (Map<String, Object>) rowEntry.get(rowKey);
+                        if (rowDetail.containsKey("plant")) {
+                            plantsWithData.add((String) rowDetail.get("plant"));
+                        }
+                    }
+                }
+                
+                // 鎵惧嚭娌℃湁鏁版嵁鐨勫伐鍘�
+                List<String> plantsWithoutData = requestedPlants.stream()
+                        .filter(plant -> !plantsWithData.contains(plant))
+                        .collect(Collectors.toList());
+                
+                if (!plantsWithoutData.isEmpty()) {
+                    // 鑾峰彇鎵�鏈夊幓閲嶇殑processName鎴杦orkshop
+                    List<String> allUniqueValues;
+                    if ("processName".equals(rowGroupBy)) {
+                        allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctProcessNames();
+                    } else if ("workshop".equals(rowGroupBy)) {
+                        allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctWorkshops();
+                    } else {
+                        // 濡傛灉rowGroupBy涓嶆槸processName鎴杦orkshop锛岃烦杩囧鐞�
+                        return result;
+                    }
+                    
+                    // 涓烘瘡涓病鏈夋暟鎹殑宸ュ巶鍒涘缓绌烘暟鎹粨鏋�
+                    for (String plant : plantsWithoutData) {
+                        for (String uniqueValue : allUniqueValues) {
+                            if (uniqueValue == null || uniqueValue.trim().isEmpty()) {
+                                continue;
+                            }
+                            
+                            // 妫�鏌ユ槸鍚﹀凡缁忓瓨鍦ㄨ繖涓��
+                            boolean exists = false;
+                            for (Map<String, Object> entry : plantTable) {
+                                if (entry.containsKey(uniqueValue)) {
+                                    Map<String, Object> detail = (Map<String, Object>) entry.get(uniqueValue);
+                                    String existingPlant = detail.containsKey("plant") ? (String) detail.get("plant") : "";
+                                    if (plant.equals(existingPlant)) {
+                                        exists = true;
+                                        break;
+                                    }
+                                }
+                            }
+                            
+                            // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂扮殑绌烘暟鎹粨鏋�
+                            if (!exists) {
+                                Map<String, Object> rowEntry = new HashMap<>();
+                                Map<String, Object> rowDetail = new HashMap<>();
+                                
+                                // 璁剧疆鍩烘湰淇℃伅
+                                rowDetail.put("plant", plant);
+                                if (groupByMajor) {
+                                    rowDetail.put("major", "");
+                                }
+                                if (groupByWorkshop && !"workshop".equals(rowGroupBy)) {
+                                    rowDetail.put("workshop", "");
+                                }
+                                
+                                // 澶勭悊processName - 濡傛灉rowGroupBy涓簑orkshop锛岄渶瑕佽缃┖鐨刾rocessName
+                                if ("workshop".equals(rowGroupBy)) {
+                                    rowDetail.put("processName", "");
+                                }
+                                
+                                // 涓烘瘡涓椂闂寸偣鍒涘缓闆跺�兼暟鎹�
+                                List<Map<String, Object>> timeDataList = new ArrayList<>();
+                                for (String timePoint : timePoints) {
+                                    Map<String, Object> pointData = new HashMap<>();
+                                    pointData.put("planDay", timePoint);
+                                    pointData.put("requireTimes", BigDecimal.ZERO);
+                                    pointData.put("designTimes", BigDecimal.ZERO);
+                                    pointData.put("capacityLoad", BigDecimal.ZERO);
+                                    timeDataList.add(pointData);
+                                }
+                                
+                                rowDetail.put("timeData", timeDataList);
+                                rowEntry.put(uniqueValue, rowDetail);
+                                plantTable.add(rowEntry);
+                            }
+                        }
+                    }
+                    
+                    // 閲嶆柊鎺掑簭缁撴灉
+                    Collections.sort(plantTable, (map1, map2) -> {
+                        String key1 = map1.keySet().iterator().next();
+                        String key2 = map2.keySet().iterator().next();
+                        
+                        // 棣栧厛鎸塺owGroupBy鎺掑簭锛坧rocessName鎴杦orkshop锛�
+                        int result1 = key1.compareTo(key2);
+                        if (result1 != 0) {
+                            return result1;
+                        }
+                        
+                        // 濡傛灉rowGroupBy鐩稿悓锛屽啀鎸塸lant鎺掑簭
+                        Map<String, Object> detail1 = (Map<String, Object>) map1.get(key1);
+                        Map<String, Object> detail2 = (Map<String, Object>) map2.get(key2);
+                        
+                        String plant1 = detail1.containsKey("plant") ? (String) detail1.get("plant") : "";
+                        String plant2 = detail2.containsKey("plant") ? (String) detail2.get("plant") : "";
+                        
+                        return plant1.compareTo(plant2);
+                    });
+                    
+                    // 鏇存柊缁撴灉
+                    result.put("plantTable", plantTable);
+                }
+            }
+        }
+        
+        return result;
+    }
+    
+    /**
+     * 浠嶮ap涓畨鍏ㄨ幏鍙朣tring鍊�
+     */
+    private String getStringValue(Map<String, Object> data, String key) {
+        Object value = data.get(key);
+        if (value == null) {
+            return null;
+        }
+        return value.toString();
+    }
+    
+    /**
+     * 浠嶮ap涓畨鍏ㄨ幏鍙朆igDecimal鍊�
+     */
+    private BigDecimal getBigDecimalValue(Map<String, Object> data, String key) {
+        Object value = data.get(key);
+        if (value == null) {
+            return null;
+        }
+        
+        if (value instanceof BigDecimal) {
+            return (BigDecimal) value;
+        } else if (value instanceof Number) {
+            return new BigDecimal(((Number) value).toString());
+        } else if (value instanceof String) {
+            try {
+                return new BigDecimal((String) value);
+            } catch (NumberFormatException e) {
+                log.warn("鏃犳硶灏嗗�艰浆鎹负BigDecimal: {}", value);
+                return null;
+            }
+        }
+        
+        return null;
+    }
 }

--
Gitblit v1.9.3