| | |
| | | plantTable.add(rowEntry); |
| | | } |
| | | |
| | | // 更新结果但不直接返回,继续执行后续注意点4的处理 |
| | | result.put("plantTable", plantTable); |
| | | result.put("timePoints", timePoints); |
| | | result.put("rowGroupBy", rowGroupBy); |
| | | } else { |
| | | // 在Service层完成聚合 |
| | | // 使用组合key来实现多维度分组(动态rowGroupBy字段 + 可选的工厂/专业/车间) |
| | | Map<String, Map<String, Object>> groupInfoMap = new HashMap<>(); |
| | | Map<String, Map<String, BigDecimal>> groupTimeDataMap = new HashMap<>(); |
| | | // 存储每个groupKey对应的processName集合 |
| | | Map<String, Set<String>> groupProcessNamesMap = new HashMap<>(); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | // 在Service层完成聚合 |
| | | // 使用组合key来实现多维度分组(动态rowGroupBy字段 + 可选的工厂/专业/车间) |
| | | Map<String, Map<String, Object>> groupInfoMap = new HashMap<>(); |
| | | Map<String, Map<String, BigDecimal>> groupTimeDataMap = new HashMap<>(); |
| | | // 存储每个groupKey对应的processName集合 |
| | | 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("跳过处理:计划开工日为null, {}={}", 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<>()); |
| | | // 遍历原始数据,按多维度分组进行聚合 |
| | | for (Map<String, Object> data : rawData) { |
| | | // 获取行分组字段值 |
| | | String rowGroupValue = getStringValue(data, rowGroupBy); |
| | | if (rowGroupValue == null || rowGroupValue.trim().isEmpty()) { |
| | | log.warn("跳过处理:{} 字段值为空", rowGroupBy); |
| | | continue; |
| | | } |
| | | groupProcessNamesMap.get(groupKey).add(processName); |
| | | } |
| | | |
| | | // 计算时间点Key |
| | | 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为workshop,则将所有processName用分号连接 |
| | | if ("workshop".equals(rowGroupBy)) { |
| | | Set<String> processNames = groupProcessNamesMap.getOrDefault(groupKey, new HashSet<>()); |
| | | if (!processNames.isEmpty()) { |
| | | String joinedProcessNames = String.join(";", processNames); |
| | | rowDetail.put("processName", joinedProcessNames); |
| | | |
| | | // 获取工序名称(用于日志和后续处理) |
| | | String processName = getStringValue(data, "processName"); |
| | | |
| | | // 处理开工日期 |
| | | Date processPlanStartDay = (Date) data.get("processPlanStartDay"); |
| | | if (processPlanStartDay == null) { |
| | | log.warn("跳过处理:计划开工日为null, {}={}", 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); |
| | | } |
| | | |
| | | // 计算时间点Key |
| | | 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为workshop,则将所有processName用分号连接 |
| | | 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")); |
| | | } |
| | | } 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); |
| | | } |
| | | |
| | | // 添加时间数据 |
| | | 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); |
| | | } |
| | | |
| | | // 在返回前查询设计产能数据并计算产能负荷 |
| | |
| | | }); |
| | | } |
| | | |
| | | // 实现注意点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或workshop |
| | | List<String> allUniqueValues; |
| | | if ("processName".equals(rowGroupBy)) { |
| | | allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctProcessNames(); |
| | | } else if ("workshop".equals(rowGroupBy)) { |
| | | allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctWorkshops(); |
| | | } else { |
| | | // 如果rowGroupBy不是processName或workshop,跳过处理 |
| | | 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为workshop,需要设置空的processName |
| | | 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(); |
| | | |
| | | // 首先按rowGroupBy排序(processName或workshop) |
| | | int result1 = key1.compareTo(key2); |
| | | if (result1 != 0) { |
| | | return result1; |
| | | } |
| | | |
| | | // 如果rowGroupBy相同,再按plant排序 |
| | | 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; |
| | | } |
| | | |