From a648158686a27902b6b50b1b41b8a3fb43791564 Mon Sep 17 00:00:00 2001 From: tzy1042411602 <1042411602@qq.com> Date: Fri, 27 Dec 2024 17:28:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E8=89=BA=E6=A8=A1=E5=9D=97,=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3=EF=BC=8C=E7=9B=B8=E5=85=B3=E5=B7=A5?= =?UTF-8?q?=E8=89=BA=E6=A0=A1=E9=AA=8C=EF=BC=8Cbom=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ruoyi/common/utils/JdUtils.java | 2 +- .../controller/BomDetailsController.java | 309 ++++++--- .../controller/ProcessRouteController.java | 104 ++- .../controller/ProductionPlanController.java | 2 +- .../com/ruoyi/system/domain/ImMaterial.java | 2 +- .../com/ruoyi/system/domain/MaterialBom.java | 2 +- .../ruoyi/system/domain/bo/MaterialBomBo.java | 2 +- .../system/domain/bo/ProcessRouteBo.java | 3 + .../domain/dto/ProcessRoutePushResultDTO.java | 12 + .../domain/dto/ProcessRouteSelectDTO.java | 55 ++ .../system/domain/dto/ProcessRouteXuDTO.java | 3 + .../ruoyi/system/domain/vo/MaterialBomVo.java | 2 +- .../system/domain/vo/ProcessRouteVo.java | 1 + .../system/domain/vo/ProductionOrderVo.java | 11 + .../com/ruoyi/system/runner/PDFGenerator.java | 467 ++++++++----- .../system/service/IProcessRouteService.java | 8 +- .../service/impl/BomDetailsServiceImpl.java | 2 +- .../service/impl/ImMaterialServiceImpl.java | 18 +- .../service/impl/MaterialBomServiceImpl.java | 31 +- .../impl/ProcessOrderProServiceImpl.java | 9 +- .../service/impl/ProcessRouteServiceImpl.java | 614 ++++++++++++++---- 21 files changed, 1220 insertions(+), 439 deletions(-) create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRoutePushResultDTO.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteSelectDTO.java diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JdUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JdUtils.java index 51bd750..e2edeaf 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JdUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JdUtils.java @@ -1463,7 +1463,7 @@ public class JdUtils { //请求参数,要求为json字符串 JsonObject json = new JsonObject(); json.addProperty("FormId", "BD_MATERIAL"); - json.addProperty("FieldKeys", "FNumber,FName,FCategoryID.FNumber,F_SVRI_Assistant.FNumber,FErpClsID"); + json.addProperty("FieldKeys", "FNumber,FName,FCategoryID.FNumber,F_SVRI_Assistant.FNumber,FErpClsID,FBaseUnitId.FName"); JsonArray filterString = new JsonArray(); log.debug("构建查询条件..."); json.add("FilterString", filterString); 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 dc3e173..02d9e6c 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 @@ -63,7 +63,7 @@ public class BomDetailsController extends BaseController { private final IBomDetailsService iBomDetailsService; - private final IMaterialPropertiesService iMaterialPropertiesService ; + private final IMaterialPropertiesService iMaterialPropertiesService; private final IProcessRouteService iProcessRouteService; private static final Logger log = LoggerFactory.getLogger(BomDetailsController.class); @@ -87,7 +87,7 @@ public class BomDetailsController extends BaseController { if (parent == null) { parent = new BomDetailsVo(); parent.setId(generateUniqueParentId(bomDetailsVo.getId())); - // parent.setUnitWeight(bomDetailsVo.getUnitWeight()); + // parent.setUnitWeight(bomDetailsVo.getUnitWeight()); parent.setParentCodeAndName(parentCodeAndName); parent.setFNumber(bomDetailsVo.getFNumber()); parent.setFName(bomDetailsVo.getFName()); @@ -213,17 +213,17 @@ public class BomDetailsController extends BaseController { //成品物料 HashMap bomFinishedProduct = getBomFinishedProduct(file); //新增成品父级物流 - if (loadChengPinMaterialPreservation(bomFinishedProduct)==1){ + if (loadChengPinMaterialPreservation(bomFinishedProduct) == 1) { log.info("新增成品父级物流成功"); } - // loadChengPinMaterialPreservation() + // loadChengPinMaterialPreservation() for (BomDetailsVo bomDetailsvo : bomDetailsVos) { BomDetails bomDetails = BeanUtil.toBean(bomDetailsvo, BomDetails.class); // 校验属性、材质、数量是否为空,并记录提示信息 if (bomDetails.getStats() == null || bomDetails.getMaterial() == null || bomDetails.getQuantity() == null) { String warningMessage = String.format("记录 %s 缺少必要字段: 属性=%s, 材质=%s, 数量=%s", - bomDetails.getPartNumber(), bomDetails.getStats(), bomDetails.getMaterial(), bomDetails.getQuantity()); + bomDetails.getPartNumber(), bomDetails.getStats(), bomDetails.getMaterial(), bomDetails.getQuantity()); missingFieldsWarnings.add(warningMessage); } // 验证物料是否存在 @@ -233,7 +233,7 @@ public class BomDetailsController extends BaseController { bomDetails.setUnitWeight("是"); } else { if (bomDetails.getStats() == null || bomDetails.getStats().equals("外购") || bomDetails.getFName().startsWith("009") || bomDetails.getFName().startsWith("AA") - || bomDetails.getFName().startsWith("AB") || bomDetails.getFName().startsWith("AC")|| bomDetails.getFName().startsWith("015")) { + || bomDetails.getFName().startsWith("AB") || bomDetails.getFName().startsWith("AC") || bomDetails.getFName().startsWith("015")) { materialsToAdd.add(bomDetails); } else if (bomDetails.getStats().equals("自制")) { materialsToAdd.add(bomDetails); @@ -266,17 +266,17 @@ public class BomDetailsController extends BaseController { System.out.println("state:=======================>" + state); //判断是否是电器物料 int result; - if (material.getTotalWeight().contains("DQ")){ + if (material.getTotalWeight().contains("DQ")) { log.info("开始新增不存在的电气物料==> 物料图号: " + material.getPartNumber() + " 物料名称: " + material.getName()); - result = loadMaterialToDQ(material, state); - }else{ + result = loadMaterialToDQ(material, state); + } else { log.info("开始新增不存在的物料==> 物料图号: " + material.getPartNumber() + " 物料名称: " + material.getName()); - result = loadMaterialPreservation(material, state); + result = loadMaterialPreservation(material, state); } if (result == 1) { log.info("新增物料成功==> 物料图号: " + material.getPartNumber() + " 物料名称: " + material.getName()); material.setUnitWeight("新增成功"); - bomDetails.add(material); + bomDetails.add(material); } else { log.error("新增物料失败==> 物料图号: " + material.getPartNumber() + " 物料名称: " + material.getName()); material.setUnitWeight("新增成功"); @@ -284,7 +284,7 @@ public class BomDetailsController extends BaseController { } BomDetailsBo bean = BeanUtil.toBean(bomDetails, BomDetailsBo.class); iBomDetailsService.updateByBo(bean); - } + } // 保存当前记录 return R.ok("导入成功"); @@ -293,7 +293,7 @@ public class BomDetailsController extends BaseController { /** * @param file */ - private HashMap getBomFinishedProduct(MultipartFile file ) throws IOException { + private HashMap getBomFinishedProduct(MultipartFile file) throws IOException { Sheet sheetAt = WorkbookFactory.create(file.getInputStream()).getSheetAt(0); Row firstRow = sheetAt.getRow(1); HashMap chenpin = new HashMap<>(); @@ -303,19 +303,21 @@ public class BomDetailsController extends BaseController { Cell cell1 = firstRow.getCell(2); log.info("获取到第一行第二列的值为:" + cell1.toString()); - chenpin.put("fnumber",cell.toString()); - chenpin.put("fname",cell1.toString()); + chenpin.put("fnumber", cell.toString()); + chenpin.put("fname", cell1.toString()); // 获取单元格的值,假设它是字符串类型 - return chenpin; + return chenpin; } + /** * 获取属性 替换成金蝶属性编码 + * * @param stats * @return */ public static String determineState(BomDetails stats) { - if (stats == null || stats.getStats().equals("外购") || stats.getFName().startsWith("009")|| - stats.getFName().startsWith("AA")|| stats.getFName().startsWith("AB")|| stats.getFName().startsWith("AC")) { + if (stats == null || stats.getStats().equals("外购") || stats.getFName().startsWith("009") || + stats.getFName().startsWith("AA") || stats.getFName().startsWith("AB") || stats.getFName().startsWith("AC")) { return "1"; } else if (stats.getStats().equals("自制")) { return "2"; @@ -343,15 +345,15 @@ public class BomDetailsController extends BaseController { if (bomDetails != null && !bomDetails.isEmpty()) { //物料清单保存方法 int i1 = loadBillOfMaterialsPreservation(bomDetails); - if (i1==1){ + if (i1 == 1) { return R.ok("bom上传成功"); - }else if (i1==0){ + } else if (i1 == 0) { return R.fail("bom上传失败"); } bomDetailsList.addAll(bomDetails); } } - return R.ok("bom上传成功",bomDetailsList); + return R.ok("bom上传成功", bomDetailsList); } @@ -373,14 +375,131 @@ public class BomDetailsController extends BaseController { System.out.println("处理物料编码:" + fnumber + ", 生产令号:" + totalWeight); if (bomDetails != null && !bomDetails.isEmpty()) { + // 检查金蝶中是否存在该物料的BOM + //JsonArray existingBom = checkBomExists(fnumber); // 物料清单保存方法 FBloadBillOfMaterialsPreservation(bomDetails); bomDetailsList.addAll(bomDetails); } } + return R.ok("成功", bomDetailsList); + } + + +/* + @PostMapping("/updateFBMaterial") + public R updateFBMaterial1(@RequestBody List> bomDetailParams) { + List bomDetailsList = new ArrayList<>(); + + // 遍历前端传来的数据 + for (Map param : bomDetailParams) { + String fnumber = param.get("fnumber"); // 物料编码 + String totalWeight = param.get("totalWeight"); // 生产令号 + + // 根据物料编码和生产令号查询 + List bomDetails = iBomDetailsService.selectByFNumberAndTotalWeight(fnumber, totalWeight); + + System.out.println("处理物料编码:" + fnumber + ", 生产令号:" + totalWeight); + + if (bomDetails != null && !bomDetails.isEmpty()) { + // 检查金蝶中是否存在该物料的BOM + JsonArray existingBom = checkBomExists(fnumber); + + if (existingBom != null && !existingBom.isEmpty()) { + // BOM已存在,需要比对用量和子项 + if (compareBomDetails(existingBom, bomDetails)) { + // BOM一致,跳过 + log.info("物料{}的BOM已存在且一致,无需更新", fnumber); + continue; + } else { + // BOM不一致,需要更新 + log.info("物料{}的BOM已存在但不一致,准备更新", fnumber); + deleteBom(fnumber); // 删除已有BOM + } + } + + // 新增BOM + FBloadBillOfMaterialsPreservation(bomDetails); + bomDetailsList.addAll(bomDetails); + } + } return R.ok("成功",bomDetailsList); } + private boolean compareBomDetails(JsonArray existingBom, List bomDetails) { + try { + // 获取现有BOM的子项和用量 + Map existingItems = new HashMap<>(); + for (JsonElement element : existingBom) { + JsonObject item = element.getAsJsonObject(); + JsonArray treeEntity = item.getAsJsonArray("FTreeEntity"); + for (JsonElement treeItem : treeEntity) { + String materialNo = treeItem.getAsJsonObject() + .get("FMATERIALIDCHILD") + .getAsJsonObject() + .get("FNumber") + .getAsString(); + double usage = treeItem.getAsJsonObject() + .get("FNUMERATOR") + .getAsDouble(); + existingItems.put(materialNo, usage); + } + } + + // 比对新BOM + for (BomDetails detail : newBom) { + Double existingUsage = existingItems.get(detail.getPartNumber()); + if (existingUsage == null || + Math.abs(existingUsage - detail.getQuantity()) > 0.000001) { + return false; + } + existingItems.remove(detail.getPartNumber()); + } + + // 检查是否有多余的子项 + return existingItems.isEmpty(); + + } catch (Exception e) { + log.error("比对BOM失败:", e); + return false; + } + } + + */ + + /** + * 检查金蝶中是否存在该物料的BOM + *//* + + + private JsonArray checkBomExists(String fnumber) { + try { + K3CloudApi client = new K3CloudApi(); + String formId = "ENG_BOM"; + + JsonObject queryParam = new JsonObject(); + queryParam.addProperty("FormId", formId); + queryParam.addProperty("FieldKeys", "FID,FMATERIALID.FNumber,FTreeEntity.FMATERIALIDCHILD.FNumber,FTreeEntity.FNUMERATOR"); + + JsonArray filterArray = new JsonArray(); + JsonObject filter = new JsonObject(); + filter.addProperty("Field", "FMATERIALID.FNumber"); + filter.addProperty("Value", fnumber); + filterArray.add(filter); + queryParam.add("FilterString", filterArray); + + String resultJson = client.executeBillQuery(queryParam.toString()); + Gson gson = new Gson(); + JsonArray result = gson.fromJson(resultJson, JsonArray.class); + + return result; + } catch (Exception e) { + log.error("查询BOM失败:", e); + return null; + } + } + +*/ /*s 物料清单保存方法 @@ -395,10 +514,10 @@ public class BomDetailsController extends BaseController { String fName = bomDetails.getFName(); String fNumber = bomDetails.getFNumber(); // 验证物料是否存在 - if ( isMaterialVerification(fNumber,fName)==0){ + if (isMaterialVerification(fNumber, fName) == 0) { log.debug("物料不存在"); //增加父级物料图号 - if (loadMaterialPreservation(bomDetails)==1){ + if (loadMaterialPreservation(bomDetails) == 1) { log.debug("物料增加成功"); } @@ -488,32 +607,32 @@ public class BomDetailsController extends BaseController { RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class); if (repoRet.getResult().getResponseStatus().isIsSuccess()) { log.debug("物料清单bom 保存成功===================>" + "图号:" + bomDetails.getFNumber()); - return 1; + return 1; } else { log.error("接口返回结果: " + gson.toJson(repoRet.getResult().getResponseStatus())); log.error("物料清单bom 保存失败===================>" + "图号:" + bomDetails.getFNumber()); - return 0 ; + return 0; } } catch (Exception e) { R.fail(e.getMessage()); } // 输出生成的Json - return 1; + return 1; } //FBOM物料清单保存 - public void FBloadBillOfMaterialsPreservation(List bomlist) { + public void FBloadBillOfMaterialsPreservation(List bomlist) { BomDetails bomDetails1 = bomlist.get(0); int verification = isMaterialVerification(bomDetails1.getFNumber(), bomDetails1.getFName()); // 验证父级物料是否存在 - if (verification==0){ + if (verification == 0) { log.debug("父级物料物料不存在"); //父级物料不存在,即调用物料新增接口 int materialVerificationResult = loadFBMaterialPreservation(bomDetails1); - if (materialVerificationResult ==1){ + if (materialVerificationResult == 1) { log.debug("父级物料保存成功"); - }else { + } else { log.error("父级物料保存失败"); } } @@ -572,16 +691,22 @@ public class BomDetailsController extends BaseController { // 添加FTreeEntity字段 fTreeEntityItem.addProperty("FReplaceGroup", 1); - if (details.getPartNumber() != null){ - if (iProcessRouteService.isAnTuDingGou(details.getPartNumber())) { - fTreeEntityItem.addProperty("FSupplyType", "C"); - } else if (details.getRemarks().equals("伊特")) { - - fTreeEntityItem.addProperty("FSupplyType", "C"); - - } else{ - fTreeEntityItem.addProperty("FSupplyType", " "); + if (details != null) { + String partNumber = details.getPartNumber(); + String remarks = details.getRemarks(); + // 先设置默认值 + String supplyType = " "; + if (partNumber != null) { + // 检查是否为安徒定购 + if (iProcessRouteService.isAnTuDingGou(partNumber)) { + supplyType = "C"; + } + // 检查是否为伊特 + else if ("伊特".equals(remarks)) { + supplyType = "C"; + } } + fTreeEntityItem.addProperty("FSupplyType", supplyType); } fTreeEntityItem.addProperty("FMATERIALTYPE", "1"); @@ -653,10 +778,10 @@ public class BomDetailsController extends BaseController { model.addProperty("FNumber", bomDetails.getFNumber()); model.addProperty("FName", bomDetails.getFName()); json.add("Model", model); - MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(bomDetails.getMaterial()); + MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(bomDetails.getMaterial()); JsonObject FSVRIAssistant = new JsonObject(); FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId()); - model.add("F_SVRI_Assistant",FSVRIAssistant); + model.add("F_SVRI_Assistant", FSVRIAssistant); // 创建FMaterialGroup对象,并加入Model JsonObject fMaterialGroup = new JsonObject(); @@ -744,16 +869,16 @@ public class BomDetailsController extends BaseController { JsonObject subHeadEntity6 = new JsonObject(); model.add("SubHeadEntity6", subHeadEntity6); //不同的属性不同的检验方案 - if (bomDetails.getStats().equals("1")){ + if (bomDetails.getStats().equals("1")) { //外购 subHeadEntity6.addProperty("FCheckIncoming", true); } - if (bomDetails.getStats().equals("2")){ + if (bomDetails.getStats().equals("2")) { //自制 subHeadEntity6.addProperty("FCheckProduct", true); subHeadEntity6.addProperty("FCheckReturnMtrl", true); } - if (bomDetails.getStats().equals("3")){ + if (bomDetails.getStats().equals("3")) { //委外 subHeadEntity6.addProperty("FCheckIncoming", true); subHeadEntity6.addProperty("FCheckProduct", true); @@ -818,7 +943,7 @@ public class BomDetailsController extends BaseController { } /*FB父级物料保存接口 - * */ + * */ public static int loadFBMaterialPreservation(BomDetails bomDetail) { K3CloudApi client = new K3CloudApi(); // 创建一个空的JsonObject @@ -927,16 +1052,16 @@ public class BomDetailsController extends BaseController { JsonObject subHeadEntity6 = new JsonObject(); model.add("SubHeadEntity6", subHeadEntity6); //不同的属性不同的检验方案 - if (bomDetail.getStats().equals("1")){ + if (bomDetail.getStats().equals("1")) { //外购 subHeadEntity6.addProperty("FCheckIncoming", true); } - if (bomDetail.getStats().equals("2")){ + if (bomDetail.getStats().equals("2")) { //自制 subHeadEntity6.addProperty("FCheckProduct", true); subHeadEntity6.addProperty("FCheckReturnMtrl", true); } - if (bomDetail.getStats().equals("3")){ + if (bomDetail.getStats().equals("3")) { //委外 subHeadEntity6.addProperty("FCheckIncoming", true); subHeadEntity6.addProperty("FCheckProduct", true); @@ -998,10 +1123,11 @@ public class BomDetailsController extends BaseController { } } + /*FB父级物料保存接口 单位 是台 * */ - public int loadChengPinMaterialPreservation(HashMap bomDetail) { + public int loadChengPinMaterialPreservation(HashMap bomDetail) { K3CloudApi client = new K3CloudApi(); // 创建一个空的JsonObject JsonObject json = new JsonObject(); @@ -1050,7 +1176,7 @@ public class BomDetailsController extends BaseController { subHeadEntity.addProperty("FIsPurchase", true); subHeadEntity.addProperty("FIsInventory", true); //成品不允许委外 - // subHeadEntity.addProperty("FIsSubContract", true); + // subHeadEntity.addProperty("FIsSubContract", true); subHeadEntity.addProperty("FIsSale", true); subHeadEntity.addProperty("FIsProduce", true); @@ -1065,8 +1191,8 @@ public class BomDetailsController extends BaseController { // 创建FStockId对象,并加入SubHeadEntity1 JsonObject fStockId = new JsonObject(); //判断是产成品还是企标 - String cangKu = "CK011"; - fStockId.addProperty("FNumber", cangKu); + String cangKu = "CK011"; + fStockId.addProperty("FNumber", cangKu); subHeadEntity1.add("FStockId", fStockId); // 创建FCurrencyId对象,并加入SubHeadEntity1 @@ -1104,8 +1230,8 @@ public class BomDetailsController extends BaseController { // 创建SubHeadEntity6对象,并加入Model 检验项 JsonObject subHeadEntity6 = new JsonObject(); model.add("SubHeadEntity6", subHeadEntity6); - subHeadEntity6.addProperty("FCheckProduct", true); - subHeadEntity6.addProperty("FCheckReturn", true); + subHeadEntity6.addProperty("FCheckProduct", true); + subHeadEntity6.addProperty("FCheckReturn", true); // 创建SubHeadEntity5对象,并加入Model JsonObject subHeadEntity5 = new JsonObject(); @@ -1163,9 +1289,11 @@ public class BomDetailsController extends BaseController { } } + /** * 物料验证 * 验证物料在金蝶中是否存在 + * * @return */ public static int isMaterialVerification(String DrawingNumber, String name) { @@ -1231,15 +1359,15 @@ public class BomDetailsController extends BaseController { model.addProperty("FNumber", bomDetails1.getPartNumber()); model.addProperty("FName", bomDetails1.getName()); MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(bomDetails1.getMaterial()); - if (materialProperties!=null){ + if (materialProperties != null) { JsonObject FSVRIAssistant = new JsonObject(); FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId()); - model.add("F_SVRI_Assistant",FSVRIAssistant); - }else { + model.add("F_SVRI_Assistant", FSVRIAssistant); + } else { //没写材料为默认为空 JsonObject FSVRIAssistant = new JsonObject(); FSVRIAssistant.addProperty("FNumber", "17"); - model.add("F_SVRI_Assistant",FSVRIAssistant); + model.add("F_SVRI_Assistant", FSVRIAssistant); } // 创建FMaterialGroup对象,并加入Model JsonObject fMaterialGroup = new JsonObject(); @@ -1257,9 +1385,9 @@ public class BomDetailsController extends BaseController { // 创建FCategoryID对象,并加入SubHeadEntity JsonObject fCategoryID = new JsonObject(); - if (states.equals("2") || states.equals("3")){ + if (states.equals("2") || states.equals("3")) { fCategoryID.addProperty("FNumber", "007"); - }else{ + } else { fCategoryID.addProperty("FNumber", "006"); } @@ -1274,11 +1402,11 @@ public class BomDetailsController extends BaseController { JsonObject fBaseUnitId = new JsonObject(); fBaseUnitId.addProperty("FNumber", "jian"); subHeadEntity.add("FBaseUnitId", fBaseUnitId); - if (states.equals("1")){ + if (states.equals("1")) { subHeadEntity.addProperty("FIsPurchase", true); subHeadEntity.addProperty("FIsSale", true); subHeadEntity.addProperty("FIsInventory", true); - }else{ + } else { subHeadEntity.addProperty("FIsPurchase", true); subHeadEntity.addProperty("FIsInventory", true); subHeadEntity.addProperty("FIsSubContract", true); @@ -1330,16 +1458,16 @@ public class BomDetailsController extends BaseController { JsonObject subHeadEntity6 = new JsonObject(); model.add("SubHeadEntity6", subHeadEntity6); //不同的属性不同的检验方案 - if (states.equals("1")){ + if (states.equals("1")) { //外购 subHeadEntity6.addProperty("FCheckIncoming", true); } - if (states.equals("2")){ + if (states.equals("2")) { //自制 subHeadEntity6.addProperty("FCheckProduct", true); subHeadEntity6.addProperty("FCheckReturnMtrl", true); } - if (states.equals("3")){ + if (states.equals("3")) { //委外 subHeadEntity6.addProperty("FCheckIncoming", true); subHeadEntity6.addProperty("FCheckProduct", true); @@ -1347,7 +1475,6 @@ public class BomDetailsController extends BaseController { } - // 创建SubHeadEntity5对象,并加入Model JsonObject subHeadEntity5 = new JsonObject(); model.add("SubHeadEntity5", subHeadEntity5); @@ -1367,9 +1494,9 @@ public class BomDetailsController extends BaseController { JsonObject fBOMUnitId = new JsonObject(); fBOMUnitId.addProperty("FNumber", "jian"); subHeadEntity5.add("FBOMUnitId", fBOMUnitId); - if (states.equals("1")){ + if (states.equals("1")) { subHeadEntity5.addProperty("FIsMainPrd", false); - }else { + } else { subHeadEntity5.addProperty("FIsMainPrd", true); } subHeadEntity5.addProperty("FIssueType", "1"); @@ -1407,6 +1534,7 @@ public class BomDetailsController extends BaseController { } return 1; } + //创建电气物料 public int loadMaterialToDQ(BomDetails bomDetails1, String states) { K3CloudApi client = new K3CloudApi(); @@ -1425,15 +1553,15 @@ public class BomDetailsController extends BaseController { model.addProperty("FNumber", bomDetails1.getPartNumber()); model.addProperty("FName", bomDetails1.getName()); MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(bomDetails1.getMaterial()); - if (materialProperties!=null){ + if (materialProperties != null) { JsonObject FSVRIAssistant = new JsonObject(); FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId()); - model.add("F_SVRI_Assistant",FSVRIAssistant); - }else { + model.add("F_SVRI_Assistant", FSVRIAssistant); + } else { //没写材料为默认为空 JsonObject FSVRIAssistant = new JsonObject(); FSVRIAssistant.addProperty("FNumber", "17"); - model.add("F_SVRI_Assistant",FSVRIAssistant); + model.add("F_SVRI_Assistant", FSVRIAssistant); } // 创建FMaterialGroup对象,并加入Model JsonObject fMaterialGroup = new JsonObject(); @@ -1451,9 +1579,9 @@ public class BomDetailsController extends BaseController { // 创建FCategoryID对象,并加入SubHeadEntity JsonObject fCategoryID = new JsonObject(); - if (states.equals("2") || states.equals("3")){ + if (states.equals("2") || states.equals("3")) { fCategoryID.addProperty("FNumber", "007"); - }else{ + } else { fCategoryID.addProperty("FNumber", "006"); } @@ -1479,7 +1607,7 @@ public class BomDetailsController extends BaseController { case "根": fBaseUnitId.addProperty("FNumber", "003"); break; - case "米": + case "米": fBaseUnitId.addProperty("FNumber", "005"); break; case "卷": @@ -1500,16 +1628,16 @@ public class BomDetailsController extends BaseController { case "条": fBaseUnitId.addProperty("FNumber", "017"); break; - case "套": + case "套": fBaseUnitId.addProperty("FNumber", "007"); break; } subHeadEntity.add("FBaseUnitId", fBaseUnitId); - if (states.equals("1")){ + if (states.equals("1")) { subHeadEntity.addProperty("FIsPurchase", true); subHeadEntity.addProperty("FIsSale", true); subHeadEntity.addProperty("FIsInventory", true); - }else{ + } else { subHeadEntity.addProperty("FIsPurchase", true); subHeadEntity.addProperty("FIsInventory", true); subHeadEntity.addProperty("FIsSubContract", true); @@ -1534,7 +1662,8 @@ public class BomDetailsController extends BaseController { break; case "根": fBaseUnitId.addProperty("FNumber", "003"); - break; case "米": + break; + case "米": fBaseUnitId.addProperty("FNumber", "005"); break; case "卷": @@ -1591,7 +1720,8 @@ public class BomDetailsController extends BaseController { break; case "根": fBaseUnitId.addProperty("FNumber", "003"); - break; case "米": + break; + case "米": fBaseUnitId.addProperty("FNumber", "005"); break; case "卷": @@ -1636,7 +1766,8 @@ public class BomDetailsController extends BaseController { break; case "根": fBaseUnitId.addProperty("FNumber", "003"); - break; case "米": + break; + case "米": fBaseUnitId.addProperty("FNumber", "005"); break; case "卷": @@ -1669,16 +1800,16 @@ public class BomDetailsController extends BaseController { JsonObject subHeadEntity6 = new JsonObject(); model.add("SubHeadEntity6", subHeadEntity6); //不同的属性不同的检验方案 - if (states.equals("1")){ + if (states.equals("1")) { //外购 subHeadEntity6.addProperty("FCheckIncoming", true); } - if (states.equals("2")){ + if (states.equals("2")) { //自制 subHeadEntity6.addProperty("FCheckProduct", true); subHeadEntity6.addProperty("FCheckReturnMtrl", true); } - if (states.equals("3")){ + if (states.equals("3")) { //委外 subHeadEntity6.addProperty("FCheckIncoming", true); subHeadEntity6.addProperty("FCheckProduct", true); @@ -1686,7 +1817,6 @@ public class BomDetailsController extends BaseController { } - // 创建SubHeadEntity5对象,并加入Model JsonObject subHeadEntity5 = new JsonObject(); model.add("SubHeadEntity5", subHeadEntity5); @@ -1707,7 +1837,7 @@ public class BomDetailsController extends BaseController { case "根": fBaseUnitId.addProperty("FNumber", "003"); break; - case "米": + case "米": fBaseUnitId.addProperty("FNumber", "005"); break; case "卷": @@ -1753,7 +1883,8 @@ public class BomDetailsController extends BaseController { break; case "根": fBaseUnitId.addProperty("FNumber", "003"); - break; case "米": + break; + case "米": fBaseUnitId.addProperty("FNumber", "005"); break; case "卷": @@ -1779,9 +1910,9 @@ public class BomDetailsController extends BaseController { break; } subHeadEntity5.add("FBOMUnitId", fBOMUnitId); - if (states.equals("1")){ + if (states.equals("1")) { subHeadEntity5.addProperty("FIsMainPrd", false); - }else { + } else { subHeadEntity5.addProperty("FIsMainPrd", true); } subHeadEntity5.addProperty("FIssueType", "1"); 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 b5593f8..1937e25 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 @@ -16,6 +16,8 @@ import com.ruoyi.system.domain.MaterialBom; import com.ruoyi.system.domain.ProcessRoute; import com.ruoyi.system.domain.bo.ProcessRouteBo; import com.ruoyi.system.domain.dto.CombinedDTO; +import com.ruoyi.system.domain.dto.ProcessRoutePushResultDTO; +import com.ruoyi.system.domain.dto.ProcessRouteSelectDTO; import com.ruoyi.system.jdmain.rouplan.Model; import com.ruoyi.system.domain.dto.ProcessRouteXuDTO; import com.ruoyi.system.domain.vo.ProcessRouteVo; @@ -24,6 +26,8 @@ import com.ruoyi.system.service.IProcessRouteService; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; @@ -33,10 +37,13 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import java.io.*; +import java.nio.file.Files; import java.util.*; /** * 工艺路线 + * * @date 2024-10-09 */ @Validated @@ -48,7 +55,7 @@ public class ProcessRouteController extends BaseController { private final IProcessRouteService iProcessRouteService; private static final Logger log = LoggerFactory.getLogger(ProcessRouteController.class); - private Long generateUniqueParentId( Long originalId) { + private Long generateUniqueParentId(Long originalId) { return originalId + 1000; } @@ -60,7 +67,8 @@ public class ProcessRouteController extends BaseController { public TableDataInfo list(ProcessRouteBo bo, PageQuery pageQuery) { try { // 查询工艺路线数据 - TableDataInfo processRouteVoTableDataInfo = iProcessRouteService.queryPageList(bo, pageQuery); + TableDataInfo processRouteVoTableDataInfo = iProcessRouteService.queryPageList(bo, + pageQuery); // 用于存储父子关系的Map,key为"物料编码_物料名称",值为父级ProcessRouteVo Map routeMap = new HashMap<>(); // 存储顶级列表 @@ -70,7 +78,8 @@ public class ProcessRouteController extends BaseController { // 遍历所有工艺路线记录 for (ProcessRouteVo processRouteVo : rows) { // 组合父级键值,物料编码 + 物料名称 - String parentCodeAndName = String.format("%s_%s", processRouteVo.getMaterialCode(), processRouteVo.getMaterialName()); + String parentCodeAndName = String.format("%s_%s", processRouteVo.getMaterialCode(), + processRouteVo.getMaterialName()); // 查找是否已存在父节点 ProcessRouteVo parent = routeMap.get(parentCodeAndName); if (parent == null) { @@ -78,7 +87,7 @@ public class ProcessRouteController extends BaseController { parent = new ProcessRouteVo(); parent.setId(generateUniqueParentId(processRouteVo.getId())); parent.setRouteDescription(processRouteVo.getRouteDescription()); - //parent.setParentId((Long.valueOf(generateUniqueParentId(processRouteVo.getId())))); + // parent.setParentId((Long.valueOf(generateUniqueParentId(processRouteVo.getId())))); parent.setMaterialCode(processRouteVo.getMaterialCode()); parent.setMaterialName(processRouteVo.getMaterialName()); parent.setMaterial(processRouteVo.getMaterial()); @@ -92,7 +101,8 @@ public class ProcessRouteController extends BaseController { topLevelList.add(parent); } // 创建子节点,并将其添加到父节点的子集 - ProcessRouteVo child = createChildVo(processRouteVo, parent.getId(),parent.getMaterialCode(),parent.getMaterialName()); + ProcessRouteVo child = createChildVo(processRouteVo, parent.getId(), parent.getMaterialCode(), + parent.getMaterialName()); parent.getChildren().add(child); } @@ -113,7 +123,8 @@ public class ProcessRouteController extends BaseController { * @param processRouteVo 原始数据 * @return ProcessRouteVo 子节点 */ - private ProcessRouteVo createChildVo(ProcessRouteVo processRouteVo,Long parentId,String materialCode,String materialName) { + private ProcessRouteVo createChildVo(ProcessRouteVo processRouteVo, Long parentId, String materialCode, + String materialName) { ProcessRouteVo child = new ProcessRouteVo(); child.setId(processRouteVo.getId()); child.setParentId(parentId); @@ -153,8 +164,7 @@ public class ProcessRouteController extends BaseController { */ @SaCheckPermission("system:route:query") @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Long id) { + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) { return R.ok(iProcessRouteService.queryById(id)); } @@ -188,20 +198,20 @@ public class ProcessRouteController extends BaseController { @SaCheckPermission("system:route:remove") @Log(title = "工艺路线", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { + public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { return toAjax(iProcessRouteService.deleteWithValidByIds(Arrays.asList(ids), true)); } - @Log(title = "明细导入", businessType = BusinessType.IMPORT) @SaCheckPermission("system:route:import") @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R importData(@RequestParam("file") MultipartFile file) throws Exception { String originalFilename = file.getOriginalFilename(); log.info("读取文件名: " + originalFilename); - ExcelResult result = ExcelUtil.importExcelSheet6(file.getInputStream(), ProcessRouteVo.class, true); - ExcelResult result1 = ExcelUtil.importExcelSheet1(file.getInputStream(), ProductionOrderVo.class, true); + ExcelResult result = ExcelUtil.importExcelSheet6(file.getInputStream(), ProcessRouteVo.class, + true); + ExcelResult result1 = ExcelUtil.importExcelSheet1(file.getInputStream(), + ProductionOrderVo.class, true); List list = result1.getList(); if (iProcessRouteService.saveData(result.getList(), list)) { return R.ok("上传物料成功"); @@ -234,14 +244,13 @@ public class ProcessRouteController extends BaseController { * 查询工艺表中所有的需要做工艺的物料 * * @return - * RequestBody List routeVoList + * RequestBody List routeVoList */ public List getProcessRouteList(@RequestParam String rooteProdet) { List list = iProcessRouteService.pushRawMater(rooteProdet); return list; } - @Log(title = "查询工艺工序集合") @SaCheckPermission("system:route:getProcessRoute") @PostMapping("/getProcessRoute") @@ -250,9 +259,9 @@ public class ProcessRouteController extends BaseController { } @Log(title = "推送工艺工序") - @SaCheckPermission("system:route:getProcessRoute") + @SaCheckPermission("system:route:pushRouteBom") @PostMapping("/pushRouteBom") - public List pushRouteBom(@RequestParam String rooteProdet) { + public ProcessRoutePushResultDTO pushRouteBom(@RequestParam String rooteProdet) { return iProcessRouteService.pushRouteBom(rooteProdet); } @@ -265,6 +274,7 @@ public class ProcessRouteController extends BaseController { public ResponseEntity> getDistinctProjectCodes(String query) { return ResponseEntity.ok(iProcessRouteService.getDistinctProjectCodes(query)); } + @Log(title = "获取工序列表") @SaCheckPermission("system:route:getRawBom") @GetMapping("/getProcessInfoList") @@ -281,56 +291,88 @@ public class ProcessRouteController extends BaseController { @Log(title = "生成这个项目的pdf") @SaCheckPermission("system:route:getRawBom") - @PostMapping("/generatePDFs") - public List generatePDFs(@RequestParam String rooteProdet) { - return iProcessRouteService.generatePDFs(rooteProdet); + @GetMapping("/generatePDFs") + public void generatePDFs(String rooteProdet, HttpServletResponse response) throws IOException { + // 调用服务层方法生成 ZIP 文件并获取其路径 + String zipFilePath = iProcessRouteService.generatePDFs(rooteProdet); + System.out.println("ZIP 文件路径: " + zipFilePath); + + // 读取文件为字节数组 + File zipFile = new File(zipFilePath); + if (!zipFile.exists()) { + throw new FileNotFoundException("ZIP 文件未找到: " + zipFilePath); + } + FileInputStream fis = new FileInputStream(zipFile); + OutputStream outputStreams = response.getOutputStream(); + response.setContentType("application/zip"); + byte[] buffer = new byte[1024]; + int len; + while ((len = fis.read(buffer)) != -1) { + outputStreams.write(buffer, 0, len); + } + outputStreams.flush(); + + fis.close(); + outputStreams.close(); } @Log(title = "更新计划时间") @SaCheckPermission("system:route:updateProcessPlan") @PostMapping("/updateProcessPlan") - public List updateProcessPlan(@RequestParam String rooteProdet) { + public List updateProcessPlan(@RequestParam String rooteProdet) { return iProcessRouteService.updateProcessPlan(rooteProdet); } + /** * 保存工艺路线 */ - @SaCheckPermission("system:route:add") + @SaCheckPermission("system:route:addRoute") @Log(title = "保存工艺路线", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping("/addRoute") - public R addRoute( @RequestBody List list) { + public R addRoute(@RequestBody List list) { return iProcessRouteService.addRoute(list); } - @SaCheckPermission("system:route:add") + @SaCheckPermission("system:route:deleteRoute") @Log(title = "删除工艺路线", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping("/deleteRoute") - public List deleteRoute( @RequestBody ProcessRoute processRoute) { + public List deleteRoute(@RequestBody ProcessRoute processRoute) { return iProcessRouteService.deleteRoute(processRoute); } @Log(title = "获取材料bom列表") @SaCheckPermission("system:route:getRawBom") @PostMapping("/getBomInfo") - public ResponseEntity> getProcessMaterialList( @RequestParam String materialCode, - @RequestParam String materialName, - @RequestParam String productionOrderNo) { + public ResponseEntity> getProcessMaterialList(@RequestParam String materialCode, + @RequestParam String materialName, + @RequestParam String productionOrderNo) { - return ResponseEntity.ok(iProcessRouteService.getProcessMaterialList(materialCode,materialName,productionOrderNo)); + return ResponseEntity + .ok(iProcessRouteService.getProcessMaterialList(materialCode, materialName, productionOrderNo)); } + @Log(title = "导入时间", businessType = BusinessType.IMPORT) @SaCheckPermission("system:route:importDataTime") @PostMapping(value = "/importDataTime", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R importDataTime(@RequestParam("file") MultipartFile file) throws Exception { String originalFilename = file.getOriginalFilename(); log.info("读取文件名: " + originalFilename); - ExcelResult result = ExcelUtil.importExcelSheet6(file.getInputStream(), ProcessRouteVo.class, true); + ExcelResult result = ExcelUtil.importExcelSheet6(file.getInputStream(), ProcessRouteVo.class, + true); List list = result.getList(); - List list1 = iProcessRouteService.importDataTime(list); + List list1 = iProcessRouteService.importDataTime(list); return R.ok("更新成功"); } + @Log(title = "获取金蝶工艺路线") + @SaCheckPermission("system:route:getSelectProcessRoute") + @PostMapping("/getSelectProcessRoute") + public List getSelectProcessRoute(@RequestParam String materilCode) { + List list = iProcessRouteService.getSelectProcessRoute(materilCode); + return list; + } + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProductionPlanController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProductionPlanController.java index fd068d7..335cc42 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProductionPlanController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProductionPlanController.java @@ -101,7 +101,7 @@ public class ProductionPlanController extends BaseController { public R add(@Validated(AddGroup.class) @RequestBody ProductionPlanBo bo) { -if (iProductionPlanService.selectByProductionCode(bo.getProductionCode()) != null) { + if (iProductionPlanService.selectByProductionCode(bo.getProductionCode()) != null) { return R.fail("该生产令号已存在"); } return toAjax(iProductionPlanService.insertByBo(bo)); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/ImMaterial.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/ImMaterial.java index 3c91984..db3353a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/ImMaterial.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/ImMaterial.java @@ -44,7 +44,7 @@ public class ImMaterial extends BaseEntity { */ private String imCategory; /* - 所属名称 + 所属名称:danwei */ private String classificationName; /* diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/MaterialBom.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/MaterialBom.java index 678a65c..f8f3d43 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/MaterialBom.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/MaterialBom.java @@ -40,7 +40,7 @@ public class MaterialBom extends BaseEntity { /** * 用量 */ - private Double quantity; + private String quantity; /** * 单位 */ diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/MaterialBomBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/MaterialBomBo.java index e397443..dcd7cba 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/MaterialBomBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/MaterialBomBo.java @@ -48,7 +48,7 @@ public class MaterialBomBo extends BaseEntity { * 用量 */ @NotNull(message = "用量不能为空", groups = { AddGroup.class, EditGroup.class }) - private Double quantity; + private String quantity; /** * 单位 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/ProcessRouteBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/ProcessRouteBo.java index 5212015..7631c29 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/ProcessRouteBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/ProcessRouteBo.java @@ -5,6 +5,7 @@ import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; import lombok.Data; import lombok.EqualsAndHashCode; +import com.fasterxml.jackson.annotation.JsonFormat; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -140,10 +141,12 @@ public class ProcessRouteBo extends BaseEntity { /** * 序开始时间 */ + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private Date xuStartTime; /** * 序结束时间 */ + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private Date xuEndTime; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRoutePushResultDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRoutePushResultDTO.java new file mode 100644 index 0000000..9b6e473 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRoutePushResultDTO.java @@ -0,0 +1,12 @@ +package com.ruoyi.system.domain.dto; + +import lombok.Data; + +import java.util.List; +@Data +public class ProcessRoutePushResultDTO { + private List successfulRoutes; + private List failedRoutes; + private List duplicateRoutes; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteSelectDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteSelectDTO.java new file mode 100644 index 0000000..d5b0277 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteSelectDTO.java @@ -0,0 +1,55 @@ +package com.ruoyi.system.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class ProcessRouteSelectDTO { + @JsonProperty("FNumber") + private String FNumber; + /* + * 物料编码 + */ + @JsonProperty("FMATERIALID.FNumber") + private String matericalCode; + /* + * 物料名称 + */ + + @JsonProperty("FMATERIALNAME") + private String matericalName; + /** + * 工序号 + */ + @JsonProperty("FOperNumber") + private Long processNo; + /** + * 工作中心(加工车间) + */ + @JsonProperty("FWorkCenterId.FName") + private String workCenter; + /** + * 工序名称 + */ + @JsonProperty("FProcessProperty") + private String processName; + /** + * 工序说明(序描述) + */ + @JsonProperty("FOperDescription") + private String processDescription; + /** + * 工序控制码 + */ + @JsonProperty("FOptCtrlCodeId.FName") + private String processControl; + /** + * 活动时长 + */ + @JsonProperty("FActivity1Qty") + private Double activityDuration; + /** + * 活动单位 + */ + private String activityUnit; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteXuDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteXuDTO.java index 7b71419..d978077 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteXuDTO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessRouteXuDTO.java @@ -15,5 +15,8 @@ public class ProcessRouteXuDTO { * 物料名称 */ private String materialName; + /** + * 工艺路线 + */ private List processRouteDT; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MaterialBomVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MaterialBomVo.java index 7c519f6..2503f84 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MaterialBomVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MaterialBomVo.java @@ -48,7 +48,7 @@ public class MaterialBomVo { * 用量 */ @ExcelProperty(value = "用量") - private Double quantity; + private String quantity; /** * 单位 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProcessRouteVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProcessRouteVo.java index 08d26a4..ce1c9e3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProcessRouteVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProcessRouteVo.java @@ -28,6 +28,7 @@ public class ProcessRouteVo { * 主键ID */ private Long id; + private String uuid; /** * 父级id diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProductionOrderVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProductionOrderVo.java index 02a622e..5329aee 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProductionOrderVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ProductionOrderVo.java @@ -85,5 +85,16 @@ public class ProductionOrderVo { @ExcelProperty(value = "上级部件图号") private String parentDrawingNo; + /** + * 主产品图号 + */ + @ExcelProperty(value = "主产品图号") + private String mainProducts; + + /** + * 主产品名称 + */ + @ExcelProperty(value = "主产品名称") + private String mainProductsName; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/PDFGenerator.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/PDFGenerator.java index 044e5e0..0c42668 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/PDFGenerator.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/runner/PDFGenerator.java @@ -17,6 +17,7 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import java.awt.image.BufferedImage; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -27,6 +28,8 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; public class PDFGenerator { @@ -36,8 +39,8 @@ public class PDFGenerator { // 绘制表格行的方法 private static void drawTableRow(PDPageContentStream contentStream, PDType0Font font, float margin, float yStart, - float tableWidth, float[] colWidths, String[] cells, PDDocument document, - PDPage page, float rowHeight, float pageHeight) throws IOException { + float tableWidth, float[] colWidths, String[] cells, PDDocument document, + PDPage page, float rowHeight, float pageHeight) throws IOException { float nextX = margin; float nextY = yStart; @@ -75,7 +78,8 @@ public class PDFGenerator { } // 生成二维码 - private static PDImageXObject generateQRCode(PDDocument document, String text, int width, int height) throws WriterException, IOException { + private static PDImageXObject generateQRCode(PDDocument document, String text, int width, int height) + throws WriterException, IOException { QRCodeWriter qrCodeWriter = new QRCodeWriter(); BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height); @@ -90,166 +94,278 @@ public class PDFGenerator { return LosslessFactory.createFromImage(document, bufferedImage); } - - public static void writeToPdf(List combinedVoList, String rooteProdet) { + public static String writeToPdf(List combinedVoList, String rooteProdet) { String fontPath = "C:\\Users\\Administrator\\AppData\\Local\\Microsoft\\Windows\\Fonts\\arial unicode ms.ttf"; + List pdfPaths = new ArrayList<>(); String directoryPath = "C:\\Users\\Administrator\\Desktop\\上传BOM\\" + rooteProdet; - - for (CombinedDTO combinedVo : combinedVoList) { - // 获取物料编码 - String materialCode1 = combinedVo.getMaterialCode(); - // 获取第一序的工序名称 - String fProcessName = combinedVo.getProcesses().get(0).getFProcessName(); - String productionOrderNumber = String.valueOf(combinedVo.getProcesses().get(0).getFBillNo()); - Date starttime = combinedVo.getProcesses().get(0).getFPlanStartTime(); - Date endtime = combinedVo.getProcesses().get(0).getFPlanFinishTime(); - String materialCode = String.valueOf(combinedVo.getMaterialUsageDTOList().get(0).getBillNumber()); - String pdfFileName = fProcessName + "_" + materialCode1.replace("/", "_") + ".pdf"; - - File existingFile = findFileWithMaterialCode(directoryPath, materialCode1); - String pdfPath; - - // 生成 PDF 文件路径 - if (existingFile == null) { - System.out.println("未找到物料编码对应的PDF文件: " + materialCode + "。将单独生成新PDF。"); - pdfPath = directoryPath + "\\" + pdfFileName; - } else { - pdfPath = directoryPath + "\\" + fProcessName + "_" + materialCode1.replace("/", "_") + "_generated.pdf"; + // 检查目录是否存在,如果不存在则创建 + File directory = new File(directoryPath); + if (!directory.exists()) { + boolean isCreated = directory.mkdirs(); + if (!isCreated) { + throw new RuntimeException("无法创建目录: " + directoryPath); } - - try { - // 创建 PDF 文件并写入内容 - PDDocument document = new PDDocument(); - PDPage page = new PDPage(); - document.addPage(page); - PDType0Font font; - try { - font = PDType0Font.load(document, new File(fontPath)); - } catch (IllegalArgumentException e) { - System.err.println("Font file not found: " + fontPath); - throw new RuntimeException("Font file not found", e); - } - - PDPageContentStream contentStream = new PDPageContentStream(document, page); - - float margin = 15; - float yStart = 740; - float rowHeight = 20f; - float pageHeight = page.getMediaBox().getHeight(); - float tableWidth = page.getMediaBox().getWidth() - 2 * margin; - - // 添加标题和右上角的二维码 - contentStream.beginText(); - contentStream.setFont(font, 14); - contentStream.newLineAtOffset(220, 780); - contentStream.showText("工序计划单"); - contentStream.endText(); - - PDImageXObject qrCode1 = generateQRCode(document, productionOrderNumber, 90, 90); - contentStream.drawImage(qrCode1, page.getMediaBox().getWidth() - 110, 710); - SimpleDateFormat formatte11r = new SimpleDateFormat("yyyy-MM-dd"); - // 绘制生产订单信息表格 - float[] colWidths = {60, 95, 110, 110, 60, 60, 55}; - drawTableRow(contentStream, font, margin, yStart, tableWidth, colWidths, new String[]{"生产令号", rooteProdet, - "开始时间", formatte11r.format(starttime), "结束时间", formatte11r.format(endtime)}, document, page, rowHeight, pageHeight); - - yStart -= rowHeight; - drawTableRow(contentStream, font, margin, yStart, tableWidth, colWidths, new String[]{"单据编号", "生产订单编号", "产品名称", "产品编码", "数量", "生产车间", "次数"}, document, page, rowHeight, pageHeight); - - yStart -= rowHeight; - drawTableRow(contentStream, font, margin, yStart, tableWidth, colWidths, new String[]{ - productionOrderNumber,combinedVo.getOrderNumber(), combinedVo.getMaterialName(), combinedVo.getMaterialCode(), - String.valueOf(combinedVo.getProcesses().get(0).getFMOQty()), combinedVo.getProcesses().get(0).getFDepartmentName(), "1", ""}, document, page, rowHeight, pageHeight); - - // 绘制工序表格 - float processTableStartY = yStart - 2 * rowHeight - 10; - float[] processColWidths = {35, 78, 35, 55, 45, 170, 55, 60, 60}; - yStart = processTableStartY; - - drawTableRow(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[]{ - "工序号", "工序名称", "数量", "工作中心", "工时(分)", "工序说明", "控制码", "开始时间", "结束时间"}, document, page, rowHeight, pageHeight); - - for (PlannedProcessVo process : combinedVo.getProcesses()) { - SimpleDateFormat formatte1r = new SimpleDateFormat("yyyy-MM-dd"); - yStart -= rowHeight; - drawTableRow(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[]{ - String.valueOf(process.getFOperNumber()), process.getFProcessName(), String.valueOf(process.getFOperQty()), - process.getFWorkCenterName(), String.format("%.2f", process.getFActivity1BaseQty()), process.getFOperDescription(), - process.getFOptCtrlCodeIFName(), - process.getFSeqPlanStartTime() != null ? formatte1r.format(process.getFSeqPlanStartTime()) : "", - process.getFSeqPlanFinishTime() != null ? (formatte1r.format(process.getFSeqPlanFinishTime())) : "" - }, document, page, rowHeight, pageHeight); - } - - // 添加生产用料清单标题 - float materialListStartY = yStart - 2 * rowHeight - 40; - yStart = materialListStartY; - - contentStream.beginText(); - contentStream.setFont(font, 12); - contentStream.newLineAtOffset(margin, yStart); - contentStream.showText("生产用料清单:"); - contentStream.showText(materialCode); - contentStream.endText(); - - // 在用料清单标题右侧添加二维码,与右上角二维码对齐 - PDImageXObject qrCode2 = generateQRCode(document, materialCode, 90, 90); - contentStream.drawImage(qrCode2, page.getMediaBox().getWidth() - 110, yStart - 31); - - yStart -= rowHeight; - - // 用料清单表头 - float[] materialColWidths = {25, 130, 110, 50, 35, 40, 40, 80, 50}; - drawTableRow(contentStream, font, margin, yStart, tableWidth, materialColWidths, new String[]{ - "序号", "物料编码", "物料名称", "规格型号", "单位", "应发数", "已领数", "仓库", "备注" - }, document, page, rowHeight, pageHeight); - - List materialUsageDTOList = combinedVo.getMaterialUsageDTOList(); - if (materialUsageDTOList != null && !materialUsageDTOList.isEmpty()) { - for (int i = 0; i < materialUsageDTOList.size(); i++) { - yStart -= rowHeight; - - // 如果空间不足,则新建页面 - if (yStart - rowHeight < margin) { - contentStream.close(); - page = new PDPage(); - document.addPage(page); - contentStream = new PDPageContentStream(document, page); - yStart = pageHeight - margin; - - // 绘制用料清单表头 - drawTableRow(contentStream, font, margin, yStart, tableWidth, materialColWidths, new String[]{ - "序号", "物料编码", "物料名称", "规格型号", "单位", "应发数", "已领数", "仓库", "备注" - }, document, page, rowHeight, pageHeight); - yStart -= rowHeight; - } - - MaterialUsageDTO material = materialUsageDTOList.get(i); - SimpleDateFormat formatte1r = new SimpleDateFormat("yyyy-MM-dd"); - drawTableRow(contentStream, font, margin, yStart, tableWidth, materialColWidths, new String[]{ - String.valueOf(i + 1), material.getMaterialCode(), material.getMaterialName(), - material.getSpecification(), material.getUnit(), - String.valueOf(material.getRequiredQty()), String.valueOf(material.getPickedQty()), - - material.getStockName(), material.getRemarks() != null ? material.getRemarks() : "" - }, document, page, rowHeight, pageHeight); + } else { + // 如果目录存在,删除其中的所有文件 + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (!file.delete()) { + System.err.println("无法删除文件: " + file.getAbsolutePath()); } } - - - contentStream.close(); - document.save(pdfPath); - System.out.println("PDF 生成成功: " + pdfPath); - - // 如果需要合并 PDF 文件 - if (existingFile != null) { - mergePdfToExisting(pdfPath, existingFile.getAbsolutePath()); + } + } + for (CombinedDTO combinedVo : combinedVoList) { + if (!combinedVoList.isEmpty()) { + // 获取物料编码 + String materialCode1 = combinedVo.getMaterialCode(); + String fProcessName; + String productionOrderNumber; + Date starttime; + Date endtime; + String materialCode; + Long fmoQty; + String fDepartmentName; + // 获取第一序的工序名称 + List processes = combinedVo.getProcesses(); + if (!processes.isEmpty()) { + fProcessName = processes.get(0).getFProcessName(); + productionOrderNumber = String.valueOf(combinedVo.getProcesses().get(0).getFBillNo()); + starttime = combinedVo.getProcesses().get(0).getFPlanStartTime(); + endtime = combinedVo.getProcesses().get(0).getFPlanFinishTime(); + materialCode = String.valueOf(combinedVo.getMaterialUsageDTOList().get(0).getBillNumber()); + fmoQty = combinedVo.getProcesses().get(0).getFMOQty(); + fDepartmentName = combinedVo.getProcesses().get(0).getFDepartmentName(); + // 其他代码... + } else { + // 处理列表为空的情况 + fProcessName = "A"; + productionOrderNumber = "A"; + starttime = new Date(); + endtime = new Date(); + materialCode = "0"; + fmoQty = 0L; + fDepartmentName = ""; } - // 在生成并合并 PDF 后,调用重命名和移动文件的方法 - processMergedPdfFiles(directoryPath, combinedVo); - } catch (IOException | WriterException e) { - e.printStackTrace(); + String pdfFileName = fProcessName + "_" + materialCode1.replace("/", "_") + "_独立" + ".pdf"; + + File existingFile = findFileWithMaterialCode(directoryPath, materialCode1); + String pdfPath; + + // 生成 PDF 文件路径 + if (existingFile == null) { + System.out.println("未找到物料编码对应的PDF文件: " + materialCode + "。将单独生成新PDF。"); + pdfPath = directoryPath + "\\" + pdfFileName; + } else { + pdfPath = directoryPath + "\\" + fProcessName + "_" + materialCode1.replace("/", "_") + + "_generated.pdf"; + } + + try { + // 创建 PDF 文件并写入内容 + PDDocument document = new PDDocument(); + PDPage page = new PDPage(); + document.addPage(page); + PDType0Font font = PDType0Font.load(document, new File(fontPath)); + + try { + font = PDType0Font.load(document, new File(fontPath)); + } catch (IllegalArgumentException e) { + System.err.println("Font file not found: " + fontPath); + throw new RuntimeException("Font file not found", e); + } + + PDPageContentStream contentStream = new PDPageContentStream(document, page); + + float margin = 15; + float yStart = 740; + float rowHeight = 20f; + float pageHeight = page.getMediaBox().getHeight(); + float tableWidth = page.getMediaBox().getWidth() - 2 * margin; + + // 添加标题和右上角的二维码 + contentStream.beginText(); + contentStream.setFont(font, 14); + contentStream.newLineAtOffset(220, 780); + contentStream.showText("工序计划单"); + contentStream.endText(); + + PDImageXObject qrCode1 = generateQRCode(document, productionOrderNumber, 90, 90); + contentStream.drawImage(qrCode1, page.getMediaBox().getWidth() - 110, 710); + SimpleDateFormat formatte11r = new SimpleDateFormat("yyyy-MM-dd"); + // 绘制生产订单信息表格 + float[] colWidths = { 60, 95, 110, 110, 60, 60, 55 }; + drawTableRow(contentStream, font, margin, yStart, tableWidth, colWidths, + new String[] { "生产令号", rooteProdet, + "开始时间", formatte11r.format(starttime), "结束时间", formatte11r.format(endtime) }, + document, page, rowHeight, pageHeight); + + yStart -= rowHeight; + drawTableRow(contentStream, font, margin, yStart, tableWidth, colWidths, + new String[] { "单据编号", "生产订单编号", "产品名称", "产品编码", "数量", "生产车间", "次数" }, document, page, + rowHeight, pageHeight); + + yStart -= rowHeight; + drawTableRow(contentStream, font, margin, yStart, tableWidth, colWidths, new String[] { + productionOrderNumber, combinedVo.getOrderNumber(), combinedVo.getMaterialName(), + combinedVo.getMaterialCode(), + String.valueOf(fmoQty), fDepartmentName, "1", "" }, document, page, rowHeight, pageHeight); + + // 绘制工序表格 + float processTableStartY = yStart - 2 * rowHeight - 10; + float[] processColWidths = { 35, 78, 35, 55, 45, 170, 55, 60, 60 }; + yStart = processTableStartY; + + drawTableRow(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[] { + "工序号", "工序名称", "数量", "工作中心", "工时(分)", "工序说明", "控制码", "开始时间", "结束时间" }, document, page, + rowHeight, pageHeight); + + for (PlannedProcessVo process : combinedVo.getProcesses()) { + SimpleDateFormat formatte1r = new SimpleDateFormat("yyyy-MM-dd"); + yStart -= rowHeight; + drawTableRow(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[] { + String.valueOf(process.getFOperNumber()), process.getFProcessName(), + String.valueOf(process.getFOperQty()), + process.getFWorkCenterName(), String.format("%.2f", process.getFActivity1BaseQty()), + process.getFOperDescription(), + process.getFOptCtrlCodeIFName(), + process.getFSeqPlanStartTime() != null + ? formatte1r.format(process.getFSeqPlanStartTime()) + : "", + process.getFSeqPlanFinishTime() != null + ? (formatte1r.format(process.getFSeqPlanFinishTime())) + : "" + }, document, page, rowHeight, pageHeight); + } + + // 添加生产用料清单标题 + yStart = yStart - 2 * rowHeight - 40; + + contentStream.beginText(); + contentStream.setFont(font, 12); + contentStream.newLineAtOffset(margin, yStart); + contentStream.showText("生产用料清单:"); + contentStream.showText(materialCode); + contentStream.endText(); + + // 在用料清单标题右侧添加二维码,与右上角二维码对齐 + PDImageXObject qrCode2 = generateQRCode(document, materialCode, 90, 90); + contentStream.drawImage(qrCode2, page.getMediaBox().getWidth() - 110, yStart - 31); + + yStart -= rowHeight; + + // 用料清单表头 + float[] materialColWidths = { 25, 130, 110, 50, 35, 40, 40, 80, 50 }; + drawTableRow(contentStream, font, margin, yStart, tableWidth, materialColWidths, new String[] { + "序号", "物料编码", "物料名称", "规格型号", "单位", "应发数", "已领数", "仓库", "备注" + }, document, page, rowHeight, pageHeight); + + List materialUsageDTOList = combinedVo.getMaterialUsageDTOList(); + if (materialUsageDTOList != null && !materialUsageDTOList.isEmpty()) { + for (int i = 0; i < materialUsageDTOList.size(); i++) { + yStart -= rowHeight; + + // 如果空间不足,则新建页面 + if (yStart - rowHeight < margin) { + contentStream.close(); + page = new PDPage(); + document.addPage(page); + contentStream = new PDPageContentStream(document, page); + yStart = pageHeight - margin; + + // 绘制用料清单表头 + drawTableRow(contentStream, font, margin, yStart, tableWidth, materialColWidths, + new String[] { + "序号", "物料编码", "物料名称", "规格型号", "单位", "应发数", "已领数", "仓库", "备注" + }, document, page, rowHeight, pageHeight); + yStart -= rowHeight; + } + + MaterialUsageDTO material = materialUsageDTOList.get(i); + SimpleDateFormat formatte1r = new SimpleDateFormat("yyyy-MM-dd"); + drawTableRow(contentStream, font, margin, yStart, tableWidth, materialColWidths, + new String[] { + String.valueOf(i + 1), material.getMaterialCode(), + material.getMaterialName(), + material.getSpecification(), material.getUnit(), + String.valueOf(material.getRequiredQty()), + String.valueOf(material.getPickedQty()), + + material.getStockName(), + material.getRemarks() != null ? material.getRemarks() : "" + }, document, page, rowHeight, pageHeight); + } + } + + contentStream.close(); + document.save(pdfPath); + pdfPaths.add(pdfPath); + System.out.println("PDF 生成成功: " + pdfPath); + + // 如果需要合并 PDF 文件 + if (existingFile != null) { + mergePdfToExisting(pdfPath, existingFile.getAbsolutePath()); + pdfPaths.add(existingFile.getAbsolutePath()); + } + + // 在生成并合并 PDF 后,调用重命名和移动文件的方法 + processMergedPdfFiles(directoryPath, combinedVo); + } catch (IOException | WriterException e) { + e.printStackTrace(); + } + } + } + // 生成ZIP文件 + String zipFilePath = directoryPath + "\\" + rooteProdet + "_工序计划单.zip"; + try { + createZipFile(pdfPaths, zipFilePath); + System.out.println("ZIP 文件生成成功: " + zipFilePath); + return zipFilePath; + } catch (IOException e) { + e.printStackTrace(); + System.err.println("ZIP 文件生成失败: " + e.getMessage()); + return null; + } + + } + + /** + * 创建ZIP文件 + * + * @param sourceFilePaths PDF文件路径列表 + * @param zipFilePath 目标ZIP文件路径 + */ + private static void createZipFile(List sourceFilePaths, String zipFilePath) throws IOException { + // 确保目标目录存在 + File zipFile = new File(zipFilePath); + if (!zipFile.getParentFile().exists()) { + zipFile.getParentFile().mkdirs(); + } + + try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath))) { + // 设置压缩级别 + zipOut.setLevel(ZipOutputStream.DEFLATED); + + for (String filePath : sourceFilePaths) { + File fileToZip = new File(filePath); + if (fileToZip.exists()) { + try (FileInputStream fis = new FileInputStream(fileToZip)) { + // 创建ZIP条目 + ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); + zipOut.putNextEntry(zipEntry); + + // 写入文件内容 + byte[] bytes = new byte[1024]; + int length; + while ((length = fis.read(bytes)) >= 0) { + zipOut.write(bytes, 0, length); + } + } + } else { + System.err.println("文件不存在: " + filePath); + } } } } @@ -269,7 +385,7 @@ public class PDFGenerator { // 合并PDF,将生成的PDF插入到已有PDF的末尾 public static void mergePdfToExisting(String generatedPdfPath, String existingPdfPath) throws IOException { try (PDDocument existingDoc = PDDocument.load(new File(existingPdfPath)); - PDDocument generatedDoc = PDDocument.load(new File(generatedPdfPath))) { + PDDocument generatedDoc = PDDocument.load(new File(generatedPdfPath))) { PDFMergerUtility merger = new PDFMergerUtility(); merger.appendDocument(existingDoc, generatedDoc); @@ -283,10 +399,36 @@ public class PDFGenerator { } public static void processMergedPdfFiles(String directoryPath, CombinedDTO combinedVo) { + String fProcessName; + String productionOrderNumber; + Date starttime; + Date endtime; + String materialCode1; + Long fmoQty; + String fDepartmentName; + // 获取第一序的工序名称 + List processes = combinedVo.getProcesses(); + if (!processes.isEmpty()) { + fProcessName = processes.get(0).getFProcessName(); + productionOrderNumber = String.valueOf(combinedVo.getProcesses().get(0).getFBillNo()); + starttime = combinedVo.getProcesses().get(0).getFPlanStartTime(); + endtime = combinedVo.getProcesses().get(0).getFPlanFinishTime(); + materialCode1 = String.valueOf(combinedVo.getMaterialUsageDTOList().get(0).getBillNumber()); + fmoQty = combinedVo.getProcesses().get(0).getFMOQty(); + fDepartmentName = combinedVo.getProcesses().get(0).getFDepartmentName(); + // 其他代码... + } else { + // 处理列表为空的情况 + fProcessName = "A"; + productionOrderNumber = "A"; + starttime = new Date(); + endtime = new Date(); + materialCode1 = "0"; + fmoQty = 0L; + fDepartmentName = ""; + } + // 获取图号和工序名称 - String materialCode1 = combinedVo.getMaterialCode(); // 图号 - String fProcessName = combinedVo.getProcesses().get(0).getFProcessName(); // 首序名称 - String departmentName = combinedVo.getProcesses().get(0).getFDepartmentName(); // 车间名称 // 找到已合并的文件路径 String originalPdfFileName = materialCode1.replace("/", "_") + ".pdf"; // 原始PDF文件名 @@ -298,7 +440,7 @@ public class PDFGenerator { String newPdfFilePath = directoryPath + "\\" + newPdfFileName; // 创建车间文件夹路径 - File departmentFolder = new File(directoryPath + "\\" + departmentName); + File departmentFolder = new File(directoryPath + "\\" + fDepartmentName); if (!departmentFolder.exists()) { departmentFolder.mkdirs(); // 创建车间文件夹 } @@ -312,7 +454,7 @@ public class PDFGenerator { File sourceFile = new File(sourcePath); File targetFile = new File(departmentFolder, targetPath); - // 检查目标文件夹是否存在,不存在则创建 + // 检查目���文件夹是否存在,不存在则创建 if (!departmentFolder.exists()) { departmentFolder.mkdirs(); // 创建车间文件夹 } @@ -339,5 +481,4 @@ public class PDFGenerator { } } - } 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 ba415d6..6363305 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 @@ -7,6 +7,8 @@ import com.ruoyi.system.domain.MaterialBom; import com.ruoyi.system.domain.ProcessRoute; import com.ruoyi.system.domain.bo.ProcessRouteBo; import com.ruoyi.system.domain.dto.CombinedDTO; +import com.ruoyi.system.domain.dto.ProcessRoutePushResultDTO; +import com.ruoyi.system.domain.dto.ProcessRouteSelectDTO; import com.ruoyi.system.jdmain.rouplan.Model; import com.ruoyi.system.domain.dto.ProcessRouteXuDTO; import com.ruoyi.system.domain.vo.ProcessRouteVo; @@ -70,14 +72,14 @@ public interface IProcessRouteService { */ List getProcessRoute(String rooteProdet); - List pushRouteBom(String rooteProdet); + ProcessRoutePushResultDTO pushRouteBom(String rooteProdet); List getSelecPlanRouteList(String rooteProdet); /** * 生成这个项目的pdf */ - List generatePDFs(String rooteProdet); + String generatePDFs(String rooteProdet); List updateProcessPlan(String rooteProdet); @@ -92,4 +94,6 @@ public interface IProcessRouteService { List importDataTime(List list); boolean isAnTuDingGou(String materialCode); + + List getSelectProcessRoute(String materilCode); } 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 5991b70..12427b3 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 @@ -93,7 +93,7 @@ public class BomDetailsServiceImpl implements IBomDetailsService { lqw.like(StringUtils.isNotBlank(bo.getName()), BomDetails::getName, bo.getName()); lqw.eq(bo.getQuantity() != null, BomDetails::getQuantity, bo.getQuantity()); lqw.eq(bo.getDenominator() != null, BomDetails::getDenominator, bo.getDenominator()); - lqw.eq(StringUtils.isNotBlank(bo.getFNumber()), BomDetails::getFNumber, bo.getFNumber()); + lqw.like(StringUtils.isNotBlank(bo.getFNumber()), BomDetails::getFNumber, bo.getFNumber()); lqw.eq(StringUtils.isNotBlank(bo.getMaterial()), BomDetails::getMaterial, bo.getMaterial()); lqw.eq(StringUtils.isNotBlank(bo.getUnitWeight()), BomDetails::getUnitWeight, bo.getUnitWeight()); lqw.like(StringUtils.isNotBlank(bo.getTotalWeight()), BomDetails::getTotalWeight, bo.getTotalWeight()); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ImMaterialServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ImMaterialServiceImpl.java index 771afe1..f3c9d89 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ImMaterialServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ImMaterialServiceImpl.java @@ -181,10 +181,8 @@ public class ImMaterialServiceImpl implements IImMaterialService { } // 调用库存查询方法,优化为批量查询而非逐个查询 Map jsonMap = queryAllKuCun(result.getRecords()); - if (jsonMap != null) { - // 更新库存信息 - updateRecordsWithKuCunInfo(jsonMap, result.getRecords()); - } + // 更新库存信息 + updateRecordsWithKuCunInfo(jsonMap, result.getRecords()); // 更新数量,更新实体类 result.setRecords(result.getRecords()); // 更新结果集 @@ -298,6 +296,13 @@ public class ImMaterialServiceImpl implements IImMaterialService { if (unitElement != null && !unitElement.isJsonNull()){ record.setUnit(unitElement.getAsString()); } + String unit = jsonObject.get("FStockUnitId.FName").getAsString(); + if (unit != null && !unit.isEmpty()) { + record.setClassificationName(unit); + }else { + record.setClassificationName("件"); + } + JsonElement qualityElement = jsonObject.get("F_UCHN_BaseProperty"); if (qualityElement != null && !qualityElement.isJsonNull()) { record.setMaterialQuality(qualityElement.getAsString()); @@ -350,7 +355,7 @@ public class ImMaterialServiceImpl implements IImMaterialService { lqw.like(StringUtils.isNotBlank(bo.getClassificationName()), ImMaterial::getClassificationName, bo.getClassificationName()); lqw.like(StringUtils.isNotBlank(bo.getImCategory()), ImMaterial::getImCategory, bo.getImCategory()); lqw.like(StringUtils.isNotBlank(bo.getMaterialQuality()), ImMaterial::getMaterialQuality, bo.getMaterialQuality()); - lqw.like(bo.getSingleWeight() != null, ImMaterial::getSingleWeight, bo.getSingleWeight()); + lqw.eq(bo.getSingleWeight() != null, ImMaterial::getSingleWeight, bo.getSingleWeight()); lqw.like(bo.getUnitPrice() != null, ImMaterial::getUnitPrice, bo.getUnitPrice()); lqw.like(StringUtils.isNotBlank(bo.getUnit()), ImMaterial::getUnit, bo.getUnit()); lqw.like(bo.getFlag() != null, ImMaterial::getFlag, bo.getFlag()); @@ -696,6 +701,7 @@ public class ImMaterialServiceImpl implements IImMaterialService { String fCategoryID = jsonObject.getStr("FCategoryID.FNumber"); String fAssistant = jsonObject.getStr("F.SVRI.Assistant.FNumber"); String fErpClsID = jsonObject.getStr("FErpClsID"); + String unit = jsonObject.getStr("FBaseUnitId.FName"); String property = MaterialProperties.getMaterialProperty(fAssistant); String fErpClsID1 = MaterialProperties.getItemAttributesMap(fErpClsID); @@ -706,7 +712,7 @@ public class ImMaterialServiceImpl implements IImMaterialService { imMaterial.setClassificationNumber(fErpClsID1); imMaterial.setImCategory(getCategory(fCategoryID)); imMaterial.setMaterialQuality(property); - + imMaterial.setClassificationName(unit); ImMaterial existingMaterial = existingMaterialsMap.get(fNumber); if (existingMaterial != null) { logger.info("更新物料==> " + existingMaterial.getMaterialCode() + " 物料名称==> " + existingMaterial.getMaterialName()); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MaterialBomServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MaterialBomServiceImpl.java index abfa87e..50cbc40 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MaterialBomServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MaterialBomServiceImpl.java @@ -109,7 +109,7 @@ public class MaterialBomServiceImpl implements IMaterialBomService { // 更新原材料相关信息 processRoute.setRawMaterialCode(bo.getMaterialCode()); // BOM物料编码 processRoute.setRawMaterialName(bo.getMaterialName()); // BOM物料名称 - processRoute.setDiscUsage(bo.getQuantity()); // 用量 + processRoute.setDiscUsage(Double.valueOf(bo.getQuantity())); // 用量 processRoute.setBomUnit(bo.getUnit()); // 单位 processRoute.setBomMaterial(bo.getMaterialType()); // 更新工艺路线 @@ -144,7 +144,7 @@ public class MaterialBomServiceImpl implements IMaterialBomService { bomDetails.setName(bo.getMaterialName()); bomDetails.setName(bo.getMaterialName()); bomDetails.setDenominator(1.0); - bomDetails.setQuantity(bo.getQuantity()); + bomDetails.setQuantity(Double.valueOf(bo.getQuantity())); bomDetails.setStats("外购"); bomDetails.setMaterial(bo.getMaterialType()); int flag = bomDetailsMapper.insert(bomDetails); @@ -160,6 +160,31 @@ public class MaterialBomServiceImpl implements IMaterialBomService { @Override public Boolean updateByBo(MaterialBomBo bo) { MaterialBom update = BeanUtil.toBean(bo, MaterialBom.class); + + // 2. 查找对应的工艺路线 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(ProcessRoute::getRouteDescription, bo.getProjectNumber()) + .eq(ProcessRoute::getProcessNo, "10") // 使用父级物料编码 + .eq(ProcessRoute::getMaterialCode, bo.getParentMaterialCode()) // 使用父级物料编码 + .eq(ProcessRoute::getMaterialName, bo.getParentMaterialName()); // 使用父级物料名称 + + ProcessRoute processRoute = processRouteMapper.selectOne(wrapper); + // 3. 如果找到对应的工艺路线,更新相关字段 + if (processRoute != null) { + processRoute.setId(processRoute.getId()); + // 更新原材料相关信息 + processRoute.setRawMaterialCode(bo.getMaterialCode()); // BOM物料编码 + processRoute.setRawMaterialName(bo.getMaterialName()); // BOM物料名称 + processRoute.setDiscUsage(Double.valueOf(bo.getQuantity())); // 用量 + processRoute.setBomUnit(bo.getUnit()); // 单位 + processRoute.setBomMaterial(bo.getMaterialType()); + // 更新工艺路线 + int updateResult = processRouteMapper.updateById(processRoute); + if (updateResult <= 0) { + throw new ServiceException("更新工艺路线失败"); + } + } + validEntityBeforeSave(update); return baseMapper.updateById(update) > 0; } @@ -201,7 +226,7 @@ public class MaterialBomServiceImpl implements IMaterialBomService { materialBomBo.setProjectNumber(bo.getProcessDescription()); materialBomBo.setParentMaterialCode(bo.getMaterialCode()); materialBomBo.setParentMaterialName(bo.getMaterialName()); - materialBomBo.setQuantity(bo.getDiscUsage()); + materialBomBo.setQuantity(String.valueOf(bo.getDiscUsage())); materialBomBo.setUnit(bo.getBomUnit()); materialBomBo.setMaterialType(bo.getBomMaterial()); materialBomBo.setMaterialCode(bo.getRawMaterialCode()); 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 309c91a..ba70f08 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 @@ -70,7 +70,8 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService { lqw.like(StringUtils.isNotBlank(bo.getProductionName()), ProcessOrderPro::getProductionName, bo.getProductionName()); lqw.eq(StringUtils.isNotBlank(bo.getDrawingNo()), ProcessOrderPro::getDrawingNo, bo.getDrawingNo()); lqw.like(StringUtils.isNotBlank(bo.getDrawingName()), ProcessOrderPro::getDrawingName, bo.getDrawingName()); - + //按照创建时间排序,最新的在顶端 + lqw.orderByDesc(true,ProcessOrderPro::getCreateTime); return lqw; } @@ -110,6 +111,12 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService { */ @Override public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + for (Long id : ids) { + ProcessOrderProVo processOrderProVo = baseMapper.selectVoById(id); + String productionOrderNo = processOrderProVo.getProductionOrderNo(); + String materialCode = processOrderProVo.getDrawingNo(); + + } if(isValid){ //TODO 做一些业务上的校验,判断是否需要校验 } 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 2b05c3d..322c156 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 @@ -53,7 +53,6 @@ import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; -import static com.ruoyi.common.core.domain.R.fail; import static com.ruoyi.system.controller.BomDetailsController.*; import static com.ruoyi.system.runner.JsonConverter.createProcessModel; import static com.ruoyi.system.runner.updatePcessPlanConver.updatePcessPlan1; @@ -108,25 +107,33 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { @Override public List queryList(ProcessRouteBo bo) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); + List routeVoList = baseMapper.selectVoList(lqw); + // 对这个集合进行重新排序,按照物料编码排序 + routeVoList.sort(Comparator.comparing(ProcessRouteVo::getMaterialCode)); + + return routeVoList; } private LambdaQueryWrapper buildQueryWrapper(ProcessRouteBo bo) { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.like(StringUtils.isNotBlank(bo.getRouteDescription()), ProcessRoute::getRouteDescription, bo.getRouteDescription()); + lqw.like(StringUtils.isNotBlank(bo.getRouteDescription()), ProcessRoute::getRouteDescription, + bo.getRouteDescription()); lqw.eq(StringUtils.isNotBlank(bo.getMaterialCode()), ProcessRoute::getMaterialCode, bo.getMaterialCode()); lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), ProcessRoute::getMaterialName, bo.getMaterialName()); lqw.eq(StringUtils.isNotBlank(bo.getBomUnit()), ProcessRoute::getBomUnit, bo.getBomUnit()); lqw.eq(bo.getProcessNo() != null, ProcessRoute::getProcessNo, bo.getProcessNo()); lqw.eq(StringUtils.isNotBlank(bo.getWorkCenter()), ProcessRoute::getWorkCenter, bo.getWorkCenter()); lqw.like(StringUtils.isNotBlank(bo.getProcessName()), ProcessRoute::getProcessName, bo.getProcessName()); - lqw.eq(StringUtils.isNotBlank(bo.getRawMaterialCode()), ProcessRoute::getRawMaterialCode, bo.getRawMaterialCode()); - lqw.like(StringUtils.isNotBlank(bo.getRawMaterialName()), ProcessRoute::getRawMaterialName, bo.getRawMaterialName()); + lqw.eq(StringUtils.isNotBlank(bo.getRawMaterialCode()), ProcessRoute::getRawMaterialCode, + bo.getRawMaterialCode()); + lqw.like(StringUtils.isNotBlank(bo.getRawMaterialName()), ProcessRoute::getRawMaterialName, + bo.getRawMaterialName()); lqw.eq(StringUtils.isNotBlank(bo.getBomMaterial()), ProcessRoute::getBomMaterial, bo.getBomMaterial()); lqw.eq(bo.getDiscWeight() != null, ProcessRoute::getDiscWeight, bo.getDiscWeight()); lqw.eq(bo.getDiscUsage() != null, ProcessRoute::getDiscUsage, bo.getDiscUsage()); - lqw.eq(StringUtils.isNotBlank(bo.getProcessDescription()), ProcessRoute::getProcessDescription, bo.getProcessDescription()); + lqw.eq(StringUtils.isNotBlank(bo.getProcessDescription()), ProcessRoute::getProcessDescription, + bo.getProcessDescription()); lqw.eq(StringUtils.isNotBlank(bo.getProcessControl()), ProcessRoute::getProcessControl, bo.getProcessControl()); lqw.eq(bo.getActivityDuration() != null, ProcessRoute::getActivityDuration, bo.getActivityDuration()); lqw.eq(StringUtils.isNotBlank(bo.getActivityUnit()), ProcessRoute::getActivityUnit, bo.getActivityUnit()); @@ -148,10 +155,22 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { public Boolean insertByBo(ProcessRouteBo bo) { ProcessRoute add = BeanUtil.toBean(bo, ProcessRoute.class); - //查询最大序为多少 - if (baseMapper.existsByProcessNoAndMaterialCode(add.getProcessNo(), add.getMaterialCode(), add.getProcessDescription())) { + // 查询最大序为多少 + if (baseMapper.existsByProcessNoAndMaterialCode(add.getProcessNo(), add.getMaterialCode(), + add.getProcessDescription())) { throw new ServiceException("序号重复,请重新输入"); } + // 1.查询当前物料的所有工序关系 + LambdaQueryWrapper route = new LambdaQueryWrapper<>(); + route.eq(ProcessRoute::getMaterialCode, add.getMaterialCode()) + .eq(ProcessRoute::getMaterialName, add.getMaterialName()) + .eq(ProcessRoute::getRouteDescription, add.getRouteDescription()); + List routeList = baseMapper.selectList(route); + // 2. 校验连续工序中相同工作中心的工序控制码 + if (!routeList.isEmpty()) { + setoProcessControl(routeList); + } + // 2. 更新所有比新序号大的工艺路线,将它们的 processNo baseMapper.updateProcessNoAfterInsert(add.getProcessNo(), add.getMaterialCode(), add.getProcessDescription()); validEntityBeforeSave(add); @@ -162,6 +181,45 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { return flag; } + private void setoProcessControl(List routeList) { + if (routeList == null || routeList.size() < 2) { + return; + } + + // 按工序号排序 + routeList.sort(Comparator.comparing(ProcessRoute::getProcessNo)); + + // 遍历处理连续相同工作中心的工序 + for (int i = 0; i < routeList.size(); i++) { + ProcessRoute current = routeList.get(i); + + // 委外中心特殊处理 + if ("委外中心".equals(current.getWorkCenter())) { + current.setProcessControl("委外+汇报"); + continue; + } + + // 查找连续相同工作中心的最后一个工序 + int j = i; + while (j + 1 < routeList.size() && + routeList.get(j + 1).getWorkCenter().equals(current.getWorkCenter())) { + j++; + } + + // 设置工序控制码 + if (i == j) { + // 单个工序设置为"汇报+质量" + current.setProcessControl("汇报+质量"); + } else { + // 连续工序,最后一个设置为"汇报+质量",其他为"汇报+免检" + for (int k = i; k <= j; k++) { + ProcessRoute route = routeList.get(k); + route.setProcessControl(k == j ? "汇报+质量" : "汇报+免检"); + } + i = j; // 跳过已处理的工序 + } + } + } /** * 修改工艺路线 @@ -196,14 +254,41 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } } - // 3. 直接更新全部字段 + // 3. 获取当前物料的所有工序关系 + LambdaQueryWrapper route = new LambdaQueryWrapper<>(); + route.eq(ProcessRoute::getMaterialCode, update.getMaterialCode()) + .eq(ProcessRoute::getMaterialName, update.getMaterialName()) + .eq(ProcessRoute::getRouteDescription, update.getRouteDescription()); + List routeList = baseMapper.selectList(route); + + // 4. 更新当前记录到列表中 + boolean found = false; + for (int i = 0; i < routeList.size(); i++) { + if (routeList.get(i).getId().equals(update.getId())) { + routeList.set(i, update); + found = true; + break; + } + } + if (!found) { + routeList.add(update); + } + + // 5. 按工序号排序 + routeList.sort(Comparator.comparing(ProcessRoute::getProcessNo)); + + // 6. 校验连续工序中相同工作中心的工序控制码 + setoProcessControl(routeList); + + // 7. 更新数据库 return baseMapper.updateById(update) > 0; } + /** * 保存前的数据校验 */ private void validEntityBeforeSave(ProcessRoute entity) { - //TODO 做一些数据校验,如唯一约束 + // TODO 做一些数据校验,如唯一约束 } /** @@ -212,24 +297,30 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { @Override public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { List cunList = new ArrayList<>(); + for (Long id : ids) { + ProcessRoute processRoute = baseMapper.selectById(id); + if (processRoute.getProcessNo() == 10) { + throw new ServiceException("最少保留首序"); + } + } // 这里你到时候改成通过ids查询出来 这个ids是你传过来要删除的,你不能通过去排序和查询en for (Long id : ids) { - //存储删掉的数据 + // 存储删掉的数据 ProcessRoute processRoute = baseMapper.selectById(id); cunList.add(processRoute); } // 批量删除 if (baseMapper.deleteBatchIds(ids) > 0) { - //随便获取一个 + // 随便获取一个 ProcessRoute processRoute = cunList.get(0); - //获取删除后其他的 工序,然后更新工序号 + // 获取删除后其他的 工序,然后更新工序号 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(ProcessRoute::getRouteDescription, processRoute.getRouteDescription()) .eq(ProcessRoute::getMaterialCode, processRoute.getMaterialCode()) .eq(ProcessRoute::getMaterialName, processRoute.getMaterialName()) .isNotNull(ProcessRoute::getProcessNo); List routeList = baseMapper.selectList(wrapper); - //工序号升序排序 + // 工序号升序排序 routeList.sort(Comparator.comparing(ProcessRoute::getProcessNo)); for (int i = 0; i < routeList.size(); i++) { @@ -256,11 +347,10 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { return true; } - public boolean saveData(List routeVoList, List productionOrderVos) { // 将 ProcessRouteVo 转换为 ProcessRoute List processRoutes = BeanUtil.copyToList(routeVoList, ProcessRoute.class); - //firstBatchQuantity + // firstBatchQuantity // 1. 处理材料 BOM processMaterialBom(processRoutes); @@ -297,14 +387,39 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { if (isDuplicateWelding && processedWeldingMaterials.contains(processRoute.getMaterialCode())) { continue; } + List selectProcessRoute = getSelectProcessRoute(processRoute.getMaterialCode()); - // 生成4个默认工序 - for (int i = 0; i <2; i++) { + if (!selectProcessRoute.isEmpty()) { + for (ProcessRouteSelectDTO processRouteSelectDTO : selectProcessRoute) { + ProcessRoute processRoute1 = new ProcessRoute(); + // 复制基本信息 + processRoute1.setMaterialCode(processRoute.getMaterialCode()); + processRoute1.setMaterialName(processRoute.getMaterialName()); + processRoute1.setRouteDescription(processRoute.getRouteDescription()); + processRoute1.setMaterial(processRoute.getMaterial()); + processRoute1.setDiscWeight(processRoute.getDiscWeight()); + + // 复制工艺信息 + processRoute1.setProcessNo(processRouteSelectDTO.getProcessNo()); + processRoute1.setProcessName(processRouteSelectDTO.getProcessName()); + processRoute1.setProcessDescription(processRouteSelectDTO.getProcessDescription()); + processRoute1.setWorkCenter(processRouteSelectDTO.getWorkCenter()); + processRoute1.setProcessControl(processRouteSelectDTO.getProcessControl()); + processRoute1.setActivityDuration(processRouteSelectDTO.getActivityDuration()); + processRoute1.setActivityUnit("分"); + + // 设置时间 + processRoute1.setCreateTime(new Date()); + processRoute1.setUpdateTime(new Date()); + + routeArrayList.add(processRoute1); + } + } else { ProcessRoute defaultRoute = new ProcessRoute(); BeanUtil.copyProperties(processRoute, defaultRoute); // 设置工序号 (10, 20, 30, 40) - defaultRoute.setProcessNo((long) ((i + 1) * 10)); + defaultRoute.setProcessNo((long) (10)); // 清空工序相关信息 defaultRoute.setWorkCenter(null); @@ -312,13 +427,15 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { defaultRoute.setProcessDescription(null); defaultRoute.setProcessControl(null); defaultRoute.setActivityDuration(null); - defaultRoute.setActivityUnit(null); + defaultRoute.setActivityUnit("分"); // 设置创建时间和更新时间 defaultRoute.setCreateTime(new Date()); defaultRoute.setUpdateTime(new Date()); routeArrayList.add(defaultRoute); + + log.info("为物料 {} 生成了默认工序,因为在金蝶中未找到对应工艺路线", processRoute.getMaterialCode()); } // 如果是重复的组焊件,标记为已处理 @@ -351,7 +468,8 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { String unit = processRoute.getBomUnit(); String materialType = processRoute.getBomMaterial(); Double quantity = processRoute.getDiscUsage() != null ? processRoute.getDiscUsage() : 0; - if (projectNumber == null || parentMaterialCode == null || parentMaterialName == null || unit == null || materialType == null) { + if (projectNumber == null || parentMaterialCode == null || parentMaterialName == null || unit == null + || materialType == null) { // 处理空值情况,例如记录日志或抛出异常 log.error("必填字段为空: {}", processRoute); continue; @@ -365,14 +483,15 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { materialBom.setMaterialName(processRoute.getRawMaterialName()); materialBom.setUnit(unit); materialBom.setMaterialType(materialType); - materialBom.setQuantity(quantity); + materialBom.setQuantity(String.valueOf(quantity)); // 这里插入 materialBom 数据 materialBomMapper.insert(materialBom); } } } - private List processBomDetails(List processRoutes, List productionOrderVos) { + private List processBomDetails(List processRoutes, + List productionOrderVos) { List bomDetailsVos = new ArrayList<>(); // 是否已处理过总装部件 boolean hasProcessedAssemblyPart = false; @@ -389,7 +508,8 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { hasProcessedAssemblyPart = true; continue; } - if (processRoute.getRawMaterialCode() != null || processRoute.getRawMaterialName() != null || processRoute.getBomMaterial() != null || processRoute.getBomUnit() != null) { + if (processRoute.getRawMaterialCode() != null || processRoute.getRawMaterialName() != null + || processRoute.getBomMaterial() != null || processRoute.getBomUnit() != null) { BomDetailsVo bomDetails = createBomDetails(processRoute); bomDetailsVos.add(bomDetails); } @@ -408,16 +528,15 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 处理单位换算 if ("mm".equals(processRoute.getBomUnit())) { - bomDetails.setQuantity(processRoute.getDiscUsage() / 1000.0); // 转换为米 - } else if ("根".equals(processRoute.getBomUnit())){ + bomDetails.setQuantity(processRoute.getDiscUsage() / 1000.0); // 转换为米 + } else if ("根".equals(processRoute.getBomUnit())) { bomDetails.setDenominator(processRoute.getDiscUsage()); bomDetails.setQuantity(1.0); - }else { + } else { bomDetails.setQuantity(processRoute.getDiscUsage()); bomDetails.setDenominator(1.0); } - // 根据 RawMaterialCode 判断是否外购 if (isOutsourced(processRoute.getRawMaterialCode())) { bomDetails.setStats("外购"); @@ -430,7 +549,8 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { return bomDetails; } - private void createAssemblyBomDetails(String zFlinghao, String zFnumber, String zFname, List productionOrderVos) { + private void createAssemblyBomDetails(String zFlinghao, String zFnumber, String zFname, + List productionOrderVos) { ArrayList bomDetailsVos = new ArrayList<>(); for (ProductionOrderVo productionOrderVo : productionOrderVos) { if (productionOrderVo != null) { @@ -449,14 +569,15 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { String drawingNo = productionOrderVo.getDrawingNo(); String remark = productionOrderVo.getRemark(); if (drawingNo != null) { - if ((isOutsourced(drawingNo) || (remark != null && remark.contains("外购件")) || drawingNo.startsWith(" ")) || drawingNo.startsWith("009")) { + if ((isOutsourced(drawingNo) || (remark != null && remark.contains("外购件")) + || drawingNo.startsWith(" ")) || drawingNo.startsWith("009")) { bomDetails.setStats("外购"); } else { bomDetails.setStats("自制"); } } - // iBomDetailsService.insertByVo(bomDetails); + // iBomDetailsService.insertByVo(bomDetails); bomDetailsVos.add(bomDetails); } @@ -488,7 +609,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId()); model.add("F_SVRI_Assistant", FSVRIAssistant); } else { - //没写材料为默认为空 + // 没写材料为默认为空 JsonObject FSVRIAssistant = new JsonObject(); FSVRIAssistant.addProperty("FNumber", "17"); model.add("F_SVRI_Assistant", FSVRIAssistant); @@ -548,7 +669,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { subHeadEntity1.addProperty("FUnitConvertDir", "1"); // 创建FStockId对象,并加入SubHeadEntity1 - //仓库代码为 半成品库007 + // 仓库代码为 半成品库007 JsonObject fStockId = new JsonObject(); fStockId.addProperty("FNumber", "007"); subHeadEntity1.add("FStockId", fStockId); @@ -581,29 +702,27 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { JsonObject subHeadEntity6 = new JsonObject(); model.add("SubHeadEntity6", subHeadEntity6); - //不同的属性不同的检验方案 + // 不同的属性不同的检验方案 if (states.equals("1")) { - //外购 + // 外购 subHeadEntity6.addProperty("FCheckIncoming", true); } if (states.equals("2")) { - //自制 + // 自制 subHeadEntity6.addProperty("FCheckProduct", true); subHeadEntity6.addProperty("FCheckReturnMtrl", true); } if (states.equals("3")) { - //委外 + // 委外 subHeadEntity6.addProperty("FCheckIncoming", true); subHeadEntity6.addProperty("FCheckProduct", true); subHeadEntity6.addProperty("FCheckReturnMtrl", true); } - // 创建SubHeadEntity5对象,并加入Model JsonObject subHeadEntity5 = new JsonObject(); model.add("SubHeadEntity5", subHeadEntity5); - // 创建FProduceUnitId对象,并加入SubHeadEntity5 JsonObject fProduceUnitId = new JsonObject(); fProduceUnitId.addProperty("FNumber", "jian"); @@ -636,13 +755,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { String jsonData = json.toString(); System.out.println(jsonData); try { - //业务对象标识 + // 业务对象标识 String formId = "BD_MATERIAL"; - //调用接口 + // 调用接口 String resultJson = client.save(formId, jsonData); - //用于记录结果 + // 用于记录结果 Gson gson = new Gson(); - //对返回结果进行解析和校验 + // 对返回结果进行解析和校验 RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class); if (repoRet.getResult().getResponseStatus().isIsSuccess()) { System.out.printf("接口返回结果: %s%n", gson.toJson(repoRet.getResult())); @@ -664,7 +783,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { code.startsWith("AC(") || code.startsWith("015") || code.contains("(M)") || code.startsWith("BC("); } - //保存到 BomDetails 表中 + // 保存到 BomDetails 表中 private void saveBomDetails(List bomDetailsVos) { List materialsToAdd = new ArrayList<>(); for (BomDetailsVo bomDetailsVo : bomDetailsVos) { @@ -713,7 +832,6 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { materialsToAdd.add(bomDetails); } - } // 新增不存在的物料 @@ -730,17 +848,18 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } // 更新物料状态 - // iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class)); + // iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class)); } } @Override public List pushGroupWeldments(ProcessRoute Bo) { - //获取这个项目中材质为组焊件 和这个物料为组焊件的图号 + // 获取这个项目中材质为组焊件 和这个物料为组焊件的图号 List processRoutes = baseMapper.selectList(); ArrayList routeArrayList = new ArrayList<>(); for (ProcessRoute processRoute : processRoutes) { - if (processRoute.getMaterial().equals("组焊件") && processRoute.getMaterialCode().equals(Bo.getMaterialCode())) { + if (processRoute.getMaterial().equals("组焊件") + && processRoute.getMaterialCode().equals(Bo.getMaterialCode())) { routeArrayList.add(processRoute); } } @@ -751,7 +870,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { public List getDistinctProjectCodes(String query) { QueryWrapper queryWrapper = new QueryWrapper<>(); // 使用 LIKE 进行模糊查询 - queryWrapper.select("DISTINCT route_description").like("route_description", query); // 根据 query 进行模糊匹配 + queryWrapper.select("DISTINCT route_description").like("route_description", query); // 根据 query 进行模糊匹配 // 获取查询结果 List resultList = baseMapper.selectObjs(queryWrapper); @@ -765,7 +884,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { @Override public List pushRawMater(String rooteProdet) { - // 拿到项目令号获取所有需要做工艺的物料 + // 拿到项目令号获取所有需要做工艺的物料 QueryWrapper queryWrapper = new QueryWrapper<>(); // 使用手动 SQL 的方式加入 DISTINCT queryWrapper.select("DISTINCT material_code", "material_name").eq("route_description", rooteProdet); @@ -775,9 +894,14 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { @Override public List getRawBom(String rooteProdet) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(ProcessRoute::getRouteDescription, rooteProdet).ne(ProcessRoute::getMaterial, "组焊件").isNotNull(ProcessRoute::getRawMaterialCode).ne(ProcessRoute::getRawMaterialCode, "").isNotNull(ProcessRoute::getRawMaterialName).ne(ProcessRoute::getRawMaterialName, "").and(wrapper1 -> wrapper1.likeRight(ProcessRoute::getRawMaterialCode, "015").or().likeRight(ProcessRoute::getRawMaterialCode, "AB")); - - + wrapper.eq(ProcessRoute::getRouteDescription, rooteProdet) + .ne(ProcessRoute::getMaterial, "组焊件") + .isNotNull(ProcessRoute::getRawMaterialCode) + .ne(ProcessRoute::getRawMaterialCode, "") + .isNotNull(ProcessRoute::getRawMaterialName) + .ne(ProcessRoute::getRawMaterialName, "") + .and(wrapper1 -> wrapper1.likeRight(ProcessRoute::getRawMaterialCode, "015") + .or().likeRight(ProcessRoute::getRawMaterialCode, "AB")); return baseMapper.selectList(wrapper); } @@ -787,7 +911,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { */ @Override public List getProcessRoute(String rooteProdet) { - //查出所有的带工序的物料 + // 查出所有的带工序的物料 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(ProcessRoute::getRouteDescription, rooteProdet).ne(ProcessRoute::getMaterialName, "") .ne(ProcessRoute::getProcessName, "按图订制") @@ -818,7 +942,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 获取当前物料编码对应的 ProcessRouteXuDTO ProcessRouteXuDTO xuDTO = groupedRoutes.get(materialCode); - // ProcessRouteDTO 对象并填充工序信息 + // ProcessRouteDTO 对象并填充工序信息 ProcessRouteDTO routeDTO = new ProcessRouteDTO(); routeDTO.setProcessNo(processRoute.getProcessNo()); routeDTO.setWorkCenter(processRoute.getWorkCenter()); @@ -838,24 +962,82 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { * 查询这个项目下的所有工艺路线,材料bom ,原材料bom集合 */ public List getRawBomList(String rooteProdet) { - return baseMapper.selectList(new LambdaQueryWrapper().eq(ProcessRoute::getRouteDescription, rooteProdet)); + return baseMapper + .selectList(new LambdaQueryWrapper().eq(ProcessRoute::getRouteDescription, rooteProdet)); } @Override - public List pushRouteBom(String rooteProdet) { + public ProcessRoutePushResultDTO pushRouteBom(String rooteProdet) { List rawBomList = getProcessRoute(rooteProdet); - for (ProcessRouteXuDTO processRouteXuDTO : rawBomList) { - LoadBomResult result = loadBillOfMaterialsPreservation(processRouteXuDTO); - // 处理返回结果 - if (result.isSuccess()) { - System.out.println("工艺路线保存保存成功: " + processRouteXuDTO.getMaterialCode() + result.getResultData()); + List successfulRoutes = new ArrayList<>(); + List failedRoutes = new ArrayList<>(); + List duplicateRoutes = new ArrayList<>(); + for (ProcessRouteXuDTO processRouteXuDTO : rawBomList) { + // 获取金蝶中的此物料工艺路线,在金蝶查询可能有多条工艺路线 + List jdProcessRoute = getSelectProcessRoute(processRouteXuDTO.getMaterialCode()); + Map> groupedByFNumber = jdProcessRoute.stream() + .collect(Collectors.groupingBy(ProcessRouteSelectDTO::getFNumber)); + // 当前物料的工艺路线 + List processRouteDT = processRouteXuDTO.getProcessRouteDT(); + // 比较工艺路线 + boolean isDifferent = compareProcessRoutes(processRouteDT, groupedByFNumber); + if (isDifferent) { + log.info("工艺路线不同,进行更新: " + processRouteXuDTO.getMaterialCode()); + + // 保存工艺路线 + LoadBomResult result = loadBillOfMaterialsPreservation(processRouteXuDTO); + // 处理返回结果 + if (result.isSuccess()) { + log.info("工艺路线保存成功: " + processRouteXuDTO.getMaterialCode() + result.getResultData()); + successfulRoutes.add(processRouteXuDTO); + } else { + log.info("工艺路线保存失败: " + processRouteXuDTO.getMaterialCode() + result.getMessage()); + failedRoutes.add(processRouteXuDTO); + } } else { - System.out.println("工艺路线保存保存失败: " + processRouteXuDTO.getMaterialCode() + result.getMessage()); + log.info("工艺路线相同,无需更新: " + processRouteXuDTO.getMaterialCode()); + duplicateRoutes.add(processRouteXuDTO.getMaterialCode()); } + } - return rawBomList; // + // 封装结果 + ProcessRoutePushResultDTO resultDTO = new ProcessRoutePushResultDTO(); + resultDTO.setSuccessfulRoutes(successfulRoutes); + resultDTO.setFailedRoutes(failedRoutes); + resultDTO.setDuplicateRoutes(duplicateRoutes); + return resultDTO; } + private boolean compareProcessRoutes(List processRouteDT, Map> groupedByFNumber) { + // 对当前物料的工艺路线进行排序 + processRouteDT.sort(Comparator.comparing(ProcessRouteDTO::getProcessNo)); + for (List jdRoutes : groupedByFNumber.values()) { + // 对金蝶中的工艺路线进行排序 + jdRoutes.sort(Comparator.comparing(ProcessRouteSelectDTO::getProcessNo)); + // 检查是否有任何一个金蝶工艺路线与当前物料的工艺路线相同 + if (areRoutesEqual(processRouteDT, jdRoutes)) { + return false; // 找到相同的工艺路线,不需要更新 + } + } + return true; // 没有找到相同的工艺路线,需要更新 + } + private boolean areRoutesEqual (List processRouteDT, List jdRoutes ) { + if (processRouteDT.size() != jdRoutes.size()) { + return false; + } + for (int i = 0; i < processRouteDT.size(); i++) { + ProcessRouteDTO localRoute = processRouteDT.get(i); + ProcessRouteSelectDTO jdRoute = jdRoutes.get(i); + if (!Objects.equals(localRoute.getProcessNo(), jdRoute.getProcessNo()) || + !Objects.equals(localRoute.getProcessName(), jdRoute.getProcessName()) || + !Objects.equals(localRoute.getWorkCenter(), jdRoute.getWorkCenter()) || + !Objects.equals(localRoute.getProcessControl(), jdRoute.getProcessControl()) || + !Objects.equals(localRoute.getActivityDuration(), jdRoute.getActivityDuration())) { + return false; + } + } + return true; + } /** * 查询工艺路线单据体 * @@ -865,7 +1047,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { @Override public List getSelecPlanRouteList(String rooteProdet) { // 根据生产令号查询生产订单编码,获取计划单据编号和工艺路线 - List planOrderList = getSelectProceOrder(rooteProdet); + List planOrderList = getSelectProceOrder1(rooteProdet); log.info("获取计划单号集合: planOrderList=====>" + planOrderList); @@ -873,7 +1055,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { List plannedProcesses = new ArrayList<>(); List combinedVoList = new ArrayList<>(); if (planOrderList == null || planOrderList.isEmpty()) { - return combinedVoList; // 返回空列表避免空指针异常 + return combinedVoList; // 返回空列表避免空指针异常 } K3CloudApi client = new K3CloudApi(); @@ -881,12 +1063,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 请求参数,要求为json字符串 JsonObject json = new JsonObject(); json.addProperty("FormId", "SFC_OperationPlanning"); - json.addProperty("FieldKeys", "FBillNo,FOperNumber,FProcessId.FName,FOptCtrlCodeId.FName,FActivity1BaseQty,FOperPlanStartTime,FOperPlanFinishTime,FOperQty,FDepartmentId.FName,FWorkCenterId.FName,FOperDescription,FPlanStartTime,FPlanFinishTime,FMOQty,FOperUnitId.FName"); + json.addProperty("FieldKeys", + "FBillNo,FOperNumber,FProcessId.FName,FOptCtrlCodeId.FName,FActivity1BaseQty,FOperPlanStartTime,FOperPlanFinishTime,FOperQty,FDepartmentId.FName,FWorkCenterId.FName,FOperDescription,FPlanStartTime,FPlanFinishTime,FMOQty,FOperUnitId.FName"); // 创建过滤条件 JsonArray filterString = new JsonArray(); JsonObject filterObject = new JsonObject(); filterObject.addProperty("FieldName", "FMONumber"); - filterObject.addProperty("Compare", "="); // 改为等号运算符 + filterObject.addProperty("Compare", "="); // 改为等号运算符 filterObject.addProperty("Value", planOrder.getFBillNo()); filterObject.addProperty("Left", ""); filterObject.addProperty("Right", ""); @@ -908,20 +1091,20 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 使用 ObjectMapper 将 JsonArray 转换为 List ObjectMapper objectMapper = new ObjectMapper(); - List plannedProcessList = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { - - }); + List plannedProcessList = objectMapper.readValue(jsonArray.toString(), + new TypeReference>() { + }); // 检查 plannedProcessList 是否为 null,避免空指针异常 if (plannedProcessList != null && !plannedProcessList.isEmpty()) { - plannedProcesses.addAll(plannedProcessList); // 将非空列表添加到最终列表中 + plannedProcesses.addAll(plannedProcessList); // 将非空列表添加到最终列表中 } - //获取用料清单列表 + // 获取用料清单列表 List materialUseList = getSelectMaterialUseList(planOrder.getFBillNo()); // 4. 将 PlanOrderVo 和对应的 PlannedProcessVo 合并成一个对象 CombinedDTO combined = new CombinedDTO(); - combined.setOrderNumber(planOrder.getFBillNo()); // 生产订单号 + combined.setOrderNumber(planOrder.getFBillNo()); // 生产订单号 combined.setMaterialCode(planOrder.getFmaterialidFnumber()); // 物料编码 combined.setMaterialName(planOrder.getFMaterialName()); // 物料名称 combined.setProcesses(plannedProcessList); @@ -931,27 +1114,27 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { combinedVoList.add(combined); } catch (Exception e) { - e.printStackTrace(); // 输出异常日志 + e.printStackTrace(); // 输出异常日志 } } - return combinedVoList; // 返回结果 + return combinedVoList; // 返回结果 } @Override - public List generatePDFs(String rooteProdet) { + public String generatePDFs(String rooteProdet) { List selecPlanRouteList = getSelecPlanRouteList(rooteProdet); - PDFGenerator.writeToPdf(selecPlanRouteList, rooteProdet); - return null; + String pathZIP = PDFGenerator.writeToPdf(selecPlanRouteList, rooteProdet); + return pathZIP; } - public List getSelectProceOrder(String rooteProdet) { K3CloudApi client = new K3CloudApi(); - //请求参数,要求为json字符串 + // 请求参数,要求为json字符串 JsonObject json = new JsonObject(); json.addProperty("FormId", "PRD_MO"); - json.addProperty("FieldKeys", "F_HBYT_SCLH,FBillNo ,FMaterialId.FNumber,FMaterialName, F_UCHN_BaseProperty_qtr"); + json.addProperty("FieldKeys", + "F_HBYT_SCLH,FBillNo ,FMaterialId.FNumber,FMaterialName, F_UCHN_BaseProperty_qtr"); JsonArray filterString = new JsonArray(); JsonObject filterObject = new JsonObject(); filterObject.addProperty("FieldName", "F_HBYT_SCLH"); @@ -977,8 +1160,9 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); // 将JsonArray转为PlanOrder列表 ObjectMapper objectMapper = new ObjectMapper(); - List planOrders = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { - }); + List planOrders = objectMapper.readValue(jsonArray.toString(), + new TypeReference>() { + }); // 输出或返回结果 System.out.println(planOrders); return planOrders; @@ -989,14 +1173,79 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } } - //获取计划订单列表 + public List getSelectProceOrder1(String rooteProdet) { + K3CloudApi client = new K3CloudApi(); + + // 第一次查询:使用 F_HBYT_SCLH + List result = queryWithFieldName(client, "F_HBYT_SCLH", rooteProdet); + + /* + * // 如果第一次查询结果为空,使用 子生产令号 重新查询 + * if (result == null || result.isEmpty()) { + * result = queryWithFieldName(client, "F_HBYT_ZSCLH", rooteProdet); + * } + */ + return result; + } + + // 将查询方法提取为私有方法 + private List queryWithFieldName(K3CloudApi client, String fieldName, String rooteProdet) { + JsonObject json = new JsonObject(); + json.addProperty("FormId", "PRD_MO"); + json.addProperty("FieldKeys", + "F_HBYT_SCLH,FBillNo ,FMaterialId.FNumber,FMaterialName, F_UCHN_BaseProperty_qtr"); + + JsonArray filterString = new JsonArray(); + JsonObject filterObject = new JsonObject(); + filterObject.addProperty("FieldName", fieldName); // 使用传入的 fieldName + filterObject.addProperty("Compare", "67"); + filterObject.addProperty("Value", rooteProdet); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 0); + filterString.add(filterObject); + + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 2000); + json.addProperty("SubSystemId", ""); + + try { + String jsonData = json.toString(); + String resultJson = String.valueOf(client.billQuery(jsonData)); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + + // 检查结果是否为空 + if (jsonArray == null || jsonArray.size() == 0) { + return null; + } + + // 转换结果 + ObjectMapper objectMapper = new ObjectMapper(); + List planOrders = objectMapper.readValue( + jsonArray.toString(), + new TypeReference>() { + }); + + return planOrders; + + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + // 获取用料清单列表 public List getSelectMaterialUseList(String FBillNo) { K3CloudApi client = new K3CloudApi(); - //请求参数,要求为json字符串 + // 请求参数,要求为json字符串 JsonObject json = new JsonObject(); json.addProperty("FormId", "PRD_PPBOM"); - json.addProperty("FieldKeys", "FBillNo,FMaterialID2.FNumber,FMaterialName1,FMaterialModel1,F_HBYT_CZ,FMaterialType,FMustQty,FPickedQty,FStockID.FName,FMEMO1,FUnitID2.FName,FNumerator,FDenominator"); + json.addProperty("FieldKeys", + "FBillNo,FMaterialID2.FNumber,FMaterialName1,FMaterialModel1,F_HBYT_CZ,FMaterialType,FMustQty,FPickedQty,FStockID.FName,FMEMO1,FUnitID2.FName,FNumerator,FDenominator"); JsonArray filterString = new JsonArray(); JsonObject filterObject = new JsonObject(); filterObject.addProperty("FieldName", "FMOBillNO"); @@ -1021,30 +1270,29 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); // 将JsonArray转为PlanOrder列表 ObjectMapper objectMapper = new ObjectMapper(); - List planOrders = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + return objectMapper.readValue(jsonArray.toString(), new TypeReference>() { }); - return planOrders; } catch (Exception e) { e.printStackTrace(); return null; } } - //工艺保存方法 + // 工艺保存方法 public LoadBomResult loadBillOfMaterialsPreservation(ProcessRouteXuDTO rawBomList) { // TODO: 实现加载和保存物料清单数据的逻辑 K3CloudApi client = new K3CloudApi(); ProcessModel processModel = createProcessModel(rawBomList); String jsonStr = JSONUtil.toJsonStr(processModel); try { - //业务对象标识 + // 业务对象标识 String formId = "ENG_Route"; - //调用接口 + // 调用接口 String resultJson = client.save(formId, jsonStr); - //用于记录结果 + // 用于记录结果 Gson gson = new Gson(); - //对返回结果进行解析和校验 + // 对返回结果进行解析和校验 RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class); if (repoRet.getResult().getResponseStatus().isIsSuccess()) { String result = gson.toJson(repoRet.getResult()); @@ -1141,37 +1389,84 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { @Override public R addRoute(List list) { - List routeArrayList = new ArrayList<>(); - for (ProcessRouteVo vo : list) { + list.sort(Comparator.comparing(ProcessRouteVo::getProcessNo)); + ProcessRouteVo previousVo = null; + + for (int i = 0; i < list.size(); i++) { + ProcessRouteVo vo = list.get(i); ProcessRoute route = new ProcessRoute(); route.setRouteDescription(vo.getRouteDescription()); route.setMaterialCode(vo.getMaterialCode()); route.setMaterialName(vo.getMaterialName()); route.setProcessNo(vo.getProcessNo()); - route.setWorkCenter(vo.getWorkCenter()); + String workCenter = vo.getWorkCenter(); + route.setWorkCenter(workCenter); route.setDiscWeight(vo.getDiscWeight()); route.setMaterial(vo.getMaterial()); route.setProcessName(vo.getProcessName()); - route.setProcessControl(vo.getProcessControl()); + // 工序控制码的逻辑判断 如果传进来的多个工序控制码中 连续的几个工序有相同的工作中心,其中相同的工序中,最大的工序号为控制码为汇报+质量 其余的为汇报+免检 + // 如果传进来的多个工序控制码中没有相同的工作中心,则直接返回汇报+质量 + + // 判断是否为最后一道工序 + boolean isLastProcess = (i == list.size() - 1); + // 设置工序控制码 + String processControl = determineProcessControl(vo, previousVo, isLastProcess); + route.setProcessControl(processControl); + route.setProcessDescription(vo.getProcessDescription()); route.setActivityDuration(vo.getActivityDuration()); route.setActivityUnit("分"); routeArrayList.add(route); + previousVo = vo; // 更新 previousVo 为当前工序 } + // 对工序列表进行工序控制码校验和设置 + setoProcessControl(routeArrayList); if (baseMapper.insertBatch(routeArrayList)) { return R.ok(); } - return null; + return R.fail("添加工艺路线失败"); + } + + /** + * 确定工序控制码 + * + * @param currentVo 当前工序 + * @param previousVo 上一道工序 + * @return 工序控制码 + */ + private String determineProcessControl(ProcessRouteVo currentVo, ProcessRouteVo previousVo, boolean isLastProcess) { + // 工序控制码的逻辑判断 如果传进来的多个工序控制码中有相同的工作中心,其中相同的工序中,最大的工序号为控制码为汇报+质量 其余的为汇报+免检 + // 如果传进来的多个工序控制码中没有相同的工作中心,则直接返回汇报+质量 + + // 1. 如果是委外中心,直接返回"委外+质量" + + if ("委外中心".equals(currentVo.getWorkCenter())) { + return "委外+质量"; + } + + // 2. 如果是最后一道工序,返回"汇报+质量" + if (isLastProcess) { + return "汇报+质量"; + } + + // 3. 检查与上一道工序的工作中心是否相同(如果存在上一道工序) + if (previousVo != null && currentVo.getWorkCenter().equals(previousVo.getWorkCenter())) { + return "汇报+免检"; + } + + // 4. 默认返回"汇报+质量" + return "汇报+免检"; } /** * 查询材料bom */ @Override - public List getProcessMaterialList(String materialCode, String materialName, String productionOrderNo) { + public List getProcessMaterialList(String materialCode, String materialName, + String productionOrderNo) { if (materialCode == null) { logger.error("做工艺的物料不存在"); throw new IllegalArgumentException("做工艺的物料不能为空"); @@ -1184,11 +1479,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { return materialBomMapper.selectList(wrapper); } - //是否是按图定制的物料 - public Boolean insertByBoToBom(MaterialBomBo bo){ - return false; + // 是否是按图定制的物料 + public Boolean insertByBoToBom(MaterialBomBo bo) { + + return false; } + /** * 删除工序 */ @@ -1196,7 +1493,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { public List deleteRoute(ProcessRoute processRoute) { int rowsAffected = baseMapper.deleteById(processRoute.getId()); if (rowsAffected > 0) { - //获取删除后其他的 工序,然后更新工序号 + // 获取删除后其他的 工序,然后更新工序号 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(ProcessRoute::getRouteDescription, processRoute.getRouteDescription()) .eq(ProcessRoute::getMaterialCode, processRoute.getMaterialCode()) @@ -1204,13 +1501,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { .isNotNull(ProcessRoute::getProcessNo); List routeList = baseMapper.selectList(wrapper); - //工序号升序排序 + // 工序号升序排序 routeList.sort(Comparator.comparing(ProcessRoute::getProcessNo)); for (int i = 0; i < routeList.size(); i++) { routeList.get(i).setProcessNo((long) (i + 1) * 10); } - //批量更新 + // 批量更新 baseMapper.insertOrUpdateBatch(routeList); return routeList; } else { @@ -1220,18 +1517,19 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { /** * 导入更新时间 + * * @param list * @return */ public List importDataTime1(List list) { - if (!list.isEmpty()){ + if (!list.isEmpty()) { for (ProcessRouteVo processRouteVo : list) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(ProcessRoute::getRouteDescription,processRouteVo.getRouteDescription()); + wrapper.eq(ProcessRoute::getRouteDescription, processRouteVo.getRouteDescription()); List processRoutes = baseMapper.selectList(wrapper); for (ProcessRoute processRoute : processRoutes) { - if (processRouteVo.getMaterialCode().equals(processRoute.getMaterialCode())){ + if (processRouteVo.getMaterialCode().equals(processRoute.getMaterialCode())) { processRoute.setXuStartTime(processRouteVo.getXuStartTime()); processRoute.setXuEndTime(processRouteVo.getXuEndTime()); } @@ -1241,12 +1539,12 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } } - return null; } /** * 导入更新时间 + * * @param list 工艺路线列表 * @return 更新后的工艺路线列表 */ @@ -1279,15 +1577,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 3. 建立复合键映射关系,用于快速查找 Map> routeMap = allProcessRoutes.stream() - .collect(Collectors.groupingBy(route -> - generateKey(route.getRouteDescription(), - route.getMaterialCode(), - route.getProcessNo(), - route.getMaterialName(), - route.getProcessName(), - route.getProcessControl(), - route.getActivityDuration()) - )); + .collect(Collectors.groupingBy(route -> generateKey(route.getRouteDescription(), + route.getMaterialCode(), + route.getProcessNo(), + route.getMaterialName(), + route.getProcessName(), + route.getProcessControl(), + route.getActivityDuration()))); // 4. 批量更新数据 List updatedRoutes = new ArrayList<>(); @@ -1328,6 +1624,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { /** * 是否是按图订购 + * * @param materialCode * @return */ @@ -1336,7 +1633,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(ProcessRoute::getMaterialCode, materialCode); wrapper.eq(ProcessRoute::getProcessName, "按图订制"); - //查询数量 + // 查询数量 Long count = baseMapper.selectCount(wrapper); return count > 0; } @@ -1346,12 +1643,12 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { * 用于匹配所有需要的字段 */ private String generateKey(String routeDescription, - String materialCode, - Long processNo, - String materialName, - String processName, - String processControl, - Double activityDuration) { + String materialCode, + Long processNo, + String materialName, + String processName, + String processControl, + Double activityDuration) { return String.format("%s:%s:%s:%s:%s:%s:%s", StringUtils.defaultString(routeDescription, ""), StringUtils.defaultString(materialCode, ""), @@ -1359,13 +1656,14 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { StringUtils.defaultString(materialName, ""), StringUtils.defaultString(processName, ""), StringUtils.defaultString(processControl, ""), - activityDuration == null?"" : activityDuration.toString()); + activityDuration == null ? "" : activityDuration.toString()); } + /** - * 获取计划订单编号,然后获取计划订单详情 单据内码 行内码 + * 获取计划订单编号,然后获取计划订单详情 单据内码 行内码 */ public List getSelecPlan(String rooteProdet) { - List planOrderList = getSelectProceOrder(rooteProdet); + List planOrderList = getSelectProceOrder1(rooteProdet); log.info("获取计划单号集合: planOrderList=====>" + planOrderList); List plannedProcesses = new ArrayList<>(); K3CloudApi client = new K3CloudApi(); @@ -1375,13 +1673,15 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { for (PlanOrderVo planOrder : planOrderList) { JsonObject json = new JsonObject(); json.addProperty("FormId", "SFC_OperationPlanning"); - json.addProperty("FieldKeys", "FID,FSubEntity_FDetailID,FProductId.FNumber,FOperNumber,FEntity_FEntryID,FProcessId.FName,FSeqNumber,FSeqName,FPlanStartTime,FPlanFinishTime," + - "FOperPlanStartTime,FOperPlanFinishTime"); + json.addProperty("FieldKeys", + "FID,FSubEntity_FDetailID,FProductId.FNumber,FOperNumber,FEntity_FEntryID,FProcessId.FName,FSeqNumber,FSeqName,FPlanStartTime,FPlanFinishTime," + + + "FOperPlanStartTime,FOperPlanFinishTime"); JsonArray filterString = new JsonArray(); JsonObject filterObject = new JsonObject(); filterObject.addProperty("FieldName", "FMONumber"); - filterObject.addProperty("Compare", "="); // 改为等号运算符 + filterObject.addProperty("Compare", "="); // 改为等号运算符 filterObject.addProperty("Value", planOrder.getFBillNo()); filterObject.addProperty("Left", ""); filterObject.addProperty("Right", ""); @@ -1399,8 +1699,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { try { String resultJson = String.valueOf(client.billQuery(jsonData)); System.out.println( - "生成查询计划订单查询 " + planOrder.getFBillNo() + " 的结果: " + resultJson - ); + "生成查询计划订单查询 " + planOrder.getFBillNo() + " 的结果: " + resultJson); JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); if (jsonArray == null || jsonArray.size() == 0) { log.info("查询订单 {} 时没有返回数据", planOrder.getFBillNo()); @@ -1408,8 +1707,9 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } ObjectMapper objectMapper = new ObjectMapper(); - List plannedProcessList = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { - }); + List plannedProcessList = objectMapper.readValue(jsonArray.toString(), + new TypeReference>() { + }); if (plannedProcessList != null && !plannedProcessList.isEmpty()) { plannedProcesses.addAll(plannedProcessList); } @@ -1430,7 +1730,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 使用 Map 结构暂存 Model 对象 Map modelMap = new HashMap<>(); for (PlanPrcessNumDTO dto : plannedProcesses) { - // 获取或创建 Model 对象 + // ��取或创建 Model 对象 Model model = modelMap.computeIfAbsent(dto.getFID(), fid -> { Model newModel = new Model(); newModel.setFID(fid); @@ -1504,5 +1804,45 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { return timeInfo; } + // 获取存在工艺 + public List getSelectProcessRoute(String materialCode) { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "ENG_Route"); + + json.addProperty("FieldKeys", + "FNumber,FMATERIALID.FNumber,FMATERIALNAME,FOperNumber,FProcessProperty,FWorkCenterId.FName,FOperDescription,FOptCtrlCodeId.FName,FActivity1Qty"); + JsonArray filterString = new JsonArray(); + JsonObject filterObject = new JsonObject(); + filterObject.addProperty("FieldName", "FMATERIALID.FNumber"); + filterObject.addProperty("Compare", "67"); + filterObject.addProperty("Value", materialCode); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 0); + filterString.add(filterObject); + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 2000); + json.addProperty("SubSystemId", ""); + + String jsonData = json.toString(); + String resultJson; + try { + // 调用API接口 + resultJson = String.valueOf(client.billQuery(jsonData)); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + // 将JsonArray转为PlanOrder列表 + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + }); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } }