|
|
|
@@ -3328,406 +3328,252 @@ ORDER BY |
|
|
|
return enrichedResults |
|
|
|
} |
|
|
|
// 修改后的逻辑 |
|
|
|
open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, Any?> { |
|
|
|
/* |
|
|
|
open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String, Any?> { |
|
|
|
println("=== Debug: getAllPickOrderLotsWithDetailsHierarchical (Repository-based) ===") |
|
|
|
println("userId filter: $userId") |
|
|
|
|
|
|
|
|
|
|
|
val user = userService.find(userId).orElse(null) |
|
|
|
if (user == null) { |
|
|
|
println("❌ User not found: $userId") |
|
|
|
return emptyMap() |
|
|
|
} |
|
|
|
|
|
|
|
// Step 1: 先找到用户有活跃任务的 do_pick_order(通过 do_pick_order_line) |
|
|
|
// 这样可以确保只获取同一个 ticket 的 pick orders |
|
|
|
val userPickOrdersForDo = pickOrderRepository.findAll() |
|
|
|
.filter { |
|
|
|
it.deleted == false && |
|
|
|
it.assignTo?.id == userId && |
|
|
|
it.type?.value == "do" && |
|
|
|
(it.status == PickOrderStatus.RELEASED || |
|
|
|
it.status == PickOrderStatus.PENDING || |
|
|
|
it.status == PickOrderStatus.PICKING || |
|
|
|
it.status == PickOrderStatus.ASSIGNED) |
|
|
|
} |
|
|
|
|
|
|
|
if (userPickOrdersForDo.isEmpty()) { |
|
|
|
println("❌ No active pick orders found for user $userId") |
|
|
|
return mapOf( |
|
|
|
"fgInfo" to null, |
|
|
|
"pickOrders" to emptyList<Any>() |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val activePickOrderIds = userPickOrdersForDo.mapNotNull { it.id } |
|
|
|
println(" Found ${activePickOrderIds.size} active pick orders assigned to user $userId") |
|
|
|
|
|
|
|
// Step 2: 通过 do_pick_order_line 找到相关的 do_pick_order |
|
|
|
val doPickOrderLineRecords = activePickOrderIds.flatMap { poId -> |
|
|
|
doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(poId) |
|
|
|
} |
|
|
|
|
|
|
|
val doPickOrderIds = doPickOrderLineRecords.mapNotNull { it.doPickOrderId }.distinct() |
|
|
|
|
|
|
|
if (doPickOrderIds.isEmpty()) { |
|
|
|
println("❌ No do_pick_order found for pick orders: $activePickOrderIds") |
|
|
|
return mapOf( |
|
|
|
"fgInfo" to null, |
|
|
|
"pickOrders" to emptyList<Any>() |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
println(" Found ${doPickOrderIds.size} do_pick_order records") |
|
|
|
|
|
|
|
// Step 3: 获取第一个 do_pick_order 的详细信息(用于构建 fgInfo) |
|
|
|
val doPickOrder = doPickOrderRepository.findById(doPickOrderIds.first()).orElse(null) |
|
|
|
|
|
|
|
// Step 1:直接按 handledBy 查当前用户的活动 do_pick_order(一个 ticket) |
|
|
|
val activeTicketStatuses = listOf("released", "picking") // 如果你用的是 DoPickOrderStatus 枚举,也可以改成 List<DoPickOrderStatus> |
|
|
|
val doPickOrder = doPickOrderRepository |
|
|
|
.findFirstByHandledByAndDeletedFalseAndTicketStatusIn(user.id!!, activeTicketStatuses) |
|
|
|
|
|
|
|
if (doPickOrder == null) { |
|
|
|
println("❌ do_pick_order not found: ${doPickOrderIds.first()}") |
|
|
|
println("❌ No active do_pick_order found for handledBy user $userId") |
|
|
|
return mapOf( |
|
|
|
"fgInfo" to null, |
|
|
|
"pickOrders" to emptyList<Any>() |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val doPickOrderId = doPickOrder.id!! |
|
|
|
println(" Using do_pick_order ID: $doPickOrderId") |
|
|
|
|
|
|
|
// Step 4: 关键修改 - 只获取这个 do_pick_order 下的所有 pick orders(无论状态) |
|
|
|
println(" Using do_pick_order ID (by handledBy): $doPickOrderId") |
|
|
|
|
|
|
|
// Step 2:用这个 do_pick_orderId 查对应的 do_pick_order_line / pick_order |
|
|
|
val allDoPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrderId) |
|
|
|
val allPickOrderIdsForThisTicket = allDoPickOrderLines.mapNotNull { it.pickOrderId }.distinct() |
|
|
|
|
|
|
|
|
|
|
|
println(" Found ${allPickOrderIdsForThisTicket.size} pick orders in this do_pick_order (including completed)") |
|
|
|
|
|
|
|
// Step 5: 加载这些 pick orders(包括 COMPLETED 状态) |
|
|
|
|
|
|
|
// Step 3:加载这些 pick orders(包括 COMPLETED) |
|
|
|
val pickOrders = pickOrderRepository.findAllById(allPickOrderIdsForThisTicket) |
|
|
|
.filter { |
|
|
|
it.deleted == false && |
|
|
|
it.assignTo?.id == userId && // 确保是分配给该用户的 |
|
|
|
.filter { |
|
|
|
it.deleted == false && |
|
|
|
it.assignTo?.id == userId && |
|
|
|
it.type?.value == "do" |
|
|
|
// 不限制状态,包括 COMPLETED |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
println(" Loaded ${pickOrders.size} pick orders (including completed)") |
|
|
|
|
|
|
|
// 收集所有需要的数据 |
|
|
|
// 收集所有需要的数据 |
|
|
|
val allPickOrderLineIds = pickOrders.flatMap { it.pickOrderLines }.mapNotNull { it.id } |
|
|
|
|
|
|
|
// 使用 Repository 批量加载所有 suggestions 和 stock out lines |
|
|
|
// 使用 Repository 批量加载所有 suggestions 和 stock out lines |
|
|
|
val allSuggestions = suggestPickLotRepository.findAllByPickOrderLineIdIn(allPickOrderLineIds) // 修复:使用 suggestPickLotRepository |
|
|
|
|
|
|
|
// Step 4:原来你从 3413 行开始的收集所有 line / lots 的逻辑,全部保留 |
|
|
|
val allPickOrderLineIds = pickOrders.flatMap { it.pickOrderLines }.mapNotNull { it.id } |
|
|
|
|
|
|
|
val allSuggestions = suggestPickLotRepository.findAllByPickOrderLineIdIn(allPickOrderLineIds) |
|
|
|
val allStockOutLines = allPickOrderLineIds.flatMap { lineId -> |
|
|
|
stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(lineId) |
|
|
|
} |
|
|
|
|
|
|
|
// 按 pickOrderLineId 分组 |
|
|
|
val suggestionsByLineId = allSuggestions.groupBy { spl: SuggestedPickLot -> // 修复:明确类型 |
|
|
|
|
|
|
|
val suggestionsByLineId = allSuggestions.groupBy { spl: SuggestedPickLot -> |
|
|
|
spl.pickOrderLine?.id |
|
|
|
} |
|
|
|
val stockOutLinesByLineId = allStockOutLines.groupBy { sol: StockOutLineInfo -> // 修复:明确类型 |
|
|
|
val stockOutLinesByLineId = allStockOutLines.groupBy { sol: StockOutLineInfo -> |
|
|
|
sol.pickOrderLineId |
|
|
|
} |
|
|
|
|
|
|
|
// 构建层级数据结构 |
|
|
|
|
|
|
|
val allPickOrderLines = mutableListOf<Map<String, Any?>>() |
|
|
|
val lineCountsPerPickOrder = mutableListOf<Int>() |
|
|
|
val pickOrderIdsList = mutableListOf<Long>() |
|
|
|
val pickOrderCodesList = mutableListOf<String>() |
|
|
|
val doOrderIdsList = mutableListOf<Long>() |
|
|
|
val deliveryOrderCodesList = mutableListOf<String>() |
|
|
|
|
|
|
|
|
|
|
|
pickOrders.forEach { po -> |
|
|
|
pickOrderIdsList.add(po.id!!) |
|
|
|
pickOrderCodesList.add(po.code ?: "") |
|
|
|
|
|
|
|
|
|
|
|
val doOrderId = po.deliveryOrder?.id |
|
|
|
if (doOrderId != null) doOrderIdsList.add(doOrderId) |
|
|
|
deliveryOrderCodesList.add(po.deliveryOrder?.code ?: "") |
|
|
|
|
|
|
|
|
|
|
|
val lines = po.pickOrderLines.filter { !it.deleted } |
|
|
|
|
|
|
|
val lineDtos = lines.map { pol -> |
|
|
|
val lineId = pol.id!! |
|
|
|
|
|
|
|
val lineDtos = po.pickOrderLines |
|
|
|
.filter { !it.deleted } |
|
|
|
.map { pol -> |
|
|
|
val lineId = pol.id |
|
|
|
val item = pol.item |
|
|
|
val uom = pol.uom |
|
|
|
val zero = BigDecimal.ZERO |
|
|
|
val today = LocalDate.now() |
|
|
|
|
|
|
|
// 使用 Repository 获取该 line 的 suggestions 和 stock out lines |
|
|
|
val suggestions = suggestionsByLineId[lineId] ?: emptyList<SuggestedPickLot>() // 修复:明确类型 |
|
|
|
val stockOutLines = stockOutLinesByLineId[lineId] ?: emptyList<StockOutLineInfo>() // 修复:明确类型 |
|
|
|
// 合并 suggestions 和 stock out lines,按 (lotId, stockOutLineId) 去重 |
|
|
|
// 合并 suggestions 和 stock out lines,按 lotId 去重(合并相同 lot 的多个条目) |
|
|
|
val lotMap = mutableMapOf<Long?, MutableMap<String, Any?>>() |
|
|
|
|
|
|
|
// 第一步:处理 suggestions,构建基础数据 |
|
|
|
suggestions.forEach { spl: SuggestedPickLot -> |
|
|
|
val ill = spl.suggestedLotLine |
|
|
|
if (ill != null) { |
|
|
|
val lotId = ill.id |
|
|
|
val il = ill.inventoryLot |
|
|
|
val w = ill.warehouse |
|
|
|
val isExpired = il?.expiryDate?.let { exp: LocalDate -> exp.isBefore(today) } == true |
|
|
|
val availableQty = (ill.inQty ?: zero) |
|
|
|
.minus(ill.outQty ?: zero) |
|
|
|
.minus(ill.holdQty ?: zero) |
|
|
|
|
|
|
|
// 查找对应的 stock out line(通过 lotId 查找,而不是通过 suggestion.stockOutLine) |
|
|
|
val stockOutLine = stockOutLines.find { sol: StockOutLineInfo -> |
|
|
|
sol.inventoryLotLineId == lotId |
|
|
|
} |
|
|
|
|
|
|
|
if (lotMap.containsKey(lotId)) { |
|
|
|
// 如果已存在,合并 requiredQty(累加) |
|
|
|
val existing = lotMap[lotId]!! |
|
|
|
val existingRequiredQty = (existing["requiredQty"] as? BigDecimal) ?: zero |
|
|
|
val newRequiredQty = spl.qty ?: zero |
|
|
|
existing["requiredQty"] = existingRequiredQty.plus(newRequiredQty) |
|
|
|
|
|
|
|
// 如果当前有 stockOutLine 但 existing 没有,更新 stockOutLine 信息 |
|
|
|
if (stockOutLine != null && existing["stockOutLineId"] == null) { |
|
|
|
existing["stockOutLineId"] = stockOutLine.id |
|
|
|
existing["stockOutLineStatus"] = stockOutLine.status |
|
|
|
existing["stockOutLineQty"] = numToBigDecimal(stockOutLine.qty as? Number) |
|
|
|
existing["actualPickQty"] = numToBigDecimal(stockOutLine.qty as? Number) |
|
|
|
existing["processingStatus"] = when { |
|
|
|
stockOutLine.status == "completed" -> "completed" |
|
|
|
stockOutLine.status == "rejected" -> "rejected" |
|
|
|
else -> "pending" |
|
|
|
} |
|
|
|
existing["lotAvailability"] = when { |
|
|
|
isExpired -> "expired" |
|
|
|
stockOutLine.status == "rejected" -> "rejected" |
|
|
|
availableQty <= zero -> "insufficient_stock" |
|
|
|
ill.status?.value == "unavailable" -> "status_unavailable" |
|
|
|
else -> "available" |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 首次遇到,创建新条目 |
|
|
|
lotMap[lotId] = mutableMapOf( |
|
|
|
"id" to lotId, |
|
|
|
"lotNo" to il?.lotNo, |
|
|
|
"expiryDate" to il?.expiryDate?.toString(), |
|
|
|
"location" to w?.code, |
|
|
|
"stockUnit" to (ill.stockUom?.uom?.udfudesc ?: uom?.udfudesc ?: "N/A"), |
|
|
|
"availableQty" to availableQty, |
|
|
|
"requiredQty" to (spl.qty ?: zero), |
|
|
|
"actualPickQty" to numToBigDecimal(stockOutLine?.qty as? Number), |
|
|
|
"inQty" to ill.inQty, |
|
|
|
"outQty" to ill.outQty, |
|
|
|
"holdQty" to ill.holdQty, |
|
|
|
"lotStatus" to ill.status?.value, |
|
|
|
"stockInLineId" to il?.stockInLine?.id, |
|
|
|
"lotAvailability" to when { |
|
|
|
isExpired -> "expired" |
|
|
|
stockOutLine?.status == "rejected" -> "rejected" |
|
|
|
availableQty <= zero -> "insufficient_stock" |
|
|
|
ill.status?.value == "unavailable" -> "status_unavailable" |
|
|
|
else -> "available" |
|
|
|
}, |
|
|
|
"processingStatus" to when { |
|
|
|
stockOutLine?.status == "completed" -> "completed" |
|
|
|
stockOutLine?.status == "rejected" -> "rejected" |
|
|
|
else -> "pending" |
|
|
|
}, |
|
|
|
"suggestedPickLotId" to spl.id, |
|
|
|
"stockOutLineId" to stockOutLine?.id, |
|
|
|
"stockOutLineStatus" to stockOutLine?.status, |
|
|
|
"stockOutLineQty" to numToBigDecimal(stockOutLine?.qty as? Number), |
|
|
|
"router" to mapOf( |
|
|
|
"id" to null, |
|
|
|
"index" to w?.order, |
|
|
|
"route" to w?.code, |
|
|
|
"area" to w?.code, |
|
|
|
"itemCode" to item?.id, |
|
|
|
"itemName" to item?.name, |
|
|
|
"uomId" to uom?.code, |
|
|
|
"noofCarton" to (spl.qty ?: zero) |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 第二步:处理 stock out lines(包括没有 suggestion 的,或更新已存在的) |
|
|
|
stockOutLines.forEach { sol: StockOutLineInfo -> |
|
|
|
val inventoryLotLineId = sol.inventoryLotLineId |
|
|
|
val stockOutLineId = sol.id |
|
|
|
|
|
|
|
if (inventoryLotLineId != null) { |
|
|
|
// 有 lot 的 stock out line |
|
|
|
if (lotMap.containsKey(inventoryLotLineId)) { |
|
|
|
// 如果 lot 已存在,更新 stockOutLine 信息(如果还没有) |
|
|
|
val existing = lotMap[inventoryLotLineId]!! |
|
|
|
if (existing["stockOutLineId"] == null) { |
|
|
|
existing["stockOutLineId"] = stockOutLineId |
|
|
|
existing["stockOutLineStatus"] = sol.status |
|
|
|
existing["stockOutLineQty"] = numToBigDecimal(sol.qty as? Number) |
|
|
|
existing["actualPickQty"] = numToBigDecimal(sol.qty as? Number) |
|
|
|
existing["processingStatus"] = when { |
|
|
|
sol.status == "completed" -> "completed" |
|
|
|
sol.status == "rejected" -> "rejected" |
|
|
|
else -> "pending" |
|
|
|
} |
|
|
|
|
|
|
|
// 更新 lotAvailability(如果 stockOutLine 是 rejected) |
|
|
|
if (sol.status == "rejected") { |
|
|
|
existing["lotAvailability"] = "rejected" |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
// lot 不存在,创建新条目(没有 suggestion 的情况) |
|
|
|
val ill = inventoryLotLineRepository.findById(inventoryLotLineId).orElse(null) |
|
|
|
if (ill != null) { |
|
|
|
val il = ill.inventoryLot |
|
|
|
val w = ill.warehouse |
|
|
|
val isExpired = il?.expiryDate?.let { exp: LocalDate -> exp.isBefore(today) } == true |
|
|
|
val availableQty = (ill.inQty ?: zero) |
|
|
|
.minus(ill.outQty ?: zero) |
|
|
|
.minus(ill.holdQty ?: zero) |
|
|
|
|
|
|
|
// 查找对应的 suggestion(如果有) |
|
|
|
val suggestion = suggestions.find { spl: SuggestedPickLot -> |
|
|
|
spl.suggestedLotLine?.id == inventoryLotLineId |
|
|
|
} |
|
|
|
|
|
|
|
lotMap[inventoryLotLineId] = mutableMapOf( |
|
|
|
"id" to inventoryLotLineId, |
|
|
|
"lotNo" to il?.lotNo, |
|
|
|
"expiryDate" to il?.expiryDate?.toString(), |
|
|
|
"location" to w?.code, |
|
|
|
"stockUnit" to (ill.stockUom?.uom?.udfudesc ?: uom?.udfudesc ?: "N/A"), |
|
|
|
"availableQty" to availableQty, |
|
|
|
"requiredQty" to (suggestion?.qty ?: zero), |
|
|
|
"actualPickQty" to numToBigDecimal(sol.qty as? Number), |
|
|
|
"inQty" to ill.inQty, |
|
|
|
"outQty" to ill.outQty, |
|
|
|
"holdQty" to ill.holdQty, |
|
|
|
"lotStatus" to ill.status?.value, |
|
|
|
"stockInLineId" to il?.stockInLine?.id, |
|
|
|
"lotAvailability" to when { |
|
|
|
isExpired -> "expired" |
|
|
|
sol.status == "rejected" -> "rejected" |
|
|
|
availableQty <= zero -> "insufficient_stock" |
|
|
|
ill.status?.value == "unavailable" -> "status_unavailable" |
|
|
|
else -> "available" |
|
|
|
}, |
|
|
|
"processingStatus" to when { |
|
|
|
sol.status == "completed" -> "completed" |
|
|
|
sol.status == "rejected" -> "rejected" |
|
|
|
else -> "pending" |
|
|
|
}, |
|
|
|
"suggestedPickLotId" to suggestion?.id, |
|
|
|
"stockOutLineId" to stockOutLineId, |
|
|
|
"stockOutLineStatus" to sol.status, |
|
|
|
"stockOutLineQty" to numToBigDecimal(sol.qty as? Number), |
|
|
|
"router" to mapOf( |
|
|
|
"id" to null, |
|
|
|
"index" to w?.order, |
|
|
|
"route" to w?.code, |
|
|
|
"area" to w?.code, |
|
|
|
"itemCode" to item?.id, |
|
|
|
"itemName" to item?.name, |
|
|
|
"uomId" to uom?.code, |
|
|
|
"noofCarton" to (suggestion?.qty ?: zero) |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val lots = lotMap.values.toList() |
|
|
|
|
|
|
|
// 处理没有 lot 的 stock out lines(noLot = true) |
|
|
|
val stockouts = stockOutLines |
|
|
|
.filter { sol: StockOutLineInfo -> sol.inventoryLotLineId == null } |
|
|
|
.map { sol: StockOutLineInfo -> |
|
|
|
mapOf( |
|
|
|
"id" to sol.id, |
|
|
|
"status" to sol.status, |
|
|
|
"qty" to numToBigDecimal(sol.qty as? Number), |
|
|
|
"lotId" to null, |
|
|
|
"lotNo" to "", |
|
|
|
"location" to "", |
|
|
|
"availableQty" to null, |
|
|
|
"noLot" to true |
|
|
|
) |
|
|
|
} |
|
|
|
// 获取该 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?.code, |
|
|
|
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.toString(), |
|
|
|
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) |
|
|
|
|
|
|
|
mapOf( |
|
|
|
"id" to lineId, |
|
|
|
"pickOrderLineId" to lineId, |
|
|
|
"pickOrderId" to po.id, |
|
|
|
"requiredQty" to pol.qty, |
|
|
|
"status" to pol.status?.value, |
|
|
|
"item" to mapOf( |
|
|
|
"id" to item?.id, |
|
|
|
"code" to item?.code, |
|
|
|
"name" to item?.name, |
|
|
|
"uomCode" to uom?.code, |
|
|
|
"uomDesc" to uom?.udfudesc, |
|
|
|
"uomShortDesc" to uom?.udfShortDesc |
|
|
|
), |
|
|
|
"lots" to lots, |
|
|
|
"stockouts" to stockouts |
|
|
|
StockOutDetailResponse( |
|
|
|
id = sol.id, |
|
|
|
status = sol.status, |
|
|
|
qty = sol.qty?.let { numToBigDecimal(it as? Number) }, |
|
|
|
lotId = ill?.id, |
|
|
|
lotNo = il?.lotNo ?: "", |
|
|
|
location = w?.code ?: "", |
|
|
|
availableQty = available, |
|
|
|
noLot = (ill == null) |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
lineCountsPerPickOrder.add(lineDtos.size) |
|
|
|
allPickOrderLines.addAll(lineDtos) |
|
|
|
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 |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
// 按 router index 排序 |
|
|
|
|
|
|
|
|
|
|
|
lineCountsPerPickOrder.add(lineDtos.size) |
|
|
|
allPickOrderLines.addAll(lineDtos) |
|
|
|
} |
|
|
|
|
|
|
|
// 排序、fgInfo、mergedPickOrder 这些也全部沿用你当前代码,只要用上面定义好的 doPickOrder/doPickOrderId 即可: |
|
|
|
allPickOrderLines.sortWith(compareBy( |
|
|
|
{ line -> |
|
|
|
val lots = line["lots"] as? List<Map<String, Any?>> |
|
|
|
val firstLot = lots?.firstOrNull() |
|
|
|
val router = firstLot?.get("router") as? Map<String, Any?> |
|
|
|
val indexValue = router?.get("index") |
|
|
|
|
|
|
|
// 提取楼层排序值:1F = 1, 2F/4F = 2, 其他 = 3 |
|
|
|
val floorSortValue = when (indexValue) { |
|
|
|
is String -> { |
|
|
|
val parts = indexValue.split("-") |
|
|
|
if (parts.isNotEmpty()) { |
|
|
|
val floorPart = parts[0].uppercase() // "1F", "2F", "4F" |
|
|
|
when (floorPart) { |
|
|
|
"1F" -> 1 |
|
|
|
"2F", "4F" -> 2 |
|
|
|
else -> 3 |
|
|
|
} |
|
|
|
} else { |
|
|
|
3 |
|
|
|
{ line -> |
|
|
|
val lots = line["lots"] as? List<Map<String, Any?>> |
|
|
|
val firstLot = lots?.firstOrNull() |
|
|
|
val router = firstLot?.get("router") as? Map<String, Any?> |
|
|
|
val indexValue = router?.get("index") |
|
|
|
val floorSortValue = when (indexValue) { |
|
|
|
is String -> { |
|
|
|
val parts = indexValue.split("-") |
|
|
|
if (parts.isNotEmpty()) { |
|
|
|
val floorPart = parts[0].uppercase() |
|
|
|
when (floorPart) { |
|
|
|
"1F" -> 1 |
|
|
|
"2F", "4F" -> 2 |
|
|
|
else -> 3 |
|
|
|
} |
|
|
|
} else 3 |
|
|
|
} |
|
|
|
else -> 3 |
|
|
|
} |
|
|
|
else -> 3 |
|
|
|
} |
|
|
|
floorSortValue |
|
|
|
}, |
|
|
|
{ line -> |
|
|
|
val lots = line["lots"] as? List<Map<String, Any?>> |
|
|
|
val firstLot = lots?.firstOrNull() |
|
|
|
val router = firstLot?.get("router") as? Map<String, Any?> |
|
|
|
val indexValue = router?.get("index") |
|
|
|
// 提取数字部分:格式为 "store_id-number" (如 "2F-004") |
|
|
|
when (indexValue) { |
|
|
|
is Number -> indexValue.toInt() |
|
|
|
is String -> { |
|
|
|
val parts = indexValue.split("-") |
|
|
|
if (parts.size > 1) { |
|
|
|
parts.last().toIntOrNull() ?: 999999 |
|
|
|
} else { |
|
|
|
indexValue.toIntOrNull() ?: 999999 |
|
|
|
floorSortValue |
|
|
|
}, |
|
|
|
{ line -> |
|
|
|
val lots = line["lots"] as? List<Map<String, Any?>> |
|
|
|
val firstLot = lots?.firstOrNull() |
|
|
|
val router = firstLot?.get("router") as? Map<String, Any?> |
|
|
|
val indexValue = router?.get("index") |
|
|
|
when (indexValue) { |
|
|
|
is Number -> indexValue.toInt() |
|
|
|
is String -> { |
|
|
|
val parts = indexValue.split("-") |
|
|
|
if (parts.size > 1) { |
|
|
|
parts.last().toIntOrNull() ?: 999999 |
|
|
|
} else { |
|
|
|
indexValue.toIntOrNull() ?: 999999 |
|
|
|
} |
|
|
|
} |
|
|
|
else -> 999999 |
|
|
|
} |
|
|
|
else -> 999999 |
|
|
|
} |
|
|
|
} |
|
|
|
)) |
|
|
|
|
|
|
|
// 构建 FG 信息 |
|
|
|
)) |
|
|
|
|
|
|
|
val fgInfo = mapOf( |
|
|
|
"doPickOrderId" to doPickOrderId, |
|
|
|
"ticketNo" to doPickOrder.ticketNo, |
|
|
|
@@ -3737,8 +3583,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A |
|
|
|
"truckLanceCode" to doPickOrder.truckLanceCode, |
|
|
|
"departureTime" to doPickOrder.truckDepartureTime?.toString() |
|
|
|
) |
|
|
|
|
|
|
|
// 构建合并后的 pick order 对象 |
|
|
|
|
|
|
|
val mergedPickOrder = if (pickOrders.isNotEmpty()) { |
|
|
|
val firstPickOrder = pickOrders.first() |
|
|
|
mapOf( |
|
|
|
@@ -3755,13 +3600,14 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A |
|
|
|
} else { |
|
|
|
null |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return mapOf( |
|
|
|
"fgInfo" to fgInfo, |
|
|
|
"pickOrders" to listOfNotNull(mergedPickOrder) |
|
|
|
) |
|
|
|
} |
|
|
|
open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String, Any?> { |
|
|
|
*/ |
|
|
|
open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, Any?> { |
|
|
|
println("=== Debug: getAllPickOrderLotsWithDetailsHierarchical (NEW STRUCTURE) ===") |
|
|
|
println("userId filter: $userId") |
|
|
|
|
|
|
|
@@ -3796,6 +3642,8 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String |
|
|
|
AND po2.status IN ('assigned', 'released', 'picking') |
|
|
|
AND po2.deleted = false |
|
|
|
) |
|
|
|
AND dpo.handled_by = :userId |
|
|
|
AND dpo.ticket_status IN ('released','picking') |
|
|
|
AND po.deleted = false |
|
|
|
AND dpo.deleted = false |
|
|
|
LIMIT 1 |
|
|
|
@@ -3812,7 +3660,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String |
|
|
|
|
|
|
|
val doPickOrderId = (doPickOrderInfo["do_pick_order_id"] as? Number)?.toLong() |
|
|
|
println(" Found do_pick_order ID: $doPickOrderId") |
|
|
|
val doTicketStatus = doPickOrderInfo["ticket_status"] |
|
|
|
val doTicketStatus = doPickOrderInfo["doTicketStatus"] |
|
|
|
// Step 2: 获取该 do_pick_order 下的所有 pick orders |
|
|
|
val pickOrdersSql = """ |
|
|
|
SELECT DISTINCT |
|
|
|
|