From 23f78e3b080f7723d83b35409df777bdec5fbd57 Mon Sep 17 00:00:00 2001 From: "han\\hanst" Date: Thu, 6 Nov 2025 08:37:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B1=9E=E6=80=A7=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=AE=A1=E7=AE=97=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/PartInformationController.java | 12 + .../part/mapper/BomManagementMapper.java | 2 +- .../part/service/PartInformationService.java | 2 + .../impl/PartInformationServiceImpl.java | 275 +++++++++++++++++- .../impl/RoutingManagementServiceImpl.java | 71 +++-- .../mapper/part/BomManagementMapper.xml | 5 +- 6 files changed, 337 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/xujie/sys/modules/part/controller/PartInformationController.java b/src/main/java/com/xujie/sys/modules/part/controller/PartInformationController.java index ec559564..0e25a27e 100644 --- a/src/main/java/com/xujie/sys/modules/part/controller/PartInformationController.java +++ b/src/main/java/com/xujie/sys/modules/part/controller/PartInformationController.java @@ -572,4 +572,16 @@ public class PartInformationController { PartInformationVo partInformation = partInformationService.getCopyRowData(part); return R.ok().put("rows", partInformation); } + + /** + * 重新计算BOM单位用量和Routing机器处理时间 + * @param data + * @return + */ + @PostMapping(value="/recalculateBomAndRouting") + @ResponseBody + public R recalculateBomAndRouting(@RequestBody PartNodeVo data) { + partInformationService.recalculateBomAndRouting(data); + return R.ok(); + } } diff --git a/src/main/java/com/xujie/sys/modules/part/mapper/BomManagementMapper.java b/src/main/java/com/xujie/sys/modules/part/mapper/BomManagementMapper.java index bd82d3f3..3a2148b5 100644 --- a/src/main/java/com/xujie/sys/modules/part/mapper/BomManagementMapper.java +++ b/src/main/java/com/xujie/sys/modules/part/mapper/BomManagementMapper.java @@ -49,7 +49,7 @@ public interface BomManagementMapper extends BaseMapper { void deleteBomHeaderByPartNo(BomHeaderEntity data); - void updateBomComponent(BomComponentEntity data); + int updateBomComponent(BomComponentEntity data); List queryOperationList(OperationEntity data); diff --git a/src/main/java/com/xujie/sys/modules/part/service/PartInformationService.java b/src/main/java/com/xujie/sys/modules/part/service/PartInformationService.java index 4244f619..1ba453b7 100644 --- a/src/main/java/com/xujie/sys/modules/part/service/PartInformationService.java +++ b/src/main/java/com/xujie/sys/modules/part/service/PartInformationService.java @@ -104,4 +104,6 @@ public interface PartInformationService extends IService void commitItemsValue(List list); PartInformationVo getCopyRowData(PartInformationVo part); + + void recalculateBomAndRouting(PartNodeVo data); } diff --git a/src/main/java/com/xujie/sys/modules/part/service/impl/PartInformationServiceImpl.java b/src/main/java/com/xujie/sys/modules/part/service/impl/PartInformationServiceImpl.java index d203f758..49d69a22 100644 --- a/src/main/java/com/xujie/sys/modules/part/service/impl/PartInformationServiceImpl.java +++ b/src/main/java/com/xujie/sys/modules/part/service/impl/PartInformationServiceImpl.java @@ -17,10 +17,8 @@ import com.xujie.sys.modules.part.mapper.PartInformationMapper; import com.xujie.sys.modules.part.mapper.QuicklyCreateBomMapper; import com.xujie.sys.modules.part.mapper.RoutingManagementMapper; import com.xujie.sys.modules.part.service.PartInformationService; -import com.xujie.sys.modules.part.vo.AgentInformationVo; -import com.xujie.sys.modules.part.vo.LocationInformationVo; -import com.xujie.sys.modules.part.vo.ManufacturerInformationVo; -import com.xujie.sys.modules.part.vo.PartInformationVo; +import com.xujie.sys.modules.part.service.RoutingManagementService; +import com.xujie.sys.modules.part.vo.*; import com.xujie.sys.modules.report.dao.ProcedureDao; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.DateUtil; @@ -62,6 +60,9 @@ public class PartInformationServiceImpl extends ServiceImpl> 查询节点BOM: partNo=" + part.getPartNo()); + + // 查询该物料的所有BOM + QueryWrapper headerWrapper = new QueryWrapper<>(); + headerWrapper.eq("site", part.getSite()) + .eq("bu_no", part.getBuNo()) + .eq("part_no", part.getPartNo()); + + List bomHeaders = bomManagementMapper.selectList(headerWrapper); + + if (bomHeaders == null || bomHeaders.isEmpty()) { + System.out.println(" >> 该节点没有BOM,跳过"); + return; + } + + System.out.println(" >> 查询到BOM数量: " + bomHeaders.size()); + + for (BomHeaderEntity header : bomHeaders) { + // 查询每个BOM的所有替代 + BomHeaderEntity detailQuery = new BomHeaderEntity(); + detailQuery.setSite(header.getSite()); + detailQuery.setBuNo(header.getBuNo()); + detailQuery.setPartNo(header.getPartNo()); + detailQuery.setEngChgLevel(header.getEngChgLevel()); + detailQuery.setBomType(header.getBomType()); + + List details = bomManagementMapper.queryBomDetail(detailQuery); + System.out.println(" >> 查询到替代数量: " + (details != null ? details.size() : 0)); + + for (BomDetailEntity detail : details) { + System.out.println(" >> 处理替代: " + detail.getAlternativeNo()); + + // 查询该替代下的所有组件 + BomDetailEntity componentQuery = new BomDetailEntity(); + BeanUtils.copyProperties(detail, componentQuery); + + List components = bomManagementMapper.queryComponentPart2(componentQuery); + System.out.println(" >> 查询到组件数量: " + (components != null ? components.size() : 0)); + + if (components == null || components.isEmpty()) { + System.out.println(" >> 该替代没有组件,跳过"); + continue; + } + + for (BomComponentVo component : components) { + try { + System.out.println(" - 计算组件: " + component.getComponentPart() + " (lineItemNo=" + component.getLineItemNo() + ")"); + + // 调用存储过程计算单位用量 + List params = new ArrayList<>(); + params.add(component.getSite()); + params.add(component.getBuNo()); + params.add(component.getPartNo()); + params.add(component.getComponentPart()); + params.add(component.getEngChgLevel()); + + List> resultList = procedureDao.getProcedureData("RFQ_BOM_Dosage", params); + if (!resultList.isEmpty()) { + Map result = resultList.get(0); + String code = String.valueOf(result.get("resultCode")); + if ("200".equalsIgnoreCase(code)) { + Object qtyObj = result.get("objectId"); + BigDecimal qtyPerAssembly = BigDecimal.ZERO; + if (qtyObj instanceof String) { + qtyPerAssembly = new BigDecimal((String) qtyObj); + } else if (qtyObj instanceof Long) { + qtyPerAssembly = BigDecimal.valueOf((Long) qtyObj); + } else if (qtyObj instanceof Double) { + qtyPerAssembly = BigDecimal.valueOf((Double) qtyObj); + } else if (qtyObj instanceof BigDecimal) { + qtyPerAssembly = (BigDecimal) qtyObj; + } + + System.out.println(" 原值: " + component.getQtyPerAssembly() + " → 新值: " + qtyPerAssembly); + + // 更新单位用量 + BomComponentEntity entityToUpdate = new BomComponentEntity(); + BeanUtils.copyProperties(component, entityToUpdate); + entityToUpdate.setQtyPerAssembly(qtyPerAssembly); + + // 打印更新条件用于诊断 + System.out.println(" WHERE条件: site=" + entityToUpdate.getSite() + + ", partNo=" + entityToUpdate.getPartNo() + + ", engChgLevel=" + entityToUpdate.getEngChgLevel() + + ", bomType=" + entityToUpdate.getBomType() + + ", alternativeNo=" + entityToUpdate.getAlternativeNo() + + ", lineItemNo=" + entityToUpdate.getLineItemNo()); + + int updateCount = bomManagementMapper.updateBomComponent(entityToUpdate); + System.out.println(" 更新结果: " + (updateCount > 0 ? "✅ 成功" : "❌ 失败 - 未找到匹配记录")); + + if (updateCount == 0) { + System.err.println(" !!! 更新失败,请检查WHERE条件是否正确"); + } + } + } + } catch (Exception e) { + System.err.println(" ❌ 计算失败: " + e.getMessage()); + e.printStackTrace(); + // 忽略单个组件计算失败,继续处理下一个 + continue; + } + } + } + } + } + + /** + * 重新计算Routing机器处理时间 + * @param part + */ + private void recalculateRoutingTime(PartNodeVo part) { + System.out.println(" >> 查询节点Routing: partNo=" + part.getPartNo()); + + // 查询该物料的所有Routing + QueryWrapper headerWrapper = new QueryWrapper<>(); + headerWrapper.eq("site", part.getSite()) + .eq("bu_no", part.getBuNo()) + .eq("part_no", part.getPartNo()); + + List routingHeaders = routingManagementMapper.selectList(headerWrapper); + + if (routingHeaders == null || routingHeaders.isEmpty()) { + System.out.println(" >> 该节点没有Routing,跳过"); + return; + } + + System.out.println(" >> 查询到Routing数量: " + routingHeaders.size()); + + for (RoutingHeaderEntity header : routingHeaders) { + try { + // 查询每个Routing的所有替代和工序 + RoutingDetailEntity detailQuery = new RoutingDetailEntity(); + detailQuery.setSite(header.getSite()); + detailQuery.setBuNo(header.getBuNo()); + detailQuery.setPartNo(header.getPartNo()); + detailQuery.setRoutingRevision(header.getRoutingRevision()); + detailQuery.setRoutingType(header.getRoutingType()); + detailQuery.setAlternativeNo("*"); + + List components = routingManagementMapper.queryRoutingComponent(detailQuery); + + if (components != null && !components.isEmpty()) { + // 获取该物料的商品组信息 + PartInformationEntity partInfo = partInformationMapper.selectOne( + new QueryWrapper() + .eq("site", part.getSite()) + .eq("sourceBu", part.getBuNo()) + .eq("part_no", part.getPartNo()) + ); + + // 从商品组获取标准工序数据 + List standardOps = null; + if (partInfo != null && partInfo.getProductGroupId1() != null) { + standardOps = routingManagementMapper.getStandardRoutingOperationByProductGroupId( + part.getSite(), part.getBuNo(), partInfo.getProductGroupId1() + ); + } + + // 构建RoutingHeaderVo用于计算 + RoutingHeaderVo headerVo = new RoutingHeaderVo(); + BeanUtils.copyProperties(header, headerVo); + + // 重要:设置该物料的codeNo,用于查询属性 + headerVo.setCodeNo(part.getCodeNo()); + headerVo.setPartNo(part.getPartNo()); + headerVo.setSite(part.getSite()); + headerVo.setBuNo(part.getBuNo()); + + // 用标准工序数据填充ref_speed等字段 + for (RoutingComponentVo vo : components) { + vo.setFlag("Y"); // 设置flag标识,用于计算工时 + + // 如果ref_speed等字段为空或为0,从标准工序获取 + if (standardOps != null) { + for (RoutingComponentVo stdOp : standardOps) { + if (stdOp.getOperationName() != null && stdOp.getOperationName().equals(vo.getOperationName())) { + if (vo.getRefSpeed() == null || vo.getRefSpeed().compareTo(BigDecimal.ZERO) == 0) { + vo.setRefSpeed(stdOp.getRefSpeed()); + } + if (vo.getRefTime() == null || vo.getRefTime().compareTo(BigDecimal.ZERO) == 0) { + vo.setRefTime(stdOp.getRefTime()); + } + if (vo.getRefEfficiency() == null || vo.getRefEfficiency().compareTo(BigDecimal.ZERO) == 0) { + vo.setRefEfficiency(stdOp.getRefEfficiency()); + } + if (vo.getRefDailyProduction() == null || vo.getRefDailyProduction().compareTo(BigDecimal.ZERO) == 0) { + vo.setRefDailyProduction(stdOp.getRefDailyProduction()); + } + break; + } + } + } + + // 确保必要字段不为null + if (vo.getRefSpeed() == null) vo.setRefSpeed(BigDecimal.ZERO); + if (vo.getRefTime() == null) vo.setRefTime(BigDecimal.ZERO); + if (vo.getRefEfficiency() == null) vo.setRefEfficiency(BigDecimal.ZERO); + if (vo.getRefDailyProduction() == null) vo.setRefDailyProduction(BigDecimal.ZERO); + } + headerVo.setOperationList(components); + + // 调用计算工时方法 + List calculatedOperations = routingManagementService.calculationTime(headerVo); + + System.out.println(" >> 计算完成,准备更新" + calculatedOperations.size() + "个工序"); + + // 更新机器处理时间 + for (RoutingComponentVo operation : calculatedOperations) { + System.out.println(" - 工序" + operation.getOperationNo() + " " + operation.getOperationName() + ": machCycleTime=" + operation.getMachCycleTime()); + RoutingComponentEntity entityToUpdate = new RoutingComponentEntity(); + BeanUtils.copyProperties(operation, entityToUpdate); + routingManagementMapper.updateRoutingComponent(entityToUpdate); + } + } + } catch (Exception e) { + System.err.println(" >> 计算失败: " + e.getMessage()); + e.printStackTrace(); + // 忽略单个Routing计算失败,继续处理下一个 + continue; + } + } + } } diff --git a/src/main/java/com/xujie/sys/modules/part/service/impl/RoutingManagementServiceImpl.java b/src/main/java/com/xujie/sys/modules/part/service/impl/RoutingManagementServiceImpl.java index 61f317fd..3c41763e 100644 --- a/src/main/java/com/xujie/sys/modules/part/service/impl/RoutingManagementServiceImpl.java +++ b/src/main/java/com/xujie/sys/modules/part/service/impl/RoutingManagementServiceImpl.java @@ -752,7 +752,10 @@ public class RoutingManagementServiceImpl extends ServiceImpl collect = partItems.stream().filter(a -> "Printing lanes".equals(a.getItemDesc())).collect(Collectors.toList()); @@ -761,10 +764,13 @@ public class RoutingManagementServiceImpl extends ServiceImpl "检测列数".equals(a.getItemDesc())).collect(Collectors.toList()); } if (!collect1.isEmpty() && !collect2.isEmpty()) { - // 1000/pitch - BigDecimal numValue1 = BigDecimal.valueOf(1000).divide(BigDecimal.valueOf(collect1.get(0).getNumValue()), scale2, RoundingMode.HALF_UP); - // 列数 属性的值 - BigDecimal numValue2 = BigDecimal.valueOf(collect2.get(0).getNumValue()); - // 1 / (速度 x 时间 x 效率 x (1000/pitch) x 列数) - BigDecimal product = BigDecimal.ONE.divide(refSpeed.multiply(refTime).multiply(refEfficiency).multiply(numValue1).multiply(numValue2), scale2, RoundingMode.HALF_UP); - // 最终结果 - machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP); + BigDecimal pitchValue = BigDecimal.valueOf(collect1.get(0).getNumValue()); + BigDecimal laneValue = BigDecimal.valueOf(collect2.get(0).getNumValue()); + + // 检查除数是否为零 + if (pitchValue.compareTo(BigDecimal.ZERO) != 0 && laneValue.compareTo(BigDecimal.ZERO) != 0) { + // 1000/pitch + BigDecimal numValue1 = BigDecimal.valueOf(1000).divide(pitchValue, scale2, RoundingMode.HALF_UP); + // 列数 属性的值 + BigDecimal numValue2 = laneValue; + // 1 / (速度 x 时间 x 效率 x (1000/pitch) x 列数) + BigDecimal divisor = refSpeed.multiply(refTime).multiply(refEfficiency).multiply(numValue1).multiply(numValue2); + if (divisor.compareTo(BigDecimal.ZERO) != 0) { + BigDecimal product = BigDecimal.ONE.divide(divisor, scale2, RoundingMode.HALF_UP); + // 最终结果 + machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP); + } + } } } else if ("Packaging".equals(operation.getOperationName())) { // (1 / (日产量 * 效率)) x 1000 - // 日产量 * 效率 - BigDecimal product = BigDecimal.ONE.divide(refDailyProduction.multiply(refEfficiency), scale2, RoundingMode.HALF_UP); - // 最终结果 - machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP); + BigDecimal divisor = refDailyProduction.multiply(refEfficiency); + if (divisor.compareTo(BigDecimal.ZERO) != 0) { + // 日产量 * 效率 + BigDecimal product = BigDecimal.ONE.divide(divisor, scale2, RoundingMode.HALF_UP); + // 最终结果 + machCycleTime = product.multiply(BigDecimal.valueOf(1000)).setScale(scale, RoundingMode.HALF_UP); + } } operation.setMachCycleTime(machCycleTime); // 机器处理时间 operation.setLaborCycleTime(machCycleTime); // 人工处理时间 - operation.setMachRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP)); // 机器单位产出 - operation.setLaborRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP)); // 人工单位产出 + // 机器单位产出和人工单位产出 + if (machCycleTime.compareTo(BigDecimal.ZERO) != 0) { + operation.setMachRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP)); + operation.setLaborRunFactor(BigDecimal.ONE.divide(machCycleTime, 4, RoundingMode.HALF_UP)); + } } } return operations; diff --git a/src/main/resources/mapper/part/BomManagementMapper.xml b/src/main/resources/mapper/part/BomManagementMapper.xml index 354c9867..0299c281 100644 --- a/src/main/resources/mapper/part/BomManagementMapper.xml +++ b/src/main/resources/mapper/part/BomManagementMapper.xml @@ -444,7 +444,7 @@ material_length2 = #{materialLength2}, unit_conversion = #{unitConversion}, component_part = #{componentPart} - where site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo} + where site = #{site} and bu_no = #{buNo} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo} @@ -455,7 +455,7 @@ shrinkage_factor = #{shrinkageFactor}, update_date = getDate(), update_by = #{updateBy} - where site = #{site} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo} + where site = #{site} and bu_no = #{buNo} and part_no = #{partNo} and eng_chg_level = #{engChgLevel} and bom_type = #{bomType} and alternative_no = #{alternativeNo} and line_item_no = #{lineItemNo} @@ -611,6 +611,7 @@ eng_chg_level, bom_type, alternative_no, + line_item_no, component_part, qty_per_assembly FROM plm_bom_component