package com.aps.core.service.impl; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; import com.aps.common.core.utils.poi.ExcelUtil; import com.aps.common.core.utils.uuid.IdUtils; import com.aps.common.core.web.domain.AjaxResult; import com.aps.core.domain.ApsPartPlan; import com.aps.core.domain.ApsResourceDateStat; import com.aps.core.domain.ApsResourceGroup; import com.aps.core.mapper.ApsAbnormalProcessAnalysisMapper; import com.aps.core.mapper.ApsResourceGroupMapper; import com.aps.core.service.IApsAbnormalProcessAnalysisService; import jakarta.annotation.Resource; 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.util.Removal; 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.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.aps.core.mapper.ApsPartRouteStatMapper; import com.aps.core.domain.ApsPartRouteStat; import com.aps.core.service.IApsPartRouteStatService; import org.springframework.transaction.annotation.Transactional; import static java.util.stream.Collectors.groupingBy; /** * 零件统计表Service业务层处理 * * @author zhl * @date 2025-04-11 */ @Slf4j @Service public class ApsPartRouteStatServiceImpl implements IApsPartRouteStatService { @Autowired private ApsPartRouteStatMapper apsPartRouteStatMapper; @Autowired private ApsResourceGroupMapper resourceGroupMapper; @Autowired private ApsResourceGroupMapper apsResourceGroupMapper; @Resource private IApsAbnormalProcessAnalysisService analysisService; /** * 查询零件统计表 * * @param id 零件统计表主键 * @return 零件统计表 */ @Override public ApsPartRouteStat selectApsPartRouteStatById(String id) { return apsPartRouteStatMapper.selectApsPartRouteStatById(id); } /** * 查询零件统计表列表 * * @param apsPartRouteStat 零件统计表 * @return 零件统计表 */ @Override public List selectApsPartRouteStatList(ApsPartRouteStat apsPartRouteStat) { return apsPartRouteStatMapper.selectApsPartRouteStatList(apsPartRouteStat); } /** * 新增零件统计表 * * @param apsPartRouteStat 零件统计表 * @return 结果 */ @Override public int insertApsPartRouteStat(ApsPartRouteStat apsPartRouteStat) { return apsPartRouteStatMapper.insertApsPartRouteStat(apsPartRouteStat); } /** * 修改零件统计表 * * @param apsPartRouteStat 零件统计表 * @return 结果 */ @Override public int updateApsPartRouteStat(ApsPartRouteStat apsPartRouteStat) { return apsPartRouteStatMapper.updateApsPartRouteStat(apsPartRouteStat); } /** * 批量删除零件统计表 * * @param ids 需要删除的零件统计表主键 * @return 结果 */ @Override public int deleteApsPartRouteStatByIds(String[] ids) { return apsPartRouteStatMapper.deleteApsPartRouteStatByIds(ids); } /** * 删除零件统计表信息 * * @param id 零件统计表主键 * @return 结果 */ @Override public int deleteApsPartRouteStatById(String id) { return apsPartRouteStatMapper.deleteApsPartRouteStatById(id); } /** * 查询零件工序并更新计划开工日期 * */ @Transactional @Override public void updatePartRoutPlanDate() { List tempList = apsPartRouteStatMapper.selectPartRoutStat(); /*对tempList 按照 workOrderNo 进行分组*/ Map> groupByWorkOrderNo = tempList.stream().collect(groupingBy(ApsPartRouteStat::getWorkOrderNo)); /*本次计算批次号*/ String batchNum = IdUtils.fastSimpleUUID(); for (Map.Entry> entry : groupByWorkOrderNo.entrySet()) { /*取出每个零件工单的工艺路线信息*/ List apsPartRouteStatList = entry.getValue(); /*按照工序号进行排序*/ apsPartRouteStatList.sort((a, b)->a.getRoadProcessNumber().compareTo(b.getRoadProcessNumber())); /*临时保存 上一道工序的工序总工时*/ ApsPartRouteStat last=null; for (int i = 0; i list = apsPartRouteStatMapper.selectResourceDateStat(); List resourceGroupList = apsResourceGroupMapper.selectApsResourceGroupList(new ApsResourceGroup()); if (!list.isEmpty()) { /*求出计划的最大时间,没有 设置为当前时间+15天*/ ApsResourceDateStat apsResourceDateStat = list.stream().max(Comparator.comparing(ApsResourceDateStat::getPlanDay)).orElse(null); LocalDate maxPlanDay = LocalDate.now().plus(15, ChronoUnit.DAYS); if (apsResourceDateStat != null) { maxPlanDay = apsResourceDateStat.getPlanDay(); } /*组织出日期表头*/ List planDays = new ArrayList<>(); LocalDate startDay = LocalDate.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); while (!startDay.isAfter(maxPlanDay)) { planDays.add(startDay.format(formatter)); startDay = startDay.plus(1, ChronoUnit.DAYS); } /*组织出列头数据*/ /*准备资源组信息*/ List>> targetList = new ArrayList<>(); resourceGroupList.forEach(resourceGroup -> { String resourceName=resourceGroup.getResourceGroupName(); /*根据日期表头的顺序,组织出每个日期下的统计项目*/ Map> maps = new HashMap<>(Map.of()); List currentDaysResouces=new ArrayList<>(); for (String planDay : planDays) { /*查找当前计划日期下的所有资源组的数据*/ Optional first = list.stream() .filter(item -> item.getPlanDay().equals(LocalDate.parse(planDay, formatter)) && item.getResourceGroupName().equals(resourceName) ).collect(Collectors.toList()).stream().findFirst(); if(first.isPresent()){ currentDaysResouces.add(first.get()); } else { ApsResourceDateStat empty = new ApsResourceDateStat(); empty.setPlanDay(LocalDate.parse(planDay, formatter)); // empty.setDesignTimes(resourceGroup.getDevicesQuantity().intValue()*resourceGroup.getTheoryHours().intValue()); empty.setDesignTimes(resourceGroup.getTheoryHours().multiply(BigDecimal.valueOf( resourceGroup.getDevicesQuantity()))); empty.setRequireTimes(BigDecimal.ZERO); empty.setResourceName(resourceName); empty.setResourceGroupName(resourceName); empty.setCapacityLoad(BigDecimal.ZERO); currentDaysResouces.add(empty); } }; maps.put(resourceName, currentDaysResouces); targetList.add(maps); }); result.put("planTitle", planDays); result.put("planTable", targetList); } return result; } @Override public void exportExcel(HttpServletResponse response) { 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 { AjaxResult stat = selectResourceDateStat(); 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()); dataRow.createCell(j*3+3).setCellValue(apsResourceDateStat.getCapacityLoad().doubleValue()+"%"); } } } 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; } }