|
|
@ -133,7 +133,22 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre |
|
|
* |
|
|
* |
|
|
* @param ifsConFactory IFS 连接工厂,每个并发线程调用 get() 获取独立连接,避免共享连接线程安全问题 |
|
|
* @param ifsConFactory IFS 连接工厂,每个并发线程调用 get() 获取独立连接,避免共享连接线程安全问题 |
|
|
*/ |
|
|
*/ |
|
|
private BomNodeData collectBomData(QuoteDetail detail, Long parentId, Integer level, Supplier<Server> ifsConFactory, Map<String, BigDecimal> costCache, Map<String, BigDecimal> workCenterCostCache) { |
|
|
|
|
|
|
|
|
private BomNodeData collectBomData(QuoteDetail detail, |
|
|
|
|
|
Long parentId, |
|
|
|
|
|
Integer level, |
|
|
|
|
|
Supplier<Server> ifsConFactory, |
|
|
|
|
|
Map<String, BigDecimal> costCache, |
|
|
|
|
|
Map<String, BigDecimal> workCenterCostCache) { |
|
|
|
|
|
return collectBomData(detail, parentId, level, ifsConFactory, costCache, workCenterCostCache, new LinkedHashSet<>()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private BomNodeData collectBomData(QuoteDetail detail, |
|
|
|
|
|
Long parentId, |
|
|
|
|
|
Integer level, |
|
|
|
|
|
Supplier<Server> ifsConFactory, |
|
|
|
|
|
Map<String, BigDecimal> costCache, |
|
|
|
|
|
Map<String, BigDecimal> workCenterCostCache, |
|
|
|
|
|
Set<String> recursionPath) { |
|
|
// 统一先尝试将临时料映射到正式料,保证新建与“切换版本刷新”取数来源一致 |
|
|
// 统一先尝试将临时料映射到正式料,保证新建与“切换版本刷新”取数来源一致 |
|
|
PartInformationEntity mappedPart = baseMapper.queryPart(detail.getSite(), detail.getPartNo()); |
|
|
PartInformationEntity mappedPart = baseMapper.queryPart(detail.getSite(), detail.getPartNo()); |
|
|
if (Objects.nonNull(mappedPart) && "Y".equals(mappedPart.getStatus())) { |
|
|
if (Objects.nonNull(mappedPart) && "Y".equals(mappedPart.getStatus())) { |
|
|
@ -161,6 +176,15 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre |
|
|
if (Objects.isNull(bom)) { |
|
|
if (Objects.isNull(bom)) { |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
String currentBomPathKey = buildBomPathKey(bom); |
|
|
|
|
|
if (recursionPath.contains(currentBomPathKey)) { |
|
|
|
|
|
String cyclePath = formatBomPath(recursionPath, currentBomPathKey); |
|
|
|
|
|
log.error("[BOM_PROCESS] 检测到BOM循环引用,终止报价创建. key={}, path={}", |
|
|
|
|
|
currentBomPathKey, cyclePath); |
|
|
|
|
|
throw new RuntimeException("检测到BOM循环引用,请先在BOM维护中调整后再报价。环路:" + cyclePath); |
|
|
|
|
|
} |
|
|
|
|
|
Set<String> nextRecursionPath = new LinkedHashSet<>(recursionPath); |
|
|
|
|
|
nextRecursionPath.add(currentBomPathKey); |
|
|
bom.setParentId(parentId); |
|
|
bom.setParentId(parentId); |
|
|
bom.setLevel(level); |
|
|
bom.setLevel(level); |
|
|
log.info("BOM信息:{}", bom); |
|
|
log.info("BOM信息:{}", bom); |
|
|
@ -205,7 +229,15 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre |
|
|
if (Objects.nonNull(childBomCheck) && "Y".equals(component.getBomFlag())) { |
|
|
if (Objects.nonNull(childBomCheck) && "Y".equals(component.getBomFlag())) { |
|
|
log.debug("[BOM_PROCESS] 递归处理半成品 - PartNo: {}", component.getComponentPart()); |
|
|
log.debug("[BOM_PROCESS] 递归处理半成品 - PartNo: {}", component.getComponentPart()); |
|
|
// 递归收集子节点,parentId 占位 -1,写入时由 doSaveBomDataRecursive 覆盖 |
|
|
// 递归收集子节点,parentId 占位 -1,写入时由 doSaveBomDataRecursive 覆盖 |
|
|
BomNodeData childNode = collectBomData(childDetail, -1L, level + 1, ifsConFactory, costCache, workCenterCostCache); |
|
|
|
|
|
|
|
|
BomNodeData childNode = collectBomData( |
|
|
|
|
|
childDetail, |
|
|
|
|
|
-1L, |
|
|
|
|
|
level + 1, |
|
|
|
|
|
ifsConFactory, |
|
|
|
|
|
costCache, |
|
|
|
|
|
workCenterCostCache, |
|
|
|
|
|
nextRecursionPath |
|
|
|
|
|
); |
|
|
if (childNode != null) { |
|
|
if (childNode != null) { |
|
|
nodeData.children.add(childNode); |
|
|
nodeData.children.add(childNode); |
|
|
// 半成品:bomId 在写入阶段填充,先清零价格(IFS 并行阶段会覆盖) |
|
|
// 半成品:bomId 在写入阶段填充,先清零价格(IFS 并行阶段会覆盖) |
|
|
@ -908,6 +940,22 @@ public class QuoteDetailBomTreeServiceImpl extends ServiceImpl<QuoteDetailBomTre |
|
|
return quoteDetail; |
|
|
return quoteDetail; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private String buildBomPathKey(QuoteDetailBomTree bom) { |
|
|
|
|
|
return String.join("|", |
|
|
|
|
|
Objects.toString(bom.getSite(), ""), |
|
|
|
|
|
Objects.toString(bom.getPartNo(), ""), |
|
|
|
|
|
Objects.toString(bom.getBomType(), ""), |
|
|
|
|
|
Objects.toString(bom.getEngChgLevel(), ""), |
|
|
|
|
|
Objects.toString(bom.getAlternativeNo(), "") |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private String formatBomPath(Set<String> recursionPath, String currentBomPathKey) { |
|
|
|
|
|
List<String> fullPath = new ArrayList<>(recursionPath); |
|
|
|
|
|
fullPath.add(currentBomPathKey); |
|
|
|
|
|
return String.join(" -> ", fullPath); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private void copyCommonFields(QuoteDetail source, QuoteDetail target) { |
|
|
private void copyCommonFields(QuoteDetail source, QuoteDetail target) { |
|
|
target.setId(source.getId()); |
|
|
target.setId(source.getId()); |
|
|
target.setQuoteId(source.getQuoteId()); |
|
|
target.setQuoteId(source.getQuoteId()); |
|
|
|