|
|
|
@@ -5019,6 +5019,252 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri |
|
|
|
"pickOrders" to pickOrderDtos |
|
|
|
) |
|
|
|
} |
|
|
|
open fun getLotDetailsByDoPickOrderRecordId3(doPickOrderRecordId: Long): LotDetailsByDoPickOrderRecordResponse { |
|
|
|
println("=== Debug: getLotDetailsByDoPickOrderRecordId3 (Repository-based) ===") |
|
|
|
println("doPickOrderRecordId: $doPickOrderRecordId") |
|
|
|
|
|
|
|
val zero = BigDecimal.ZERO |
|
|
|
val today = LocalDate.now() |
|
|
|
|
|
|
|
// 1) 获取 DoPickOrderRecord |
|
|
|
val dpor = doPickOrderRecordRepository.findById(doPickOrderRecordId).orElse(null) |
|
|
|
?: return LotDetailsByDoPickOrderRecordResponse( |
|
|
|
fgInfo = null, |
|
|
|
pickOrders = emptyList() |
|
|
|
) |
|
|
|
|
|
|
|
println("🔍 Found DoPickOrderRecord: id=${dpor.id}, ticketNo=${dpor.ticketNo}") |
|
|
|
|
|
|
|
// 2) 构建 fgInfo |
|
|
|
val fgInfo = FgInfoResponse( |
|
|
|
doPickOrderId = dpor.id, |
|
|
|
ticketNo = dpor.ticketNo, |
|
|
|
storeId = dpor.storeId, |
|
|
|
shopCode = dpor.shopCode, |
|
|
|
shopName = dpor.shopName, |
|
|
|
truckLanceCode = dpor.truckLanceCode, |
|
|
|
departureTime = dpor.truckDepartureTime |
|
|
|
) |
|
|
|
|
|
|
|
// 3) 通过 DoPickOrderLineRecord 获取 pickOrderIds |
|
|
|
val lineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(dpor.recordId!!) |
|
|
|
println("🔍 Found ${lineRecords.size} DoPickOrderLineRecord records") |
|
|
|
|
|
|
|
var pickOrderIds = lineRecords.mapNotNull { it.pickOrderId }.distinct() |
|
|
|
|
|
|
|
// 备用方案:如果 lineRecords 中没有 pickOrderId,尝试使用 DoPickOrderRecord.pickOrderId |
|
|
|
if (pickOrderIds.isEmpty() && dpor.pickOrderId != null) { |
|
|
|
println("⚠️ WARNING: No pickOrderIds in lineRecords, using DoPickOrderRecord.pickOrderId=${dpor.pickOrderId}") |
|
|
|
pickOrderIds = listOf(dpor.pickOrderId!!) |
|
|
|
} |
|
|
|
|
|
|
|
if (pickOrderIds.isEmpty()) { |
|
|
|
println("❌ ERROR: No pickOrderIds found for doPickOrderRecordId=$doPickOrderRecordId") |
|
|
|
return LotDetailsByDoPickOrderRecordResponse( |
|
|
|
fgInfo = fgInfo, |
|
|
|
pickOrders = emptyList() |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
println("🔍 Using pickOrderIds: $pickOrderIds") |
|
|
|
|
|
|
|
// 4) 批量加载所有相关数据 |
|
|
|
val pickOrders = pickOrderRepository.findAllById(pickOrderIds) |
|
|
|
.filter { !it.deleted } |
|
|
|
|
|
|
|
if (pickOrders.isEmpty()) { |
|
|
|
println("❌ ERROR: No pick orders found for ids: $pickOrderIds") |
|
|
|
return LotDetailsByDoPickOrderRecordResponse( |
|
|
|
fgInfo = fgInfo, |
|
|
|
pickOrders = emptyList() |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
println("🔍 Found ${pickOrders.size} pick orders") |
|
|
|
|
|
|
|
// 5) 收集所有 pickOrderLineIds |
|
|
|
val allPickOrderLineIds = pickOrders |
|
|
|
.flatMap { it.pickOrderLines } |
|
|
|
.filter { !it.deleted } |
|
|
|
.mapNotNull { it.id } |
|
|
|
|
|
|
|
println("🔍 Found ${allPickOrderLineIds.size} pick order lines") |
|
|
|
|
|
|
|
// 6) 批量加载 suggestions 和 stock out lines |
|
|
|
val allSuggestions = if (allPickOrderLineIds.isNotEmpty()) { |
|
|
|
suggestPickLotRepository.findAllByPickOrderLineIdIn(allPickOrderLineIds) |
|
|
|
} else { |
|
|
|
emptyList() |
|
|
|
} |
|
|
|
|
|
|
|
val allStockOutLines = if (allPickOrderLineIds.isNotEmpty()) { |
|
|
|
allPickOrderLineIds.flatMap { lineId -> |
|
|
|
stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(lineId) |
|
|
|
} |
|
|
|
} else { |
|
|
|
emptyList() |
|
|
|
} |
|
|
|
|
|
|
|
// 7) 按 pickOrderLineId 分组 |
|
|
|
val suggestionsByLineId = allSuggestions.groupBy { it.pickOrderLine?.id } |
|
|
|
val stockOutLinesByLineId = allStockOutLines.groupBy { it.pickOrderLineId } |
|
|
|
|
|
|
|
// 8) 批量加载所有 inventoryLotLineIds |
|
|
|
val allInventoryLotLineIds = allSuggestions |
|
|
|
.mapNotNull { it.suggestedLotLine?.id } |
|
|
|
.distinct() |
|
|
|
|
|
|
|
val inventoryLotLinesMap = if (allInventoryLotLineIds.isNotEmpty()) { |
|
|
|
inventoryLotLineRepository.findAllById(allInventoryLotLineIds) |
|
|
|
.associateBy { it.id!! } |
|
|
|
} else { |
|
|
|
emptyMap() |
|
|
|
} |
|
|
|
|
|
|
|
// 9) 构建响应 |
|
|
|
val pickOrderDtos = pickOrders.map { po -> |
|
|
|
val lineDtos = po.pickOrderLines |
|
|
|
.filter { !it.deleted } |
|
|
|
.map { pol -> |
|
|
|
val lineId = pol.id |
|
|
|
val item = pol.item |
|
|
|
val uom = pol.uom |
|
|
|
|
|
|
|
// 获取该 line 的 suggestions 和 stock out lines |
|
|
|
val suggestions = lineId?.let { suggestionsByLineId[it] } ?: emptyList() |
|
|
|
val stockOutLines = lineId?.let { stockOutLinesByLineId[it] } ?: emptyList() |
|
|
|
|
|
|
|
// 构建 lots(合并相同 lot 的多个 suggestions) |
|
|
|
val lotMap = mutableMapOf<Long?, LotDetailResponse>() |
|
|
|
|
|
|
|
suggestions.forEach { spl -> |
|
|
|
val ill = spl.suggestedLotLine |
|
|
|
if (ill != null && ill.id != null) { |
|
|
|
val illId = ill.id!! |
|
|
|
val illEntity = inventoryLotLinesMap[illId] ?: ill |
|
|
|
val il = illEntity.inventoryLot |
|
|
|
val w = illEntity.warehouse |
|
|
|
val isExpired = il?.expiryDate?.let { exp -> exp.isBefore(today) } == true |
|
|
|
|
|
|
|
val availableQty = (illEntity.inQty ?: zero) |
|
|
|
.minus(illEntity.outQty ?: zero) |
|
|
|
.minus(illEntity.holdQty ?: zero) |
|
|
|
|
|
|
|
// 查找对应的 stock out line |
|
|
|
val stockOutLine = stockOutLines.find { sol -> |
|
|
|
sol.inventoryLotLineId == illId |
|
|
|
} |
|
|
|
|
|
|
|
// 计算 actualPickQty |
|
|
|
val actualPickQty = stockOutLine?.qty?.let { numToBigDecimal(it as? Number) } |
|
|
|
|
|
|
|
if (lotMap.containsKey(illId)) { |
|
|
|
// 合并 requiredQty |
|
|
|
val existing = lotMap[illId]!! |
|
|
|
val newRequiredQty = (existing.requiredQty ?: zero).plus(spl.qty ?: zero) |
|
|
|
lotMap[illId] = existing.copy(requiredQty = newRequiredQty) |
|
|
|
} else { |
|
|
|
lotMap[illId] = LotDetailResponse( |
|
|
|
id = illId, |
|
|
|
lotNo = il?.lotNo, |
|
|
|
expiryDate = il?.expiryDate, |
|
|
|
location = w?.name, |
|
|
|
stockUnit = illEntity.stockUom?.uom?.udfudesc ?: uom?.udfudesc ?: "N/A", |
|
|
|
availableQty = availableQty, |
|
|
|
requiredQty = spl.qty, |
|
|
|
actualPickQty = actualPickQty, |
|
|
|
inQty = illEntity.inQty, |
|
|
|
outQty = illEntity.outQty, |
|
|
|
holdQty = illEntity.holdQty, |
|
|
|
lotStatus = illEntity.status?.value, |
|
|
|
lotAvailability = when { |
|
|
|
isExpired -> "expired" |
|
|
|
stockOutLine?.status == "rejected" -> "rejected" |
|
|
|
availableQty <= zero -> "insufficient_stock" |
|
|
|
illEntity.status?.value == "unavailable" -> "status_unavailable" |
|
|
|
else -> "available" |
|
|
|
}, |
|
|
|
processingStatus = when { |
|
|
|
stockOutLine?.status == "completed" -> "completed" |
|
|
|
stockOutLine?.status == "rejected" -> "rejected" |
|
|
|
else -> "pending" |
|
|
|
}, |
|
|
|
suggestedPickLotId = spl.id, |
|
|
|
stockOutLineId = stockOutLine?.id, |
|
|
|
stockOutLineStatus = stockOutLine?.status, |
|
|
|
stockOutLineQty = stockOutLine?.qty?.let { numToBigDecimal(it as? Number) }, |
|
|
|
router = RouterInfoResponse( |
|
|
|
id = null, |
|
|
|
index = w?.order, |
|
|
|
route = w?.code, |
|
|
|
area = w?.code |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val lots = lotMap.values.toList() |
|
|
|
|
|
|
|
// 构建 stockouts(包括没有 lot 的) |
|
|
|
val stockouts = stockOutLines.map { sol -> |
|
|
|
val illId = sol.inventoryLotLineId |
|
|
|
val ill = illId?.let { inventoryLotLinesMap[it] } |
|
|
|
val il = ill?.inventoryLot |
|
|
|
val w = ill?.warehouse |
|
|
|
val available = if (ill == null) null else |
|
|
|
(ill.inQty ?: zero) |
|
|
|
.minus(ill.outQty ?: zero) |
|
|
|
.minus(ill.holdQty ?: zero) |
|
|
|
|
|
|
|
StockOutDetailResponse( |
|
|
|
id = sol.id, |
|
|
|
status = sol.status, |
|
|
|
qty = sol.qty?.let { numToBigDecimal(it as? Number) }, |
|
|
|
lotId = ill?.id, |
|
|
|
lotNo = il?.lotNo ?: "", |
|
|
|
location = w?.name ?: "", |
|
|
|
availableQty = available, |
|
|
|
noLot = (ill == null) |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
PickOrderLineDetailResponse( |
|
|
|
id = lineId, |
|
|
|
requiredQty = pol.qty, |
|
|
|
status = pol.status?.value, |
|
|
|
item = ItemInfoResponse( |
|
|
|
id = item?.id, |
|
|
|
code = item?.code, |
|
|
|
name = item?.name, |
|
|
|
uomCode = uom?.code, |
|
|
|
uomDesc = uom?.udfudesc, |
|
|
|
uomShortDesc = uom?.udfShortDesc |
|
|
|
), |
|
|
|
lots = lots, |
|
|
|
stockouts = stockouts |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
PickOrderDetailResponse( |
|
|
|
pickOrderId = po.id, |
|
|
|
pickOrderCode = po.code, |
|
|
|
doOrderId = po.deliveryOrder?.id, |
|
|
|
deliveryOrderCode = po.deliveryOrder?.code, |
|
|
|
consoCode = po.consoCode, |
|
|
|
status = po.status?.value, |
|
|
|
targetDate = po.targetDate?.toLocalDate(), |
|
|
|
pickOrderLines = lineDtos |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
println("✅ Successfully built response with ${pickOrderDtos.size} pick orders") |
|
|
|
|
|
|
|
return LotDetailsByDoPickOrderRecordResponse( |
|
|
|
fgInfo = fgInfo, |
|
|
|
pickOrders = pickOrderDtos |
|
|
|
) |
|
|
|
} |
|
|
|
// 新增:从 do_pick_order_record 表查询(用于已完成的 pick orders) |
|
|
|
open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { |
|
|
|
try { |
|
|
|
|