@@ -150,23 +150,25 @@ open class BomService(
var baseUnit: Integer? = null
var baseUnitName: String? = null
var stockQty: BigDecimal? = null
var stockUnit: Integer? = null
var stockUnitName: String? = null
if (item?.id != null) {
val itemId = item.id!!
try {
// ---- 1) 获取 item 的真实 stock unit ----
val stockItemUom = itemUomService.findStock UnitByItemId(itemId)
val itemStockUnit = stock ItemUom?.uom
// ---- 1) 获取 item 的真实 sale unit ----
val saleItemUom = itemUomService.findSales UnitByItemId(itemId)
val itemSaleUnit = sale ItemUom?.uom
// saleUnitId: 使用 item 的 stock unit uom id
saleUnitId = itemStockUnit?.id
// saleUnitCode: 从 Excel 数据查找 uom_conversion,如果失败则使用 Excel 数据本身
// ---- 2) 确定 sale unit(来自 Excel column 7)----
if (excelSalesUnit != null) {
// Excel 找到了 uom_conversion
saleUnitId = excelSalesUnit.id
saleUnitCode = excelSalesUnit.udfudesc
// 检查 Excel sales unit 与 item stock unit 是否匹配
if (itemStockUnit != null && excelSalesUnit.id != itemStock Unit.id) {
// 检查 Excel sales unit 与 item sale unit 是否匹配
if (itemSaleUnit != null && excelSalesUnit.id != itemSale Unit.id) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
@@ -174,7 +176,7 @@ open class BomService(
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Excel sales unit (${excelSalesUnit.code}/${excelSalesUnit.udfudesc}) does not match item stock unit (${itemStockUnit.code}/${itemStock Unit.udfudesc})",
reason = "Excel sales unit (${excelSalesUnit.code}/${excelSalesUnit.udfudesc}) does not match item sale unit (${itemSaleUnit.code}/${itemSale Unit.udfudesc})",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
@@ -182,7 +184,7 @@ open class BomService(
}
} else {
// Excel 没有找到 uom_conversion,使用 Excel 数据本身
saleUnitCode = excelSalesUnitCode ?: itemStockUnit?.udfudesc
saleUnitCode = excelSalesUnitCode
if (excelSalesUnitCode != null) {
bomMaterialImportIssues.add(
@@ -200,26 +202,85 @@ open class BomService(
}
}
// ---- 2) 从 saleQty + item 的真实 stock unit 转换为 baseQty ----
if (excelSaleQty != null && itemStockUnit != null) {
val baseResult = itemUomService.convertUomByItem(
ConvertUomByItemRequest(
itemId = itemId,
qty = excelSaleQty,
uomId = itemStockUnit.id!!,
targetUnit = "baseUnit"
// ---- 3) 从 saleQty(sale unit)转换为 baseQty(base unit)----
if (excelSaleQty != null && excelSalesUnit != null && excelSalesUnit.id != null) {
try {
// 先检查 item 是否有 base unit
val baseItemUom = itemUomService.findBaseUnitByItemId(itemId)
if (baseItemUom == null) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to baseQty: item base unit not found",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
} else {
val baseResult = itemUomService.convertUomByItem(
ConvertUomByItemRequest(
itemId = itemId,
qty = excelSaleQty,
uomId = excelSalesUnit.id!!,
targetUnit = "baseUnit"
)
)
baseQty = baseResult.newQty
// 获取 base unit 信息
baseUnit = baseItemUom.uom?.id?.toInt()?.let { Integer.valueOf(it) } as? Integer
baseUnitName = baseItemUom.uom?.udfudesc
// 验证转换结果
if (baseQty == null) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to baseQty: conversion returned null",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
}
}
} catch (e: IllegalArgumentException) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to baseQty: ${e.message ?: "IllegalArgumentException"}",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
)
baseQty = baseResult.newQty
}
// ---- 3) 获取 item 的真实 base unit ----
val baseItemUom = itemUomService.findBaseUnitByItemId(itemId)
baseUnit = baseItemUom?.uom?.id?.toInt()?.let { Integer.valueOf(it) } as? Integer
baseUnitName = baseItemUom?.uom?.udfudesc
// 如果 baseQty 转换失败,记录问题
if (baseQty == null && excelSaleQty != null && itemStockUnit != null) {
println("【BOM Import Warning】bomCode=$bomCode, item=${item.code} 转 baseQty 失败: ${e.message}")
} catch (e: Exception) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to baseQty: ${e.javaClass.simpleName} - ${e.message ?: "Unknown error"}",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
println("【BOM Import Error】bomCode=$bomCode, item=${item.code} 转 baseQty 失败: ${e.message}")
}
} else if (excelSaleQty != null && excelSalesUnit == null) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
@@ -227,12 +288,92 @@ open class BomService(
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to baseQty: conversion faile d",
reason = "Cannot convert saleQty to baseQty: Excel sales unit not foun d",
srcQty = excelSaleQty,
srcUomCode = itemStockUnit.c ode
srcUomCode = excelSalesUnitC ode
)
)
} else if (excelSaleQty != null && itemStockUnit == null) {
}
// ---- 4) 从 saleQty(sale unit)转换为 stockQty(stock unit)----
if (excelSaleQty != null && excelSalesUnit != null && excelSalesUnit.id != null) {
try {
// 先检查 item 是否有 stock unit
val stockItemUom = itemUomService.findStockUnitByItemId(itemId)
if (stockItemUom == null) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to stockQty: item stock unit not found",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
} else {
val stockResult = itemUomService.convertUomByItem(
ConvertUomByItemRequest(
itemId = itemId,
qty = excelSaleQty,
uomId = excelSalesUnit.id!!,
targetUnit = "stockUnit"
)
)
stockQty = stockResult.newQty
// 获取 stock unit 信息
stockUnit = stockItemUom.uom?.id?.toInt()?.let { Integer.valueOf(it) } as? Integer
stockUnitName = stockItemUom.uom?.udfudesc
// 验证转换结果
if (stockQty == null) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to stockQty: conversion returned null",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
}
}
} catch (e: IllegalArgumentException) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to stockQty: ${e.message ?: "IllegalArgumentException"}",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
println("【BOM Import Warning】bomCode=$bomCode, item=${item.code} 转 stockQty 失败: ${e.message}")
} catch (e: Exception) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to stockQty: ${e.javaClass.simpleName} - ${e.message ?: "Unknown error"}",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
println("【BOM Import Error】bomCode=$bomCode, item=${item.code} 转 stockQty 失败: ${e.message}")
}
} else if (excelSaleQty != null && excelSalesUnit == null) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
@@ -240,13 +381,37 @@ open class BomService(
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to baseQty: item stock unit not found",
reason = "Cannot convert saleQty to stockQty: Excel sales unit not found",
srcQty = excelSaleQty,
srcUomCode = null
srcUomCode = excelSalesUnitCode
)
)
}
// 最终检查:如果 stockQty 仍然为 null,记录问题
if (stockQty == null && excelSaleQty != null && excelSalesUnit != null && excelSalesUnit.id != null) {
// 检查是否已经记录过这个问题(避免重复)
val alreadyReported = bomMaterialImportIssues.any { issue ->
issue.itemId == item.id &&
issue.reason.contains("stockQty", ignoreCase = true) &&
issue.srcQty == excelSaleQty
}
if (!alreadyReported) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
bomId = bomId,
bomCode = bomCode,
itemId = item.id,
itemCode = item.code,
itemName = item.name,
reason = "Cannot convert saleQty to stockQty: conversion failed (final check)",
srcQty = excelSaleQty,
srcUomCode = excelSalesUnit.code
)
)
}
}
} catch (e: IllegalArgumentException) {
bomMaterialImportIssues.add(
BomMaterialImportIssue(
@@ -301,15 +466,21 @@ open class BomService(
this.uom = req.uom // BOM 原始 UOM(column 3,保留)
this.uomName = req.uomName
// 新逻辑:使用 Excel column 6 的 saleQty 和 item stock unit
// 新逻辑:使用 Excel column 6 的 saleQty 和 column 7 的 sales unit
this.saleQty = saleQty
this.salesUnit = item?.id?.let { itemUomService.findStockUnitByItemId(it)?.uom }
this.salesUnit = excelSalesUnit // 使用 Excel 的 sales unit,不是 item 的 stock unit
this.salesUnitCode = saleUnitCode
// 从 sale unit 转换为 base unit
this.baseQty = baseQty
this.baseUnit = baseUnit
this.baseUnitName = baseUnitName
// 从 sale unit 转换为 stock unit(新增)
this.stockQty = stockQty
this.stockUnit = stockUnit
this.stockUnitName = stockUnitName
this.bom = req.bom
}
return bomMaterialRepository.saveAndFlush(bomMaterial)