From baed4a18253b383b90358aa7a7a76a7aa6d105ac Mon Sep 17 00:00:00 2001 From: fengyuan_yang <1976974459@qq.com> Date: Wed, 22 Jul 2026 09:14:22 +0800 Subject: [PATCH] =?UTF-8?q?2026-07-16=20=E9=94=80=E5=94=AE=E6=8A=A5?= =?UTF-8?q?=E4=BB=B7=EF=BC=8CpartType=20=3D=20Purchased=20=E7=9A=84?= =?UTF-8?q?=E6=88=90=E6=9C=AC=E5=8F=A3=E5=BE=84=E6=94=B9=E4=B8=BA=E2=80=9C?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E5=8F=96=20IFS=20=E6=88=90=E6=9C=AC=E2=80=9D?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/QuoteDetailBomTreeService.java | 10 +++ .../impl/QuoteDetailBomTreeServiceImpl.java | 65 +++++++++++++++++++ .../service/impl/QuoteDetailServiceImpl.java | 26 ++++++-- 3 files changed, 96 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/spring/modules/quote/service/QuoteDetailBomTreeService.java b/src/main/java/com/spring/modules/quote/service/QuoteDetailBomTreeService.java index c8dfca0a..ca417ba2 100644 --- a/src/main/java/com/spring/modules/quote/service/QuoteDetailBomTreeService.java +++ b/src/main/java/com/spring/modules/quote/service/QuoteDetailBomTreeService.java @@ -36,6 +36,16 @@ public interface QuoteDetailBomTreeService extends IService * @return 预估材料成本(estimated_material_cost) */ BigDecimal queryEstimatedMaterialCost(String site, String partNo); + + /** + * 根据物料编码查询 IFS 库存价值(InventoryValue)。 + * 采购类成本口径改造后,Purchased/Purchased (raw) 节点优先使用该值。 + * + * @param site 站点 + * @param partNo 物料编码 + * @return IFS InventoryValue(查询失败返回0) + */ + BigDecimal queryInventoryValue(String site, String partNo); /** * 根据物料编码查询物料类型 diff --git a/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java b/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java index f91e48b1..36085824 100644 --- a/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java +++ b/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java @@ -236,6 +236,17 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl().eq("username", username)); + if (ifsUser == null || !org.apache.commons.lang3.StringUtils.isNotBlank(ifsUser.getIfsUsername()) + || !org.apache.commons.lang3.StringUtils.isNotBlank(ifsUser.getIfsPassword())) { + log.warn("queryInventoryValue - User {} has no IFS account configured, fallback to DB unit cost", username); + BigDecimal cost = baseMapper.getPartCost(site, partNo); + BigDecimal result = cost != null ? cost : BigDecimal.ZERO; + log.info("queryInventoryValue - Fallback result from DB unit cost: {}", result); + return result; + } + + Server ifsCon = ifsServer.getIfsServer(ifsUser.getIfsUsername(), ifsUser.getIfsPassword()); + PartInformationEntity part = new PartInformationEntity(); + part.setSite(site); + part.setPartNo(partNo); + log.info("queryInventoryValue - Calling IFS getInventoryValueByPartNo with params: site={}, partNo={}", site, partNo); + + Map map = baseSearchBean.getInventoryValueByPartNo(ifsCon, part); + log.info("queryInventoryValue - IFS API response: {}", map); + + if (Objects.equals(map.get("resultCode"), "200")) { + InventoryPartUnitCostSumVo unitCostSumVo = JSONObject.parseObject(map.get("obj"), InventoryPartUnitCostSumVo.class); + String inventoryValueStr = unitCostSumVo.getInventoryValue(); + BigDecimal inventoryValue = org.apache.commons.lang3.StringUtils.isNotBlank(inventoryValueStr) + ? new BigDecimal(inventoryValueStr) : BigDecimal.ZERO; + log.info("queryInventoryValue - Successfully retrieved InventoryValue from IFS: {}", inventoryValue); + return inventoryValue; + } else { + log.warn("queryInventoryValue - Failed to retrieve from IFS, resultCode={}, resultMsg={}", + map.get("resultCode"), map.get("resultMsg")); + return BigDecimal.ZERO; + } + } catch (Exception e) { + log.error("queryInventoryValue - Exception occurred for partNo={}: {}", partNo, e.getMessage(), e); + return BigDecimal.ZERO; + } + } + @Override public String queryPartType(String site, String partNo) { return baseMapper.queryPartType(site, partNo); diff --git a/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailServiceImpl.java b/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailServiceImpl.java index a2a8b97f..3e12c024 100644 --- a/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailServiceImpl.java +++ b/src/main/java/com/spring/modules/quote/service/impl/QuoteDetailServiceImpl.java @@ -208,7 +208,9 @@ public class QuoteDetailServiceImpl extends ServiceImpl map = new HashMap<>(); - // 用于缓存IFS接口获取的物料预估成本,避免在循环中重复调用降低性能 + // 用于缓存 IFS 接口获取的 InventoryValue(采购类节点直接成本口径) + Map inventoryValueCache = new HashMap<>(); + // 兼容历史数据的兜底缓存(仅在 partType 无法识别但 bomType=Purchase 时使用) Map estimatedCostCache = new HashMap<>(); long perfAttrStartTime = System.currentTimeMillis(); @@ -337,17 +339,31 @@ public class QuoteDetailServiceImpl extends ServiceImpl { + long ifsStart = System.currentTimeMillis(); + BigDecimal cost = quoteDetailBomTreeService.queryInventoryValue(bomTree.getSite(), bomTree.getPartNo()); + log.info("[COST_CALC] [PERF_LOG] Fetched InventoryValue for {} from IFS/DB in {} ms", + bomTree.getPartNo(), (System.currentTimeMillis() - ifsStart)); + return cost == null ? BigDecimal.ZERO : cost; + }); + log.info("[COST_CALC] Part {} with partType={} uses direct InventoryValue as node material cost: {}", + bomTree.getPartNo(), partType, bomQuotePrice); + } else if ("Purchase".equals(bomTree.getBomType())) { + // 兼容历史脏数据:当 partType 未识别,但节点 bomType 为 Purchase 时仍维持旧兜底逻辑 String cacheKey = bomTree.getSite() + "_" + bomTree.getPartNo(); BigDecimal estimatedMaterialCost = estimatedCostCache.computeIfAbsent(cacheKey, k -> { long ifsStart = System.currentTimeMillis(); BigDecimal cost = quoteDetailBomTreeService.queryEstimatedMaterialCost(bomTree.getSite(), bomTree.getPartNo()); - log.info("[COST_CALC] [PERF_LOG] Fetched estimated material cost for {} from IFS/DB in {} ms", bomTree.getPartNo(), (System.currentTimeMillis() - ifsStart)); + log.info("[COST_CALC] [PERF_LOG] Legacy fallback fetched estimated material cost for {} in {} ms", + bomTree.getPartNo(), (System.currentTimeMillis() - ifsStart)); return cost == null ? BigDecimal.ZERO : cost; }); bomQuotePrice = bomQuotePrice.add(estimatedMaterialCost); - log.info("[COST_CALC] Semi-finished product {} is Purchase type, add estimated material cost {}, accumulated cost is {}", + log.info("[COST_CALC] Legacy fallback node {} (bomType=Purchase) adds estimated material cost {}, accumulated cost {}", bomTree.getPartNo(), estimatedMaterialCost, bomQuotePrice); }