From f274ea473d1ba857c8ac213fc43524b4e773cf71 Mon Sep 17 00:00:00 2001 From: zhanghl <253316343@qq.com> Date: 星期四, 22 五月 2025 16:24:01 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev --- aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java | 601 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 598 insertions(+), 3 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 756bec0..0fa2422 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 @@ -6,9 +6,7 @@ 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.mapper.*; import com.aps.core.service.IApsGasMaterialUsageService; import com.aps.core.service.IApsGasPipingRouteStatService; import com.aps.core.service.IApsStandardProcessService; @@ -1009,4 +1007,601 @@ 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(); + + // 鎸夊伐鍗曞彿鍒嗙粍锛屼究浜庡鐞嗗悓涓�宸ュ崟鐨勪笉鍚屽伐搴� + 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); + + // 鎸夊伐搴忓彿鎺掑簭 + 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); + } + } + + // 鎵归噺鎻掑叆鏁版嵁 + 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"; // 榛樿涓�"鏃�"绮掑害 + + // 纭畾鍒嗙粍缁村害 - 宸ュ巶銆佷笓涓氥�佽溅闂� + 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")); + + // 鏋勫缓鏌ヨ鏉′欢 + 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()) { + result.put("plantTable", plantTable); + result.put("timePoints", timePoints); + return result; + } + + // 鍦⊿ervice灞傚畬鎴愯仛鍚� + // 浣跨敤缁勫悎key鏉ュ疄鐜板缁村害鍒嗙粍锛堝伐搴忓悕 + 鍙�夌殑宸ュ巶/涓撲笟/杞﹂棿锛� + Map<String, Map<String, Object>> groupInfoMap = new HashMap<>(); + Map<String, Map<String, BigDecimal>> groupTimeDataMap = new HashMap<>(); + + // 閬嶅巻鍘熷鏁版嵁锛屾寜澶氱淮搴﹀垎缁勮繘琛岃仛鍚� + for (Map<String, Object> data : rawData) { + String processName = getStringValue(data, "processName"); + if (processName == null) { + log.warn("璺宠繃澶勭悊锛氬伐搴忓悕绉颁负null"); + continue; + } + + // 澶勭悊寮�宸ユ棩鏈� + Date processPlanStartDay = (Date) data.get("processPlanStartDay"); + if (processPlanStartDay == null) { + log.warn("璺宠繃澶勭悊锛氳鍒掑紑宸ユ棩涓簄ull, processName={}", processName); + continue; + } + + // 鏋勫缓鍒嗙粍閿� - 鍩轰簬宸ュ簭鍚嶅拰鍙�夌殑鍏朵粬缁村害 + String plant = getStringValue(data, "plant"); + String major = getStringValue(data, "major"); + String workshop = getStringValue(data, "workshop"); + + StringBuilder groupKeyBuilder = new StringBuilder(processName); + + // 鏍规嵁鐢ㄦ埛閫夋嫨鐨勫垎缁勭淮搴︽坊鍔犲埌鍒嗙粍閿� + 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("processName", processName); + groupInfo.put("plant", plant); + groupInfo.put("major", major); + groupInfo.put("workshop", workshop); + groupInfoMap.put(groupKey, groupInfo); + } + + // 璁$畻鏃堕棿鐐筀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> processEntry = new HashMap<>(); + Map<String, Object> processDetail = new HashMap<>(); + + // 鑾峰彇璇ュ垎缁勭殑鍩烘湰淇℃伅 + Map<String, Object> groupInfo = groupInfoMap.get(groupKey); + String processName = (String) groupInfo.get("processName"); + + // 娣诲姞宸ュ簭鍩烘湰淇℃伅 + if (groupByPlant) { + processDetail.put("plant", groupInfo.get("plant")); + } + if (groupByMajor) { + processDetail.put("major", groupInfo.get("major")); + } + if (groupByWorkshop) { + processDetail.put("workshop", groupInfo.get("workshop")); + } + + // 娣诲姞鏃堕棿鏁版嵁 + 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); + pointData.put("designTimes", 0); // 璁捐宸ユ椂鏆傛椂缁�0 + + // 鑾峰彇璇ユ椂闂寸偣鐨勯渶姹傚伐鏃讹紝濡傛灉涓嶅瓨鍦ㄥ垯璁句负0 + BigDecimal requireTimes = timeMap.getOrDefault(timePoint, BigDecimal.ZERO); + pointData.put("requireTimes", requireTimes); + + // 璁$畻浜ц兘璐熻嵎锛堟殏鏃朵负0锛� + pointData.put("capacityLoad", 0); + + timeDataList.add(pointData); + } + + processDetail.put("timeData", timeDataList); + processEntry.put(processName, processDetail); + plantTable.add(processEntry); + } + + result.put("plantTable", plantTable); + result.put("timePoints", timePoints); + + 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