From 3ec73b339b4eab3a63deaca9e23000fedff1ba66 Mon Sep 17 00:00:00 2001 From: fengyuan_yang <1976974459@qq.com> Date: Fri, 30 Jan 2026 14:56:56 +0800 Subject: [PATCH] =?UTF-8?q?2026-01-30=20=E6=8A=A5=E4=BB=B7=E3=80=90?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E7=89=88=E6=9C=AC=E3=80=91=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=9D=90=E6=96=99=E6=88=90=E6=9C=AC=E6=97=B6=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E9=87=8D=E8=AF=95=E5=8A=9F=E8=83=BD=EF=BC=8C=E9=98=B2=E6=AD=A2?= =?UTF-8?q?ifs=E8=BF=9E=E6=8E=A5=E8=B6=85=E6=97=B6=E9=80=A0=E6=88=90?= =?UTF-8?q?=E6=88=90=E6=9C=AC=E4=B8=BA0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/QuoteDetailBomTreeServiceImpl.java | 143 ++++++++++++++---- 1 file changed, 116 insertions(+), 27 deletions(-) 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 cbca4c3c..a434b7db 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 @@ -123,33 +123,58 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl "Y".equals(c.getStatus())).count(); + log.info("[BOM_PROCESS] 开始处理子物料 - 父物料: {}, 层级: {}, 子物料总数: {}, 需查询成本数: {}", + bom.getPartNo(), level, totalComponents, needCostQueryCount); + // 3、查询子物料是否存在BOM信息 + int processedCount = 0; + int costQuerySuccessCount = 0; + int costQueryFailCount = 0; + for (QuoteDetailBom component : componentParts) { + processedCount++; component.setCreateBy(detail.getCreateBy()); component.setCreateDate(detail.getCreateDate()); QuoteDetail quoteDetail = createQuoteDetail(detail, component); // 物料是半成品 QuoteDetailBomTree bomTree = isComponentBom(quoteDetail); if (Objects.nonNull(bomTree) && "Y".equals(component.getBomFlag())) { - long id = initQuoteDetailBomTree(quoteDetail ,bom.getId(),level+1); + log.debug("[BOM_PROCESS] 递归处理半成品 - PartNo: {}, 当前进度: {}/{}", + component.getComponentPart(), processedCount, totalComponents); + long id = initQuoteDetailBomTree(quoteDetail, bom.getId(), level + 1); // 如果是BOM 为子料绑定是哪个Bom component.setBomId(id); // 半成品 价格为0 component.setUnitPrice(BigDecimal.ZERO); component.setActualPrice(BigDecimal.ZERO); component.setQuotePrice(BigDecimal.ZERO); - }else{ + } else { component.setBomFlag("N"); } if ("Y".equals(component.getStatus())) { - //getFinalPartCost(component, server); // 获取最终的物料的成本 使用当前用的 + // 记录查询前的状态,用于判断是否成功 + BigDecimal beforePrice = component.getUnitPrice(); getFinalPartCost(component, ifsCon); + // 判断成本查询是否成功(成功后价格不为0或有变化) + if (component.getUnitPrice() != null && component.getUnitPrice().compareTo(BigDecimal.ZERO) > 0) { + costQuerySuccessCount++; + } else { + costQueryFailCount++; + } } //新增子物料信息 component.setTreeId(bom.getId()); quoteDetailBomService.save(component); } + + // 统计日志:记录处理结果 + log.info("[BOM_PROCESS] 子物料处理完成 - 父物料: {}, 层级: {}, 处理总数: {}, 成本查询成功: {}, 成本查询失败: {}", + bom.getPartNo(), level, processedCount, costQuerySuccessCount, costQueryFailCount); + return bom.getId(); } @@ -203,35 +228,99 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl map = baseSearchBean.getInventoryValueByPartNo(ifsServer, part); - if (Objects.equals(map.get("resultCode"),"200")){ - // 返回成功 将成本 - InventoryPartUnitCostSumVo unitCostSumVo = JSONObject.parseObject(map.get("obj"), InventoryPartUnitCostSumVo.class); + part.setSite(site); + part.setPartNo(partNo); + + Map map = null; + boolean success = false; + String lastErrorMsg = null; + + // 重试机制 + for (int retryCount = 1; retryCount <= MAX_RETRY_COUNT; retryCount++) { try { - BigDecimal unitCost = new BigDecimal(unitCostSumVo.getInventoryValue()); - component.setUnitPrice(unitCost); - component.setActualPrice(unitCost); - component.setQuotePrice(unitCost); - }catch (Exception e){ - component.setUnitPrice(BigDecimal.ZERO); - component.setActualPrice(BigDecimal.ZERO); - component.setQuotePrice(BigDecimal.ZERO); - log.error("PartNo:{},Site:{},成本信息异常:{}", component.getPartNo(), component.getSite(),e.getMessage()); + log.debug("[COST_QUERY] 第 {} 次尝试查询 - PartNo: {}", retryCount, partNo); + + map = baseSearchBean.getInventoryValueByPartNo(ifsServer, part); + + if (Objects.equals(map.get("resultCode"), "200")) { + // 返回成功 + InventoryPartUnitCostSumVo unitCostSumVo = JSONObject.parseObject(map.get("obj"), InventoryPartUnitCostSumVo.class); + BigDecimal unitCost = new BigDecimal(unitCostSumVo.getInventoryValue()); + component.setUnitPrice(unitCost); + component.setActualPrice(unitCost); + component.setQuotePrice(unitCost); + + log.info("[COST_QUERY] 查询成功 - PartNo: {}, Site: {}, UnitCost: {}, 尝试次数: {}", + partNo, site, unitCost, retryCount); + success = true; + break; + } else { + // 接口返回错误 + lastErrorMsg = map.get("resultMsg"); + log.warn("[COST_QUERY] 第 {} 次查询失败 - PartNo: {}, Site: {}, ResultCode: {}, ErrorMsg: {}", + retryCount, partNo, site, map.get("resultCode"), lastErrorMsg); + + // 账号密码错误不重试,直接抛异常 + if (lastErrorMsg != null && lastErrorMsg.contains("You have entered an invalid username and/or password")) { + log.error("[COST_QUERY] IFS账号密码错误,停止重试 - PartNo: {}", partNo); + throw new RuntimeException(lastErrorMsg); + } + + // 如果不是最后一次重试,等待后继续 + if (retryCount < MAX_RETRY_COUNT) { + log.info("[COST_QUERY] 等待 {}ms 后进行第 {} 次重试 - PartNo: {}", + RETRY_INTERVAL_MS, retryCount + 1, partNo); + Thread.sleep(RETRY_INTERVAL_MS); + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + log.error("[COST_QUERY] 重试等待被中断 - PartNo: {}, Site: {}", partNo, site); + break; + } catch (RuntimeException e) { + // 重新抛出运行时异常(如账号密码错误) + throw e; + } catch (Exception e) { + lastErrorMsg = e.getMessage(); + log.warn("[COST_QUERY] 第 {} 次查询异常 - PartNo: {}, Site: {}, Exception: {}", + retryCount, partNo, site, e.getMessage()); + + // 如果不是最后一次重试,等待后继续 + if (retryCount < MAX_RETRY_COUNT) { + try { + Thread.sleep(RETRY_INTERVAL_MS); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + break; + } + } } - }else { - // 接口返回异常,处理成本数据为0 - log.error("接口返回400"); + } + + // 所有重试都失败,设置成本为0 + if (!success) { + log.error("[COST_QUERY] 查询失败(已重试 {} 次)- PartNo: {}, Site: {}, 最后错误: {}", + MAX_RETRY_COUNT, partNo, site, lastErrorMsg); component.setUnitPrice(BigDecimal.ZERO); component.setActualPrice(BigDecimal.ZERO); component.setQuotePrice(BigDecimal.ZERO); - String resultMsg = map.get("resultMsg"); - if (resultMsg.contains("You have entered an invalid username and/or password")){ - throw new RuntimeException(resultMsg); - } } }