Browse Source

2026-01-30

报价【切换版本】查询材料成本时加了重试功能,防止ifs连接超时造成成本为0
master
fengyuan_yang 4 weeks ago
parent
commit
3ec73b339b
  1. 135
      src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java

135
src/main/java/com/spring/modules/quote/service/impl/QuoteDetailBomTreeServiceImpl.java

@ -123,33 +123,58 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre
// QuoteDetailBom purchase = getPurchaseComponentPart(detail, bom, componentParts.size()+1);
// componentParts.add(purchase);
// }
log.info("BOM子物料:{}",componentParts);
// 统计日志记录子物料数量和需要查询成本的数量
int totalComponents = componentParts.size();
long needCostQueryCount = componentParts.stream().filter(c -> "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<QuoteDetailBomTre
return purchase;
}
private void getFinalPartCost(QuoteDetailBom component,Server ifsServer) {
/**
* 获取物料成本带重试机制
* @param component 物料组件
* @param ifsServer IFS服务器连接
*/
private void getFinalPartCost(QuoteDetailBom component, Server ifsServer) {
// 最大重试次数
final int MAX_RETRY_COUNT = 3;
// 重试间隔毫秒
final long RETRY_INTERVAL_MS = 1000;
String partNo = component.getComponentPart();
String site = component.getSite();
log.info("[COST_QUERY] 开始查询物料成本 - PartNo: {}, Site: {}", partNo, site);
PartInformationEntity part = new PartInformationEntity();
part.setSite(component.getSite());
part.setPartNo(component.getComponentPart());
Map<String, String> 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<String, String> map = null;
boolean success = false;
String lastErrorMsg = null;
// 重试机制
for (int retryCount = 1; retryCount <= MAX_RETRY_COUNT; retryCount++) {
try {
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);
}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.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);
}
}else {
// 接口返回异常,处理成本数据为0
log.error("接口返回400");
// 如果不是最后一次重试等待后继续
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;
}
}
}
}
// 所有重试都失败设置成本为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);
}
}
}

Loading…
Cancel
Save