From 1a3717d3057fe3469afff2887950df8c916f6c0e Mon Sep 17 00:00:00 2001 From: tzy Date: Fri, 21 Nov 2025 16:31:50 +0800 Subject: [PATCH] =?UTF-8?q?BOM=E6=8E=A8=E9=80=81=E5=88=86=E7=BB=84=20?= =?UTF-8?q?=E5=B7=A5=E8=89=BA=E6=8E=A8=E9=80=81=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 2 +- .../controller/BomDetailsController.java | 11 +- .../controller/ProcessOrderProController.java | 312 +++++++++++++++++- .../controller/ProcessRouteController.java | 21 +- .../ruoyi/system/domain/dto/JdVersionDTO.java | 5 + .../system/domain/dto/ProcessRouteGetDTO.java | 157 +++++++++ .../java/com/ruoyi/system/runner/JdUtil.java | 70 ++++ .../ruoyi/system/runner/JsonConverter.java | 4 +- .../system/service/IProcessRouteService.java | 4 +- .../service/impl/BomDetailsServiceImpl.java | 1 - .../impl/ProcessOrderProServiceImpl.java | 11 +- .../service/impl/ProcessRouteServiceImpl.java | 42 +-- 12 files changed, 585 insertions(+), 55 deletions(-) create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/JdVersionDTO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteGetDTO.java diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 771a8d8..a1afa3b 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -29,7 +29,7 @@ server: port: 8033 servlet: # 应用的访问路径 - context-path: /dev-api + context-path: / undertow: # HTTP post内容的最大大小。当值为-1时,默认值为大小是无限的 max-http-post-size: -1 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomDetailsController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomDetailsController.java index 6c9d183..cf7ade0 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomDetailsController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomDetailsController.java @@ -371,7 +371,7 @@ public class BomDetailsController extends BaseController { // 遍历前端传来的数据 for (Map param : bomDetailParams) { String fnumber = param.get("fnumber"); // 物料编码 - String fname = param.get("fname"); // 物料编码 + String groupName = param.get("groupName"); // 物料编码 totalWeight = param.get("totalWeight"); // 生产令号 // 根据物料编码和生产令号查询 @@ -427,7 +427,7 @@ public class BomDetailsController extends BaseController { if (needUpload) { try { // 物料清单保存方法,判断是电气还是生产 - BOMUploadResult bomUploadResult = FBloadBillOfMaterialsPreservation(bomDetails, bo); + BOMUploadResult bomUploadResult = FBloadBillOfMaterialsPreservation(bomDetails, bo,groupName); if (bomUploadResult.isSuccess()) { KindegeeLogDTO logDTO = new KindegeeLogDTO(); logDTO.setProjectCode(bo.getProductionOrderNo()); @@ -716,7 +716,7 @@ public class BomDetailsController extends BaseController { } // FBOM物料清单保存 - public BOMUploadResult FBloadBillOfMaterialsPreservation(List bomlist, ProcessOrderPro bo) { + public BOMUploadResult FBloadBillOfMaterialsPreservation(List bomlist, ProcessOrderPro bo,String groupName) { BomDetails bomDetails1 = bomlist.get(0); int verification = isMaterialVerification(bomDetails1.getFNumber(), bomDetails1.getFName()); @@ -733,7 +733,6 @@ public class BomDetailsController extends BaseController { } // TODO: 实现加载和保存物料清单数据的逻辑 - K3CloudApi client = new K3CloudApi(); // 创建一个空的JsonObject JsonObject json = new JsonObject(); @@ -750,7 +749,8 @@ public class BomDetailsController extends BaseController { JsonObject fGroupType = new JsonObject(); model.add("FGroup", fGroupType); - fGroupType.addProperty("FNumber", "TT001"); + //分组 + fGroupType.addProperty("FNumber", groupName); // 创建FMATERIALID对象,并加入Model JsonObject fMaterialId = new JsonObject(); model.add("FMATERIALID", fMaterialId); @@ -834,7 +834,6 @@ public class BomDetailsController extends BaseController { } fTreeEntityList.add(fTreeEntityItem); } - String jsonData = json.toString(); try { String resultJson = new K3CloudApi().save("ENG_BOM", json.toString()); // 直接用 Jackson 解析 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java index ef10bdc..7205dad 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java @@ -22,6 +22,7 @@ import com.ruoyi.system.domain.dto.ProcessRoutePushResultDTO; import com.ruoyi.system.domain.vo.*; import com.ruoyi.system.domain.vo.BomDataVO; import com.ruoyi.system.mapper.ProcessOrderProMapper; +import com.ruoyi.system.runner.JdUtil; import com.ruoyi.system.service.*; import com.ruoyi.system.service.impl.ProductionOrderServiceImpl; import lombok.RequiredArgsConstructor; @@ -551,17 +552,13 @@ public class ProcessOrderProController extends BaseController { //获取工艺数据信息 List excelDTOList = iProcessOrderProService.getRouteAndBomDetail(routeList,processDataList,orderPro); - excelDTOList.sort(Comparator.comparing( - ProcessRouteExcelDTO::getMaterial, - Comparator.nullsLast((m1, m2) -> { + excelDTOList.sort(Comparator.comparing(ProcessRouteExcelDTO::getMaterial, Comparator.nullsLast((m1, m2) -> { // 总装部件优先 boolean isTotal1 = "总装部件".equals(m1); boolean isTotal2 = "总装部件".equals(m2); - if (isTotal1 && !isTotal2) return -1; if (!isTotal1 && isTotal2) return 1; if (isTotal1 && isTotal2) return 0; - // 其他材质按字母顺序排序 if (m1 == null && m2 == null) return 0; if (m1 == null) return 1; @@ -1131,4 +1128,309 @@ public class ProcessOrderProController extends BaseController { } return mapList; } + + + + @SaCheckPermission("system:route:exportRoute") + @Log(title = "下载工艺生产表", businessType = BusinessType.EXPORT) + @PostMapping("/exportRoute2") + public void exportRoute2(@RequestParam("id") Long id, HttpServletResponse response) { + try { + ProcessOrderPro orderPro = processOrderProMapper.selectById(id); + + // 下载Excel文件 + SmbUtil.downloadExcelFiles(orderPro.getProductionOrderNo()); + + // 构建文件路径 + String excelName = "D:\\file\\" + orderPro.getProductionOrderNo() + "汇总表.xlsx"; + String rawDataFile = "D:\\file\\RawDataTable.xlsx"; + + File file = new File(excelName); + if (!file.exists()) { + throw new ServiceException("项目 " + orderPro.getProductionOrderNo() + " 未出图"); + } + + // 1. 读取第一个sheet的数据list - 使用POI直接读取以保留空格 + List allDataList = readExcelWithPOI(excelName); + List routeList = readExcelPOIRoute(excelName); + //获取此项目的物料最新BOM 并且 将工艺路线拉取出来 + ArrayList routes = new ArrayList<>(); + for (ProcessRoute processRoute : routeList) { + //TODO 获取最新的BOM版本的型号 + String bomVersion = JdUtil.readGetTheLatestVersion(processRoute.getMaterialCode()); + //TODO 获取此物料的所有工艺路线 + + } + // 2. 读取原始表数据 + List rawDataList = readRawDataTable(rawDataFile); + + // 3. 数据分类处理 + List vmiList = new ArrayList<>(); // 009开头 + List elecOutList = new ArrayList<>(); // 两个空格和017开头 + List supplierList = new ArrayList<>(); // 甲供件 + List evoProductsList = new ArrayList<>(); // 伊特 + List processDataList = new ArrayList<>(); // 工艺数据(剩余数据) + + // 分类逻辑 + for (ProductionOrderVo item : allDataList) { + String materialCode = item.getDrawingNo(); + String remark = item.getRemark(); // 使用备注字段 + + // 009开头的加入VMI表 + if (materialCode != null) { + String drawingNo = item.getDrawingNo(); + String drawingName = item.getDrawingName(); + if (drawingName != null) { + ImMaterial material = imMaterialService.selectByCodeAndName(drawingNo, drawingName); + if (material != null) { + //判断是否是VMI物料 + if ("true".equals(material.getClassificationName())) { + // 检查是否已存在相同的DrawingNo + boolean found = false; + for (VMIDataVO existingVmi : vmiList) { + if (drawingNo.equals(existingVmi.getDrawingNo())) { + // 将数量和批次数量相加 + Integer currentQuantity = existingVmi.getQuantity() != null ? existingVmi.getQuantity() : 0; + Integer itemQuantity = item.getQuantity() != null ? item.getQuantity().intValue() : 0; + existingVmi.setQuantity(currentQuantity + itemQuantity); + + Integer currentBatchQuantity = existingVmi.getBatchQuantity() != null ? existingVmi.getBatchQuantity() : 0; + Integer itemBatchQuantity = item.getBatchQuantity() != null ? Integer.parseInt(item.getBatchQuantity()) : 0; + existingVmi.setBatchQuantity(currentBatchQuantity + itemBatchQuantity); + found = true; + break; + } + } + + // 如果没有找到相同的DrawingNo,则添加新的VMI数据 + if (!found) { + VMIDataVO vmiData = convertToVMIDataVO(item); + vmiList.add(vmiData); + } + continue; // 已分类,跳过后续检查 + } + } + } + + // 电气外包分类条件:物料编码开头空格/特定前缀 或 备注包含"外购" + if (materialCode.startsWith(" ") + || materialCode.startsWith("009301") || materialCode.startsWith("009999") + || materialCode.startsWith("017003") || materialCode.startsWith("017002") + || materialCode.startsWith("009001") || materialCode.startsWith("009081") + || (remark != null && remark.contains("外购"))) { + // 过滤安全库存:如果属于安全库存,则进入工艺数据列表 + Boolean isSafeStock = iSafetyStockService.isSafeCode(materialCode.trim()); + if (isSafeStock) { + // 属于安全库存,添加到工艺数据列表 + processDataList.add(item); + continue; // 已分类,跳过后续检查 + } else { + // 不属于安全库存,检查是否已存在相同的DrawingNo + boolean found = false; + for (ElecOutDataVO existingElec : elecOutList) { + if (item.getDrawingNo() != null && item.getDrawingNo().equals(existingElec.getDrawingNo())) { + // 将数量和批次数量相加 + Double currentQuantity = existingElec.getQuantity() != null ? existingElec.getQuantity() : 0.0; + Double itemQuantity = item.getQuantity() != null ? item.getQuantity() : 0.0; + Double newQuantity = currentQuantity + itemQuantity; + existingElec.setQuantity(newQuantity); + + // 批次数量相加(String类型) + String currentBatchQuantity = existingElec.getBatchQuantity() != null ? (existingElec.getBatchQuantity()).toString() : "0"; + String itemBatchQuantity = item.getBatchQuantity() != null ? item.getBatchQuantity() : "0"; + try { + Integer currentBatch = Integer.valueOf(currentBatchQuantity); + Integer itemBatch = Integer.valueOf(itemBatchQuantity); + String newBatchQuantity = String.valueOf(currentBatch + itemBatch); + existingElec.setBatchQuantity(Integer.valueOf(newBatchQuantity)); + } catch (NumberFormatException e) { + // 如果转换失败,保持原值 + existingElec.setBatchQuantity(Integer.valueOf(currentBatchQuantity)); + } + found = true; + break; + } + } + + // 如果没有找到相同的DrawingNo,则添加新的电气外包数据 + if (!found) { + ElecOutDataVO elecData = convertToElecOutDataVO(item); + elecOutList.add(elecData); + } + continue; // 已分类,跳过后续检查 + } + } + + // 备注是甲供件的 + if (remark != null && remark.contains("甲供件")) { + SupProvidDataVO supplierData = convertToSupProvidDataVO(item); + supplierList.add(supplierData); + continue; // 已分类,跳过后续检查 + } + + // 备注是伊特 + if (remark != null && remark.contains("伊特")) { + EVOProductsDataVO evoData = convertToEVOProductsDataVO(item); + evoProductsList.add(evoData); + continue; // 已分类,跳过后续检查 + } + } + + // 检查是否已存在相同的DrawingNo + boolean found = false; + for (ProductionOrderVo existingProcess : processDataList) { + if (item.getDrawingNo() != null && item.getDrawingNo().equals(existingProcess.getDrawingNo())) { + // 将数量和批次数量相加 + Double currentQuantity = existingProcess.getQuantity() != null ? existingProcess.getQuantity() : 0.0; + Double itemQuantity = item.getQuantity() != null ? item.getQuantity() : 0.0; + Double newQuantity = currentQuantity + itemQuantity; + existingProcess.setQuantity(newQuantity); + + // 批次数量相加(String类型) + String currentBatchQuantity = existingProcess.getBatchQuantity() != null ? existingProcess.getBatchQuantity() : "0"; + String itemBatchQuantity = item.getBatchQuantity() != null ? item.getBatchQuantity() : "0"; + try { + Integer currentBatch = Integer.valueOf(currentBatchQuantity); + Integer itemBatch = Integer.valueOf(itemBatchQuantity); + String newBatchQuantity = String.valueOf(currentBatch + itemBatch); + existingProcess.setBatchQuantity(newBatchQuantity); + } catch (NumberFormatException e) { + // 如果转换失败,保持原值 + existingProcess.setBatchQuantity(currentBatchQuantity); + } + found = true; + break; + } + } + + // 如果没有找到相同的DrawingNo,则添加新的工艺数据 + if (!found) { + processDataList.add(item); + } + + } + + // 使用Excel模板文件 + String templatePath = "D:/java/excel-template/生产及工艺计划模版.xlsx"; + String outputPath = "D:/file/" + orderPro.getProductionOrderNo() + "生产及工艺计划表.xlsx"; + + // 准备模板数据 + Map staticDataMap = new HashMap<>(); + staticDataMap.put("productionOrderNo", orderPro.getProductionOrderNo()); + staticDataMap.put("productionName", orderPro.getProductionName()); + + //获取工艺数据信息 + /* List excelDTOList = iProcessOrderProService.getRouteAndBomDetail(routeList,processDataList,orderPro); + excelDTOList.sort(Comparator.comparing(ProcessRouteExcelDTO::getMaterial, Comparator.nullsLast((m1, m2) -> { + // 总装部件优先 + boolean isTotal1 = "总装部件".equals(m1); + boolean isTotal2 = "总装部件".equals(m2); + if (isTotal1 && !isTotal2) return -1; + if (!isTotal1 && isTotal2) return 1; + if (isTotal1 && isTotal2) return 0; + // 其他材质按字母顺序排序 + if (m1 == null && m2 == null) return 0; + if (m1 == null) return 1; + if (m2 == null) return -1; + return m1.compareTo(m2); + }) + ).thenComparing( + ProcessRouteExcelDTO::getMaterialCode, + Comparator.nullsLast(new VersionComparator()) + ));*/ + // 准备动态数据映射 + List dynamicDataMappingList = new ArrayList<>(); + + // 添加生产订单数据 + if (!allDataList.isEmpty()) { + List> productionDataList = convertProductionOrderToMapList(allDataList, orderPro.getProductionOrderNo()); + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProductionOrder", productionDataList)); + } + + // 添加工艺数据(第七个sheet:工艺及生产计划表) + if (!processDataList.isEmpty()) { + List> processDataMapList = convertProductionOrderToMapList(processDataList, orderPro.getProductionOrderNo()); + + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessData", processDataMapList)); + } + + // 添加VMI数据 + if (!vmiList.isEmpty()) { + List> vmiDataList = convertVMIDataToMapList(vmiList); + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("VMIDataVO", vmiDataList)); + } + + // 添加电气外购数据 + if (!elecOutList.isEmpty()) { + List> elecDataList = convertElecOutDataToMapList(elecOutList); + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ElecOutDataVO", elecDataList)); + } + + // 添加BOM数据 + if (!rawDataList.isEmpty()) { + List> bomDataList = convertBomDataToMapList(rawDataList); + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("BomDataVO", bomDataList)); + } + + // 添加甲供件数据 + if (!supplierList.isEmpty()) { + List> supplierDataList = convertSupProvidDataToMapList(supplierList); + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("SupProvidDataVO", supplierDataList)); + } + + // 添加伊特产品数据 + if (!evoProductsList.isEmpty()) { + List> evoDataList = convertEVOProductsDataToMapList(evoProductsList); + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("EVOProductsDataVO", evoDataList)); + } + // 添加伊特产品数据 + /*if (!excelDTOList.isEmpty()) { + List> evoRouteDataList = convertRouteDataToMapList(excelDTOList); + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessRouteExcelDTO", evoRouteDataList)); + }*/ + + // 使用模板导出Excel + ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, outputPath, staticDataMap, dynamicDataMappingList); + + // 设置响应头 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = URLEncoder.encode(orderPro.getProductionOrderNo() + "_分类BOM表", "UTF-8") + .replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + // 将生成的文件写入响应 + File outputFile = new File(outputPath); + if (outputFile.exists()) { + try (FileInputStream fis = new FileInputStream(outputFile); + OutputStream os = response.getOutputStream()) { + byte[] buffer = new byte[8192]; + int length; + while ((length = fis.read(buffer)) > 0) { + os.write(buffer, 0, length); + } + os.flush(); + } + // 删除临时文件 + outputFile.delete(); + } + + } catch (Exception e) { + log.error("导出分类BOM表失败", e); + throw new RuntimeException("导出失败: " + e.getMessage()); + } + } + + + + + + + + + + + + + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessRouteController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessRouteController.java index 3bbef1e..bb0fff5 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessRouteController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessRouteController.java @@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.metadata.WriteSheet; import com.ruoyi.common.annotation.Log; @@ -309,7 +310,7 @@ public class ProcessRouteController extends BaseController { ServletOutputStream os = response.getOutputStream(); // 使用 EasyExcel 写入已有Excel的第七个sheet(index=6) - try (com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(os) + try (ExcelWriter excelWriter = EasyExcel.write(os) .withTemplate(file) // 指定模板文件 .autoCloseStream(true) .build()) { @@ -450,8 +451,8 @@ public class ProcessRouteController extends BaseController { @Log(title = "推送工艺工序") @SaCheckPermission("system:route:pushRouteBom") @PostMapping("/pushRouteBom") - public R pushRouteBom(@RequestParam String rooteProdet) { - return iProcessRouteService.pushRouteBom(rooteProdet); + public R pushRouteBom(@RequestParam String rooteProdet,@RequestParam String groupName) { + return iProcessRouteService.pushRouteBom(rooteProdet,groupName); } /** @@ -557,10 +558,7 @@ public class ProcessRouteController extends BaseController { @Log(title = "获取金蝶列表") @SaCheckPermission("system:route:getProcessRouteList") @GetMapping("/getProcessRouteList") - public ResponseEntity> getProcessRouteList( - @RequestParam(value = "materialCode") String materialCode, - @RequestParam(value = "materialName") String materialName, - @RequestParam(value = "productionOrderNo") String productionOrderNo) { + public ResponseEntity> getProcessRouteList(@RequestParam(value = "materialCode") String materialCode, @RequestParam(value = "materialName") String materialName, @RequestParam(value = "productionOrderNo") String productionOrderNo) { return ResponseEntity.ok(iProcessRouteService.getProcessRouteList(materialCode, materialName, productionOrderNo)); } @@ -856,19 +854,18 @@ public class ProcessRouteController extends BaseController { if (!file.exists()) { throw new ServiceException("文件不存在,请确认路径是否正确"); } - List processRoutes = new ArrayList<>(); //读取file的所有的物料编码 try { if (file.exists()) { // 读取Excel的sheet6 从第三行开始 读取到第4列 无数据的跳过 - DefaultExcelListener listener = new DefaultExcelListener<>(true); - EasyExcel.read(ExcelName, ProcessRouteVo.class, listener) + DefaultExcelListener listener = new DefaultExcelListener<>(true); + EasyExcel.read(ExcelName, ProcessRouteGetDTO.class, listener) .sheet(6) .headRowNumber(3) .doRead(); - List list = listener.getExcelResult().getList(); - List list1 = iProcessRouteService.getProcessRouteGD(list); + List list = listener.getExcelResult().getList(); + List list1 = iProcessRouteService.getProcessRouteGD(list,rooteProdet); List bomDetailsList = new ArrayList<>(); List routeList = new ArrayList<>(); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/JdVersionDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/JdVersionDTO.java new file mode 100644 index 0000000..d866682 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/JdVersionDTO.java @@ -0,0 +1,5 @@ +package com.ruoyi.system.domain.dto; + +public class JdVersionDTO { + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteGetDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteGetDTO.java new file mode 100644 index 0000000..48dbb68 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteGetDTO.java @@ -0,0 +1,157 @@ +package com.ruoyi.system.domain.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; +@Data +public class ProcessRouteGetDTO { + + private String routeDescription; + + /** + * 物料编码 + */ + + @ExcelProperty(value = "物料编码") + private String materialCode; + + /** + * 物料名称 + */ + @ExcelProperty(value = "名称") + private String materialName; + /** + * 材质 + */ + + @ExcelProperty(value = "材质") + private String material; + + /** + * 单重KG + */ + @ExcelProperty(value="单重KG",index=3) + private Double discWeight; + /** + * 材料BOM物料编码 + */ + @ExcelProperty(value="物料编码",index=4) + private String rawMaterialCode; + + + + /** + * 材料BOM物料名称 + */ + @ExcelProperty(value="物料名称") + private String rawMaterialName; + /** + * bom材质 + */ + @ExcelProperty(value="材质") + private String bomMaterial; + /** + * 材料BOM单位 + */ + @ExcelProperty(value="材料单重KG") + private Double bomDanZhong; + + /** + * 材料BOM用量 + */ + @ExcelProperty(value="用量") + private String discUsage; + /** + * 材料BOM单位 + */ + @ExcelProperty(value="单位") + private String bomUnit; + + /** + * 工序号 + */ + @ExcelProperty(value="工序号") + private Long processNo; + + /** + * 工作中心(加工车间) + */ + @ExcelProperty(value="工作中心(加工车间)") + private String workCenter; + + /** + * 工序名称 + */ + @ExcelProperty(value="工序名称") + private String processName; + + /** + * 工序说明(序描述) + */ + @ExcelProperty(value="工序说明(序描述)") + private String processDescription; + + /** + * 工序控制 + */ + @ExcelProperty(value="工序控制") + private String processControl; + + /** + * 活动时长 + */ + @ExcelProperty(value="活动时长") + private Double activityDuration; + + /** + * 活动单位 + */ + @ExcelProperty(value="活动单位") + private String activityUnit; + + /** + * 单台数量 + */ + @ExcelProperty(value="单台数量") + private Long unitQuantity; + + /** + * 本批数量 + */ + + @ExcelProperty(value="本批数量") + private Long batchQuantity; + + /** + * 首批数量 + */ + @ExcelProperty(value="首批数量") + private Double firstBatchQuantity; + /** + * 计划开始时间 + */ + @ExcelProperty(value="起始日期") + private Date planStartTime; + + /** + * 计划结束时间 + */ + @ExcelProperty(value="完成日期") + private Date planEndTime; + + /** + * 序开始时间 + */ + private Date xuStartTime; + + /** + * 序结束时间 + */ + @ExcelProperty(value="完成日期") + private Date xuEndTime; + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java index 5f46bee..a292b80 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java @@ -3225,5 +3225,75 @@ public class JdUtil { return best; } + /** + * 获取最新的BOM版本的型号 + * @param materialCode + * @return List + */ + public static String readGetTheLatestVersion(String materialCode) { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "SFC_OperationReport"); + json.addProperty("FieldKeys", "F_HBYT_SCLH,FBillNo,FMoNumber,FWorkShopID.FName,FOperNumber,FOperDescription,FQuaQty,FFinishQty,FStockInQuaAuxQty,FStockInFailAuxQty,F_HBYT_RKD,FDate"); + // 是否为入库点 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + filterObject.addProperty("FieldName", "F_HBYT_RKD"); + filterObject.addProperty("Compare", "74"); + filterObject.addProperty("Value", true); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 0); + filterString.add(filterObject); + JsonObject filterObject1 = new JsonObject(); + filterObject1.addProperty("FieldName", "FDocumentStatus"); + filterObject1.addProperty("Compare", "105"); + filterObject1.addProperty("Value", "A"); + filterObject1.addProperty("Left", ""); + filterObject1.addProperty("Right", ""); + filterObject1.addProperty("Logic", 1); + filterString.add(filterObject1); + JsonObject filterObject2 = new JsonObject(); + filterObject2.addProperty("FieldName", "FDocumentStatus"); + filterObject2.addProperty("Compare", "105"); + filterObject2.addProperty("Value", "B"); + filterObject2.addProperty("Left", ""); + filterObject2.addProperty("Right", ""); + filterObject2.addProperty("Logic", 1); + filterString.add(filterObject2); + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 10000); + json.addProperty("SubSystemId", ""); + List processReportDTOList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + }); + processReportDTOList.addAll(pageList); + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + return " "; + } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JsonConverter.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JsonConverter.java index a057ac7..30aebb0 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JsonConverter.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JsonConverter.java @@ -34,7 +34,7 @@ public class JsonConverter { return jsonString; } - public static ProcessModel createProcessModel(ProcessRouteXuDTO processRoute) { + public static ProcessModel createProcessModel(ProcessRouteXuDTO processRoute,String groupName) { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建 Material 对象 Material material = new Material(); @@ -49,7 +49,7 @@ public class JsonConverter { // 创建 RouteGroup 对象 RouteGroup routeGroup = new RouteGroup(); - routeGroup.setFNumber("TEST"); + routeGroup.setFNumber(groupName); // 创建 FEntity 对象并设置 FSubEntity FEntity entity = new FEntity(); entity.setFSeqNumber("0"); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IProcessRouteService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IProcessRouteService.java index 72771db..81df52b 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/IProcessRouteService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IProcessRouteService.java @@ -85,7 +85,7 @@ public interface IProcessRouteService { * 推送工艺路线 */ - R pushRouteBom(String rooteProdet); + R pushRouteBom(String rooteProdet,String groupName); /** * 获取所有的项目令号 */ @@ -139,7 +139,7 @@ public interface IProcessRouteService { List getProcessMaterialListAll(String routeDescription); - List getProcessRouteGD(List list); + List getProcessRouteGD(List list,String rooteProdet); //获取物料首个工序的工作中心 String getRouteCode(String materialCode,String code); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BomDetailsServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BomDetailsServiceImpl.java index 35b12de..332ef8a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BomDetailsServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BomDetailsServiceImpl.java @@ -210,7 +210,6 @@ public class BomDetailsServiceImpl implements IBomDetailsService { // 使用Map缓存MaterialBom,避免双重循环带来的性能问题 if (!materialBoms.isEmpty() && !bomDetails.isEmpty()) { - Map materialBomMap = materialBoms.stream() .collect(Collectors.toMap( mb -> mb.getMaterialCode() + "-" + mb.getMaterialName(), diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessOrderProServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessOrderProServiceImpl.java index 3b769a3..b039210 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessOrderProServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessOrderProServiceImpl.java @@ -1159,16 +1159,13 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService { Function normalize = s -> s == null ? "" : s.trim().toUpperCase(); // 按 materialCode 分组(工艺路线) - Map> routeMap = allRoutes.stream() - .collect(Collectors.groupingBy(r -> normalize.apply(r.getMaterialCode()))); + Map> routeMap = allRoutes.stream().collect(Collectors.groupingBy(r -> normalize.apply(r.getMaterialCode()))); // 按 parentMaterialCode 分组(BOM) - Map> bomMap = allBoms.stream() - .collect(Collectors.groupingBy(b -> normalize.apply(b.getParentMaterialCode()))); + Map> bomMap = allBoms.stream().collect(Collectors.groupingBy(b -> normalize.apply(b.getParentMaterialCode()))); // 把订单数据做成 Map - Map orderMap = processDataList.stream() - .collect(Collectors.toMap(vo -> normalize.apply(vo.getDrawingNo()), vo -> vo, (a, b) -> a)); + Map orderMap = processDataList.stream().collect(Collectors.toMap(vo -> normalize.apply(vo.getDrawingNo()), vo -> vo, (a, b) -> a)); // 合并 material keys LinkedHashSet materialKeys = new LinkedHashSet<>(); @@ -1200,7 +1197,7 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService { : (orderVo != null ? (orderVo.getMaterial() != null ? orderVo.getMaterial().trim() : null) : null); Double originalUnitWeight = !processRoutes.isEmpty() ? processRoutes.get(0).getDiscWeight() : (orderVo != null ? orderVo.getSingleWeight() : null); - // 🔹 新增两个数量字段 + // 新增两个数量字段 Double unitQuantity = !processRoutes.isEmpty() ? processRoutes.get(0).getUnitQuantity() : (orderVo != null ? orderVo.getQuantity() : null); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessRouteServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessRouteServiceImpl.java index e71a4c8..8d38d77 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessRouteServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessRouteServiceImpl.java @@ -240,25 +240,32 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { * @return */ @Override - public List getProcessRouteGD(List list) { + public List getProcessRouteGD(List list,String rooteProdet) { List materialAndRouteList = new ArrayList<>(); - for (ProcessRouteVo processRoute : list) { + for (ProcessRouteGetDTO processRoute : list) { + // 跳过空行或解析为空的记录,避免空指针 + if (processRoute == null) { + continue; + } //获取固定工艺路线和物料清单 - List routeList = JdUtil.getRouteGuDing(processRoute.getRouteDescription()); - List materialUseX = JdUtil.getMaterialUseX(processRoute.getRouteDescription()); + List routeList = JdUtil.getRouteGuDing(rooteProdet); + List materialUseX = JdUtil.getMaterialUseX(rooteProdet); if (materialUseX == null || routeList == null) { continue; } //表格错乱错行了 JDMaterialAndRoute jdMaterialAndRoute = new JDMaterialAndRoute(); - jdMaterialAndRoute.setMaterialCode(processRoute.getRouteDescription()); - jdMaterialAndRoute.setMaterialName(processRoute.getMaterialCode()); - jdMaterialAndRoute.setCaizhi(processRoute.getMaterialName()); - jdMaterialAndRoute.setDanzhong(processRoute.getMaterial()); + jdMaterialAndRoute.setMaterialCode(processRoute.getMaterialCode()); + jdMaterialAndRoute.setMaterialName(processRoute.getMaterialName()); + jdMaterialAndRoute.setCaizhi(processRoute.getMaterial()); + jdMaterialAndRoute.setDanzhong(processRoute.getDiscUsage()); jdMaterialAndRoute.setMaterialUseDTOS(materialUseX); jdMaterialAndRoute.setPlannedProcessVos(routeList); - jdMaterialAndRoute.setBenpi(processRoute.getUnitQuantity()); - jdMaterialAndRoute.setDantai(Long.valueOf(processRoute.getActivityUnit())); + // 避免后续使用时空指针,为空则置为0 + Long batchQuantity = processRoute.getBatchQuantity(); + Long unitQuantity = processRoute.getUnitQuantity(); + jdMaterialAndRoute.setBenpi(batchQuantity != null ? batchQuantity : 0L); + jdMaterialAndRoute.setDantai(unitQuantity != null ? unitQuantity : 0L); materialAndRouteList.add(jdMaterialAndRoute); } @@ -1255,7 +1262,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } @Override - public R pushRouteBom(String rooteProdet) { + public R pushRouteBom(String rooteProdet,String groupName) { List rawBomList = getProcessRoute(rooteProdet); List successfulRoutes = new ArrayList<>(); List failedRoutes = new ArrayList<>(); @@ -1272,7 +1279,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { if (isDifferent) { log.info("工艺路线不同,进行更新: " + processRouteXuDTO.getMaterialCode()); // 保存工艺路线 - LoadBomResult result = loadBillOfMaterialsPreservation(processRouteXuDTO); + LoadBomResult result = loadBillOfMaterialsPreservation(processRouteXuDTO,groupName); // 处理返回结果 if (result.isSuccess()) { log.info("工艺路线保存成功: " + processRouteXuDTO.getMaterialCode() + result.getResultData()); @@ -1322,7 +1329,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { log.info("工艺路线不同,进行更新: " + processRouteXuDTO.getMaterialCode()); // 保存工艺路线 - LoadBomResult result = loadBillOfMaterialsPreservation(processRouteXuDTO); + LoadBomResult result = loadBillOfMaterialsPreservation(processRouteXuDTO,""); // 处理返回结果 if (result.isSuccess()) { log.info("工艺路线保存成功: " + processRouteXuDTO.getMaterialCode() + result.getResultData()); @@ -1616,10 +1623,10 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } // 工艺保存方法 - public LoadBomResult loadBillOfMaterialsPreservation(ProcessRouteXuDTO rawBomList) { + public LoadBomResult loadBillOfMaterialsPreservation(ProcessRouteXuDTO rawBomList,String groupName) { // TODO: 实现加载和保存物料清单数据的逻辑 K3CloudApi client = new K3CloudApi(); - ProcessModel processModel = createProcessModel(rawBomList); + ProcessModel processModel = createProcessModel(rawBomList,groupName); String jsonStr = JSONUtil.toJsonStr(processModel); log.debug("推送工艺报文=====》{}",JSONUtil.toJsonStr(jsonStr)); @@ -2334,10 +2341,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { public List getProcessRouteList(String materialCode, String materialName, String productionOrderNo) { QueryWrapper wrapper = new QueryWrapper<>(); - wrapper.eq("FProductId_FNumber", materialCode) - .eq("f_product_name", materialName) - .eq("F_HBYT_SCLH", productionOrderNo) - .orderByAsc("FMATERIALID_FNumber"); // 按工序号排序 + wrapper.eq("FProductId_FNumber", materialCode).eq("f_product_name", materialName).eq("F_HBYT_SCLH", productionOrderNo).orderByAsc("FMATERIALID_FNumber"); // 按工序号排序 List productionRouteTwos = productionRouteTwoMapper.selectList(wrapper); if (CollectionUtils.isEmpty(productionRouteTwos)) {