diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index a788a81..0238aea 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -167,6 +167,12 @@ org.bouncycastle bcprov-jdk15to18 + + com.hierynomus + smbj + 0.14.0 + + com.itextpdf diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java index e3bfa40..a27373e 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java @@ -34,6 +34,8 @@ public class SecurityConfig { .antMatchers("/system/proPlan/**").anonymous() .antMatchers("/system/mrp/**").anonymous() .antMatchers("/system/orderPro/**").anonymous() + .antMatchers("/system/cost/**").anonymous() + .antMatchers("/dev-api/system/cost/**").anonymous() // .antMatchers("/dev-api/system/proPlan/overdue").anonymous() // .antMatchers("/dev-api/system/proPlan/expiryProjects").anonymous() .antMatchers("/dev-api/system/material/list/").anonymous() diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml index b5d9c14..fc2d270 100644 --- a/ruoyi-system/pom.xml +++ b/ruoyi-system/pom.xml @@ -6,7 +6,7 @@ ruoyi-vue-plus com.ruoyi 4.7.0 - + org.apache.maven.pluginsmaven-compiler-plugin88 4.0.0 ruoyi-system 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 57d44de..4b97a28 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 @@ -21,21 +21,20 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.result.BOMUploadResult; +import com.ruoyi.system.domain.dto.BOMItem; +import com.ruoyi.system.domain.dto.BOMUploadResult; import com.ruoyi.common.utils.JdUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.BomDetails; -import com.ruoyi.system.domain.FigureSave; import com.ruoyi.system.domain.MaterialProperties; import com.ruoyi.system.domain.ProcessOrderPro; import com.ruoyi.system.domain.bo.BomDetailsBo; -import com.ruoyi.system.domain.bo.ProcessOrderProBo; import com.ruoyi.system.domain.dto.JdValidateBomDTO; import com.ruoyi.system.domain.dto.JdChildDTO; import com.ruoyi.system.domain.dto.KindegeeLogDTO; import com.ruoyi.system.domain.vo.BomDetailsVo; import com.ruoyi.system.domain.vo.ElectricalMaterialBomVO; -import com.ruoyi.system.mapper.FigureSaveMapper; +import com.ruoyi.system.mapper.BomDetailsMapper; import com.ruoyi.system.mapper.ProcessOrderProMapper; import com.ruoyi.system.runner.JdUtil; import com.ruoyi.system.service.*; @@ -45,8 +44,6 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.WorkbookFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -84,8 +81,10 @@ public class BomDetailsController extends BaseController { private final IProcessOrderProService iProcessOrderProService; - private final IFigureSaveService iFigureSaveService; private final ProcessOrderProMapper processOrderProMapper; + + private final BomDetailsMapper bomDetailsMapper; + /** * 查询bom明细列表 */ @@ -382,27 +381,38 @@ public class BomDetailsController extends BaseController { for (BomDetails material : bomDetails) { // 获取工艺表中的非委外工时 Double fbWorkTime = iProcessRouteService.getFbWorkTime(material); - if (material.getPartNumber() != null && material.getName() != null && material.getUnitWeight().equals("否")) { String state = determineState(material); - log.info("开始新增不存在的物料 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName()); - try { - int result = loadMaterialPreservation(material, state, fbWorkTime); - if (result == 1) { - log.info("新增物料成功 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName()); - material.setUnitWeight("新增成功"); - } else { - log.error("新增物料失败 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName()); + //判断bom类型是生产还是电气 + if (material.getBomType().equals("0")) { + try { + int result = loadMaterialPreservation(material, state, fbWorkTime); + if (result == 1) { + material.setUnitWeight("新增成功"); + } else { + failedMaterials.add(material.getPartNumber()); + } + // 更新物料状态 + iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class)); + } catch (Exception e) { + failedMaterials.add(material.getPartNumber()); + } + } else { + try { + int result = loadMaterialToDQ(material, state); + if (result == 1) { + material.setUnitWeight("新增成功"); + } else { + failedMaterials.add(material.getPartNumber()); + } + // 更新物料状态 + iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class)); + } catch (Exception e) { failedMaterials.add(material.getPartNumber()); } - // 更新物料状态 - iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class)); - } catch (Exception e) { - log.error("处理物料时发生异常: {}", e.getMessage()); - failedMaterials.add(material.getPartNumber()); } + } else { - log.error("物料信息不完整,无法新增物料"); failedMaterials.add(material.getPartNumber()); } } @@ -411,22 +421,20 @@ public class BomDetailsController extends BaseController { boolean needUpload = !validateBOM(fnumber, bomDetails); if (needUpload) { try { - // 物料清单保存方法 + // 物料清单保存方法,判断是电气还是生产 BOMUploadResult bomUploadResult = FBloadBillOfMaterialsPreservation(bomDetails, bo); if (bomUploadResult.isSuccess()) { KindegeeLogDTO logDTO = new KindegeeLogDTO(); logDTO.setProjectCode(bo.getProductionOrderNo()); logDTO.setMaterialCode(fnumber); // 使用物料编码而不是单个物料的编码 - logDTO.setMaterialName(fname); - logDTO.setCode(bomUploadResult.getNumber()); - logDTO.setReason(bomUploadResult.getNumber()+"OK"); + logDTO.setCode("200"); + logDTO.setReason("成功上传"+"版本号:"+bomUploadResult.getNumber()); logDTOS.add(logDTO); } else { KindegeeLogDTO logDTO = new KindegeeLogDTO(); logDTO.setProjectCode(bo.getProductionOrderNo()); logDTO.setMaterialCode(fnumber); - logDTO.setMaterialName(fname); - logDTO.setCode(bomUploadResult.getNumber()); + logDTO.setCode("300"); logDTO.setReason(bomUploadResult.getErrorMessage()); logDTOS.add(logDTO); } @@ -439,8 +447,7 @@ public class BomDetailsController extends BaseController { KindegeeLogDTO logDTO = new KindegeeLogDTO(); logDTO.setProjectCode(bo.getProductionOrderNo()); logDTO.setMaterialCode(fnumber); - logDTO.setMaterialName(fname); - logDTO.setCode("200"); + logDTO.setCode("100"); logDTO.setReason("BOM已存在且一致"); logDTOS.add(logDTO); log.info("BOM已存在且一致,物料编码: {},跳过保存", fnumber); @@ -450,13 +457,14 @@ public class BomDetailsController extends BaseController { //更新项目进度 ProcessOrderPro processOrderProBo = iProcessOrderProService.selectByProjectNumber(totalWeight); - processOrderProBo.setDrawingType( JSONUtil.toJsonStr(logDTOS)); + processOrderProBo.setDrawingType(JSONUtil.toJsonStr(logDTOS)); processOrderProBo.setBomStatus(2L); processOrderProMapper.updateById(processOrderProBo); // 返回处理结果 return R.ok("成功", bomDetailsList); } + private boolean validateBOM(String fnumber, List bomDetails) { List JDBomList = JdUtil.getSelectBomList(fnumber); @@ -701,7 +709,7 @@ public class BomDetailsController extends BaseController { } // FBOM物料清单保存 - public BOMUploadResult FBloadBillOfMaterialsPreservation(List bomlist, ProcessOrderPro bo) { + public BOMUploadResult FBloadBillOfMaterialsPreservation(List bomlist, ProcessOrderPro bo) { BomDetails bomDetails1 = bomlist.get(0); int verification = isMaterialVerification(bomDetails1.getFNumber(), bomDetails1.getFName()); @@ -805,9 +813,7 @@ public class BomDetailsController extends BaseController { fTreeEntityItem.addProperty("F_HBYT_BJBM", details.getPartdiagramCode()); fTreeEntityItem.addProperty("F_HBYT_BJMC", details.getPartdiagramName()); fTreeEntityItem.addProperty("FDOSAGETYPE", "2"); - //判断这个在原材料表中单位如果是根,的话 那分子就是1 分母就是分子 - - fTreeEntityItem.addProperty("FNUMERATOR", details.getQuantity()); + fTreeEntityItem.addProperty("FNUMERATOR", details.getQuantity()); // 分子 fTreeEntityItem.addProperty("FDENOMINATOR", details.getDenominator()); // 添加货主信息 查看这个bom中是否符合货主信息 @@ -1724,7 +1730,10 @@ public class BomDetailsController extends BaseController { return 1; } - // 创建电气物料 + /** + * / 创建电气物料 + */ + public int loadMaterialToDQ(BomDetails bomDetails1, String states) { K3CloudApi client = new K3CloudApi(); // 创建一个空的JsonObject @@ -1738,7 +1747,8 @@ public class BomDetailsController extends BaseController { // 添加Model字段 model.addProperty("FMATERIALID", 0); - model.addProperty("FSpecification", bomDetails1.getRemarks());// 备注仓库 + model.addProperty("FSpecification", bomDetails1.getMaterial());// 规格 为存入的材质字段 + model.addProperty("F_HBYT_PP", bomDetails1.getWareHouse());// 品牌 为存入的仓库字段 model.addProperty("FNumber", bomDetails1.getPartNumber()); model.addProperty("FName", bomDetails1.getName()); MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(bomDetails1.getMaterial()); @@ -2108,10 +2118,9 @@ public class BomDetailsController extends BaseController { subHeadEntity1.add("FPickStockId", fPickStockId); subHeadEntity5.addProperty("FOverControlMode", "1"); - subHeadEntity5.addProperty("FStandHourUnitId", "3600"); + subHeadEntity5.addProperty("FStandHourUnitId", "60"); subHeadEntity5.addProperty("FBackFlushType", "1"); String jsonData = json.toString(); - System.out.println(jsonData); try { // 业务对象标识 String formId = "BD_MATERIAL"; @@ -2135,6 +2144,7 @@ public class BomDetailsController extends BaseController { } return 1; } + public BOMUploadResult parseK3Response(String jsonResponse) { try { ObjectMapper mapper = new ObjectMapper(); @@ -2166,20 +2176,61 @@ public class BomDetailsController extends BaseController { * @param file 导入文件 */ - @Log(title = "明细导入", businessType = BusinessType.IMPORT) - @SaCheckPermission("system:details:import") - @PostMapping(value = "/importData21", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public R importData21(@RequestPart("file") MultipartFile file) throws Exception { + @Log(title = "导入电气bom", businessType = BusinessType.IMPORT) + @SaCheckPermission("system:details:importElectricalBom") + @PostMapping(value = "/importElectricalBom", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public void importElectricalBom(@RequestPart("file") MultipartFile file) throws Exception { List electricalMaterialBomVOS = ExcelUtil.importExcel(file.getInputStream(), ElectricalMaterialBomVO.class); + List list = new ArrayList<>(); for (ElectricalMaterialBomVO bomVO : electricalMaterialBomVOS) { BomDetails bomDetails = new BomDetails(); bomDetails.setTotalWeight(bomVO.getProductionOrderNo()); - bomDetails.setFNumber(bomVO.getDrawingNo()); - bomDetails.setFName(bomVO.getDrawingName()); - bomDetails.setPartdiagramCode(bomVO.getParentDrawingNo()); - bomDetails.setPartdiagramName(bomVO.getParentPart()); + bomDetails.setFNumber(bomVO.getParentDrawingNo()); + bomDetails.setFName(bomVO.getParentPart()); + bomDetails.setPartNumber(bomVO.getDrawingNo()); + bomDetails.setName(bomVO.getDrawingName()); + bomDetails.setMaterial(bomVO.getModel());// + bomDetails.setWareHouse(bomVO.getBrand()); + bomDetails.setStats("外购"); + String quantity = bomVO.getQuantity().toString(); + bomDetails.setQuantity(quantity); + bomDetails.setRemarks(bomVO.getUnit()); + bomDetails.setUpdateTime(new Date()); + bomDetails.setBomType("1");//0 是生产bom 1 是电气bom + list.add(bomDetails); } - return null; + List bomDetailsVos1 = BeanUtil.copyToList(list, BomDetailsVo.class); + List bomDetails = saveBomDetails(bomDetailsVos1); + bomDetailsMapper.insertBatch(bomDetails); + + } + + // 保存到 BomDetails 表中 + //TODO: 使用本地库加速 + private List saveBomDetails(List bomDetailsVos) { + List materialsToAdd = new ArrayList<>(); + for (BomDetailsVo bomDetailsVo : bomDetailsVos) { + BomDetails bomDetails = BeanUtil.toBean(bomDetailsVo, BomDetails.class); + // 验证物料是否存在 + int materialVerification = isMaterialVerification(bomDetails.getPartNumber(), bomDetails.getName()); + if (materialVerification == 1) { + bomDetails.setUnitWeight("是"); + materialsToAdd.add(bomDetails); + } else if (materialVerification == 2) { + bomDetails.setUnitWeight("否"); + materialsToAdd.add(bomDetails); + } else if (materialVerification == 3) { + bomDetails.setUnitWeight("编码名称不符"); + materialsToAdd.add(bomDetails); + } + } + return materialsToAdd; + } + @Log(title = "推送工艺工序") + @SaCheckPermission("system:route:viewGetBomUploadStatus") + @PostMapping("/viewGetBomUploadStatus") + public R viewGetBomUploadStatus(@RequestParam String rooteProdet) { + return iProcessRouteService.viewGetBomUploadStatus(rooteProdet); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomVariableController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomVariableController.java index d76f63a..bd3c1c0 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomVariableController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/BomVariableController.java @@ -267,7 +267,7 @@ public class BomVariableController extends BaseController { if (decimalIndex != -1) { quantityStr = quantityStr.substring(0, decimalIndex); } - bomDetails.setQuantity(Double.valueOf(quantityStr)); + bomDetails.setQuantity(quantityStr); } // 检查并转换单重 if (!rowData.get(5).isEmpty()) { diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ImMaterialController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ImMaterialController.java index 3707ac6..88bc4de 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ImMaterialController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ImMaterialController.java @@ -271,7 +271,7 @@ public class ImMaterialController extends BaseController { @XxlJob("updateMaterials") public Boolean updateMaterials() throws Exception { Date date = new Date(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); List imMaterials = updateJdMaterial(sdf.format(date)); Boolean result = iImMaterialService.updateByFMid(imMaterials); return result; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/KingdeeWorkCenterDataController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/KingdeeWorkCenterDataController.java index 3feff7d..7e529b9 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/KingdeeWorkCenterDataController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/KingdeeWorkCenterDataController.java @@ -2,8 +2,10 @@ package com.ruoyi.system.controller; import java.io.File; import java.time.LocalDate; +import java.time.temporal.ChronoUnit; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.stream.Collectors; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; @@ -19,12 +21,14 @@ import com.ruoyi.common.utils.HttpRequestUtil; import com.ruoyi.common.utils.WxRobotUtil; import com.ruoyi.common.poi.ExcelTemplateProc; import com.ruoyi.common.poi.DynamicDataMapping; +import com.ruoyi.system.domain.ProcessRoute; import com.ruoyi.system.domain.SafetyStock; import com.ruoyi.system.domain.WlStockData; import com.ruoyi.system.domain.dto.*; import com.ruoyi.system.domain.vo.WlStockDataVo; import com.ruoyi.system.mapper.WlStockDataMapper; import com.ruoyi.system.runner.JdUtil; +import com.ruoyi.system.service.IProcessRouteService; import com.ruoyi.system.service.ISafetyStockService; import com.xxl.job.core.handler.annotation.XxlJob; import lombok.RequiredArgsConstructor; @@ -39,6 +43,7 @@ import cn.hutool.core.collection.CollUtil; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; import com.ruoyi.common.annotation.RepeatSubmit; @@ -74,7 +79,8 @@ public class KingdeeWorkCenterDataController extends BaseController { private static final Logger log = LoggerFactory.getLogger(KingdeeWorkCenterDataController.class); private final WlStockDataMapper baseMapper; private final ISafetyStockService iSafetyStockService; - + @Autowired + IProcessRouteService iProcessRouteService; /** * 查询金蝶工段数据列表 */ @@ -381,8 +387,9 @@ public class KingdeeWorkCenterDataController extends BaseController { msg.append("- ").append(workCenter).append(" (无数据)\n"); continue; } - - List dataList = result.getData(); + //加入暂停项目的过滤 + List dataList = result.getData().stream().filter(item -> item.getMoOrderNo() != null && !item.getMoOrderNo().contains("暂停")) + .collect(Collectors.toList()); msg.append("- ").append(workCenter).append(" (共").append(dataList.size()).append("条数据)\n"); // 生成Excel文件 @@ -433,10 +440,8 @@ public class KingdeeWorkCenterDataController extends BaseController { List kingdeeWorkCenterDataVos = new ArrayList<>(); parameter.addProperty("FWorkCenterName", workCenter); Object[] parameters = new Object[]{parameter.toString()}; - String execute = client.execute( - "Ljint.Kingdee.YiTe.KanBan.WebApi.ProduceWebApi.ExecuteService,Ljint.Kingdee.YiTe.KanBan.WebApi", - parameters); - log.info("金蝶接口返回数据: {}", execute); + String execute = client.execute("Ljint.Kingdee.YiTe.KanBan.WebApi.ProduceWebApi.ExecuteService,Ljint.Kingdee.YiTe.KanBan.WebApi121303", parameters); + log.info("金蝶接口:" + workCenter + "===> 返回数据: {}", execute); // 解析响应 JSONObject response = JSONObject.parseObject(execute); @@ -444,7 +449,6 @@ public class KingdeeWorkCenterDataController extends BaseController { String errorMsg = response.getString("Message"); return R.fail("获取工段数据失败:" + errorMsg); } - // 获取明天的日期字符串 (格式: yyyy-MM-dd) String yesterday = DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd"); @@ -518,26 +522,30 @@ public class KingdeeWorkCenterDataController extends BaseController { public R getMassageDelayDate() { try { // String robotId = "4d2f037d-0cee-493a-a4ff-1758f67b8069"; - String robotId = "483489b2-b219-468c-851f-f56a34a62d91"; + String robotId = "483489b2-b219-468c-851f-f56a34a62d91"; + // String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e"; List workCenters = Arrays.asList("机一工段", "机二工段", "机三工段", "装一工段", "装二工段", "委外中心", "电钳工段", "铆焊工段"); String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"); - StringBuilder msg = new StringBuilder(); - msg.append("🏭 延期数据更新提醒\n\n") - .append("更新时间:").append(currentTime).append("\n\n") - .append("🔧 工作中心数据统计:\n"); + // 构建Markdown消息 + StringBuilder markdownMsg = new StringBuilder(); + markdownMsg.append("# 生产延期数据更新提醒\n\n") + .append("> **统计时间:** ").append(currentTime).append("\n\n") + .append("## 🔧 工作中心数据统计:\n"); // 获取并统计每个工段的数据 for (String workCenter : workCenters) { try { R> result = getKingdeeDelayData(workCenter); + List data = result.getData(); if (R.isError(result) || CollUtil.isEmpty(result.getData())) { - msg.append("- ").append(workCenter).append(" (无数据)\n"); + markdownMsg.append("- ").append(workCenter).append(":无数据\n"); continue; } + List dataList = result.getData().stream().filter(item -> item.getMoOrderNo() != null && !item.getMoOrderNo().contains("暂停")) + .collect(Collectors.toList()); - List dataList = result.getData(); - msg.append("- ").append(workCenter).append(" (共").append(dataList.size()).append("条数据)\n"); + markdownMsg.append("- ").append(workCenter).append(":共 ").append(dataList.size()).append(" 条\n"); // 生成Excel文件 String fileName = String.format("%s生产延期数据_%s.xlsx", workCenter, @@ -558,12 +566,18 @@ public class KingdeeWorkCenterDataController extends BaseController { } catch (Exception e) { log.error("获取工段{}数据失败", workCenter, e); - msg.append("- ").append(workCenter).append(" (获取失败: ").append(e.getMessage()).append(")\n"); + markdownMsg.append("- ").append(workCenter).append(":获取失败: ").append(e.getMessage()).append("\n"); } } - msg.append("\n详细数据请查看发送的Excel文件!"); - wxRobotUtil.sendMsgToWeChatGroup(msg.toString(), robotId, true); // @所有人 + // 结尾提示与分段发送 + markdownMsg.append("\n> **📊 详细数据请查看发送的Excel文件!**"); + String messageContent = markdownMsg.toString(); + int maxLength = 4096; + for (int i = 0; i < messageContent.length(); i += maxLength) { + String part = messageContent.substring(i, Math.min(i + maxLength, messageContent.length())); + wxRobotUtil.sendMarkdownMsgToWeChatGroup(part, robotId); + } return R.ok(); @@ -916,6 +930,7 @@ public class KingdeeWorkCenterDataController extends BaseController { map.put("FDate", item.getFDate()); map.put("FDeliveryDate", item.getFDeliveryDate()); map.put("FUCHNText2", item.getFUCHNText2()); + map.put("FCreateDate", item.getFCreateDate()); mapList.add(map); index++; } @@ -944,6 +959,7 @@ public class KingdeeWorkCenterDataController extends BaseController { map.put("FApplicationDate", item.getFApplicationDate()); map.put("FUCHNText", item.getFUCHNText()); map.put("FCreatorIdFName", item.getFCreatorIdFName()); + map.put("FCreateDate", item.getFCreateDate()); mapList.add(map); index++; } @@ -956,7 +972,6 @@ public class KingdeeWorkCenterDataController extends BaseController { */ private List filterPurchaseOrders(List allOrders) { LocalDate today = LocalDate.now(); - DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); log.info("开始过滤采购订单,总数: {}, 当前日期: {}", allOrders.size(), today.format(outputFormatter)); @@ -966,30 +981,45 @@ public class KingdeeWorkCenterDataController extends BaseController { String productionOrderNo = allOrder.getFUCHNText2(); String deliveryDate = allOrder.getFDeliveryDate(); - // 条件3: 交货日期不能为空,并且必须早于今天 + // ✅ 条件1: 暂停项目过滤 + if (productionOrderNo != null && productionOrderNo.contains("暂停")) { + log.debug("过滤掉: 暂停项目: {}", productionOrderNo); + continue; + } + + // ✅ 条件2: 交货日期不能为空 if (deliveryDate == null || deliveryDate.trim().isEmpty()) { log.debug("过滤掉: 交货日期为空"); continue; } try { - String dateStr = deliveryDate.split("T")[0]; // 取 yyyy-MM-dd 部分 - LocalDate delivery = LocalDate.parse(dateStr, inputFormatter); + // ✅ 格式化交货日期 + LocalDate delivery = parseDate(deliveryDate); + if (delivery == null) { + log.warn("解析交货日期失败: {}", deliveryDate); + continue; + } - // 转换格式 String formatted = delivery.format(outputFormatter); allOrder.setFDeliveryDate(formatted); + // ✅ 条件3: 只保留交货日期早于今天的 if (!delivery.isBefore(today)) { log.debug("过滤掉: 交货日期未过期: {}", formatted); continue; } - } catch (Exception e) { - log.warn("解析交货日期失败: {}", deliveryDate, e); - continue; - } + allOrder.setFQty(formatQty(allOrder.getFQty())); + // ✅ 顺便格式化其他日期字段 + allOrder.setFDate(formatDate(allOrder.getFDate())); + allOrder.setFDeliveryDate(formatDate(allOrder.getFDeliveryDate())); + allOrder.setFCreateDate(formatDate(allOrder.getFCreateDate())); - filteredOrders.add(allOrder); + filteredOrders.add(allOrder); + + } catch (Exception e) { + log.warn("处理订单异常: {}", productionOrderNo, e); + } } log.info("过滤完成,剩余数量: {}", filteredOrders.size()); @@ -1002,7 +1032,6 @@ public class KingdeeWorkCenterDataController extends BaseController { */ private List filterReqPurchaseOrders(List allOrders) { LocalDate today = LocalDate.now(); - DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); log.info("开始过滤采购申请订单,总数: {}, 当前日期: {}", allOrders.size(), today.format(outputFormatter)); @@ -1010,39 +1039,54 @@ public class KingdeeWorkCenterDataController extends BaseController { for (PurchaseRequestExcelDTO allOrder : allOrders) { String productionOrderNo = allOrder.getFUCHNText(); - String deliveryDate = allOrder.getFArrivalDate(); - if (allOrder.getFCloseStatus().equals("A")) { + String arrivalDate = allOrder.getFArrivalDate(); + + // 状态转换 + if ("A".equals(allOrder.getFCloseStatus())) { allOrder.setFCloseStatus("未关闭"); } - if (allOrder.getFDocumentStatus().equals("C")) { + if ("C".equals(allOrder.getFDocumentStatus())) { allOrder.setFDocumentStatus("已审核"); } + // 暂停项目过滤 + if (productionOrderNo != null && productionOrderNo.contains("暂停")) { + log.debug("过滤掉: 暂停项目: {}", productionOrderNo); + continue; + } - // 条件3: 交货日期不能为空,并且必须早于今天 - if (deliveryDate == null || deliveryDate.trim().isEmpty()) { - log.debug("过滤掉: 交货日期为空"); + // 到货日期不能为空 + if (arrivalDate == null || arrivalDate.trim().isEmpty()) { + log.debug("过滤掉: 到货日期为空"); continue; } try { - String dateStr = deliveryDate.split("T")[0]; // 取 yyyy-MM-dd 部分 - LocalDate delivery = LocalDate.parse(dateStr, inputFormatter); + LocalDate delivery = parseDate(arrivalDate); + if (delivery == null) { + log.warn("解析到货日期失败: {}", arrivalDate); + continue; + } - // 转换格式 + // 转换为中文日期格式 String formatted = delivery.format(outputFormatter); allOrder.setFArrivalDate(formatted); + // 只保留已过期的日期 if (!delivery.isBefore(today)) { - log.debug("过滤掉: 交货日期未过期: {}", formatted); + log.debug("过滤掉: 到货日期未过期: {}", formatted); continue; } - } catch (Exception e) { - log.warn("解析交货日期失败: {}", deliveryDate, e); - continue; - } + allOrder.setFReqQty(formatQty(allOrder.getFReqQty())); + allOrder.setFCreateDate(formatDate(allOrder.getFCreateDate())); + allOrder.setFApplicationDate(formatDate(allOrder.getFApplicationDate())); + allOrder.setFArrivalDate(formatDate(allOrder.getFArrivalDate())); - filteredOrders.add(allOrder); + filteredOrders.add(allOrder); + + } catch (Exception e) { + log.warn("处理订单异常: {}", productionOrderNo, e); + } } log.info("过滤完成,剩余数量: {}", filteredOrders.size()); @@ -1123,4 +1167,499 @@ public class KingdeeWorkCenterDataController extends BaseController { } } + /** + * 将日期字符串(如 "2025-09-22T10:52:03.6" 或 "2025-09-22")格式化为 "yyyy年MM月dd日" + */ + private String formatDate(String dateStr) { + if (dateStr == null || dateStr.isEmpty()) { + return null; + } + try { + LocalDate date = parseDate(dateStr); + if (date != null) { + return date.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")); + } + } catch (Exception ignored) { + } + return dateStr; // 解析失败则返回原值 + } + + /** + * 解析日期字符串,支持带 T 的 ISO 格式或普通 yyyy-MM-dd 格式 + */ + private LocalDate parseDate(String dateStr) { + if (dateStr == null || dateStr.trim().isEmpty()) { + return null; + } + try { + // 先取出 T 之前的部分 + String clean = dateStr.split("T")[0]; + return LocalDate.parse(clean, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } catch (Exception e) { + log.debug("日期解析失败: {}", dateStr, e); + return null; + } + } + + /** + * 单据状态编码到中文的映射 + * A -> 创建,B -> 审核中,C -> 已审核,其它原样返回 + */ + private String mapDocumentStatus(String status) { + if (status == null || status.trim().isEmpty()) { + return ""; + } + switch (status) { + case "A": + return "创建"; + case "B": + return "审核中"; + case "C": + return "已审核"; + default: + return status; + } + } + + /** + * 格式化数量为两位小数 + */ + private String formatQty(String qtyStr) { + if (qtyStr == null || qtyStr.trim().isEmpty()) { + return "0.00"; + } + try { + double value = Double.parseDouble(qtyStr); + return String.format("%.2f", value); + } catch (NumberFormatException e) { + log.debug("数量格式化失败: {}", qtyStr, e); + return qtyStr; + } + } + + @Log(title = "获取开工延时的生产订单") + @XxlJob("getConstructionDelay") + @PostMapping("/getConstructionDelay") + public R getConstructionDelay() { + try { + + // String robotId = "4d2f037d-0cee-493a-a4ff-1758f67b8069"; + String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e"; + String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"); + StringBuilder msg = new StringBuilder(); + msg.append("🏭 生产订单未开工的延期通知\n\n").append("更新时间:").append(currentTime).append("\n\n").append("🔧 订单数据统计:\n"); + // 获取生产订单数据 + List purchaseOrderList1 = JdUtil.getConstructionDelay(); + + List purchaseOrderList = filterConstructionDel(purchaseOrderList1); + msg.append("- 到期未开工:").append(purchaseOrderList.size()).append("条\n"); + // 生成Excel文件使用采购模板 + String fileName = String.format("生产订单未开工的延期数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss")); + String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName; + // 准备模板数据 + Map staticDataMap = new HashMap<>(); + staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss")); + staticDataMap.put("purchaseOrderCount", purchaseOrderList.size()); + List dynamicDataMappingList = new ArrayList<>(); + // 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化) + if (!purchaseOrderList.isEmpty()) { + List> orderDataList = new ArrayList<>(); + // 为避免循环中重复远程查询,增加简单的单号级缓存 + Map plannCache = new HashMap<>(); + int index = 1; + for (ConstructionDelayDTO item : purchaseOrderList) { + String billNo = item.getFBillNo(); + OperationPlannDTO plann = plannCache.get(billNo); + if (plann == null) { + try { + plann = JdUtil.getOperationPlann(billNo); + } catch (Exception ex) { + log.warn("获取工序汇报单失败,单号:{},原因:{}", billNo, ex.getMessage()); + } + plannCache.put(billNo, plann); // 即便为 null 也缓存,避免重复失败调用 + } + Map map = new HashMap<>(); + map.put("index", index++); + map.put("F_HBYT_SCLH", item.getF_HBYT_SCLH()); + map.put("FBillNo", item.getFBillNo()); + map.put("FPickMtrlStatus", item.getFPickMtrlStatus()); + map.put("FWorkShopIDFName", item.getFWorkShopIDFName()); + map.put("FMaterialIdFNumber", item.getFMaterialIdFNumber()); + map.put("FMaterialName", item.getFMaterialName()); + // 工序号/数量/工序名称做空值保护,避免因远程返回空导致 NPE + String operNumber = (plann != null && StringUtils.hasText(plann.getFOperNumber())) ? plann.getFOperNumber() : "-"; + String operQty = (plann != null && StringUtils.hasText(plann.getFOperQty())) ? formatQty(plann.getFOperQty()) : "-"; + String processName = (plann != null && StringUtils.hasText(plann.getFProcessIdFName())) ? plann.getFProcessIdFName() : "-"; + map.put("FOperNumber", operNumber); + map.put("FOperQty", operQty); + map.put("FProcessIdFName", processName); + map.put("FPlanStartDate", item.getFPlanStartDate()); + map.put("FPlanFinishDate", item.getFPlanFinishDate()); + map.put("Deydays", item.getDeydays()); + map.put("createTime", new Date()); + orderDataList.add(map); + } + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ConstructionDelayDTO", orderDataList)); + } + // 使用采购模板生成Excel + String templatePath = "EXCEL模板/生产开工未领料模板.xlsx"; + ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList); + // 发送Excel文件 + File excelFile = new File(filePath); + if (excelFile.exists()) { + wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId); + FileUtils.deleteQuietly(excelFile); + } + msg.append("\n详细数据请查看发送的Excel文件!"); + wxRobotUtil.sendMsgToWeChatGroup(msg.toString(), robotId, true); // @所有人 + + return R.ok(); + + } catch (Exception e) { + log.error("发送工段数据失败", e); + return R.fail("发送工段数据失败:" + e.getMessage()); + } + } + + + @Log(title = "工序汇报单订单-未入库") + @XxlJob("getProductionOrder") + @PostMapping("/getProductionOrder") + public R getProductionOrder() { + //TO DO: + + try { + String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e"; + String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"); + StringBuilder msg = new StringBuilder(); + msg.append("🏭 工序汇报未入库\n\n").append("更新时间:").append(currentTime).append("\n\n").append("🔧 订单数据统计:\n"); + + //工序汇报单,未入库列表 + List processReportDTOList = JdUtil.getProcessReport(); + msg.append("- 到期未开工:").append(processReportDTOList.size()).append("条\n"); + // 生成Excel文件使用采购模板 + String fileName = String.format("工序汇报未入库的延期数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss")); + String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName; + // 准备模板数据 + Map staticDataMap = new HashMap<>(); + staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss")); + staticDataMap.put("purchaseOrderCount", processReportDTOList.size()); + List dynamicDataMappingList = new ArrayList<>(); + // 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化) + if (!processReportDTOList.isEmpty()) { + List> reportList = new ArrayList<>(); + int index = 1; + for (ProcessReportDTO item : processReportDTOList) { + Map map = new HashMap<>(); + map.put("index", index++); + map.put("FSCLH", item.getFSCLH()); + map.put("FBillNo", item.getFBillNo()); + map.put("FWorkShopID", item.getFWorkShopID()); + map.put("FMoNumber", item.getFMoNumber()); + map.put("FOperNumber", item.getFOperNumber()); + map.put("FOperDescription", item.getFOperDescription()); + map.put("FQuaQty", formatQty(item.getFQuaQty())); + map.put("FFinishQty", formatQty(item.getFFinishQty())); + map.put("FStockInQuaAuxQty", formatQty(item.getFStockInQuaAuxQty())); + map.put("FStockInFailAuxQty", formatQty(item.getFStockInFailAuxQty())); + map.put("FRKD", item.getFRKD()); + map.put("FDate", parseDate(item.getFDate())); + map.put("createTime", new Date()); + reportList.add(map); + } + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessReportDTO", reportList)); + } + // 使用采购模板生成Excel + String templatePath = "EXCEL模板/工序汇报未入库.xlsx"; + ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList); + // 发送Excel文件 + File excelFile = new File(filePath); + if (excelFile.exists()) { + wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId); + FileUtils.deleteQuietly(excelFile); + } + msg.append("\n详细数据请查看发送的Excel文件!"); + wxRobotUtil.sendMsgToWeChatGroup(msg.toString(), robotId, true); // @所有人 + + return R.ok(); + + } catch (Exception e) { + log.error("发送工段数据失败", e); + return R.fail("发送工段数据失败:" + e.getMessage()); + } + } + + + @Log(title = "工序转移未及时转移") + @XxlJob("getProcessTransferForm") + @PostMapping("/getProcessTransferForm") + public R getProcessTransferForm() { + //TO D0:需要查询工序计划的时间是否在今日 + try { + String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e"; + String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"); + // 构建 Markdown 消息 + StringBuilder markdownMsg = new StringBuilder(); + markdownMsg.append("🏭 **工序转移**\n\n"); + markdownMsg.append("- 📊 统计时间:").append(currentTime).append("\n"); + markdownMsg.append("- 📋 订单数据统计:\n"); + //工序汇报单,未入库列表 + List processReportDTOList = JdUtil.getProcessTransferForm(); + markdownMsg.append(" - 工序转移数据:").append(processReportDTOList.size()).append("条\n"); + // 追加Excel文件提示 + if (processReportDTOList.size() > 0) { + markdownMsg.append("\n📄 详细数据请查看发送的 Excel 文件\n"); + } + // 生成Excel文件使用采购模板 + String fileName = String.format("工序转移数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss")); + String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName; + // 准备模板数据 + Map staticDataMap = new HashMap<>(); + staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss")); + staticDataMap.put("purchaseOrderCount", processReportDTOList.size()); + List dynamicDataMappingList = new ArrayList<>(); + // 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化) + if (!processReportDTOList.isEmpty()) { + + List> reportList = new ArrayList<>(); + int index = 1; + for (ProcessTransferFormDTO item : processReportDTOList) { + //ProcessRoute routes = iProcessRouteService.getProcessRoutesXuTime(item.getFSCLH(), item.getFProductIdNumber(), item.getFInOperNumber()); + /* Date inStart = (routes == null ? null : routes.getXuStartTime()); + Date createDate = null; + if (StringUtils.hasText(item.getFCreateDate())) { + try { + createDate = DateUtil.parse(item.getFCreateDate()); + } catch (Exception ignored) { } + } + // 当两者时间均可用时:仅过滤“未晚于转入序开始”的记录(即不延迟) + if (inStart != null && createDate != null && createDate.before(inStart)) { + continue; + }*/ + Map map = new HashMap<>(); + map.put("index", index++); + map.put("FSCLH", item.getFSCLH()); + map.put("FProductIdNumber", item.getFProductIdNumber()); + map.put("FDocumentStatus", mapDocumentStatus(item.getFDocumentStatus())); + map.put("FMOBillNo", item.getFMOBillNo()); + map.put("FBillNo", item.getFBillNo()); + map.put("FProductName", item.getFProductName()); + map.put("FOutDeptIdFName", item.getFOutDeptIdFName()); + map.put("FOutOperNumber", item.getFOutOperNumber()); + map.put("FOutProcessIdName", item.getFOutProcessIdName()); + map.put("FInDeptIdFName", item.getFInDeptIdFName()); + map.put("FInOperNumber", item.getFInOperNumber()); + map.put("FInProcessIdFName", item.getFInProcessIdFName()); + map.put("FOperUnit", item.getFOperUnit()); + map.put("FOperTransferQty", formatQty(item.getFOperTransferQty())); + map.put("FOperQualifiedQty", formatQty(item.getFOperQualifiedQty())); + map.put("FOperProFailQty", formatQty(item.getFOperProFailQty())); + map.put("FCreateDate", parseDate(item.getFCreateDate())); + map.put("createTime", new Date()); + reportList.add(map); + } + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessTransferFormDTO", reportList)); + } + // 使用采购模板生成Excel + String templatePath = "EXCEL模板/工序转移数据.xlsx"; + ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList); + // 发送消息 + wxRobotUtil.sendMarkdownMsgToWeChatGroup(markdownMsg.toString(), robotId); + + // 发送Excel文件 + File excelFile = new File(filePath); + if (excelFile.exists()) { + wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId); + FileUtils.deleteQuietly(excelFile); + } + + return R.ok(); + + } catch (Exception e) { + log.error("发送工段数据失败", e); + return R.fail("发送工段数据失败:" + e.getMessage()); + } + } + + private List> convertConstructionDelayToMapList(List purchaseOrderList) { + List> mapList = new ArrayList<>(); + int index = 1; + for (ConstructionDelayDTO item : purchaseOrderList) { + Map map = new HashMap<>(); + map.put("index", index); + + // —— 按照 ConstructionDelayDTO 字段 —— + map.put("F_HBYT_SCLH", item.getF_HBYT_SCLH()); // 生产令号 + map.put("FBillNo", item.getFBillNo()); // 单据编码(若有) + map.put("FWorkShopIDFName", item.getFWorkShopIDFName()); // 车间名称 + map.put("FMaterialIdFNumber", item.getFMaterialIdFNumber()); // 物料编码 + map.put("FMaterialName", item.getFMaterialName()); // 物料名称 + map.put("FPlanStartDate", formatDate(item.getFPlanStartDate())); // 计划开工时间(格式化) + map.put("FPlanFinishDate", formatDate(item.getFPlanFinishDate())); // 计划完工时间(格式化) + map.put("Deydays", item.getDeydays()); // 超期天数 + mapList.add(map); + index++; + } + return mapList; + } + + private List filterConstructionDel(List allPurchaseOrderList) { + LocalDate today = LocalDate.now(); + DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); + + log.info("开始过滤生产订单,总数: {}, 当前日期: {}", allPurchaseOrderList.size(), today.format(outputFormatter)); + List filteredOrders = new ArrayList<>(); + + for (ConstructionDelayDTO allOrder : allPurchaseOrderList) { + String productionOrderNo = allOrder.getF_HBYT_SCLH(); + String deliveryDate = allOrder.getFPlanFinishDate(); + + // ✅ 条件1: 暂停项目过滤 + if (productionOrderNo != null && productionOrderNo.contains("暂停")) { + log.debug("过滤掉: 暂停项目: {}", productionOrderNo); + continue; + } // ✅ 条件1: 暂停项目过滤 + if (productionOrderNo == null || productionOrderNo.isEmpty()) { + log.debug("过滤掉: 无令号项目: {}", productionOrderNo); + continue; + } + try { + // ✅ 格式化交货日期 + LocalDate delivery = parseDate(deliveryDate); + if (delivery == null) { + log.warn("解析交货日期失败: {}", deliveryDate); + continue; + } + String formatted = delivery.format(outputFormatter); + allOrder.setFPlanFinishDate(formatted); + // ✅ 顺便格式化其他日期字段 + LocalDate planStart = parseDate(allOrder.getFPlanStartDate()); + if (planStart == null) { + log.warn("解析开工日期失败: {}", allOrder.getFPlanStartDate()); + continue; + } + // 计算过期天数:今天减去开工时间 + long delayDays = ChronoUnit.DAYS.between(planStart, today); + if (delayDays > 2) { + allOrder.setDeydays((int) delayDays); + allOrder.setFPlanStartDate(planStart.format(outputFormatter)); + allOrder.setFPlanFinishDate(formatted); + filteredOrders.add(allOrder); + } else { + log.debug("订单{} 延期{}天,不满足>2天条件,过滤", productionOrderNo, delayDays); + } + + } catch (Exception e) { + log.warn("处理订单异常: {}", productionOrderNo, e); + } + } + + log.info("过滤完成,剩余数量: {}", filteredOrders.size()); + return filteredOrders; + } + + /** + * 质检不及时数据 + */ + @XxlJob("getUninspectedData") + @Log(title = "质检不及时数据", businessType = BusinessType.DELETE) + @PostMapping("/getUninspectedData") + public R> getUninspectedData() { + try { + String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e"; + String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"); + //工序汇报单,未入库列表 + List processReportDTOList = JdUtil.getUninspectedData(); + + // 构建Markdown消息 + StringBuilder markdownMsg = new StringBuilder(); + markdownMsg.append("# 工序质检不及时告警通知\n\n") + .append("> **统计时间:** ").append(currentTime).append("\n") + .append("> **未质检工序数量:** ").append(processReportDTOList.size()).append(" 条\n\n"); + + // 如果有未质检数据,显示前N条详细信息(默认3条) + if (!processReportDTOList.isEmpty()) { + markdownMsg.append("## 🔍 未质检工序详情(前2条)\n\n"); + int displayCount = Math.min(2, processReportDTOList.size()); + for (int i = 0; i < displayCount; i++) { + ProcessInspectionDTO item = processReportDTOList.get(i); + markdownMsg.append("### ").append(i + 1).append(". ").append(item.getFMaterialName()).append("\n") + .append("> **生产订单号:** ").append(item.getMoOrderNo()).append("\n") + .append("> **工序名称:** ").append(item.getFProcessName()).append("\n") + .append("> **工作中心:** ").append(item.getFWorkCenterName()).append("\n") + .append("> **检验状态:** ").append(item.getFInspectStatus()).append("\n") + .append("> **待检数量:** ").append(item.getFWaitInspectQty()).append("\n") + .append("> **已检数量:** ").append(item.getFFinishInspectQty()).append("\n") + .append("> **合格数量:** ").append(item.getFQuaQty()).append("\n") + .append("> **提交检验时间:** ").append(item.getFSubmitInspectTime()).append("\n\n"); + } + if (processReportDTOList.size() > displayCount) { + markdownMsg.append("> **注意:** 还有 ").append(processReportDTOList.size() - displayCount).append(" 条未质检记录,详细信息请查看Excel文件\n\n"); + } + } else { + markdownMsg.append("## ✅ 暂无未质检工序\n\n"); + } + + markdownMsg.append("> **创建时间:** ").append(DateUtil.formatDateTime(new Date())).append("\n"); + + // 追加Excel提示到Markdown消息 + markdownMsg.append("\n> **📊 详细数据请查看发送的Excel文件!**"); + // 生成Excel文件使用采购模板 + String fileName = String.format("工序未质检数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss")); + String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName; + // 准备模板数据 + Map staticDataMap = new HashMap<>(); + staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss")); + staticDataMap.put("purchaseOrderCount", processReportDTOList.size()); + List dynamicDataMappingList = new ArrayList<>(); + // 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化) + if (!processReportDTOList.isEmpty()) { + List> reportList = new ArrayList<>(); + int index = 1; + for (ProcessInspectionDTO item : processReportDTOList) { + Map map = new HashMap<>(); + map.put("index", index++); + map.put("moBillNo", item.getMoBillNo()); + map.put("moOrderNo", item.getMoOrderNo()); + map.put("fMaterialName", item.getFMaterialName()); + map.put("fProcessName", item.getFProcessName()); + map.put("fWorkCenterName", item.getFWorkCenterName()); + map.put("fInspectStatus", item.getFInspectStatus()); + map.put("fWaitInspectQty", item.getFWaitInspectQty()); + map.put("fFinishInspectQty", item.getFFinishInspectQty()); + map.put("fQuaQty", item.getFQuaQty()); + map.put("fReworkQty", item.getFReworkQty()); + map.put("fFailQty", item.getFFailQty()); + map.put("fSubmitInspectTime", item.getFSubmitInspectTime()); + map.put("fFinishInspectTime", item.getFFinishInspectTime()); + map.put("fDescription", parseDate(item.getFDescription())); + reportList.add(map); + } + dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessInspectionDTO", reportList)); + } + // 使用采购模板生成Excel + String templatePath = "EXCEL模板/质检模板.xlsx"; + ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList); + // 发送Excel文件 + File excelFile = new File(filePath); + if (excelFile.exists()) { + wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId); + FileUtils.deleteQuietly(excelFile); + } + // 发送Markdown消息(企业微信要求使用 msgtype=markdown),并按长度分段 + String messageContent = markdownMsg.toString(); + int maxLength = 4096; + for (int i = 0; i < messageContent.length(); i += maxLength) { + String part = messageContent.substring(i, Math.min(i + maxLength, messageContent.length())); + wxRobotUtil.sendMarkdownMsgToWeChatGroup(part, robotId); + } + + return R.ok(); + + } catch (Exception e) { + log.error("发送工段数据失败", e); + return R.fail("发送工段数据失败:" + e.getMessage()); + } + } + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/PartCostController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/PartCostController.java new file mode 100644 index 0000000..e148f09 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/PartCostController.java @@ -0,0 +1,119 @@ +package com.ruoyi.system.controller; + +import java.util.List; +import java.util.Arrays; + +import lombok.RequiredArgsConstructor; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.validate.AddGroup; +import com.ruoyi.common.core.validate.EditGroup; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.vo.PartCostVo; +import com.ruoyi.system.domain.bo.PartCostBo; +import com.ruoyi.system.service.IPartCostService; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 零件成本 + * + * @author 田志阳 + * @date 2025-10-24 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/cost") +public class PartCostController extends BaseController { + + private final IPartCostService iPartCostService; + + /** + * 查询零件成本列表 + */ + @SaCheckPermission("system:cost:list") + @GetMapping("/list") + public TableDataInfo list(PartCostBo bo, PageQuery pageQuery) { + return iPartCostService.queryPageList(bo, pageQuery); + } + + /** + * 导出零件成本列表 + */ + @SaCheckPermission("system:cost:export") + @Log(title = "零件成本", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(PartCostBo bo, HttpServletResponse response) { + List list = iPartCostService.queryList(bo); + ExcelUtil.exportExcel(list, "零件成本", PartCostVo.class, response); + } + + /** + * 获取零件成本详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("system:cost:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(iPartCostService.queryById(id)); + } + + /** + * 新增零件成本 + */ + @SaCheckPermission("system:cost:add") + @Log(title = "零件成本", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody PartCostBo bo) { + return toAjax(iPartCostService.insertByBo(bo)); + } + + /** + * 修改零件成本 + */ + @SaCheckPermission("system:cost:edit") + @Log(title = "零件成本", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody PartCostBo bo) { + return toAjax(iPartCostService.updateByBo(bo)); + } + + /** + * 删除零件成本 + * + * @param ids 主键串 + */ + @SaCheckPermission("system:cost:remove") + @Log(title = "零件成本", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(iPartCostService.deleteWithValidByIds(Arrays.asList(ids), true)); + } + + + + /** + * 在金蝶获取成本价 + */ + @SaCheckPermission("system:cost:getObtainPartData") + @Log(title = "在金蝶获取成本价", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/getObtainPartData") + public R getObtainPartData() { + return toAjax(iPartCostService.getObtainPartData()); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/PcRigidChainController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/PcRigidChainController.java index f5f0032..d99e4dd 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/PcRigidChainController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/PcRigidChainController.java @@ -170,9 +170,8 @@ public class PcRigidChainController extends BaseController { DefaultExcelListener excelListener = new DefaultExcelListener<>(true); EasyExcel.read(new ByteArrayInputStream(fileBytes), PcRigidChainVo.class, excelListener) - .excelType(ExcelTypeEnum.XLS) .sheet(readSheet.getSheetNo()) - .headRowNumber(4) + .headRowNumber(3) .doRead(); List list = excelListener.getExcelResult().getList(); @@ -214,38 +213,6 @@ public class PcRigidChainController extends BaseController { PcRigidChain dbChain = chainMap.get(searchKey); if (dbChain != null) { matchedCount++; - log.info("找到匹配记录: {}", typeName); - - // 记录修改前的关键字段值 - log.info("修改前字段值:"); - log.info(" - ID: {}", dbChain.getId()); - log.info(" - Journey: {} -> {}", dbChain.getJourney(), vOne); - log.info(" - TypeName: {} -> {}", dbChain.getTypeName(), typeName); - log.info(" - Type: {} -> {}", dbChain.getType(), type); - log.info(" - Box: {} -> {}", dbChain.getBox(), box); - log.info(" - AxialDirection: {} -> {}", dbChain.getAxialDirection(), s); - - // 记录Excel中的关键字段值 - log.info("Excel数据关键字段:"); - log.info(" - VOne: {}", pcRigidChainVO.getVOne()); - log.info(" - VTwo: {}", pcRigidChainVO.getVTwo()); - log.info(" - VThree: {}", pcRigidChainVO.getVThree()); - log.info(" - LOne: {}", pcRigidChainVO.getLOne()); - log.info(" - LTwo: {}", pcRigidChainVO.getLTwo()); - log.info(" - LThree: {}", pcRigidChainVO.getLThree()); - log.info(" - SumWeight: {}", pcRigidChainVO.getSumWeight()); - log.info(" - ChainWeight: {}", pcRigidChainVO.getChainWeight()); - log.info(" - DynamicLoad: {}", pcRigidChainVO.getDynamicLoad()); - log.info(" - DeadLoad: {}", pcRigidChainVO.getDeadLoad()); - log.info(" - Speed: {}", pcRigidChainVO.getSpeed()); - log.info(" - Efficiency: {}", pcRigidChainVO.getEfficiency()); - log.info(" - ChainPitch: {}", pcRigidChainVO.getChainPitch()); - log.info(" - PitchRadius: {}", pcRigidChainVO.getPitchRadius()); - log.info(" - MinimumAltitude: {}", pcRigidChainVO.getMinimumAltitude()); - log.info(" - SingleMeterChainWeight: {}", pcRigidChainVO.getSingleMeterChainWeight()); - log.info(" - DrivingBoxWeight: {}", pcRigidChainVO.getDrivingBoxWeight()); - log.info(" - ChainBoxWeight: {}", pcRigidChainVO.getChainBoxWeight()); - log.info(" - Univalence: {}", pcRigidChainVO.getUnivalence()); // 执行字段复制和更新 BeanUtil.copyProperties(pcRigidChainVO, dbChain, "id"); @@ -254,34 +221,8 @@ public class PcRigidChainController extends BaseController { dbChain.setType(type); dbChain.setBox(box); dbChain.setAxialDirection(s); - dbChain.setCreateTime(new Date()); dbChain.setUpdateTime(new Date()); - // 记录修改后的关键字段值 - log.info("修改后字段值:"); - log.info(" - Journey: {}", dbChain.getJourney()); - log.info(" - TypeName: {}", dbChain.getTypeName()); - log.info(" - Type: {}", dbChain.getType()); - log.info(" - Box: {}", dbChain.getBox()); - log.info(" - AxialDirection: {}", dbChain.getAxialDirection()); - log.info(" - LOne: {}", dbChain.getLOne()); - log.info(" - LTwo: {}", dbChain.getLTwo()); - log.info(" - LThree: {}", dbChain.getLThree()); - log.info(" - SumWeight: {}", dbChain.getSumWeight()); - log.info(" - ChainWeight: {}", dbChain.getChainWeight()); - log.info(" - DynamicLoad: {}", dbChain.getDynamicLoad()); - log.info(" - DeadLoad: {}", dbChain.getDeadLoad()); - log.info(" - Speed: {}", dbChain.getSpeed()); - log.info(" - Efficiency: {}", dbChain.getEfficiency()); - log.info(" - ChainPitch: {}", dbChain.getChainPitch()); - log.info(" - PitchRadius: {}", dbChain.getPitchRadius()); - log.info(" - MinimumAltitude: {}", dbChain.getMinimumAltitude()); - log.info(" - SingleMeterChainWeight: {}", dbChain.getSingleMeterChainWeight()); - log.info(" - DrivingBoxWeight: {}", dbChain.getDrivingBoxWeight()); - log.info(" - ChainBoxWeight: {}", dbChain.getChainBoxWeight()); - log.info(" - Univalence: {}", dbChain.getUnivalence()); - log.info(" - CreateTime: {}", dbChain.getCreateTime()); - log.info(" - UpdateTime: {}", dbChain.getUpdateTime()); pcRigidChainsToUpdate.add(dbChain); log.info("物料: {} 已添加到更新列表", typeName); @@ -301,27 +242,7 @@ public class PcRigidChainController extends BaseController { int failCount = 0; for (PcRigidChain pcRigidChain : pcRigidChainsToUpdate) { - log.info("正在更新物料: {}, ID: {}", pcRigidChain.getTypeName(), pcRigidChain.getId()); - // 记录更新前的关键字段值 - log.info("更新前数据库字段值:"); - log.info(" - Journey: {}", pcRigidChain.getJourney()); - log.info(" - LOne: {}", pcRigidChain.getLOne()); - log.info(" - LTwo: {}", pcRigidChain.getLTwo()); - log.info(" - LThree: {}", pcRigidChain.getLThree()); - log.info(" - SumWeight: {}", pcRigidChain.getSumWeight()); - log.info(" - ChainWeight: {}", pcRigidChain.getChainWeight()); - log.info(" - DynamicLoad: {}", pcRigidChain.getDynamicLoad()); - log.info(" - DeadLoad: {}", pcRigidChain.getDeadLoad()); - log.info(" - Speed: {}", pcRigidChain.getSpeed()); - log.info(" - Efficiency: {}", pcRigidChain.getEfficiency()); - log.info(" - ChainPitch: {}", pcRigidChain.getChainPitch()); - log.info(" - PitchRadius: {}", pcRigidChain.getPitchRadius()); - log.info(" - MinimumAltitude: {}", pcRigidChain.getMinimumAltitude()); - log.info(" - SingleMeterChainWeight: {}", pcRigidChain.getSingleMeterChainWeight()); - log.info(" - DrivingBoxWeight: {}", pcRigidChain.getDrivingBoxWeight()); - log.info(" - ChainBoxWeight: {}", pcRigidChain.getChainBoxWeight()); - log.info(" - Univalence: {}", pcRigidChain.getUnivalence()); - + pcRigidChain.setUpdateTime(new Date()); int i = pcRigidChainMapper.updateById(pcRigidChain); if (i > 0) { successCount++; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java index 964faee..53c8d0f 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessOrderProController.java @@ -236,10 +236,14 @@ public class ProcessOrderProController extends BaseController { */ @SaCheckPermission("system:processOrderPro:uploadPDF") - @Log(title = "上传PDF", businessType = BusinessType.UPDATE) + @Log(title = "下载PDF", businessType = BusinessType.UPDATE) + @CrossOrigin(origins = "*", allowedHeaders = "*", exposedHeaders = {"Content-Disposition", "Content-Length"}) @GetMapping("/uploadPDF") public void uploadPDF(@RequestParam Long id, HttpServletResponse response) { try { + // CORS headers for all responses (success and error) + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition, Content-Length"); // 调用service方法获取文件路径 R result = iProcessOrderProService.uploadPDF(id); if (result.getCode() != 200) { @@ -264,6 +268,7 @@ public class ProcessOrderProController extends BaseController { response.setContentType("application/zip"); response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(file.getName(), "UTF-8") + "\""); response.setHeader("Content-Length", String.valueOf(file.length())); + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition, Content-Length"); // 写入文件流 try (FileInputStream fis = new FileInputStream(file); @@ -343,6 +348,7 @@ public class ProcessOrderProController extends BaseController { public List getOverdueProjects() { return iProcessOrderProService.getOverdueProjects(); } + @SaCheckPermission("system:orderPro:geMRPResults") @Log(title = "获取MRP复核结果", businessType = BusinessType.OTHER) @PostMapping("/getMRPResults/{id}") @@ -423,7 +429,6 @@ public class ProcessOrderProController extends BaseController { } } - // 电气外包分类条件:物料编码开头空格/特定前缀 或 备注包含"外购" if (materialCode.startsWith(" ") || materialCode.startsWith("009301") || materialCode.startsWith("009999") @@ -541,11 +546,11 @@ public class ProcessOrderProController extends BaseController { // 总装部件优先 boolean isTotal1 = "总装部件".equals(m1); boolean isTotal2 = "总装部件".equals(m2); - + if (isTotal1 && !isTotal2) return -1; if (!isTotal1 && isTotal2) return 1; if (isTotal1 && isTotal2) return 0; - + // 其他材质按字母顺序排序 if (m1 == null && m2 == null) return 0; if (m1 == null) return 1; @@ -652,7 +657,6 @@ public class ProcessOrderProController extends BaseController { if (row == null) { continue; } - ProcessRoute vo = new ProcessRoute(); // 根据列索引读取数据,保留原始空格 @@ -747,9 +751,7 @@ public class ProcessOrderProController extends BaseController { if (row == null) { continue; } - ProductionOrderVo vo = new ProductionOrderVo(); - // 根据列索引读取数据,保留原始空格 vo.setId(getCellValueAsLong(row.getCell(0))); vo.setDrawingNo(getCellValueAsString(row.getCell(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 f15f33b..14ec26d 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 @@ -443,7 +443,7 @@ public class ProcessRouteController extends BaseController { @Log(title = "推送工艺工序") @SaCheckPermission("system:route:pushRouteBom") @PostMapping("/pushRouteBom") - public ProcessRoutePushResultDTO pushRouteBom(@RequestParam String rooteProdet) { + public R pushRouteBom(@RequestParam String rooteProdet) { return iProcessRouteService.pushRouteBom(rooteProdet); } @@ -644,7 +644,7 @@ public class ProcessRouteController extends BaseController { materialBom.setUnit(materialUsageDTO.getChildUnit()); materialBom.setMaterialType(materialUsageDTO.getCaizhi()); //保留四位小数 - materialBom.setQuantity(String.valueOf(new BigDecimal(materialUsageDTO.getFenzi()).divide(new BigDecimal(materialUsageDTO.getFenmu()),4, RoundingMode.HALF_UP))); + materialBom.setQuantity(String.valueOf(BigDecimal.valueOf(materialUsageDTO.getFenzi()).divide(new BigDecimal(materialUsageDTO.getFenmu()),4, RoundingMode.HALF_UP))); return materialBom; } @@ -658,7 +658,7 @@ public class ProcessRouteController extends BaseController { bomDetails.setUnitWeight("是"); bomDetails.setWareHouse(materialUsageDTO.getChildUnit()); //子项分子 - bomDetails.setQuantity(materialUsageDTO.getFenzi()); + bomDetails.setQuantity(String.valueOf(materialUsageDTO.getFenzi())); //子项分母 bomDetails.setDenominator(Double.valueOf(materialUsageDTO.getFenmu())); bomDetails.setName(materialUsageDTO.getMaterialName()); @@ -801,7 +801,7 @@ public class ProcessRouteController extends BaseController { bomDetails.setUnitWeight("是"); bomDetails.setWareHouse(materialUsageDTO.getUnit()); //子项分子 - bomDetails.setQuantity(materialUsageDTO.getFNumerator()); + bomDetails.setQuantity(String.valueOf(materialUsageDTO.getFNumerator())); //子项分母 bomDetails.setDenominator(materialUsageDTO.getFDenominator()); bomDetails.setName(materialUsageDTO.getMaterialName()); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/BomDetails.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/BomDetails.java index 73ea2a7..e605705 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/BomDetails.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/BomDetails.java @@ -76,7 +76,7 @@ public class BomDetails extends BaseEntity { * 子项分子 */ @JsonProperty("FNUMERATOR") - private Double quantity; + private String quantity; /** * 子项分母 */ @@ -106,4 +106,8 @@ public class BomDetails extends BaseEntity { * 子项单重 */ private Double singleWeghit; + /** + *bom类型 + */ + private String bomType; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/PartCost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PartCost.java new file mode 100644 index 0000000..147ee12 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PartCost.java @@ -0,0 +1,72 @@ +package com.ruoyi.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 零件成本对象 part_cost + * + * @author 田志阳 + * @date 2025-10-24 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("part_cost") +public class PartCost extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * ID + */ + @TableId(value = "id") + private Long id; + /** + * 物料编码 + */ + @JsonProperty("FMaterialId.FNumber") + private String materialCode; + /** + * 物料名称 + */ + @JsonProperty("FMaterialName") + private String materialName; + /** + * 成本价 + */ + @JsonProperty("FPrice") + private BigDecimal costPrice; + /** + * 创建日期 + */ + @JsonProperty("FCreateDate") + private Date createDate; + /** + * 车间 + */ + @JsonProperty("FEntryWorkShopId.FName") + private String workshop; + /** + * 单位 + */ + @JsonProperty("FUnitID.FName") + private String unit; + /** + * 仓库 + */ + @JsonProperty("FStockId.FName") + private String warehouse; + /** + * 规格型号 + */ + @JsonProperty("FSpecification") + private String specificationModel; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/BomDetailsBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/BomDetailsBo.java index 8dd9c55..7f8e441 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/BomDetailsBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/BomDetailsBo.java @@ -79,4 +79,8 @@ public class BomDetailsBo extends BaseEntity { * 单重 */ private Double danzhong; + /** + *bom类型 + */ + private String bomType; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/PartCostBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/PartCostBo.java new file mode 100644 index 0000000..c031874 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/PartCostBo.java @@ -0,0 +1,88 @@ +package com.ruoyi.system.domain.bo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.validate.AddGroup; +import com.ruoyi.common.core.validate.EditGroup; +import lombok.Data; +import lombok.EqualsAndHashCode; +import javax.validation.constraints.*; + +import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 零件成本业务对象 part_cost + * + * @author 田志阳 + * @date 2025-10-24 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class PartCostBo extends BaseEntity { + + /** + * ID + */ + @NotNull(message = "ID不能为空", groups = { EditGroup.class }) + + private Long id; + + /** + * 物料编码 + */ + @NotBlank(message = "物料编码不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FMaterialId.FNumber") + private String materialCode; + + /** + * 物料名称 + */ + @NotBlank(message = "物料名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FMaterialName") + private String materialName; + + /** + * 成本价 + */ + @NotNull(message = "成本价不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FPrice") + private BigDecimal costPrice; + + /** + * 创建日期 + */ + @NotNull(message = "创建日期不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FCreateDate") + private Date createDate; + + /** + * 车间 + */ + @NotBlank(message = "车间不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FEntryWorkShopId.FName") + private String workshop; + + /** + * 单位 + */ + @NotBlank(message = "单位不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FUnitID.FName") + private String unit; + + /** + * 仓库 + */ + @NotBlank(message = "仓库不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FStockId.FName") + private String warehouse; + /** + * 规格型号 + */ + @NotBlank(message = "规格型号", groups = { AddGroup.class, EditGroup.class }) + @JsonProperty("FSpecification") + private String specificationModel; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/BOMItem.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/BOMItem.java new file mode 100644 index 0000000..fa05565 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/BOMItem.java @@ -0,0 +1,10 @@ +package com.ruoyi.system.domain.dto; + +import lombok.Data; + +import java.util.List; +@Data +public class BOMItem { + int id; + private List items; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/result/BOMUploadResult.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/BOMUploadResult.java similarity index 95% rename from ruoyi-common/src/main/java/com/ruoyi/common/result/BOMUploadResult.java rename to ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/BOMUploadResult.java index 45f9c0b..59033bd 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/result/BOMUploadResult.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/BOMUploadResult.java @@ -1,4 +1,4 @@ -package com.ruoyi.common.result; +package com.ruoyi.system.domain.dto; import lombok.Data; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ConstructionDelayDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ConstructionDelayDTO.java new file mode 100644 index 0000000..f6d3fcc --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ConstructionDelayDTO.java @@ -0,0 +1,48 @@ +package com.ruoyi.system.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.Date; + +@Data +public class ConstructionDelayDTO { + //生产令号 + @JsonProperty("F_HBYT_SCLH") + private String F_HBYT_SCLH; + //单据编码 + @JsonProperty("FBillNo") + private String FBillNo; + //车间名称 + @JsonProperty("FWorkShopID.FName") + private String FWorkShopIDFName; + //物料编码 + @JsonProperty("FMaterialId.FNumber") + private String FMaterialIdFNumber; + //物料名称 + @JsonProperty("FMaterialName") + private String FMaterialName; + //计划开工时间 + @JsonProperty("FPlanStartDate") + private String FPlanStartDate; + //计划完工时间 + @JsonProperty("FPlanFinishDate") + private String FPlanFinishDate; + //计划完工时间 + @JsonProperty("FPickMtrlStatus") + private String FPickMtrlStatus; + //超期天数 + private int Deydays; + + @JsonProperty("FOperNumber") + private String FOperNumber; + + @JsonProperty("FOperQty") + private String FOperQty; + + @JsonProperty("FOutProcessId.FName") + private String FProcessIdFName; + + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/InspectionSheetDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/InspectionSheetDTO.java new file mode 100644 index 0000000..e7ecd59 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/InspectionSheetDTO.java @@ -0,0 +1,64 @@ +package com.ruoyi.system.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 质检检验单数据 + * @author tzy + * @date 2025-10-26 + */ + +@Data +public class InspectionSheetDTO { + //生产令号 + @JsonProperty("F_UCHN_Text") + private String productionOrderNumber; + + //单据编码 + @JsonProperty("FBillNo") + private String FBillNo; + + //单据状态 + @JsonProperty("FDocumentStatus") + private String DocumentStatus; + + //物料编码 + @JsonProperty("FMaterialId.FNumber") + private String FMaterialIdFNumber; + + //物料名称 + @JsonProperty("FMaterialName") + private String FMaterialName; + + //规格型号 + @JsonProperty("FMaterialModel") + private String FMaterialModel; + + //质检状态 + @JsonProperty("FQCStatus") + private String FQCStatus; + + // 检验结果 + @JsonProperty("FInspectResult") + private String FInspectResult; + + // 单位 + @JsonProperty("FUnitID.FName") + private String FUnitIDFName; + + // 检验数量 + @JsonProperty("FInspectQty") + private String FInspectQty; + + // 合格数 + @JsonProperty("FQualifiedQty") + private String FQualifiedQty; + + // 不合格数 + @JsonProperty("FUnqualifiedQty") + private String FUnqualifiedQty; + + //超期天数 + private int Deydays; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlannDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlannDTO.java new file mode 100644 index 0000000..8241a0f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlannDTO.java @@ -0,0 +1,18 @@ +package com.ruoyi.system.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class OperationPlannDTO { + + @JsonProperty("FOperNumber") + private String FOperNumber; + + @JsonProperty("FOperQty") + private String FOperQty; + + @JsonProperty("FOutProcessId.FName") + private String FProcessIdFName; + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessInspectionDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessInspectionDTO.java new file mode 100644 index 0000000..1745d22 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessInspectionDTO.java @@ -0,0 +1,51 @@ +package com.ruoyi.system.domain.dto; + +import lombok.Data; + +@Data +public class ProcessInspectionDTO { + /** 单编号 */ + private String moBillNo; + + /** 生产订单号 */ + private String moOrderNo; + + /** 子订单号 */ + private String subOrderNo; + + /** 物料名称 */ + private String fMaterialName; + + /** 工序名称 */ + private String fProcessName; + + /** 工作中心(工段)名称 */ + private String fWorkCenterName; + + /** 检验状态(如:未完成、已完成) */ + private String fInspectStatus; + + /** 待检数量 */ + private Integer fWaitInspectQty; + + /** 已检验数量 */ + private Integer fFinishInspectQty; + + /** 合格数量 */ + private Integer fQuaQty; + + /** 返工数量 */ + private Integer fReworkQty; + + /** 报废数量 */ + private Integer fFailQty; + + /** 提交检验时间(字符串格式,如 "12-24") */ + private String fSubmitInspectTime; + + /** 完成检验时间(字符串格式) */ + private String fFinishInspectTime; + + /** 备注或描述 */ + private String fDescription; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessReportDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessReportDTO.java new file mode 100644 index 0000000..34c9d5c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessReportDTO.java @@ -0,0 +1,60 @@ +package com.ruoyi.system.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 工序汇报单实体 + * @author tzy + * @date 2025-10-28 + */ +@Data +public class ProcessReportDTO { + //生产令号 + @JsonProperty("F_HBYT_SCLH") + private String FSCLH; + + //单据编号 + @JsonProperty("FBillNo") + private String FBillNo; + + //加工车间 + @JsonProperty("FWorkShopID.FName") + private String FWorkShopID; + + //工序号 + @JsonProperty("FOperNumber") + private String FOperNumber; + //工序说明 + @JsonProperty("FOperDescription") + private String FOperDescription; + + + //合格数量 + @JsonProperty("FQuaQty") + private String FQuaQty; + //合格数量 + @JsonProperty("FMoNumber") + private String FMoNumber; + + // 完工数量 + @JsonProperty("FFinishQty") + private String FFinishQty; + + // 合格品入库数量 + @JsonProperty("FStockInQuaAuxQty") + private String FStockInQuaAuxQty; + + //不合格品入库数量 + @JsonProperty("FStockInFailAuxQty") + private String FStockInFailAuxQty; + + //入库点 + @JsonProperty("F_HBYT_RKD") + private String FRKD; + + //单据日期 + @JsonProperty("FDate") + private String FDate; + +} 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 a4081a4..d8d4698 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 @@ -19,6 +19,11 @@ public class ProcessRouteXuDTO { * 工序路线描述 */ private String processDescription; + /** + * + */ + private String errorMessage; + /** * 工艺路线 */ diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessTransferFormDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessTransferFormDTO.java new file mode 100644 index 0000000..8302b3c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessTransferFormDTO.java @@ -0,0 +1,77 @@ +package com.ruoyi.system.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 工序转移单 + * @author tzy + * @date 2025-10-28 + */ +@Data +public class ProcessTransferFormDTO { + + //生产令号 + @JsonProperty("F_HBYT_SCLH") + private String FSCLH; + //单据编码 + @JsonProperty("FBillNo") + private String FBillNo; + //单据编码 + @JsonProperty("FDocumentStatus") + private String FDocumentStatus; + //单据编码 + @JsonProperty("FMOBillNo") + private String FMOBillNo; + //产品编码 + @JsonProperty("FProductId.FNumber") + private String FProductIdNumber; + + //产品名称 + @JsonProperty("FProductName") + private String FProductName; + + //转出加工车间 + @JsonProperty("FOutDeptId.FName") + private String FOutDeptIdFName; + + //转出工序计划号 + @JsonProperty("FOutOperNumber") + private String FOutOperNumber; + + //转出作业 + @JsonProperty("FOutProcessId.FName") + private String FOutProcessIdName; + + //转入加工车间 + @JsonProperty("FInDeptId.FName") + private String FInDeptIdFName; + + //转入工序计划号 + @JsonProperty("FInOperNumber") + private String FInOperNumber; + + //转入作业 + @JsonProperty("FInProcessId.FName") + private String FInProcessIdFName; + + //工序单位 + @JsonProperty("FOperUnitId.FName") + private String FOperUnit; + + //转移数量 + @JsonProperty("FOperTransferQty") + private String FOperTransferQty; + + //合格数量 + @JsonProperty("FOperQualifiedQty") + private String FOperQualifiedQty; + + //工废数量 + @JsonProperty("FOperProFailQty") + private String FOperProFailQty; + + //创建日期 + @JsonProperty("FCreateDate") + private String FCreateDate; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProductionOrderDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProductionOrderDTO.java new file mode 100644 index 0000000..9aeaddc --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProductionOrderDTO.java @@ -0,0 +1,70 @@ +package com.ruoyi.system.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + + +/** + * 生产订单开工未领料数据 + * @author tzy + * @date 2025-10-26 + */ + +@Data +public class ProductionOrderDTO { + + //生产令号 + @JsonProperty("F_HBYT_SCLH") + private String productionOrderNumber; + + //单据编码 + @JsonProperty("FBillNo") + private String FBillNo; + + //单据状态 + @JsonProperty("FDocumentStatus") + private String DocumentStatus; + + //物料编码 + @JsonProperty("FMaterialId.FNumber") + private String FMaterialIdFNumber; + + //物料名称 + @JsonProperty("FMaterialName") + private String FMaterialName; + + //材质 + @JsonProperty("F_UCHN_BaseProperty_qtr") + private String material; + + //单位 + @JsonProperty("FUnitId.FName") + private String unit; + + //生产车间 + @JsonProperty("FWorkShopID.FName") + private String productionWorkshop; + + //数量 + @JsonProperty("FQty") + private String quantity; + + //业务状态 + @JsonProperty("FStatus") + private String businessStatus; + + //领料状态 + @JsonProperty("FPickMtrlStatus") + private String materialRequisitionStatus; + + //计划开工时间 + @JsonProperty("FPlanStartDate") + private String FPlanStartDate; + + //计划完工时间 + @JsonProperty("FPlanFinishDate") + private String FPlanFinishDate; + + //超期天数 + private int Deydays; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseOrderExcelDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseOrderExcelDTO.java index c08eeb6..8f9e72e 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseOrderExcelDTO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseOrderExcelDTO.java @@ -52,5 +52,10 @@ public class PurchaseOrderExcelDTO { */ @JsonProperty("F_UCHN_Text2") private String FUCHNText2; + /** + * 创建日期 + */ + @JsonProperty("FCreateDate") + private String FCreateDate; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseRequestExcelDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseRequestExcelDTO.java index 316bb92..7f38fa1 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseRequestExcelDTO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/PurchaseRequestExcelDTO.java @@ -79,11 +79,17 @@ public class PurchaseRequestExcelDTO { * 生产令号 */ @JsonProperty("F_UCHN_Text") - private String FUCHNText;/** + private String FUCHNText; + /** * 生产令号 */ @JsonProperty("FCreatorId.FName") private String FCreatorIdFName; + /** + * 创建日期 + */ + @JsonProperty("FCreateDate") + private String FCreateDate; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/BomDetailsVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/BomDetailsVo.java index b81c08b..6e8ddbb 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/BomDetailsVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/BomDetailsVo.java @@ -103,5 +103,8 @@ public class BomDetailsVo { private Double danZhong; private Double singleWeghit; - + /** + *bom类型 + */ + private String bomType; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ElectricalMaterialBomVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ElectricalMaterialBomVO.java index 9edc78e..01edf56 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ElectricalMaterialBomVO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/ElectricalMaterialBomVO.java @@ -41,7 +41,7 @@ public class ElectricalMaterialBomVO { * 品牌 */ @ExcelProperty(value = "品牌") - private Double Brand; + private String Brand; /** * 单台数量 @@ -58,7 +58,7 @@ public class ElectricalMaterialBomVO { * 单位 */ @ExcelProperty(value = "单位") - private Double unit; + private String unit; /** * 备注 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/PartCostVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/PartCostVo.java new file mode 100644 index 0000000..a84f1c8 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/PartCostVo.java @@ -0,0 +1,79 @@ +package com.ruoyi.system.domain.vo; + +import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.ruoyi.common.annotation.ExcelDictFormat; +import com.ruoyi.common.convert.ExcelDictConvert; +import lombok.Data; + + +/** + * 零件成本视图对象 part_cost + * + * @author 田志阳 + * @date 2025-10-24 + */ +@Data +@ExcelIgnoreUnannotated +public class PartCostVo { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ExcelProperty(value = "ID") + + private Long id; + + /** + * 物料编码 + */ + @ExcelProperty(value = "物料编码") + + private String materialCode; + + /** + * 物料名称 + */ + @ExcelProperty(value = "物料名称") + private String materialName; + + /** + * 成本价 + */ + @ExcelProperty(value = "成本价") + private BigDecimal costPrice; + + /** + * 创建日期 + */ + @ExcelProperty(value = "创建日期") + private Date createDate; + + /** + * 车间 + */ + @ExcelProperty(value = "车间") + private String workshop; + + /** + * 单位 + */ + @ExcelProperty(value = "单位") + private String unit; + + /** + * 仓库 + */ + @ExcelProperty(value = "仓库") + private String warehouse; + /** + * 规格型号 + */ + @ExcelProperty(value = "规格型号") + private String specificationModel; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PartCostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PartCostMapper.java new file mode 100644 index 0000000..75840f1 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PartCostMapper.java @@ -0,0 +1,15 @@ +package com.ruoyi.system.mapper; + +import com.ruoyi.system.domain.PartCost; +import com.ruoyi.system.domain.vo.PartCostVo; +import com.ruoyi.common.core.mapper.BaseMapperPlus; + +/** + * 零件成本Mapper接口 + * + * @author 田志阳 + * @date 2025-10-24 + */ +public interface PartCostMapper extends BaseMapperPlus { + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java index ffb28d6..8680350 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java @@ -1,5 +1,7 @@ package com.ruoyi.system.runner; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; @@ -8,8 +10,10 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.kingdee.bos.webapi.entity.RepoRet; import com.kingdee.bos.webapi.sdk.K3CloudApi; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.JdUtils; import com.ruoyi.system.domain.BomDetails; +import com.ruoyi.system.domain.PartCost; import com.ruoyi.system.domain.dto.*; import com.ruoyi.system.domain.vo.*; import com.ruoyi.system.jdmain.rouplan.Model; @@ -312,7 +316,7 @@ public class JdUtil { 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) { @@ -419,7 +423,7 @@ public class JdUtil { 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) { @@ -499,7 +503,7 @@ public class JdUtil { JsonObject resultObject = new Gson().fromJson(resultJson, JsonObject.class); JsonArray rows = resultObject.getAsJsonObject("Result").getAsJsonArray("Rows"); - if (rows == null){ + if (rows == null) { System.err.println("No data returned for materialCode: " + materialCode); return new ArrayList<>(); } @@ -519,26 +523,29 @@ public class JdUtil { return rptDTOS; } - private static String getStringFromJsonArray(JsonArray array, int index) { - return array.size() > index && !array.get(index).isJsonNull() ? array.get(index).getAsString() : ""; - } - private static double getDoubleFromJsonArray(JsonArray array, int index) { - if (array.size() > index && !array.get(index).isJsonNull()) { - String value = array.get(index).getAsString(); - if (!value.isEmpty()) { - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - System.err.println("NumberFormatException for value: " + value); - } + private static String getStringFromJsonArray(JsonArray array, int index) { + return array.size() > index && !array.get(index).isJsonNull() ? array.get(index).getAsString() : ""; + } + + private static double getDoubleFromJsonArray(JsonArray array, int index) { + if (array.size() > index && !array.get(index).isJsonNull()) { + String value = array.get(index).getAsString(); + if (!value.isEmpty()) { + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + System.err.println("NumberFormatException for value: " + value); } } - return 0.0; } + return 0.0; + } + /** * 查询生产订单单据体 - *查询 + * 查询 + * * @param materialCode * @return */ @@ -584,7 +591,7 @@ public class JdUtil { filterObject3.addProperty("Right", ""); filterObject3.addProperty("Logic", 0); filterString.add(filterObject3); - JsonObject filterObject4 = new JsonObject(); + JsonObject filterObject4 = new JsonObject(); filterObject4.addProperty("FieldName", "FNoStockInQty"); filterObject4.addProperty("Compare", "21"); // 改为等号运算符 filterObject4.addProperty("Value", 0); @@ -619,14 +626,16 @@ public class JdUtil { return promoList; // 返回结果 } + /** * 查询生产订单未入库 本项目除外 - *查询 + * 查询 + * * @param materialCode * @return */ - public static List getProMoListLimitByProCode(String materialCode,String proCode) { + public static List getProMoListLimitByProCode(String materialCode, String proCode) { K3CloudApi client = new K3CloudApi(); // 请求参数,要求为json字符串 JsonObject json = new JsonObject(); @@ -709,14 +718,16 @@ public class JdUtil { return promoList; // 返回结果 } + /** * 查询生产订单未入库 本项目 - *查询 + * 查询 + * * @param materialCode * @return */ - public static List getProMoListByProCode(String materialCode,String proCode) { + public static List getProMoListByProCode(String materialCode, String proCode) { K3CloudApi client = new K3CloudApi(); // 请求参数,要求为json字符串 JsonObject json = new JsonObject(); @@ -799,9 +810,11 @@ public class JdUtil { return promoList; // 返回结果 } + /** * 查询采购订单 单据体 * 将预留量更改为 剩余未入库数量20250325 + * * @param materialCode * @return */ @@ -860,14 +873,16 @@ public class JdUtil { return plannedProcessList; // 返回结果 } + /** * 查询采购订单 单据体 * 将预留量更改为 剩余未入库数量20250325 + * * @param materialCode * @return */ - public static List getPurchaseOrderListByProCode(String materialCode,String proCode) { + public static List getPurchaseOrderListByProCode(String materialCode, String proCode) { K3CloudApi client = new K3CloudApi(); @@ -929,7 +944,8 @@ public class JdUtil { return plannedProcessList; // 返回结果 } - public static List getPurchaseRequestByProCode(String materialCode,String proCode) { + + public static List getPurchaseRequestByProCode(String materialCode, String proCode) { K3CloudApi client = new K3CloudApi(); @@ -983,8 +999,9 @@ public class JdUtil { return plannedProcessList; // 返回结果 } + // 采购申请(本项目除外) - public static List getPurchaseRequestByLimitProCode(String materialCode,String proCode) { + public static List getPurchaseRequestByLimitProCode(String materialCode, String proCode) { K3CloudApi client = new K3CloudApi(); @@ -1038,13 +1055,15 @@ public class JdUtil { return plannedProcessList; // 返回结果 } + /** * 查询生产用料清单单据体 * 查询子项物料的未领料量 + * * @param materialCode * @return */ - public static List getWeiLingliaoLimBen(String materialCode,String procode) { + public static List getWeiLingliaoLimBen(String materialCode, String procode) { K3CloudApi client = new K3CloudApi(); @@ -1130,9 +1149,11 @@ public class JdUtil { return plannedProcessList; // 返回结果 } + /** * 查询生产用料清单单据体 * 查询子项物料的未领料量 + * * @param materialCode * @return */ @@ -1215,13 +1236,15 @@ public class JdUtil { return plannedProcessList; // 返回结果 } + /** * 查询生产用料清单单据体 * 查询子项物料的未领料量限制生产令号 + * * @param materialCode * @return */ - public static List getWeiLingliaoByProcode(String materialCode,String procode) { + public static List getWeiLingliaoByProcode(String materialCode, String procode) { K3CloudApi client = new K3CloudApi(); @@ -1308,6 +1331,7 @@ public class JdUtil { return plannedProcessList; // 返回结果 } + public static List getKuCun(String materialCode) { K3CloudApi client = new K3CloudApi(); @@ -1355,8 +1379,9 @@ public class JdUtil { return plannedProcessList; // 返回结果 } + public static Double getKeyong(String materialCode) { - List analyzeRpt =getInvReserveAnalyzeRpt(materialCode); + List analyzeRpt = getInvReserveAnalyzeRpt(materialCode); if (analyzeRpt.isEmpty()) { System.err.println("No inventory data found for materialCode: " + materialCode); return 0.0; // 返回 0.0 而不是 null @@ -1385,6 +1410,7 @@ public class JdUtil { } return fSecAVBQty + productionQty + purchaseQty - fSecQty; } + // 金蝶物料查询 public static int isMaterialVerification(String DrawingNumber, String name) { if (DrawingNumber == null || DrawingNumber.isEmpty() || name == null || name.isEmpty()) { @@ -1409,10 +1435,11 @@ public class JdUtil { return 1; // 编码未找到,返回1表示正常 } } + /*本接口用于实现物料清单 的禁用功能*/ public static void jtestForbidMaterial(String FNumber) throws Exception { K3CloudApi api = new K3CloudApi(); - String data = "{\"CreateOrgId\": 0,\"Numbers\": ["+"\""+FNumber+"\""+"],\"Ids\": \"\",\"PkEntryIds\":[],\"NetworkCtrl\": \"\",\"IgnoreInterationFlag\": \"\"}"; + String data = "{\"CreateOrgId\": 0,\"Numbers\": [" + "\"" + FNumber + "\"" + "],\"Ids\": \"\",\"PkEntryIds\":[],\"NetworkCtrl\": \"\",\"IgnoreInterationFlag\": \"\"}"; String result = api.excuteOperation("ENG_BOM", "Forbid", data); Gson gson = new Gson(); RepoRet repoRet = gson.fromJson(result, RepoRet.class); @@ -1423,6 +1450,7 @@ public class JdUtil { fail("物料提交接口: " + gson.toJson(repoRet.getResult())); } } + //用料清单查询接口腹肌无聊 public static List getFuji(String materialCode) { List jinYongDTOS = new ArrayList<>(); @@ -1456,7 +1484,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); List JinYongDTOList = objectMapper.readValue(jsonArray.toString(), - new TypeReference>() {}); + new TypeReference>() { + }); if (JinYongDTOList != null && !JinYongDTOList.isEmpty()) { jinYongDTOS.addAll(JinYongDTOList); } @@ -1469,6 +1498,7 @@ public class JdUtil { return jinYongDTOS; } + //查询物料 FMATERIALID SubHeadEntity5FEntryId public static List getEntryID(String materialCode) { List jinYongDTOS = new ArrayList<>(); @@ -1502,7 +1532,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); List JinYongDTOList = objectMapper.readValue(jsonArray.toString(), - new TypeReference>() {}); + new TypeReference>() { + }); if (JinYongDTOList != null && !JinYongDTOList.isEmpty()) { jinYongDTOS.addAll(JinYongDTOList); } @@ -1515,8 +1546,9 @@ public class JdUtil { return jinYongDTOS; } + //修改物料工时,固定单位=分 - public static void atestSaveMaterial(int FMATERIALID,int fEntryId,String materialCode ,double laborTime) throws Exception { + public static void atestSaveMaterial(int FMATERIALID, int fEntryId, String materialCode, double laborTime) throws Exception { K3CloudApi api = new K3CloudApi(false); // 创建主 JSON 对象 JsonObject mainObject = new JsonObject(); @@ -1555,8 +1587,8 @@ public class JdUtil { mainObject.add("NeedReturnFields", needReturnFields); // 将 Model 添加到主对象 mainObject.add("Model", modelObject); - String data = mainObject.toString(); - String result = api.save("BD_Material", data); + String data = mainObject.toString(); + String result = api.save("BD_Material", data); Gson gson = new Gson(); RepoRet sRet = gson.fromJson(result, RepoRet.class); if (sRet.isSuccessfully()) { @@ -1565,8 +1597,9 @@ public class JdUtil { fail("物料保存接口: " + gson.toJson(sRet.getResult())); } } + //新增父级物料 - public static int loadChengPinMaterialPreservation(BomDetails bomDetail, Double fbWorkTime ) { + public static int loadChengPinMaterialPreservation(BomDetails bomDetail, Double fbWorkTime) { K3CloudApi client = new K3CloudApi(); // 创建一个空的JsonObject JsonObject json = new JsonObject(); @@ -1580,7 +1613,7 @@ public class JdUtil { // 添加Model字段 model.addProperty("FMATERIALID", 0); - if(!(bomDetail.getDanZhong() ==null)){ + if (!(bomDetail.getDanZhong() == null)) { model.addProperty("F_HBYT_DZ", bomDetail.getDanZhong()); } model.addProperty("FNumber", bomDetail.getFNumber()); @@ -1726,6 +1759,7 @@ public class JdUtil { } } + //查询物料 作用于更新到物料的 仓位 是否启用VMI public static List getEntryID2(String materialCode) { List jinYongDTOS = new ArrayList<>(); @@ -1760,7 +1794,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); List entryVmis = objectMapper.readValue(jsonArray.toString(), - new TypeReference>() {}); + new TypeReference>() { + }); if (entryVmis != null && !entryVmis.isEmpty()) { jinYongDTOS.addAll(entryVmis); } @@ -1773,6 +1808,7 @@ public class JdUtil { return jinYongDTOS; } + //更新VMI public static String updateVMI(int FMATERIALID, int fEntryId1, int fEntryId2, String cangkunum, String cangWeiNum) throws Exception { K3CloudApi api = new K3CloudApi(false); @@ -1811,7 +1847,7 @@ public class JdUtil { JsonObject fStockPlaceIdFF100002 = new JsonObject(); fStockPlaceIdFF100002.addProperty("FNumber", cangWeiNum); // - // fStockPlaceId.add("FSTOCKPLACEID__FF100002", fStockPlaceIdFF100002); + // fStockPlaceId.add("FSTOCKPLACEID__FF100002", fStockPlaceIdFF100002); fStockPlaceId.add("FSTOCKPLACEID__FF100002", fStockPlaceIdFF100002); subHeadEntity1.add("FStockPlaceId", fStockPlaceId); @@ -1839,6 +1875,7 @@ public class JdUtil { return errorMessage; } } + public static void updateDanzhong(int FMATERIALID, String danzhong) throws Exception { K3CloudApi api = new K3CloudApi(false); JsonObject json = new JsonObject(); @@ -1869,6 +1906,7 @@ public class JdUtil { System.out.println(errorMessage); } } + //查询物料清单 的 行iD public static List getFID(String materialCode) { List jinYongDTOS = new ArrayList<>(); @@ -1902,7 +1940,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); List JinYongDTOList = objectMapper.readValue(jsonArray.toString(), - new TypeReference>() {}); + new TypeReference>() { + }); if (JinYongDTOList != null && !JinYongDTOList.isEmpty()) { jinYongDTOS.addAll(JinYongDTOList); } @@ -1915,8 +1954,9 @@ public class JdUtil { return jinYongDTOS; } + //更新物料清单 的 行ID - public static String updateHuozhu(int FID, int FENTRYID,String code) throws Exception { + public static String updateHuozhu(int FID, int FENTRYID, String code) throws Exception { K3CloudApi api = new K3CloudApi(false); JsonObject json = new JsonObject(); @@ -1959,14 +1999,15 @@ public class JdUtil { RepoRet sRet = gson.fromJson(result, RepoRet.class); if (sRet.isSuccessfully()) { String successMessage = String.format("物料清单 %s 保存成功", sRet.getResult().getResponseStatus()); - log.info("更新货主信息物料编码==>"+code+" 保存成功"); + log.info("更新货主信息物料编码==>" + code + " 保存成功"); return successMessage; } else { String errorMessage = String.format("物料 %s 保存失败: %s", FENTRYID, gson.toJson(sRet.getResult())); - log.info("更新货主信息物料编码"+code+"保存失败"+"原因:"+gson.toJson(sRet.getResult())); + log.info("更新货主信息物料编码" + code + "保存失败" + "原因:" + gson.toJson(sRet.getResult())); return errorMessage; } } + //查询物料清单 的 行iD public static JdHuoZhu getFIDToProductionOrder(PlanOrderVo planOrder) { K3CloudApi client = new K3CloudApi(); @@ -1999,7 +2040,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); List jinYongDTOList = objectMapper.readValue(jsonArray.toString(), - new TypeReference>() {}); + new TypeReference>() { + }); if (jinYongDTOList != null && !jinYongDTOList.isEmpty()) { return jinYongDTOList.get(0); // 返回第一个对象 } @@ -2012,6 +2054,7 @@ public class JdUtil { return null; // 如果没有找到,返回 null } + //保存更新生产订单的开工时间 public static String updateOrder(JdHuoZhu jdHuoZhu, Model numDTO, Date xuStartTime, Date xuEndTime) throws Exception { String planStartDate = dateFormat.format(xuStartTime); @@ -2051,16 +2094,17 @@ public class JdUtil { RepoRet sRet = gson.fromJson(result, RepoRet.class); if (sRet.isSuccessfully()) { String successMessage = String.format("生产订单 %s 保存成功", sRet.getResult().getResponseStatus()); - log.info("物料编码"+numDTO.getFID()+"保存成功"); + log.info("物料编码" + numDTO.getFID() + "保存成功"); return successMessage; } else { String errorMessage = String.format("物料 %s 保存失败: %s", +numDTO.getFID(), gson.toJson(sRet.getResult())); - log.info("物料编码"+numDTO.getFID()+"保存失败"+"原因:"+gson.toJson(sRet.getResult())); + log.info("物料编码" + numDTO.getFID() + "保存失败" + "原因:" + gson.toJson(sRet.getResult())); return errorMessage; } } + public static List getSubHeadEntity1Id(String materialCode) { - ListsubHeadEntityDTOS = new ArrayList<>(); + List subHeadEntityDTOS = new ArrayList<>(); K3CloudApi client = new K3CloudApi(); JsonObject json = new JsonObject(); json.addProperty("FormId", "BD_MATERIAL"); @@ -2092,7 +2136,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); List JinYongDTOList = objectMapper.readValue(jsonArray.toString(), - new TypeReference>() {}); + new TypeReference>() { + }); if (JinYongDTOList != null && !JinYongDTOList.isEmpty()) { subHeadEntityDTOS.addAll(JinYongDTOList); } @@ -2105,7 +2150,8 @@ public class JdUtil { return subHeadEntityDTOS; } - public static String updateKunCun(int FMATERIALID, int fEntryId1, int fMaxPOQty, int FSafeStock) throws Exception { + + public static String updateKunCun(int FMATERIALID, int fEntryId1, int fMaxPOQty, int FSafeStock) throws Exception { K3CloudApi api = new K3CloudApi(false); JsonObject json = new JsonObject(); @@ -2156,6 +2202,7 @@ public class JdUtil { return errorMessage; } } + //获取用料清单 根据父级物料编码,作为bom校验使用 public static List getSelectBomList(String FMaterialCode) { K3CloudApi client = new K3CloudApi(); @@ -2201,7 +2248,8 @@ public class JdUtil { return null; } } - public static String updateOldFuNumber(String FMATERIALID, String FNumber, String FOldNumber) throws Exception { + + public static String updateOldFuNumber(String FMATERIALID, String FNumber, String FOldNumber) throws Exception { K3CloudApi api = new K3CloudApi(false); JsonObject json = new JsonObject(); @@ -2246,8 +2294,8 @@ public class JdUtil { JsonObject obj = element.getAsJsonObject(); String key = obj.get("FID").getAsString() + "_" + - obj.get("FMATERIALID.FNumber").getAsString() + "_" + - obj.get("FITEMNAME").getAsString(); + obj.get("FMATERIALID.FNumber").getAsString() + "_" + + obj.get("FITEMNAME").getAsString(); JdValidateBomDTO parentDTO = bomMap.computeIfAbsent(key, k -> { JdValidateBomDTO dto = new JdValidateBomDTO(); dto.setFID(obj.get("FID").getAsString()); @@ -2277,8 +2325,10 @@ public class JdUtil { return new ArrayList<>(); } } + /** * 获取生产用料清单 + * * @param F_HBYT_SCLH * @return */ @@ -2327,6 +2377,7 @@ public class JdUtil { return materialUsageDTO2List; // 返回结果 } + //用料清单查询接口腹肌无聊 public static List getEngBom(String materialCode) { List jinYongDTOS = new ArrayList<>(); @@ -2360,7 +2411,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); List JinYongDTOList = objectMapper.readValue(jsonArray.toString(), - new TypeReference>() {}); + new TypeReference>() { + }); if (JinYongDTOList != null && !JinYongDTOList.isEmpty()) { jinYongDTOS.addAll(JinYongDTOList); } @@ -2377,6 +2429,7 @@ public class JdUtil { /** * 获取固定工艺路线 + * * @param FMaterialCode * @return */ @@ -2419,7 +2472,8 @@ public class JdUtil { if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(jsonArray.toString(), new TypeReference>() {}); + return objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + }); } else { return Collections.emptyList(); } @@ -2428,8 +2482,10 @@ public class JdUtil { } return Collections.emptyList(); } + /** * 获取物料清单 + * * @param FMaterialCode * @return */ @@ -2469,7 +2525,8 @@ public class JdUtil { JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); if (jsonArray != null && jsonArray.size() > 0) { ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(jsonArray.toString(), new TypeReference>() {}); + return objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + }); } else { return Collections.emptyList(); } @@ -2478,8 +2535,10 @@ public class JdUtil { } return Collections.emptyList(); } + /** * 查询金蝶资产卡片 + * * @return */ @@ -2522,7 +2581,7 @@ public class JdUtil { // 请求参数,要求为json字符串 JsonObject json = new JsonObject(); json.addProperty("FormId", "PUR_PurchaseOrder"); - json.addProperty("FieldKeys", "FBillNo,FDate,FSupplierId.FName,FMaterialId.FNumber,FMaterialName,FQty,FDeliveryDate,F_UCHN_Text2"); + json.addProperty("FieldKeys", "FBillNo,FDate,FSupplierId.FName,FMaterialId.FNumber,FMaterialName,FQty,FDeliveryDate,F_UCHN_Text2,FCreateDate"); // 创建过滤条件 JsonObject filterObject = new JsonObject(); JsonArray filterString = new JsonArray(); @@ -2579,14 +2638,13 @@ public class JdUtil { /** * 采购申请单 - * @return List */ public static List getPurchaseRequestOrder() { K3CloudApi client = new K3CloudApi(); // 请求参数,要求为json字符串 JsonObject json = new JsonObject(); json.addProperty("FormId", "PUR_Requisition"); - json.addProperty("FieldKeys", "FBillNo,FBillTypeID,FDocumentStatus,FCloseStatus,FSuggestPurDate,FSuggestSupplierId.FName,FMaterialId.FNumber,FMaterialName,FPriceUnitId.FName,FReqQty,FArrivalDate,FApplicationDate,F_UCHN_Text,FCreatorId.FName"); + json.addProperty("FieldKeys", "FBillNo,FBillTypeID,FDocumentStatus,FCloseStatus,FSuggestPurDate,FSuggestSupplierId.FName,FMaterialId.FNumber,FMaterialName,FCreateDate,FPriceUnitId.FName,FReqQty,FArrivalDate,FApplicationDate,F_UCHN_Text,FCreatorId.FName"); // 创建过滤条件 JsonObject filterObject = new JsonObject(); JsonArray filterString = new JsonArray(); @@ -2631,4 +2689,538 @@ public class JdUtil { return purchaseRequestExcelDTOList; // 返回结果 } + + public static List getConstructionDelay() { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "PRD_MO"); + json.addProperty("FieldKeys", "F_HBYT_SCLH,FBillNo,FWorkShopID.FName,FMaterialId.FNumber,FMaterialName,FPlanStartDate,FPlanFinishDate,FPickMtrlStatus"); + // 创建过滤条件 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + filterObject.addProperty("FieldName", "FStatus"); + filterObject.addProperty("Compare", "105"); + filterObject.addProperty("Value", "4"); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 0); + filterString.add(filterObject); + + JsonObject filterObject1 = new JsonObject(); + filterObject1.addProperty("FieldName", "FPickMtrlStatus"); + filterObject1.addProperty("Compare", "29"); + filterObject1.addProperty("Value", "1"); + filterObject1.addProperty("Left", ""); + filterObject1.addProperty("Right", ""); + filterObject1.addProperty("Logic", 0); + filterString.add(filterObject1); + + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 10000); + json.addProperty("SubSystemId", ""); + + List constructionDelayDTOList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue( + jsonArray.toString(), new TypeReference>() { + }); + constructionDelayDTOList.addAll(pageList); + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + + return constructionDelayDTOList; // 返回结果 + } + + public static List getObtainPartData() { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "PRD_PickMtrl"); + json.addProperty("FieldKeys", "FMaterialId.FNumber,FSpecification,FMaterialName,FPrice,FCreateDate,FEntryWorkShopId.FName,FUnitID.FName,FStockId.FName"); + // 创建过滤条件 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + filterObject.addProperty("FieldName", "FDocumentStatus"); + filterObject.addProperty("Compare", "105"); + filterObject.addProperty("Value", "C"); + 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", 10000); + json.addProperty("SubSystemId", ""); + + List partCostBoList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + }); + partCostBoList.addAll(pageList); + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + + return partCostBoList; // 返回结果 + } + + /** + * 获取生产订单开工未领料数据 + * 不包含暂停状态的项目 + */ + public static List getProductionOrder() { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "PRD_MO"); + json.addProperty("FieldKeys", "F_HBYT_SCLH,FBillNo,FDocumentStatus,FMaterialId.FNumber,FMaterialName,F_UCHN_BaseProperty_qtr,FUnitId.FName,FWorkShopID.FName,FQty,FStatus,FPickMtrlStatus,FPlanStartDate,FPlanFinishDate"); + // 创建过滤条件 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + filterObject.addProperty("FieldName", "FPickMtrlStatus"); + filterObject.addProperty("Compare", "29"); + filterObject.addProperty("Value", "1"); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 0); + filterString.add(filterObject); + + JsonObject filterObject1 = new JsonObject(); + filterObject1.addProperty("FieldName", "F_HBYT_SCLH"); + filterObject1.addProperty("Compare", "34"); + filterObject1.addProperty("Value", "暂停"); + filterObject1.addProperty("Left", ""); + filterObject1.addProperty("Right", ""); + filterObject1.addProperty("Logic", 0); + filterString.add(filterObject1); + + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 10000); + json.addProperty("SubSystemId", ""); + List productionOrderDTOList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue( + jsonArray.toString(), new TypeReference>() { + }); + productionOrderDTOList.addAll(pageList); + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + + return productionOrderDTOList; // 返回结果 + } + + /** + * 待转序查询,工序转移单非委外列表 + * 不包含暂停状态的项目 + */ + public static List getProcessTransferForm() { + //TOdo: 创建实体类 + + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "SFC_OperationTransfer"); + json.addProperty("FieldKeys", "F_HBYT_SCLH,FProductId.FNumber,FBillNo,FMOBillNo,FDocumentStatus,FProductName,FOutDeptId.FName,FOutOperNumber,FOutProcessId.FName,FInDeptId.FName,FInOperNumber,FInProcessId.FName,FOperUnitId.FName,FOperTransferQty,FOperQualifiedQty,FOperProFailQty,FCreateDate"); + // 创建过滤条件 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + filterObject.addProperty("FieldName", "FDocumentStatus"); + filterObject.addProperty("Compare", "105"); + filterObject.addProperty("Value", "B"); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 1); + filterString.add(filterObject); + + JsonObject filterObject2 = new JsonObject(); + filterObject2.addProperty("FieldName", "FDocumentStatus"); + filterObject2.addProperty("Compare", "105"); + filterObject2.addProperty("Value", "A"); + filterObject2.addProperty("Left", ""); + filterObject2.addProperty("Right", ""); + filterObject2.addProperty("Logic", 1); + filterString.add(filterObject2); + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 10000); + json.addProperty("SubSystemId", ""); + List processTransferFormDTOList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue( + jsonArray.toString(), new TypeReference>() { + }); + processTransferFormDTOList.addAll(pageList); + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + + return processTransferFormDTOList; // 返回结果 + } + + /** + * 质检检验单 ,数据用来判定是否质检 + */ + public static List getQMInspectBill() { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "SFC_OperationTransfer"); + json.addProperty("FieldKeys", "F_UCHN_Text,FBillNo,FDocumentStatus,FMaterialId.FNumber,FMaterialName,FMaterialModel,FQCStatus,FInspectResult,FUnitID.FName,FInspectQty,FQualifiedQty,FUnqualifiedQty"); + // 创建过滤条件 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + //质检转态:计划1 质检开始2 质检状态3 :FQCStatus + filterObject.addProperty("FieldName", "FQCStatus"); + filterObject.addProperty("Compare", "29"); + filterObject.addProperty("Value", "1"); + 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", 10000); + json.addProperty("SubSystemId", ""); + List inspectionSheetDTOList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + }); + inspectionSheetDTOList.addAll(pageList); + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + + return inspectionSheetDTOList; // 返回结果 + } + + /** + * 工序汇报单 用来查询是否入库 + * 判断条件是否入库点,合格数量和入库数量是否相同 + */ + public static List getProcessReport() { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "SFC_OperationReport"); + json.addProperty("FieldKeys", "F_HBYT_SCLH,FBillNo,FMoNumber,FWorkShopID.FName,FOperNumber,FOperDescription,FQuaQty,FFinishQty,FStockInQuaAuxQty,FStockInFailAuxQty,F_HBYT_RKD,FDate"); + // 是否为入库点 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + filterObject.addProperty("FieldName", "F_HBYT_RKD"); + filterObject.addProperty("Compare", "74"); + filterObject.addProperty("Value", true); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 0); + filterString.add(filterObject); + JsonObject filterObject1 = new JsonObject(); + filterObject1.addProperty("FieldName", "FDocumentStatus"); + filterObject1.addProperty("Compare", "105"); + filterObject1.addProperty("Value", "A"); + filterObject1.addProperty("Left", ""); + filterObject1.addProperty("Right", ""); + filterObject1.addProperty("Logic", 1); + filterString.add(filterObject1); + JsonObject filterObject2 = new JsonObject(); + filterObject2.addProperty("FieldName", "FDocumentStatus"); + filterObject2.addProperty("Compare", "105"); + filterObject2.addProperty("Value", "B"); + filterObject2.addProperty("Left", ""); + filterObject2.addProperty("Right", ""); + filterObject2.addProperty("Logic", 1); + filterString.add(filterObject2); + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 10000); + json.addProperty("SubSystemId", ""); + List processReportDTOList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue(jsonArray.toString(), new TypeReference>() { + }); + processReportDTOList.addAll(pageList); + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + + return processReportDTOList; // 返回结果 + } + + + /** + * 从金蝶获取质检看板数据 + */ + public static List getUninspectedData() { + List kingdeeWorkCenterDataVos = new ArrayList<>(); + try { + K3CloudApi client = new K3CloudApi(); + // 调用金蝶接口 + String execute = client.execute( + "Ljint.Kingdee.YiTe.KanBan.WebApi.QualityWebApi.ExecuteService,Ljint.Kingdee.YiTe.KanBan.WebApi", + new String[]{" "} + ); + // 解析返回结果 + JSONObject response = JSONObject.parseObject(execute); + if (response == null) { + log.error("金蝶接口返回为空!"); + return Collections.emptyList(); + } + if (!"true".equalsIgnoreCase(response.getString("IsSuccess"))) { + String errorMsg = response.getString("Message"); + log.error("金蝶接口调用失败:{}", errorMsg); + return Collections.emptyList(); + } + // 获取数据数组 + JSONArray dataArray = response.getJSONArray("data"); + if (dataArray == null || dataArray.isEmpty()) { + log.warn("金蝶接口返回的质检数据为空!"); + return Collections.emptyList(); + } + // 解析每个工段下的 QueryList + for (int i = 0; i < dataArray.size(); i++) { + JSONArray queryList = dataArray.getJSONObject(i).getJSONArray("QueryList"); + if (queryList == null || queryList.isEmpty()) { + continue; + } + for (int j = 0; j < queryList.size(); j++) { + JSONObject item = queryList.getJSONObject(j); + if (item == null) continue; + // 转换为实体对象 + ProcessInspectionDTO data = new ProcessInspectionDTO(); + data.setMoBillNo(item.getString("MoBillNo")); + data.setMoOrderNo(item.getString("MoOrderNo")); + data.setSubOrderNo(item.getString("SubOrderNo")); + data.setFMaterialName(item.getString("FMaterialName")); + data.setFProcessName(item.getString("FProcessName")); + data.setFWorkCenterName(item.getString("FWorkCenterName")); + data.setFInspectStatus(item.getString("FInspectStatus")); + data.setFWaitInspectQty(item.getInteger("FWaitInspectQty")); + data.setFFinishInspectQty(item.getInteger("FFinishInspectQty")); + data.setFQuaQty(item.getInteger("FQuaQty")); + data.setFReworkQty(item.getInteger("FReworkQty")); + data.setFFailQty(item.getInteger("FFailQty")); + data.setFSubmitInspectTime(item.getString("FSubmitInspectTime")); + data.setFFinishInspectTime(item.getString("FFinishInspectTime")); + data.setFDescription(item.getString("FDescription")); + kingdeeWorkCenterDataVos.add(data); + } + } + + } catch (Exception e) { + log.error("调用金蝶接口获取质检看板数据异常:{}", e.getMessage(), e); + return Collections.emptyList(); + } + return kingdeeWorkCenterDataVos; + } + + + /** + * 工序汇报单 用来查询是否入库 + * 判断条件是否入库点,合格数量和入库数量是否相同 + */ + public static OperationPlannDTO getOperationPlann(String FBillNo) { + K3CloudApi client = new K3CloudApi(); + // 请求参数,要求为json字符串 + JsonObject json = new JsonObject(); + json.addProperty("FormId", "SFC_OperationPlanning"); + json.addProperty("FieldKeys", "FOperNumber,FOperQty,FProcessId.FName"); + // 是否为入库点 + JsonObject filterObject = new JsonObject(); + JsonArray filterString = new JsonArray(); + filterObject.addProperty("FieldName", "FMONumber"); + filterObject.addProperty("Compare", "67"); + filterObject.addProperty("Value", FBillNo); + filterObject.addProperty("Left", ""); + filterObject.addProperty("Right", ""); + filterObject.addProperty("Logic", 0); + filterString.add(filterObject); + + JsonObject filterObjec1t = new JsonObject(); + filterObjec1t.addProperty("FieldName", "FOperStatus"); + filterObjec1t.addProperty("Compare", "105"); + filterObjec1t.addProperty("Value", "4"); + filterObjec1t.addProperty("Left", ""); + filterObjec1t.addProperty("Right", ""); + filterObjec1t.addProperty("Logic", 0); + filterString.add(filterObjec1t); + json.add("FilterString", filterString); + json.addProperty("OrderString", ""); + json.addProperty("TopRowCount", 0); + json.addProperty("StartRow", 0); + json.addProperty("Limit", 10000); + json.addProperty("SubSystemId", ""); + List processReportDTOList = new ArrayList<>(); + int pageSize = 10000; + int startRow = 0; + ObjectMapper objectMapper = new ObjectMapper(); + try { + while (true) { + JsonObject pageJson = new Gson().fromJson(json.toString(), JsonObject.class); + pageJson.addProperty("StartRow", startRow); + pageJson.addProperty("Limit", pageSize); + String resultJson = String.valueOf(client.billQuery(pageJson.toString())); + JsonArray jsonArray = new Gson().fromJson(resultJson, JsonArray.class); + if (jsonArray == null || jsonArray.size() == 0) { + break; + } + List pageList = objectMapper.readValue(jsonArray.toString(), + new TypeReference>() { + }); + if (pageList != null && !pageList.isEmpty()) { + processReportDTOList.addAll(pageList); + } + if (jsonArray.size() < pageSize) { + break; + } + startRow += pageSize; + } + } catch (Exception e) { + e.printStackTrace(); // 输出异常日志 + } + + if (processReportDTOList.isEmpty()) { + return null; + } + // 选择工序号最小的作为代表项(通常为最后一道工序) + OperationPlannDTO best = null; + int bestOper = Integer.MAX_VALUE; + for (OperationPlannDTO dto : processReportDTOList) { + int oper = Integer.MAX_VALUE; + try { + String numStr = dto.getFOperNumber(); + if (numStr != null) { + oper = Integer.parseInt(numStr.trim()); + } + } catch (Exception ignore) { + oper = Integer.MAX_VALUE; + } + if (oper <= bestOper) { + bestOper = oper; + best = dto; + } + } + return best; + } + + } 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 11a53c9..e33a6d7 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 @@ -18,10 +18,9 @@ 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; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.time.format.DateTimeFormatter; @@ -104,14 +103,24 @@ public class PDFGenerator { throw new RuntimeException("无法创建目录: " + directoryPath); } } else { - // 如果目录存在,删除其中的所有文件 - File[] files = directory.listFiles(); - if (files != null) { - for (File file : files) { - if (!file.delete()) { - System.err.println("无法删除文件: " + file.getAbsolutePath()); + // 目录存在:使用NIO递归清理目录内容(不删除根目录本身) + try { + Path root = Paths.get(directoryPath); + if (java.nio.file.Files.exists(root)) { + try (java.util.stream.Stream walk = java.nio.file.Files.walk(root)) { + walk.filter(p -> !p.equals(root)) + .sorted(java.util.Comparator.reverseOrder()) // 先删子路径再删父路径 + .forEach(p -> { + try { + java.nio.file.Files.deleteIfExists(p); + } catch (IOException e) { + System.err.println("删除失败: " + p.toString() + ": " + e.getMessage()); + } + }); } } + } catch (IOException e) { + throw new RuntimeException("清理目录失败: " + directoryPath + ", " + e.getMessage(), e); } } for (CombinedDTO combinedVo : combinedVoList) { @@ -125,10 +134,12 @@ public class PDFGenerator { String materialCode; Long fmoQty; String fDepartmentName; - // 获取第一序的工序名称 + String OrderNumber = ""; + // 获取第一序的工序名称 List processes = combinedVo.getProcesses(); if (!processes.isEmpty()) { fProcessName = processes.get(0).getFProcessName(); + OrderNumber = combinedVo.getOrderNumber(); productionOrderNumber = String.valueOf(combinedVo.getProcesses().get(0).getFBillNo()); starttime = combinedVo.getProcesses().get(0).getFPlanStartTime(); endtime = combinedVo.getProcesses().get(0).getFPlanFinishTime(); @@ -166,11 +177,11 @@ public class PDFGenerator { // 获取当前时间的毫秒时间戳 long timestamp = System.currentTimeMillis(); - String pdfPath = departmentFolder.getAbsolutePath() + "\\" + fDepartmentName + "_" - + materialCode1.replace("/", "_") + "_" + productionOrderNumber + ".pdf"; + String pdfPath = departmentFolder.getAbsolutePath() + "\\" + fDepartmentName + "_" + materialCode1.replace("/", "_") + "_" + productionOrderNumber + ".pdf"; + PDDocument document = null; try { // 创建 PDF 文件并写入内容 - PDDocument document = new PDDocument(); + document = new PDDocument(); PDPage page = new PDPage(); document.addPage(page); PDType0Font font = PDType0Font.load(document, new File(fontPath)); @@ -223,14 +234,15 @@ public class PDFGenerator { float[] processColWidths = { 35, 78, 35, 55, 45, 170, 55, 60, 60 }; yStart = processTableStartY; - drawTableRow(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[] { + // 使用支持换行的方法绘制表头 + yStart = drawTableRowWithWrap(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[] { + // 使用支持换行的方法绘制数据行,特别是工序说明字段 + yStart = drawTableRowWithWrap(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()), @@ -309,6 +321,14 @@ public class PDFGenerator { pdfPaths.add(pdfPath); } catch (IOException | WriterException e) { e.printStackTrace(); + } finally { + if (document != null) { + try { + document.close(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } } } } @@ -478,4 +498,122 @@ public class PDFGenerator { } } + // ... 其他代码 ... + + // Java 8兼容的文本换行处理方法 + private static List wrapText(String text, PDType0Font font, float fontSize, float maxWidth) throws IOException { + List lines = new ArrayList(); + if (text == null || text.trim().isEmpty()) { + lines.add(""); + return lines; + } + + // 去除换行符,用空格替换 + text = text.replace("\n", " ").replace("\r", " ").trim(); + + // 增加边距,确保文本不会超出边界 + float effectiveWidth = maxWidth - 20; // 增加边距到20个单位 + + StringBuilder currentLine = new StringBuilder(); + + // 逐字符处理,更好地支持中文 + for (int i = 0; i < text.length(); i++) { + char currentChar = text.charAt(i); + String testLine = currentLine.toString() + currentChar; + + float textWidth = font.getStringWidth(testLine) / 1000 * fontSize; + + if (textWidth <= effectiveWidth) { + currentLine.append(currentChar); + } else { + // 当前行已满,开始新行 + if (currentLine.length() > 0) { + lines.add(currentLine.toString().trim()); + currentLine = new StringBuilder(); + currentLine.append(currentChar); + } else { + // 单个字符就超宽(极少见情况),强制添加 + lines.add(String.valueOf(currentChar)); + } + } + } + + // 添加最后一行 + if (currentLine.length() > 0) { + lines.add(currentLine.toString().trim()); + } + + // 如果没有任何内容,至少返回一个空行 + if (lines.isEmpty()) { + lines.add(""); + } + + return lines; + } + + // Java 8兼容的改进表格绘制方法,支持自动换行 + private static float drawTableRowWithWrap(PDPageContentStream contentStream, PDType0Font font, float margin, + float yStart, float tableWidth, float[] colWidths, String[] cells, PDDocument document, + PDPage page, float baseRowHeight, float pageHeight) throws IOException { + + float nextX = margin; + float nextY = yStart; + float fontSize = 10; + int maxColumns = Math.min(cells.length, colWidths.length); + + // 计算每列的文本行数,确定实际行高 + List> allCellLines = new ArrayList>(); + int maxLines = 1; + + for (int i = 0; i < maxColumns; i++) { + String cellText = cells[i] != null ? cells[i] : ""; + List lines = wrapText(cellText, font, fontSize, colWidths[i]); + allCellLines.add(lines); + maxLines = Math.max(maxLines, lines.size()); + } + + float actualRowHeight = baseRowHeight * maxLines; + + // 检查是否需要分页 + if (nextY - actualRowHeight < margin) { + contentStream.close(); + // 创建新页面 + page = new PDPage(); + document.addPage(page); + contentStream = new PDPageContentStream(document, page); + // 重置Y坐标为新页面顶部 + nextY = pageHeight - margin; + } + + // 绘制表格边框和内容 + nextX = margin; + for (int i = 0; i < maxColumns; i++) { + List lines = allCellLines.get(i); + + // 绘制单元格边框 + contentStream.moveTo(nextX, nextY); + contentStream.lineTo(nextX, nextY - actualRowHeight); + contentStream.lineTo(nextX + colWidths[i], nextY - actualRowHeight); + contentStream.lineTo(nextX + colWidths[i], nextY); + contentStream.closeAndStroke(); + + // 绘制文本内容 + for (int lineIndex = 0; lineIndex < lines.size(); lineIndex++) { + String line = lines.get(lineIndex); + if (!line.isEmpty()) { + contentStream.beginText(); + contentStream.setFont(font, fontSize); + float textY = nextY - 15 - (lineIndex * (fontSize + 2)); + contentStream.newLineAtOffset(nextX + 8, textY); // 增加左边距到8个单位 + contentStream.showText(line); + contentStream.endText(); + } + } + + nextX += colWidths[i]; + } + + return nextY - actualRowHeight; // 返回下一行的Y坐标 + } + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java index decf946..4b49deb 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java @@ -70,7 +70,6 @@ public class updatePcessPlanConver { String formId = "SFC_OperationPlanning"; //调用接口 String resultJson = client.save(formId, jsonOutput); - System.out.println("调用接口:+++++" + jsonOutput); //用于记录结果 Gson gson = new Gson(); //对返回结果进行解析和校验 @@ -108,7 +107,6 @@ public class updatePcessPlanConver { //业务对象标识工序计划表 String formId = "SFC_OperationPlanning"; //调用接口 - System.out.println("调用接口:"+model.getFProcessId_number()+"+++++" + jsonOutput); String resultJson = client.save(formId, jsonOutput); //用于记录结果 Gson gson = new Gson(); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IPartCostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IPartCostService.java new file mode 100644 index 0000000..dbbe25c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IPartCostService.java @@ -0,0 +1,50 @@ +package com.ruoyi.system.service; + +import com.ruoyi.system.domain.vo.PartCostVo; +import com.ruoyi.system.domain.bo.PartCostBo; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.domain.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 零件成本Service接口 + * + * @author 田志阳 + * @date 2025-10-24 + */ +public interface IPartCostService { + + /** + * 查询零件成本 + */ + PartCostVo queryById(Long id); + + /** + * 查询零件成本列表 + */ + TableDataInfo queryPageList(PartCostBo bo, PageQuery pageQuery); + + /** + * 查询零件成本列表 + */ + List queryList(PartCostBo bo); + + /** + * 新增零件成本 + */ + Boolean insertByBo(PartCostBo bo); + + /** + * 修改零件成本 + */ + Boolean updateByBo(PartCostBo bo); + + /** + * 校验并批量删除零件成本信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + boolean getObtainPartData(); +} 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 ae80c09..b9d1e3b 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 @@ -3,6 +3,7 @@ package com.ruoyi.system.service; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.system.domain.dto.BOMItem; import com.ruoyi.system.domain.BomDetails; import com.ruoyi.system.domain.MaterialBom; import com.ruoyi.system.domain.ProcessRoute; @@ -84,7 +85,7 @@ public interface IProcessRouteService { * 推送工艺路线 */ - ProcessRoutePushResultDTO pushRouteBom(String rooteProdet); + R pushRouteBom(String rooteProdet); /** * 获取所有的项目令号 */ @@ -143,4 +144,9 @@ public interface IProcessRouteService { String getRouteCode(String materialCode,String code); List selectByProjectNumber(String productionOrderNo); + + R viewGetBomUploadStatus(String rooteProdet); + + //根据令号和物料编码 查询工艺路线 + ProcessRoute getProcessRoutesXuTime(String productionOrderNo, String materialCode,String xu); } 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 3adb968..35b12de 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 @@ -107,6 +107,7 @@ public class BomDetailsServiceImpl implements IBomDetailsService { lqw.like(StringUtils.isNotBlank(bo.getFName()), BomDetails::getFName, bo.getFName()); lqw.eq(StringUtils.isNotBlank(bo.getStats()), BomDetails::getStats, bo.getStats()); lqw.eq(StringUtils.isNotBlank(bo.getWareHouse()), BomDetails::getWareHouse, bo.getWareHouse()); + lqw.eq(StringUtils.isNotBlank(bo.getBomType()), BomDetails::getBomType, bo.getBomType()); lqw.orderByAsc(BomDetails::getTotalWeight); return lqw; } @@ -222,11 +223,10 @@ public class BomDetailsServiceImpl implements IBomDetailsService { MaterialBom matchedMaterialBom = materialBomMap.get(key); if (matchedMaterialBom != null) { if (matchedMaterialBom.getUnit().equals("根")) { - bomDetail.setQuantity(Double.valueOf(String.valueOf(matchedMaterialBom.getQuantity()).split("/")[0])); + bomDetail.setQuantity(String.valueOf(matchedMaterialBom.getQuantity()).split("/")[0]); bomDetail.setDenominator(Double.valueOf(String.valueOf(matchedMaterialBom.getQuantity()).split("/")[1])); - } else { - bomDetail.setQuantity(Double.valueOf(String.valueOf(matchedMaterialBom.getQuantity()))); + bomDetail.setQuantity(String.valueOf(matchedMaterialBom.getQuantity())); } } } 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 d1569a2..c549c66 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 @@ -179,21 +179,6 @@ public class ImMaterialServiceImpl implements IImMaterialService { try { LambdaQueryWrapper lqw = buildQueryWrapper(bo); - lqw.like(StringUtils.isNotBlank(bo.getMaterialCode()), ImMaterial::getMaterialCode, bo.getMaterialCode()); - lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), ImMaterial::getMaterialName, bo.getMaterialName()); - 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.eq(bo.getSingleWeight() != null, ImMaterial::getSingleWeight, bo.getSingleWeight()); - lqw.eq( ImMaterial::getForbidStatus, "A"); - lqw.like(StringUtils.isNotBlank(bo.getUnit()), ImMaterial::getUnit, bo.getUnit()); - lqw.like(bo.getFlag() != null, ImMaterial::getFlag, bo.getFlag()); - lqw.orderBy(true, false, ImMaterial::getModifyDate); - - - System.out.println("+++++++++++++++++++++++++++++++++++++++"+lqw.getSqlSegment()); - - // 执行查询 Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); if (CollectionUtils.isEmpty(result.getRecords())) { return TableDataInfo.build(result); // 如果结果为空,直接返回 @@ -414,11 +399,10 @@ public class ImMaterialServiceImpl implements IImMaterialService { lqw.like(StringUtils.isNotBlank(bo.getImCategory()), ImMaterial::getImCategory, bo.getImCategory()); lqw.like(StringUtils.isNotBlank(bo.getMaterialQuality()), ImMaterial::getMaterialQuality, bo.getMaterialQuality()); lqw.eq(bo.getSingleWeight() != null, ImMaterial::getSingleWeight, bo.getSingleWeight()); - lqw.eq(bo.getForbidStatus() != null, ImMaterial::getForbidStatus, "否"); - lqw.like(bo.getUnitPrice() != null, ImMaterial::getUnitPrice, bo.getUnitPrice()); + lqw.eq( ImMaterial::getForbidStatus, "A"); lqw.like(StringUtils.isNotBlank(bo.getUnit()), ImMaterial::getUnit, bo.getUnit()); lqw.like(bo.getFlag() != null, ImMaterial::getFlag, bo.getFlag()); - lqw.orderBy(true, false, ImMaterial::getUnit); + lqw.orderBy(true, false, ImMaterial::getModifyDate); return lqw; } @@ -745,9 +729,11 @@ public class ImMaterialServiceImpl implements IImMaterialService { // 根据 materialId 查询是否存在 ImMaterial existing = baseMapper.selectByMid(imMaterial.getMaterialId()); if (imMaterial.getForbidStatus().equals("A")){ - imMaterial.setForbidStatus("否"); + imMaterial.setForbidStatus("A"); + imMaterial.setUpdateTime(new Date()); }else { - imMaterial.setForbidStatus("是"); + imMaterial.setForbidStatus("B"); + imMaterial.setUpdateTime(new Date()); } if (existing != null) { 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 d54227a..a780711 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 @@ -145,7 +145,7 @@ public class MaterialBomServiceImpl implements IMaterialBomService { bomDetails.setName(bo.getMaterialName()); bomDetails.setName(bo.getMaterialName()); bomDetails.setDenominator(1.0); - bomDetails.setQuantity(Double.valueOf(bo.getQuantity())); + bomDetails.setQuantity(bo.getQuantity()); bomDetails.setStats("外购"); bomDetails.setMaterial(bo.getMaterialType()); int flag = bomDetailsMapper.insert(bomDetails); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PartCostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PartCostServiceImpl.java new file mode 100644 index 0000000..55f9ccd --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PartCostServiceImpl.java @@ -0,0 +1,166 @@ +package com.ruoyi.system.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.domain.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.runner.JdUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.bo.PartCostBo; +import com.ruoyi.system.domain.vo.PartCostVo; +import com.ruoyi.system.domain.PartCost; +import com.ruoyi.system.mapper.PartCostMapper; +import com.ruoyi.system.service.IPartCostService; + +import java.math.BigDecimal; +import java.util.*; + +/** + * 零件成本Service业务层处理 + * + * @author 田志阳 + * @date 2025-10-24 + */ +@RequiredArgsConstructor +@Service +public class PartCostServiceImpl implements IPartCostService { + + private final PartCostMapper baseMapper; + + /** + * 查询零件成本 + */ + @Override + public PartCostVo queryById(Long id){ + return baseMapper.selectVoById(id); + } + + /** + * 查询零件成本列表 + */ + @Override + public TableDataInfo queryPageList(PartCostBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询零件成本列表 + */ + @Override + public List queryList(PartCostBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(PartCostBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getMaterialCode()), PartCost::getMaterialCode, bo.getMaterialCode()); + lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), PartCost::getMaterialName, bo.getMaterialName()); + lqw.eq(bo.getCostPrice() != null, PartCost::getCostPrice, bo.getCostPrice()); + lqw.eq(bo.getCreateDate() != null, PartCost::getCreateDate, bo.getCreateDate()); + lqw.eq(StringUtils.isNotBlank(bo.getWorkshop()), PartCost::getWorkshop, bo.getWorkshop()); + lqw.eq(StringUtils.isNotBlank(bo.getUnit()), PartCost::getUnit, bo.getUnit()); + lqw.eq(StringUtils.isNotBlank(bo.getWarehouse()), PartCost::getWarehouse, bo.getWarehouse()); + lqw.eq(StringUtils.isNotBlank(bo.getSpecificationModel()), PartCost::getSpecificationModel, bo.getSpecificationModel()); + return lqw; + } + + /** + * 新增零件成本 + */ + @Override + public Boolean insertByBo(PartCostBo bo) { + PartCost add = BeanUtil.toBean(bo, PartCost.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改零件成本 + */ + @Override + public Boolean updateByBo(PartCostBo bo) { + PartCost update = BeanUtil.toBean(bo, PartCost.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(PartCost entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除零件成本 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + @Override + public boolean getObtainPartData() { + List list = JdUtil.getObtainPartData(); + if (list == null || list.isEmpty()) { + return false; + } + + Map uniq = new LinkedHashMap<>(); + for (PartCost pc : list) { + if (pc == null) continue; + + String code = pc.getMaterialCode(); + String name = pc.getMaterialName(); + BigDecimal cost = pc.getCostPrice(); + + // 过滤无效数据 + if (StringUtils.isBlank(code) || StringUtils.isBlank(name) || cost == null || cost.compareTo(BigDecimal.ZERO) == 0) { + continue; + } + + // 以 物料编码 + 名称 为唯一键 + String key = code + "|" + name; + + PartCost existing = uniq.get(key); + // 保留 createDate 最新的 + if (existing == null || + (pc.getCreateDate() != null && + (existing.getCreateDate() == null || pc.getCreateDate().after(existing.getCreateDate())))) { + uniq.put(key, pc); + } + } + + List deduped = new ArrayList<>(uniq.values()); + if (deduped.isEmpty()) { + return false; + } + + // 删除旧记录 + for (PartCost pc : deduped) { + LambdaQueryWrapper delWrapper = Wrappers.lambdaQuery(); + delWrapper.eq(PartCost::getMaterialCode, pc.getMaterialCode()) + .eq(PartCost::getMaterialName, pc.getMaterialName()); + baseMapper.delete(delWrapper); + } + + // 批量插入最新记录 + return baseMapper.insertBatch(deduped); + } + +} 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 e75191d..334bc75 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 @@ -538,7 +538,7 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService { log.info("出图接口响应=====>{}", response); // 2. 开始轮询状态接口,直到完成 boolean finished = false; - int maxRetry = 60; // 最多轮询 60 次(根据需求调整,比如 60*5s=5分钟) + int maxRetry = 360; // 最多轮询 60 次(根据需求调整,比如 60*5s=5分钟) int count = 0; while (!finished && count < maxRetry) { @@ -968,9 +968,7 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService { FigureSave figureSave = figureSaveMapper.selectById(id); ProcessOrderPro processOrderPro = baseMapper.selectById(figureSave); if (figureSave == null) return "图纸信息不存在"; - String code = figureSave.getProductionCode(); - // 2. 拼接本地路径和FTP路径 String localPath = Constants.BASIC_URL; String ftpPath = ""; @@ -1252,7 +1250,7 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService { dto.setRawMaterialName(bom.getMaterialName()); dto.setBomMaterial(bom.getMaterialType()); dto.setBomUnit(bom.getUnit()); - + // 单位转换:如果单位为mm,则数值乘以1000 String quantity = bom.getQuantity(); if ("mm".equals(bom.getUnit()) && quantity != null) { diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessRouteServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProcessRouteServiceImpl.java index aaf0fe1..7e44f61 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 @@ -19,11 +19,12 @@ import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.system.domain.dto.BOMItem; +import com.ruoyi.system.domain.dto.BOMUploadResult; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.controller.ProcessRouteController; import com.ruoyi.system.domain.*; import com.ruoyi.system.domain.bo.MaterialBomBo; -import com.ruoyi.system.domain.bo.ProcessOrderProBo; import com.ruoyi.system.domain.bo.ProcessRouteBo; import com.ruoyi.system.domain.dto.*; import com.ruoyi.system.domain.vo.*; @@ -265,7 +266,6 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } - /** * @param materialCode * @return @@ -291,8 +291,40 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { @Override public List selectByProjectNumber(String productionOrderNo) { LambdaQueryWrapper war = new LambdaQueryWrapper<>(); - war.eq(ProcessRoute::getRouteDescription,productionOrderNo); - return baseMapper.selectList(war); + war.eq(ProcessRoute::getRouteDescription, productionOrderNo); + return baseMapper.selectList(war); + } + + /** + * 获取bom的上传状态 + */ + @Override + public R viewGetBomUploadStatus(String rooteProdet) { + ProcessOrderPro processOrderPro = processOrderProMapper.selectByProjectNumber(rooteProdet); + String drawingType = processOrderPro.getDrawingType(); // 这里就是 JSON + // 转换 JSON 数组 -> List + List bomItems = JSONUtil.toList(drawingType, KindegeeLogDTO.class); + BOMItem result = new BOMItem(); + result.setItems(bomItems); + return R.ok(result); + } + + /** + * @param productionOrderNo + * @param materialCode + * @param xu + * @return + */ + @Override + public ProcessRoute getProcessRoutesXuTime(String productionOrderNo, String materialCode, String xu) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(ProcessRoute::getRouteDescription, productionOrderNo) + .eq(ProcessRoute::getMaterialCode, materialCode) + .eq(ProcessRoute::getProcessNo,xu); + if (baseMapper.selectOne(wrapper) != null) { + return baseMapper.selectOne(wrapper); + } + return null; } @@ -569,8 +601,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { saveBomDetails(bomDetailsVos); List routeArrayList = new ArrayList<>(); Map inventoryCache = new HashMap<>(); - - + // 批量查询所有需要的库存信息 boolean allEmpty = processRoutes.stream().allMatch(route -> route.getProcessNo() == null && route.getProcessName() == null); //获取工艺中所有的时间 挑选出最早的时间和最晚的时间 // 获取最早的开始时间 @@ -585,13 +616,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { .max(Comparator.comparing(ProcessRoute::getXuEndTime)) .map(ProcessRoute::getXuEndTime) .orElse(null); - //更新至计划模块中 + //更新至计划模块中 if (earliestStartTime != null && latestEndTime != null) { - ProcessOrderPro processOrderPro = processOrderProMapper.selectByProjectNumber(processRoutes.get(0).getRouteDescription()); + ProcessOrderPro processOrderPro = processOrderProMapper.selectByProjectNumber(processRoutes.get(0).getRouteDescription()); processOrderPro.setPlanStartTime(earliestStartTime); processOrderPro.setPlanEndTime(latestEndTime); processOrderPro.setUpdateTime(new Date()); - log.info("更新计划生成令号为:{},计划开始时间:{},计划结束时间:{}",processRoutes.get(0).getRouteDescription(), earliestStartTime, latestEndTime); + log.info("更新计划生成令号为:{},计划开始时间:{},计划结束时间:{}", processRoutes.get(0).getRouteDescription(), earliestStartTime, latestEndTime); processOrderProMapper.updateById(processOrderPro); } @@ -681,23 +712,42 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } } } else { - for (ProcessRoute processRoute : processRoutes) { - if (processRoute.getProcessNo() != null - ||processRoute.getWorkCenter()!= null - ||processRoute.getProcessName() != null - ||processRoute.getMaterial().equals("总装部件")) { - processRoute.setActivityUnit("分"); - processRoute.setCreateTime(new Date()); - processRoute.setUpdateTime(new Date()); - processRoute.setBatchQuantity(processRoute.getBatchQuantity()); - processRoute.setUnitQuantity(processRoute.getUnitQuantity()); - routeArrayList.add(processRoute); - } + Date now = new Date(); + + // 先组装 routeArrayList + routeArrayList = processRoutes.stream() + .filter(pr -> pr.getProcessNo() != null + || pr.getWorkCenter() != null + || pr.getProcessName() != null) + .map(pr -> { + // 如果描述为空,则用工序控制码 + if (pr.getProcessDescription() == null || pr.getProcessDescription().isEmpty()) { + pr.setProcessDescription(pr.getProcessName()); + } + // 公共逻辑 + pr.setActivityUnit("分"); + pr.setCreateTime(now); + pr.setUpdateTime(now); + return pr; + }) + .collect(Collectors.toList()); + + // ✅ 校验是否存在相同物料编码 + 相同工序号 + Set duplicateKeys = routeArrayList.stream() + .map(pr -> pr.getMaterialCode() + "-" + pr.getProcessNo()) + .filter(Objects::nonNull) + .collect(Collectors.groupingBy(key -> key, Collectors.counting())) + .entrySet().stream() + .filter(e -> e.getValue() > 1) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + + if (!duplicateKeys.isEmpty()) { + log.error("发现重复的物料编码+工序号组合: {}", duplicateKeys); + throw new RuntimeException("存在重复的物料编码和工序号组合: " + duplicateKeys); } } - try { - return baseMapper.insertBatch(routeArrayList); } catch (Exception e) { log.error("批量插入工艺路线失败", e); @@ -733,10 +783,10 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { if ("mm".equals(unit)) { // 将毫米转换为米并保留4位小数 materialBom.setQuantity(String.valueOf(new BigDecimal(quantity).divide(BigDecimal.valueOf(1000), 4, RoundingMode.HALF_UP))); - } else if("根".equals(unit) && quantity.contains("/")){ + } else if ("根".equals(unit) && quantity.contains("/")) { //写入工艺表时分数的体现 直接取分母 以"/"为分割符,取第二个字符串 materialBom.setQuantity(quantity); - }else { + } else { // 其他单位直接使用原值,保留2位小数 materialBom.setQuantity(String.valueOf(new BigDecimal(quantity).setScale(2, RoundingMode.HALF_UP))); } @@ -777,6 +827,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { bomDetails.setPartdiagramName(productionOrderVo.getParentPart()); bomDetails.setPartNumber(productionOrderVo.getDrawingNo()); bomDetails.setName(productionOrderVo.getDrawingName()); + bomDetails.setBomType("0"); Double quantity = productionOrderVo.getQuantity(); bomDetails.setQuantity(quantity != null ? quantity : 0.0); @@ -830,6 +881,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { bomDetails.setFName(processRoute.getMaterialName()); bomDetails.setPartNumber(processRoute.getRawMaterialCode()); bomDetails.setName(processRoute.getRawMaterialName()); + bomDetails.setBomType("0"); // 添加单重验证和日志 Double discWeight = processRoute.getDiscWeight(); bomDetails.setDanZhong(discWeight); @@ -838,7 +890,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 处理单位换算 if ("mm".equals(processRoute.getBomUnit())) { - bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage())/ 1000.0); // 转换为米 + bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage()) / 1000.0); // 转换为米 bomDetails.setDenominator(1.0); // 转换为米 } else if ("根".equals(processRoute.getBomUnit())) { // 写入工艺表时分数的体现 直接取分母 以"/"为分割符,取第二个字符串 @@ -846,7 +898,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { String quanity2 = processRoute.getDiscUsage().split("/")[1]; bomDetails.setQuantity(Double.parseDouble(quanity)); bomDetails.setDenominator(Double.parseDouble(quanity2)); - bomDetails.setDenominator( Double.parseDouble(processRoute.getDiscUsage().split("/")[1])); + bomDetails.setDenominator(Double.parseDouble(processRoute.getDiscUsage().split("/")[1])); bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage().split("/")[0])); } else { bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage())); @@ -1072,12 +1124,12 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { // 验证物料是否存在 int materialVerification = isMaterialVerification(bomDetails.getPartNumber(), bomDetails.getName()); - if (materialVerification ==1) { + if (materialVerification == 1) { bomDetails.setUnitWeight("是"); - } else if(materialVerification ==2){ + } else if (materialVerification == 2) { bomDetails.setUnitWeight("否"); materialsToAdd.add(bomDetails); - }else if(materialVerification ==3){ + } else if (materialVerification == 3) { bomDetails.setUnitWeight("编码名称不符"); } @@ -1206,7 +1258,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { } @Override - public ProcessRoutePushResultDTO pushRouteBom(String rooteProdet) { + public R pushRouteBom(String rooteProdet) { List rawBomList = getProcessRoute(rooteProdet); List successfulRoutes = new ArrayList<>(); List failedRoutes = new ArrayList<>(); @@ -1217,6 +1269,14 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { Map> groupedByFNumber = jdProcessRoute.stream().collect(Collectors.groupingBy(ProcessRouteSelectDTO::getFNumber)); // 当前物料的工艺路线 List processRouteDT = processRouteXuDTO.getProcessRouteDT(); + /*boolean hasDuplicate = processRouteDT.stream() + .map(ProcessRouteDTO::getProcessNo) // 取出所有 processNo + .filter(Objects::nonNull) // 避免空指针 + .collect(Collectors.toSet()) // 放进 Set + .size() < processRouteDT.size(); + if (hasDuplicate){ + return R.fail("工序号重复请检查!"); + }*/ // 比较工艺路线 boolean isDifferent = compareProcessRoutes(processRouteDT, groupedByFNumber); if (isDifferent) { @@ -1229,6 +1289,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { successfulRoutes.add(processRouteXuDTO); } else { log.info("工艺路线保存失败: " + processRouteXuDTO.getMaterialCode() + result.getMessage()); + processRouteXuDTO.setErrorMessage( result.getMessage()); failedRoutes.add(processRouteXuDTO); } } else { @@ -1246,7 +1307,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { //更新项目状态 推送工艺 processOrderPro.setBomStatus(3L); processOrderProMapper.updateById(processOrderPro); - return resultDTO; + return R.ok(resultDTO); } public ProcessRoutePushResultDTO pushRouteQBBom(String rooteProdet) { @@ -1566,6 +1627,8 @@ public class ProcessRouteServiceImpl implements IProcessRouteService { K3CloudApi client = new K3CloudApi(); ProcessModel processModel = createProcessModel(rawBomList); String jsonStr = JSONUtil.toJsonStr(processModel); + + log.debug("推送工艺报文=====》{}",JSONUtil.toJsonStr(jsonStr)); try { // 业务对象标识 String formId = "ENG_Route"; diff --git a/ruoyi-system/src/main/resources/EXCEL模板/工序汇报未入库.xlsx b/ruoyi-system/src/main/resources/EXCEL模板/工序汇报未入库.xlsx new file mode 100644 index 0000000..55c25e7 Binary files /dev/null and b/ruoyi-system/src/main/resources/EXCEL模板/工序汇报未入库.xlsx differ diff --git a/ruoyi-system/src/main/resources/EXCEL模板/工序转移数据.xlsx b/ruoyi-system/src/main/resources/EXCEL模板/工序转移数据.xlsx new file mode 100644 index 0000000..2aa858b Binary files /dev/null and b/ruoyi-system/src/main/resources/EXCEL模板/工序转移数据.xlsx differ diff --git a/ruoyi-system/src/main/resources/EXCEL模板/生产开工未领料模板.xlsx b/ruoyi-system/src/main/resources/EXCEL模板/生产开工未领料模板.xlsx new file mode 100644 index 0000000..e2a47ca Binary files /dev/null and b/ruoyi-system/src/main/resources/EXCEL模板/生产开工未领料模板.xlsx differ diff --git a/ruoyi-system/src/main/resources/EXCEL模板/采购订单模板1.xlsx b/ruoyi-system/src/main/resources/EXCEL模板/采购订单模板1.xlsx index 45fe0f5..c0becc7 100644 Binary files a/ruoyi-system/src/main/resources/EXCEL模板/采购订单模板1.xlsx and b/ruoyi-system/src/main/resources/EXCEL模板/采购订单模板1.xlsx differ diff --git a/ruoyi-system/src/main/resources/mapper/system/BomDetailsMapper.xml b/ruoyi-system/src/main/resources/mapper/system/BomDetailsMapper.xml index 2cf6d83..1893072 100644 --- a/ruoyi-system/src/main/resources/mapper/system/BomDetailsMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/BomDetailsMapper.xml @@ -26,6 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + diff --git a/ruoyi-system/src/main/resources/mapper/system/PartCostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/PartCostMapper.xml new file mode 100644 index 0000000..29688f7 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/PartCostMapper.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-system/src/main/resources/mapper/system/ProcessOrderProMapper.xml b/ruoyi-system/src/main/resources/mapper/system/ProcessOrderProMapper.xml index 16c75ec..a9479ed 100644 --- a/ruoyi-system/src/main/resources/mapper/system/ProcessOrderProMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/ProcessOrderProMapper.xml @@ -27,7 +27,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"