package com.aps.core.service.mainPlan.impl; import com.aps.common.core.annotation.Excel; import com.aps.common.core.utils.DateUtils; import com.aps.common.core.utils.poi.ExcelUtil; import com.aps.common.core.utils.uuid.IdUtils; import com.aps.common.core.web.page.TableDataInfo; import com.aps.common.security.utils.DictUtils; import com.aps.common.security.utils.SecurityUtils; import com.aps.core.controller.basicData.ApsGasPipelineCapacityPlanController; import com.aps.core.domain.ApsGasPipelineCapacityPlan; import com.aps.core.domain.mainPlan.ApsWeldSeamStatisticsV2; import com.aps.core.mapper.mainPlan.ApsWeldSeamStatisticsV2Mapper; import com.aps.core.service.mainPlan.IApsWeldSeamStatisticsV2Service; import com.aps.system.api.domain.SysDictData; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.servlet.http.HttpServletResponse; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.util.CellRangeAddress; 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 org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.math.BigDecimal; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; /** * 焊缝统计表V2Service业务层处理 * * @date 2023-08-01 */ @Service public class ApsWeldSeamStatisticsV2ServiceImpl implements IApsWeldSeamStatisticsV2Service { @Autowired private ApsWeldSeamStatisticsV2Mapper apsWeldSeamStatisticsV2Mapper; @Autowired private ApsGasPipelineCapacityPlanController apsGasPipelineCapacityPlanController; /** * 查询焊缝统计表V2列表 * * @param apsWeldSeamStatisticsV2 焊缝统计表V2 * @return 焊缝统计表V2 */ @Override public List selectApsWeldSeamStatisticsV2List(ApsWeldSeamStatisticsV2 apsWeldSeamStatisticsV2) { return apsWeldSeamStatisticsV2Mapper.selectApsWeldSeamStatisticsV2List(apsWeldSeamStatisticsV2); } /** * 修改焊缝统计表V2 * * @param apsWeldSeamStatisticsV2 焊缝统计表V2 * @return 更新后的记录 */ @Override @Transactional(rollbackFor = Exception.class) public ApsWeldSeamStatisticsV2 updateApsWeldSeamStatisticsV2(ApsWeldSeamStatisticsV2 apsWeldSeamStatisticsV2) { // 设置更新时间 apsWeldSeamStatisticsV2.setUpdateTime(DateUtils.getNowDate()); apsWeldSeamStatisticsV2.setUpdateBy(SecurityUtils.getUsername()); // 1. 从数据库获取原始记录,以保留其他字段不变 ApsWeldSeamStatisticsV2 originalData = apsWeldSeamStatisticsV2Mapper.selectApsWeldSeamStatisticsV2ById(apsWeldSeamStatisticsV2.getId()); if (originalData == null) { throw new RuntimeException("记录不存在,ID: " + apsWeldSeamStatisticsV2.getId()); } // 2. 只更新reserveEmergencyOrderOutput和days两个字段 originalData.setReserveEmergencyOrderOutput(apsWeldSeamStatisticsV2.getReserveEmergencyOrderOutput()); originalData.setDays(apsWeldSeamStatisticsV2.getDays()); originalData.setUpdateTime(apsWeldSeamStatisticsV2.getUpdateTime()); originalData.setUpdateBy(apsWeldSeamStatisticsV2.getUpdateBy()); // 3. 确保所有用于计算的BigDecimal字段不为null java.math.BigDecimal pipingOrderReq = (originalData.getPipingOrderRequirement() != null) ? originalData.getPipingOrderRequirement() : java.math.BigDecimal.ZERO; java.math.BigDecimal pipingPredictionReq = (originalData.getPipingPredictionRequirement() != null) ? originalData.getPipingPredictionRequirement() : java.math.BigDecimal.ZERO; java.math.BigDecimal gasOrderReq = (originalData.getGasOrderRequirement() != null) ? originalData.getGasOrderRequirement() : java.math.BigDecimal.ZERO; java.math.BigDecimal gasPredictionReq = (originalData.getGasPredictionRequirement() != null) ? originalData.getGasPredictionRequirement() : java.math.BigDecimal.ZERO; java.math.BigDecimal reserveEmergencyOutput = (originalData.getReserveEmergencyOrderOutput() != null) ? originalData.getReserveEmergencyOrderOutput() : java.math.BigDecimal.ZERO; // 4. 属性1:重新计算total(合计) java.math.BigDecimal total = pipingOrderReq .add(pipingPredictionReq) .add(gasOrderReq) .add(gasPredictionReq) .add(reserveEmergencyOutput); originalData.setTotal(total); // 5. 如果days不为空且大于0,重新计算requirementDayWeldSeam和isSatisfy if(originalData.getDays() != null && originalData.getDays().doubleValue() > 0) { // 属性2:计算需求日焊缝 = 合计/天数,四舍五入 double result = total.doubleValue() / originalData.getDays().doubleValue(); java.math.BigDecimal requirementDayWeldSeam = new java.math.BigDecimal(result).setScale(0, java.math.RoundingMode.HALF_UP); originalData.setRequirementDayWeldSeam(requirementDayWeldSeam); // 属性3:判断是否满足 if(originalData.getProductionDayWeldSeam() != null) { if(originalData.getProductionDayWeldSeam().compareTo(requirementDayWeldSeam) >= 0) { originalData.setIsSatisfy("1"); // 满足 } else { originalData.setIsSatisfy("0"); // 不满足 } } else { originalData.setIsSatisfy("0"); // 默认不满足 } } else { // 如果天数为空或为0,设置为不满足 originalData.setIsSatisfy("0"); } // 6. 更新数据库 apsWeldSeamStatisticsV2Mapper.updateApsWeldSeamStatisticsV2(originalData); // 7. 返回更新后的完整记录 return originalData; } /** * 刷新焊缝统计表数据 * * @param username 操作用户 * @return 受影响的记录数 */ @Override @Transactional(rollbackFor = Exception.class) public int refreshWeldSeamStatistics(String username) { // 1. 清空统计表 apsWeldSeamStatisticsV2Mapper.truncateTable(); // 2. 获取最新的统计数据 List statisticsList = apsWeldSeamStatisticsV2Mapper.queryWeldSeamStatistics(); // 3. 设置创建信息和ID,并获取生产日焊缝数据 Date now = new Date(); for (ApsWeldSeamStatisticsV2 statistics : statisticsList) { // 使用UUID作为ID statistics.setId(IdUtils.fastUUID()); statistics.setCreateBy(username); statistics.setCreateTime(now); // 先计算需求日焊缝(requirementDayWeldSeam) if(statistics.getDays() != null && statistics.getDays().doubleValue() > 0 && statistics.getTotal() != null) { // 计算需求日焊缝 = 合计/天数,四舍五入 double result = statistics.getTotal().doubleValue() / statistics.getDays().doubleValue(); BigDecimal requirementDayWeldSeam = new BigDecimal(result).setScale(0, java.math.RoundingMode.HALF_UP); statistics.setRequirementDayWeldSeam(requirementDayWeldSeam); } else if (statistics.getRequirementDayWeldSeam() == null) { // 如果无法计算且之前没有值,设置默认值 statistics.setRequirementDayWeldSeam(BigDecimal.ZERO); } // 设置生产日焊缝(productionDayWeldSeam) // 根据year、month、productionBase查询对应的生产日焊缝数据 if (statistics.getYear() != null && statistics.getMonth() != null && statistics.getProductionBase() != null) { // 创建查询条件 ApsGasPipelineCapacityPlan queryParam = new ApsGasPipelineCapacityPlan(); queryParam.setYear(statistics.getYear().toString()); queryParam.setMonth(statistics.getMonth().toString()); queryParam.setOrgCode(statistics.getProductionBase()); // 直接调用Controller的list方法获取数据 TableDataInfo tableDataInfo = apsGasPipelineCapacityPlanController.list(queryParam); List capacityPlans = (List) tableDataInfo.getRows(); // 遍历找到processName为"气体管路轨道焊接组"的记录 for (ApsGasPipelineCapacityPlan plan : capacityPlans) { if ("气体管路轨道焊接组".equals(plan.getProcessName()) && plan.getDayProduceAllNum() != null) { // 设置生产日焊缝值 statistics.setProductionDayWeldSeam(plan.getDayProduceAllNum()); break; // 找到匹配记录后退出循环 } } } // 如果没有找到匹配的产能规划数据,设置默认状态 if (statistics.getProductionDayWeldSeam() == null) { statistics.setProductionDayWeldSeam(BigDecimal.ZERO); } // 最后统一计算isSatisfy(是否满足) // 当生产日焊缝 >= 需求日焊缝时为满足,否则为不满足 if (statistics.getRequirementDayWeldSeam() != null && statistics.getProductionDayWeldSeam() != null && statistics.getProductionDayWeldSeam().compareTo(statistics.getRequirementDayWeldSeam()) >= 0) { statistics.setIsSatisfy("1"); // 满足 } else { statistics.setIsSatisfy("0"); // 不满足 } } // 4. 批量插入数据 int count = 0; if (!statisticsList.isEmpty()) { count = apsWeldSeamStatisticsV2Mapper.batchInsert(statisticsList); } return count; } @Override public void exportWeldSeamStatistics(HttpServletResponse response) throws IOException { //1. 获取数据源 List list = apsWeldSeamStatisticsV2Mapper.selectApsWeldSeamStatisticsV2List(new ApsWeldSeamStatisticsV2()); List isRequireDic = DictUtils.getDictCache("aps_task_is_require"); List factoryDic = DictUtils.getDictCache("aps_factory"); //2. 创建Excel工作簿 SXSSFWorkbook wb = new SXSSFWorkbook(500); ExcelUtil excelUtil = new ExcelUtil<>(ApsWeldSeamStatisticsV2.class); excelUtil.init(list, "焊缝统计表", "焊缝统计表", Excel.Type.EXPORT); excelUtil.createWorkbook(); excelUtil.createExcelField(); Map cellStyleMap = excelUtil.createStyles(wb); CellStyle titleStyle = cellStyleMap.get("header_WHITE_GREY_50_PERCENT"); CellStyle dataStyle = cellStyleMap.get("data_CENTER_BLACK_WHITE_STRING_false"); SXSSFSheet sheet = wb.createSheet("焊缝统计表"); List> titleList= initRowTitle(); //3. 构建表头 for (int i = 0; i < titleList.size(); i++) { SXSSFRow titleRow = sheet.createRow(i); LinkedHashMap map = titleList.get(i); AtomicInteger index = new AtomicInteger(); titleList.get(i).forEach((key,value)->{ SXSSFCell cell = titleRow.createCell(index.get()); cell.setCellValue(value); cell.setCellStyle(titleStyle); index.getAndIncrement(); }); } //5. 构建数据行 LinkedHashMap first = titleList.get(0); ArrayList> titles = new ArrayList<>(first.entrySet()); List stringFiledKeys=Arrays.asList("productionBase","isSatisfy"); for (int rowInx = 0; rowInx < list.size(); rowInx++) { SXSSFRow dataRow = sheet.createRow(rowInx + 2); ApsWeldSeamStatisticsV2 statistics = list.get(rowInx); ObjectMapper mapper = new ObjectMapper(); ObjectNode node = mapper.valueToTree(statistics); for (int colInx = 0; colInx < titles.size(); colInx++) { Map.Entry entry = titles.get(colInx); String filedKey = entry.getKey(); SXSSFCell cell = dataRow.createCell(colInx); JsonNode jsonNode = node.get(filedKey); if(filedKey.equals("productionBase")){ factoryDic.stream().filter(x->x.getDictValue().equals(jsonNode.textValue())).findFirst().ifPresent( sysDictData -> cell.setCellValue(sysDictData.getDictLabel()) ); }else if(filedKey.equals("isSatisfy")){ isRequireDic.stream().filter(x->x.getDictValue().equals(jsonNode.textValue())).findFirst().ifPresent( sysDictData -> cell.setCellValue(sysDictData.getDictLabel()) ); }else{ cell.setCellValue(jsonNode.longValue()); } cell.setCellStyle(dataStyle); } } for (int i = 0; i < sheet.getRow(0).getLastCellNum(); i++) { sheet.setColumnWidth(i, 20 * 256); } //4.合并表头 sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 2, 2)); sheet.addMergedRegion(new CellRangeAddress(0, 0, 3, 4)); sheet.addMergedRegion(new CellRangeAddress(0, 0, 5, 6)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 7, 7)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 8, 8)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 9, 9)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 10, 10)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 11, 11)); sheet.addMergedRegion(new CellRangeAddress(0, 1, 12, 12)); //3. 设置响应头 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); wb.write(response.getOutputStream()); } private List> initRowTitle(){ List> list = new ArrayList<>(); LinkedHashMap level1 = new LinkedHashMap<>(); level1.put("year","年份"); level1.put("month","月份"); level1.put("productionBase","生产基地"); level1.put("pipingOrderRequirement","订单需求"); level1.put("gasOrderRequirement","订单需求"); level1.put("pipingPredictionRequirement","预测需求"); level1.put("gasPredictionRequirement","预测需求"); level1.put("reserveEmergencyOrderOutput","预留紧急订单产出"); level1.put("total","合计"); level1.put("days","天数"); level1.put("requirementDayWeldSeam","需求日焊缝"); level1.put("productionDayWeldSeam","生产日焊缝"); level1.put("isSatisfy","是否满足"); list.add(level1); LinkedHashMap level2 = new LinkedHashMap<>(); level2.put("year","年份"); level2.put("month","月份"); level2.put("productionBase","生产基地"); level2.put("pipingOrderRequirement","管路"); level2.put("gasOrderRequirement","气柜"); level2.put("pipingPredictionRequirement","管路"); level2.put("gasPredictionRequirement","气柜"); level2.put("reserveEmergencyOrderOutput","预留紧急订单产出"); level2.put("total","合计"); level2.put("days","天数"); level2.put("requirementDayWeldSeam","需求日焊缝"); level2.put("productionDayWeldSeam","生产日焊缝"); level2.put("isSatisfy","是否满足"); list.add(level2); return list; } }