package com.aps.core.service.impl; 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.service.IApsGasMaterialUsageService; import com.aps.core.service.IApsGasPipingRouteStatService; import com.aps.core.service.IApsStandardProcessService; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.streaming.SXSSFCell; 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.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.*; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; import static java.util.stream.Collectors.groupingBy; /** * 气体管路产能负载统计Service业务层处理 * * @author hjy * @date 2025-04-24 */ @Slf4j @Service public class ApsGasPipingRouteStatServiceImpl implements IApsGasPipingRouteStatService { @Autowired private ApsGasPipingRouteStatMapper apsGasPipingRouteStatMapper; @Autowired private ApsGasPipingPlanMapper apsGasPipingPlanMapper; @Autowired private ApsGasPipelineCapacityPlanMapper apsGasPipelineCapacityPlanMapper; @Autowired private IApsGasMaterialUsageService apsGasMaterialUsageService; @Autowired private IApsStandardProcessService apsStandardProcessService; /** * 查询气体管路产能负载统计 * * @param id 气体管路产能负载统计主键 * @return 气体管路产能负载统计 */ @Override public ApsGasPipingRouteStat selectApsGasPipingRouteStatById(String id) { return apsGasPipingRouteStatMapper.selectApsGasPipingRouteStatById(id); } /** * 查询气体管路产能负载统计列表 * * @param apsGasPipingRouteStat 气体管路产能负载统计 * @return 气体管路产能负载统计 */ @Override public List selectApsGasPipingRouteStatList(ApsGasPipingRouteStat apsGasPipingRouteStat) { return apsGasPipingRouteStatMapper.selectApsGasPipingRouteStatList(apsGasPipingRouteStat); } /** * 新增气体管路产能负载统计 * * @param apsGasPipingRouteStat 气体管路产能负载统计 * @return 结果 */ @Override public int insertApsGasPipingRouteStat(ApsGasPipingRouteStat apsGasPipingRouteStat) { apsGasPipingRouteStat.setCreateTime(DateUtils.getNowDate()); apsGasPipingRouteStat.setCreateBy(SecurityUtils.getUsername()); return apsGasPipingRouteStatMapper.insertApsGasPipingRouteStat(apsGasPipingRouteStat); } /** * 修改气体管路产能负载统计 * * @param apsGasPipingRouteStat 气体管路产能负载统计 * @return 结果 */ @Override public int updateApsGasPipingRouteStat(ApsGasPipingRouteStat apsGasPipingRouteStat) { apsGasPipingRouteStat.setUpdateBy(SecurityUtils.getUsername()); apsGasPipingRouteStat.setUpdateTime(DateUtils.getNowDate()); return apsGasPipingRouteStatMapper.updateApsGasPipingRouteStat(apsGasPipingRouteStat); } /** * 批量删除气体管路产能负载统计 * * @param ids 需要删除的气体管路产能负载统计主键 * @return 结果 */ @Override public int deleteApsGasPipingRouteStatByIds(String[] ids) { return apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatByIds(ids); } /** * 删除气体管路产能负载统计信息 * * @param id 气体管路产能负载统计主键 * @return 结果 */ @Override public int deleteApsGasPipingRouteStatById(String id) { return apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatById(id); } @Override public boolean computeCapacity() { // PageHelper.startPage(1, 500); List apsGasPipingPlans = apsGasPipingPlanMapper.selectApsGasPipingPlanWithProcess(new ApsGasPipingPlan()); List apsGasPipingRouteStatList = new ArrayList<>(); /*本次计算批次号*/ String batchNum = IdUtils.fastSimpleUUID(); try { apsGasPipingPlans.forEach(apsGasPipingPlan -> { List apsProcessRoutes = apsGasPipingPlan.getApsProcessRoutes(); //按照工序序号升序排序 apsProcessRoutes.sort((a, b)->b.getProcessNumber().compareTo(a.getProcessNumber())); //是否找到当前工序 boolean isCurrentProcess = false; boolean lastProcessStartTimeIsBeforeNow = false; ApsGasPipingRouteStat preApsProcessRoute = null; for (int i=0;i apsGasMaterialUsageList = apsGasMaterialUsageService.selectApsGasMaterialUsageList(apsGasMaterialUsage); // apsGasPipingRouteStat.setStandardDosage(apsProcessRoute.getStandardTime().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 tempInsertList = new ArrayList<>(); for (int i = 0; i < apsGasPipingRouteStatList.size(); i++) { tempInsertList.add(apsGasPipingRouteStatList.get(i)); if(tempInsertList.size()==500){ apsGasPipingRouteStatMapper.insertApsGasPipingRouteStatBatch(tempInsertList); tempInsertList = new ArrayList<>(); }else if(i==apsGasPipingRouteStatList.size()-1){ apsGasPipingRouteStatMapper.insertApsGasPipingRouteStatBatch(tempInsertList); } } apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatByBatchNum(batchNum); } catch (Exception e) { e.printStackTrace(); return false; } return true; } public JSONObject getCapacityPlanDataBackup(ApsGasPipingRouteStat apsGasPipingRouteStat) { JSONObject result = new JSONObject(); YearMonth yearMonth = YearMonth.parse(apsGasPipingRouteStat.getSearchEndDate()); int daysInMonth = yearMonth.lengthOfMonth(); LinkedHashSet startPlanTimeSet = new LinkedHashSet<>(); //工序分组统计 LinkedHashMap> processMap = new LinkedHashMap<>(); List>> processList = new ArrayList<>(); try { //获取标准工序名称 ApsStandardProcess apsStandardProcess = new ApsStandardProcess(); apsStandardProcess.setMajor(apsGasPipingRouteStat.getMajor().equals("gas")?"气柜":"管路"); List apsStandardProcessList = apsStandardProcessService.selectApsStandardProcessList(apsStandardProcess); apsStandardProcessList.sort((a, b)->a.getProcessName().compareTo(b.getProcessName())); for(ApsStandardProcess temp:apsStandardProcessList){ processMap.put(temp.getProcessName(), new ArrayList()); } //获取工序计划产能数据 HashMap 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 yearMonths = getYearMonthsInRange(start, end); startPlanTimeSet.addAll(yearMonths); } List apsGasPipelineCapacityPlanList = apsGasPipelineCapacityPlanMapper.selectApsGasPipelineCapacityPlanList(searchCapacityPlan); apsGasPipelineCapacityPlanList.forEach(apsGasPipelineCapacityPlan -> { apsGasPipingPlanMap.put(apsGasPipelineCapacityPlan.getProcessName()+"-"+apsGasPipelineCapacityPlan.getYear()+"-"+(Integer.parseInt(apsGasPipelineCapacityPlan.getMonth())<10?"0"+apsGasPipelineCapacityPlan.getMonth():apsGasPipelineCapacityPlan.getMonth()),apsGasPipelineCapacityPlan); }); //计算日产能数据 DateTimeFormatter formatter = null; List 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(""); 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.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 apsResourceDateStatList = processMap.get(apsGasPipingRouteStatTemp.getProcessName()); apsResourceDateStatList.add(apsResourceDateStat); processMap.put(apsGasPipingRouteStatTemp.getProcessName(), apsResourceDateStatList); } } //聚合每道工序的开工时间和产能 processMap.forEach((processName, apsResourceDateStatList) -> { LinkedHashMap 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 tempList = new ArrayList<>(); dayMap.forEach((key, value) -> { tempList.add(value); }); HashMap> temp = new HashMap<>(); temp.put(processName, tempList); processList.add(temp); }); //排序时间标题 List sortedStartPlanTimeList = new ArrayList<>(startPlanTimeSet); Collections.sort(sortedStartPlanTimeList); for (int i=0;i> temp = processList.get(i); for (Map.Entry> entry : temp.entrySet()){ List apsResourceDateStatList = entry.getValue(); String key = entry.getKey(); List crtList = new ArrayList<>(); for(String tempTime:sortedStartPlanTimeList) { if("month".equals(apsGasPipingRouteStat.getSearchType())){ tempTime += "-01"; } LocalDate crtDate = LocalDate.parse(tempTime, formatter); Optional 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 startPlanTimeSet = new LinkedHashSet<>(); //工序分组统计 LinkedHashMap> processMap = new LinkedHashMap<>(); List>> processList = new ArrayList<>(); try { //获取标准工序名称 ApsStandardProcess apsStandardProcess = new ApsStandardProcess(); apsStandardProcess.setMajor(apsGasPipingRouteStat.getMajor().equals("gas")?"气柜":"管路"); List apsStandardProcessList = apsStandardProcessService.selectApsStandardProcessList(apsStandardProcess); apsStandardProcessList.sort((a, b)->a.getProcessName().compareTo(b.getProcessName())); for(ApsStandardProcess temp:apsStandardProcessList){ processMap.put(temp.getProcessName(), new ArrayList()); } //获取工序计划产能数据 HashMap 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 yearMonths = getYearMonthsInRange(start, end); startPlanTimeSet.addAll(yearMonths); } List 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 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(""); 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 apsResourceDateStatList = processMap.get(apsGasPipingRouteStatTemp.getProcessName()); apsResourceDateStatList.add(apsResourceDateStat); processMap.put(apsGasPipingRouteStatTemp.getProcessName(), apsResourceDateStatList); } } //聚合每道工序的开工时间和产能 for (Map.Entry> entry : processMap.entrySet()) { String processName = entry.getKey(); List apsResourceDateStatList = entry.getValue(); if("day".equals(apsGasPipingRouteStat.getSearchType())) { // 按天统计时保持原有逻辑,不按工厂分组 LinkedHashMap 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 + "-" + 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(new BigDecimal(0)); } apsResourceDateStatTemp.setResourceGroupName(processName); apsResourceDateStatTemp.setPlanDay(apsResourceDateStat.getPlanDay()); dayMap.put(dateKey, apsResourceDateStatTemp); } } List tempList = new ArrayList<>(dayMap.values()); HashMap> temp = new HashMap<>(); temp.put(processName, tempList); processList.add(temp); } else { // 按月统计时才按工厂分组 if (apsResourceDateStatList.isEmpty()) { // 从产能规划数据中获取所有的工厂 Set 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 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 tempList = new ArrayList<>(dayMap.values()); HashMap> temp = new HashMap<>(); temp.put(processName + "_" + plant, tempList); processList.add(temp); } } else { // 按工厂分组,并过滤掉plant为null或空字符串的记录 Map> plantGroups = apsResourceDateStatList.stream() .filter(stat -> stat.getPlant() != null && !stat.getPlant().trim().isEmpty()) .collect(groupingBy(ApsResourceDateStat::getPlant)); // 如果过滤后没有有效的工厂数据,跳过这个工序 if (plantGroups.isEmpty()) { continue; } // 对每个工厂的数据进行处理 for (Map.Entry> plantEntry : plantGroups.entrySet()) { String plant = plantEntry.getKey(); // 再次确认plant不为空 if (plant == null || plant.trim().isEmpty()) { continue; } List plantStats = plantEntry.getValue(); LinkedHashMap 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 tempList = new ArrayList<>(dayMap.values()); HashMap> temp = new HashMap<>(); temp.put(processName + "_" + plant, tempList); processList.add(temp); } } } } //排序时间标题 List sortedStartPlanTimeList = new ArrayList<>(startPlanTimeSet); Collections.sort(sortedStartPlanTimeList); for (int i=0;i> temp = processList.get(i); for (Map.Entry> entry : temp.entrySet()){ List apsResourceDateStatList = entry.getValue(); String key = entry.getKey(); List crtList = new ArrayList<>(); for(String tempTime:sortedStartPlanTimeList) { if("month".equals(apsGasPipingRouteStat.getSearchType())){ tempTime += "-01"; } LocalDate crtDate = LocalDate.parse(tempTime, formatter); Optional 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", processList); result.put("planTitle", sortedStartPlanTimeList); } catch (Exception e) { e.printStackTrace(); } return result; } @Override public void exportExcel(HttpServletResponse response, ApsGasPipingRouteStat apsGasPipingRouteStat) { SXSSFWorkbook wb = new SXSSFWorkbook(500); wb.createSheet(); wb.setSheetName(0, "气柜管路产能负载统计表"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); Map styles = createStyles(wb); CellStyle title = styles.get("title"); try { JSONObject stat = getCapacityPlanData(apsGasPipingRouteStat); List days = (List) stat.get("planTitle"); List>> table= (List>>) stat.get("planTable"); SXSSFSheet sheet = wb.getSheetAt(0); /*填写日期列 和 工时列*/ SXSSFRow rowDay = sheet.createRow(0); SXSSFRow rowTitle = sheet.createRow(1); SXSSFCell daytitle = rowDay.createCell(0); daytitle.setCellValue("日期"); daytitle.setCellStyle(title); SXSSFCell titleCell = rowTitle.createCell(0); titleCell.setCellValue("工序"); titleCell.setCellStyle(title); for (int i = 0; i < days.size(); i++) { SXSSFCell dateCell = rowDay.createCell(i * 3 + 1); SXSSFCell designHoursCell = rowTitle.createCell(i * 3 + 1); SXSSFCell requireHoursCell = rowTitle.createCell(i * 3 + 2); SXSSFCell loadCell = rowTitle.createCell(i * 3 + 3); dateCell.setCellValue(days.get(i)); designHoursCell.setCellValue("设计工时"); requireHoursCell.setCellValue("需求工时"); loadCell.setCellValue("产能负荷"); /*set cell style*/ dateCell.setCellStyle(title); designHoursCell.setCellStyle(title); requireHoursCell.setCellStyle(title); loadCell.setCellStyle(title); /*合并日期单元格*/ sheet.addMergedRegion( new CellRangeAddress(0, 0, i*3+1, i*3+3)); } for (int i = 0; i < table.size(); i++) { Map> resourceList = table.get(i); /*创建数据行*/ SXSSFRow dataRow = sheet.createRow(i+2); for( Map.Entry> entry : resourceList.entrySet()){ String resourceName = entry.getKey(); List resourceDateStats = entry.getValue(); 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().doubleValue()); dataRow.createCell(j*3+2).setCellValue(apsResourceDateStat.getRequireTimes().doubleValue()); if(apsResourceDateStat.getCapacityLoad()!=null){ dataRow.createCell(j*3+3).setCellValue(apsResourceDateStat.getCapacityLoad().doubleValue()+"%"); }else{ dataRow.createCell(j*3+3).setCellValue("%"); } } } } wb.write(response.getOutputStream()); } catch (Exception e) { log.error("导出Excel异常{}", e.getMessage()); } finally { IOUtils.closeQuietly(wb); } } private Map createStyles(SXSSFWorkbook wb) { Map styles=new HashMap<>(); CellStyle style = wb.createCellStyle(); style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); Font titleFont = wb.createFont(); titleFont.setFontName("Arial"); titleFont.setFontHeightInPoints((short) 12); titleFont.setBold(true); style.setFont(titleFont); DataFormat dataFormat = wb.createDataFormat(); style.setDataFormat(dataFormat.getFormat("@")); styles.put("title", style); return styles; } public static List getYearMonthsInRange(YearMonth start, YearMonth end) { List 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 tempList = apsGasPipingRouteStatMapper.queryTempStat(); Map> groupByOrderNo = tempList.stream().collect(groupingBy(ApsGasPipingRouteStat::getWorkOrderNo)); Boolean hasBefore = false; LocalDateTime now = LocalDateTime.now(); for (Map.Entry> entry : groupByOrderNo.entrySet()) { List statPerOrder = entry.getValue(); /*num 为根据完工时间排序出的序号,按此排序,可保证是按完工时间倒叙排列*/ statPerOrder.sort((a, b)->a.getNum().compareTo(b.getNum())); ApsGasPipingRouteStat last=null; for (int i = 0; i = 工单当前工序 代表是未来工序,才进行计划开工日 和计划完工日的计算 * 当工艺工序号 < 工单当前工序 过去工序,不进行计算 * */ if( stat.getRouteProcessNumber().compareTo(stat.getCurrentProcessNumber())>=0){ /*倒排时 下一道工序存在 比当前时间小的计划时间,则当前计划开始和结束时间都是当前时间*/ if(hasBefore){ stat.setWarning(true); stat.setProcessPlanEndDay(transDate(now)); stat.setProcessPlanStartDay(transDate(now)); }else{ /*下一道工序计划时间都正常时,*/ 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()); } /** * 保存钣金统计数据 */ @Transactional @Override public void saveGasPipingRoutStateList() { String batchNum = IdUtils.fastSimpleUUID(); List tempList = apsGasPipingRouteStatMapper.queryTempStat(); Map> groupByOrderNo = tempList.stream().collect(groupingBy(ApsGasPipingRouteStat::getWorkOrderNo)); LocalDateTime now = LocalDateTime.now(); /*待保存的数据*/ List cptStateList = new ArrayList<>(); for (Map.Entry> entry : groupByOrderNo.entrySet()) { List statPerOrder = entry.getValue(); /*num 为根据完工时间排序出的序号,按此排序,可保证是按完工时间倒叙排列*/ statPerOrder.sort((a, b)->a.getNum().compareTo(b.getNum())); ApsGasPipingRouteStat last=null; /*当前工序是否存在 计划开工时间 小于 当前的时间,如果存在后续设置为当前时间*/ boolean hasBefore = false; for (int i = 0; i = 工单当前工序 代表是未来工序,才进行计划开工日 和计划完工日的计算 * 当工艺工序号 < 工单当前工序 过去工序,不进行计算 * */ if( stat.getRoadProcessNumber().compareTo(stat.getCurrentProcessNumber())>=0){ /*倒排时 下一道工序存在 比当前时间小的计划时间,则当前计划开始和结束时间都是当前时间*/ if(hasBefore){ stat.setWarning(true); stat.setProcessPlanEndDay(transDate(now)); stat.setProcessPlanStartDay(transDate(now)); }else{ /*下一道工序计划时间都正常时,*/ 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 batch = cptStateList.subList(i, end); apsGasPipingRouteStatMapper.insertApsGasPipingRouteStatBatch(batch); log.info("批量插入数据,开始位置:{},结束位置:{}", i, end); } } apsGasPipingRouteStatMapper.deleteApsGasPipingRouteStatByBatchNum(batchNum); log.info("批量插入数据完成,batchNum:"+batchNum); } }