| @@ -1250,8 +1250,37 @@ open class PickOrderService( | |||
| println("⚠️ WARNING: do_pick_order $doPickOrderId not found, skipping") | |||
| return@forEach | |||
| } | |||
| println("🔍 Processing do_pick_order ID: ${dpo.id}, ticket: ${dpo.ticketNo}") | |||
| // ✅ 新增:检查这个 do_pick_order 下是否还有其他未完成的 pick orders | |||
| val allDoPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(dpo.id!!) | |||
| val allPickOrderIdsInDpo = allDoPickOrderLines.mapNotNull { it.pickOrderId }.distinct() | |||
| println("🔍 DEBUG: This do_pick_order has ${allPickOrderIdsInDpo.size} pick orders") | |||
| // ✅ 检查每个 pick order 的状态 | |||
| val pickOrderStatuses = allPickOrderIdsInDpo.map { poId -> | |||
| val po = pickOrderRepository.findById(poId).orElse(null) | |||
| poId to po?.status | |||
| } | |||
| pickOrderStatuses.forEach { (poId, status) -> | |||
| println("🔍 DEBUG: Pick order $poId status: $status") | |||
| } | |||
| // ✅ 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表 | |||
| val allPickOrdersCompleted = pickOrderStatuses.all { (_, status) -> | |||
| status == PickOrderStatus.COMPLETED | |||
| } | |||
| if (!allPickOrdersCompleted) { | |||
| println("⏳ Not all pick orders in this do_pick_order are completed, keeping do_pick_order alive") | |||
| println("🔍 DEBUG: Completed pick orders: ${pickOrderStatuses.count { it.second == PickOrderStatus.COMPLETED }}/${pickOrderStatuses.size}") | |||
| return@forEach // ✅ 跳过这个 do_pick_order,不删除它 | |||
| } | |||
| println("✅ All pick orders in this do_pick_order are completed, moving to record table") | |||
| // 2) 先复制 do_pick_order -> do_pick_order_record | |||
| val dpoRecord = DoPickOrderRecord( | |||
| @@ -3516,261 +3545,307 @@ ORDER BY | |||
| val enrichedResults = filteredResults | |||
| return enrichedResults | |||
| } | |||
| open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, Any?> { | |||
| println("=== Debug: getAllPickOrderLotsWithDetailsHierarchical (NEW STRUCTURE) ===") | |||
| 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 基本信息 | |||
| val doPickOrderSql = """ | |||
| SELECT DISTINCT | |||
| dpo.id as do_pick_order_id, | |||
| dpo.ticket_no, | |||
| dpo.store_id, | |||
| dpo.TruckLanceCode, | |||
| dpo.truck_departure_time, | |||
| dpo.ShopCode, | |||
| dpo.ShopName | |||
| FROM fpsmsdb.do_pick_order dpo | |||
| INNER JOIN fpsmsdb.do_pick_order_line dpol ON dpol.do_pick_order_id = dpo.id AND dpol.deleted = 0 | |||
| INNER JOIN fpsmsdb.pick_order po ON po.id = dpol.pick_order_id | |||
| WHERE po.assignTo = :userId | |||
| AND po.type = 'do' | |||
| AND po.status IN ('assigned', 'released', 'picking') | |||
| AND po.deleted = false | |||
| AND dpo.deleted = false | |||
| LIMIT 1 | |||
| """.trimIndent() | |||
| val doPickOrderInfo = jdbcDao.queryForMap(doPickOrderSql, mapOf("userId" to userId)).orElse(null) | |||
| if (doPickOrderInfo == null) { | |||
| println("❌ No do_pick_order found for user $userId") | |||
| return mapOf( | |||
| "fgInfo" to null, | |||
| "pickOrders" to emptyList<Any>() | |||
| ) | |||
| } | |||
| val doPickOrderId = (doPickOrderInfo["do_pick_order_id"] as? Number)?.toLong() | |||
| println("🔍 Found do_pick_order ID: $doPickOrderId") | |||
| // ✅ Step 2: 获取该 do_pick_order 下的所有 pick orders | |||
| val pickOrdersSql = """ | |||
| SELECT DISTINCT | |||
| dpol.pick_order_id, | |||
| dpol.pick_order_code, | |||
| dpol.do_order_id, | |||
| dpol.delivery_order_code, | |||
| po.consoCode, | |||
| po.status, | |||
| DATE_FORMAT(po.targetDate, '%Y-%m-%d') as targetDate | |||
| FROM fpsmsdb.do_pick_order_line dpol | |||
| INNER JOIN fpsmsdb.pick_order po ON po.id = dpol.pick_order_id | |||
| WHERE dpol.do_pick_order_id = :doPickOrderId | |||
| AND dpol.deleted = 0 | |||
| AND po.deleted = false | |||
| ORDER BY dpol.pick_order_id | |||
| """.trimIndent() | |||
| // ... existing code ... | |||
| open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, Any?> { | |||
| println("=== Debug: getAllPickOrderLotsWithDetailsHierarchical (NEW STRUCTURE) ===") | |||
| 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 基本信息 | |||
| val doPickOrderSql = """ | |||
| SELECT DISTINCT | |||
| dpo.id as do_pick_order_id, | |||
| dpo.ticket_no, | |||
| dpo.store_id, | |||
| dpo.TruckLanceCode, | |||
| dpo.truck_departure_time, | |||
| dpo.ShopCode, | |||
| dpo.ShopName | |||
| FROM fpsmsdb.do_pick_order dpo | |||
| INNER JOIN fpsmsdb.do_pick_order_line dpol ON dpol.do_pick_order_id = dpo.id AND dpol.deleted = 0 | |||
| INNER JOIN fpsmsdb.pick_order po ON po.id = dpol.pick_order_id | |||
| WHERE po.assignTo = :userId | |||
| AND po.type = 'do' | |||
| AND EXISTS ( | |||
| SELECT 1 | |||
| FROM fpsmsdb.do_pick_order_line dpol2 | |||
| INNER JOIN fpsmsdb.pick_order po2 ON po2.id = dpol2.pick_order_id | |||
| WHERE dpol2.do_pick_order_id = dpo.id | |||
| AND dpol2.deleted = 0 | |||
| AND po2.status IN ('assigned', 'released', 'picking') | |||
| AND po2.deleted = false | |||
| ) | |||
| AND po.deleted = false | |||
| AND dpo.deleted = false | |||
| LIMIT 1 | |||
| """.trimIndent() | |||
| val doPickOrderInfo = jdbcDao.queryForMap(doPickOrderSql, mapOf("userId" to userId)).orElse(null) | |||
| if (doPickOrderInfo == null) { | |||
| println("❌ No do_pick_order found for user $userId") | |||
| return mapOf( | |||
| "fgInfo" to null, | |||
| "pickOrders" to emptyList<Any>() | |||
| ) | |||
| } | |||
| val doPickOrderId = (doPickOrderInfo["do_pick_order_id"] as? Number)?.toLong() | |||
| println("🔍 Found do_pick_order ID: $doPickOrderId") | |||
| // ✅ Step 2: 获取该 do_pick_order 下的所有 pick orders | |||
| val pickOrdersSql = """ | |||
| SELECT DISTINCT | |||
| dpol.pick_order_id, | |||
| dpol.pick_order_code, | |||
| dpol.do_order_id, | |||
| dpol.delivery_order_code, | |||
| po.consoCode, | |||
| po.status, | |||
| DATE_FORMAT(po.targetDate, '%Y-%m-%d') as targetDate | |||
| FROM fpsmsdb.do_pick_order_line dpol | |||
| INNER JOIN fpsmsdb.pick_order po ON po.id = dpol.pick_order_id | |||
| WHERE dpol.do_pick_order_id = :doPickOrderId | |||
| AND dpol.deleted = 0 | |||
| AND po.deleted = false | |||
| ORDER BY dpol.pick_order_id | |||
| """.trimIndent() | |||
| val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderId" to doPickOrderId)) | |||
| println("🔍 Found ${pickOrdersInfo.size} pick orders") | |||
| // ✅ Step 3: 为每个 pick order 获取 lines 和 lots | |||
| val allPickOrderLines = mutableListOf<Map<String, Any?>>() | |||
| val lineCountsPerPickOrder = mutableListOf<Int>() | |||
| val pickOrderIds = mutableListOf<Long>() | |||
| val pickOrderCodes = mutableListOf<String>() | |||
| val doOrderIds = mutableListOf<Long>() | |||
| val deliveryOrderCodes = mutableListOf<String>() | |||
| pickOrdersInfo.forEach { poInfo -> | |||
| val pickOrderId = (poInfo["pick_order_id"] as? Number)?.toLong() | |||
| val pickOrderCode = poInfo["pick_order_code"] as? String | |||
| val doOrderId = (poInfo["do_order_id"] as? Number)?.toLong() | |||
| val deliveryOrderCode = poInfo["delivery_order_code"] as? String | |||
| val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderId" to doPickOrderId)) | |||
| println("🔍 Found ${pickOrdersInfo.size} pick orders") | |||
| // 收集 IDs 和 codes | |||
| pickOrderId?.let { pickOrderIds.add(it) } | |||
| pickOrderCode?.let { pickOrderCodes.add(it) } | |||
| doOrderId?.let { doOrderIds.add(it) } | |||
| deliveryOrderCode?.let { deliveryOrderCodes.add(it) } | |||
| // ✅ Step 3: 为每个 pick order 获取 lines 和 lots(包括 null stock 的) | |||
| val pickOrders = pickOrdersInfo.map { poInfo -> | |||
| val pickOrderId = (poInfo["pick_order_id"] as? Number)?.toLong() | |||
| // ✅ 查询该 pick order 的所有 lines 和 lots | |||
| val linesSql = """ | |||
| SELECT | |||
| po.id as pickOrderId, | |||
| po.code as pickOrderCode, | |||
| po.consoCode as pickOrderConsoCode, | |||
| DATE_FORMAT(po.targetDate, '%Y-%m-%d') as pickOrderTargetDate, | |||
| po.type as pickOrderType, | |||
| po.status as pickOrderStatus, | |||
| po.assignTo as pickOrderAssignTo, | |||
| pol.id as pickOrderLineId, | |||
| pol.qty as pickOrderLineRequiredQty, | |||
| pol.status as pickOrderLineStatus, | |||
| i.id as itemId, | |||
| i.code as itemCode, | |||
| i.name as itemName, | |||
| uc.code as uomCode, | |||
| uc.udfudesc as uomDesc, | |||
| uc.udfShortDesc as uomShortDesc, | |||
| ill.id as lotId, | |||
| il.lotNo, | |||
| DATE_FORMAT(il.expiryDate, '%Y-%m-%d') as expiryDate, | |||
| w.name as location, | |||
| COALESCE(uc.udfudesc, 'N/A') as stockUnit, | |||
| w.`order` as routerIndex, | |||
| w.code as routerRoute, | |||
| CASE | |||
| WHEN sol.status = 'rejected' THEN NULL | |||
| ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) | |||
| END as availableQty, | |||
| COALESCE(spl.qty, 0) as requiredQty, | |||
| COALESCE(sol.qty, 0) as actualPickQty, | |||
| spl.id as suggestedPickLotId, | |||
| ill.status as lotStatus, | |||
| sol.id as stockOutLineId, | |||
| sol.status as stockOutLineStatus, | |||
| COALESCE(sol.qty, 0) as stockOutLineQty, | |||
| COALESCE(ill.inQty, 0) as inQty, | |||
| COALESCE(ill.outQty, 0) as outQty, | |||
| COALESCE(ill.holdQty, 0) as holdQty, | |||
| CASE | |||
| WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 'expired' | |||
| WHEN sol.status = 'rejected' THEN 'rejected' | |||
| WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) <= 0 THEN 'insufficient_stock' | |||
| WHEN ill.status = 'unavailable' THEN 'status_unavailable' | |||
| ELSE 'available' | |||
| END as lotAvailability, | |||
| CASE | |||
| WHEN sol.status = 'completed' THEN 'completed' | |||
| WHEN sol.status = 'rejected' THEN 'rejected' | |||
| WHEN sol.status = 'created' THEN 'pending' | |||
| ELSE 'pending' | |||
| END as processingStatus | |||
| FROM fpsmsdb.pick_order po | |||
| JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id AND pol.deleted = false | |||
| JOIN fpsmsdb.items i ON i.id = pol.itemId | |||
| LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = pol.uomId | |||
| // ✅ 查询该 pick order 的所有 lines 和 lots | |||
| val linesSql = """ | |||
| SELECT | |||
| po.id as pickOrderId, | |||
| po.code as pickOrderCode, | |||
| po.consoCode as pickOrderConsoCode, | |||
| DATE_FORMAT(po.targetDate, '%Y-%m-%d') as pickOrderTargetDate, | |||
| po.type as pickOrderType, | |||
| po.status as pickOrderStatus, | |||
| po.assignTo as pickOrderAssignTo, | |||
| -- ✅ 关键修改:使用 LEFT JOIN 来包含没有 lot 的 pick order lines | |||
| LEFT JOIN ( | |||
| SELECT spl.pickOrderLineId, spl.suggestedLotLineId AS lotLineId | |||
| FROM fpsmsdb.suggested_pick_lot spl | |||
| UNION | |||
| SELECT sol.pickOrderLineId, sol.inventoryLotLineId | |||
| FROM fpsmsdb.stock_out_line sol | |||
| WHERE sol.deleted = false | |||
| ) ll ON ll.pickOrderLineId = pol.id | |||
| pol.id as pickOrderLineId, | |||
| pol.qty as pickOrderLineRequiredQty, | |||
| pol.status as pickOrderLineStatus, | |||
| LEFT JOIN fpsmsdb.suggested_pick_lot spl | |||
| ON spl.pickOrderLineId = pol.id AND spl.suggestedLotLineId = ll.lotLineId | |||
| LEFT JOIN fpsmsdb.stock_out_line sol | |||
| ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ll.lotLineId AND sol.deleted = false | |||
| LEFT JOIN fpsmsdb.inventory_lot_line ill ON ill.id = ll.lotLineId AND ill.deleted = false | |||
| LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId AND il.deleted = false | |||
| LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId | |||
| i.id as itemId, | |||
| i.code as itemCode, | |||
| i.name as itemName, | |||
| uc.code as uomCode, | |||
| uc.udfudesc as uomDesc, | |||
| uc.udfShortDesc as uomShortDesc, | |||
| WHERE po.id = :pickOrderId | |||
| AND po.deleted = false | |||
| ORDER BY | |||
| COALESCE(w.`order`, 999999) ASC, | |||
| pol.id ASC, | |||
| il.lotNo ASC | |||
| """.trimIndent() | |||
| ill.id as lotId, | |||
| il.lotNo, | |||
| DATE_FORMAT(il.expiryDate, '%Y-%m-%d') as expiryDate, | |||
| w.name as location, | |||
| COALESCE(uc.udfudesc, 'N/A') as stockUnit, | |||
| w.`order` as routerIndex, | |||
| w.code as routerRoute, | |||
| CASE | |||
| WHEN sol.status = 'rejected' THEN NULL | |||
| ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) | |||
| END as availableQty, | |||
| COALESCE(spl.qty, 0) as requiredQty, | |||
| COALESCE(sol.qty, 0) as actualPickQty, | |||
| spl.id as suggestedPickLotId, | |||
| ill.status as lotStatus, | |||
| sol.id as stockOutLineId, | |||
| sol.status as stockOutLineStatus, | |||
| COALESCE(sol.qty, 0) as stockOutLineQty, | |||
| COALESCE(ill.inQty, 0) as inQty, | |||
| COALESCE(ill.outQty, 0) as outQty, | |||
| COALESCE(ill.holdQty, 0) as holdQty, | |||
| CASE | |||
| WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 'expired' | |||
| WHEN sol.status = 'rejected' THEN 'rejected' | |||
| WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) <= 0 THEN 'insufficient_stock' | |||
| WHEN ill.status = 'unavailable' THEN 'status_unavailable' | |||
| ELSE 'available' | |||
| END as lotAvailability, | |||
| CASE | |||
| WHEN sol.status = 'completed' THEN 'completed' | |||
| WHEN sol.status = 'rejected' THEN 'rejected' | |||
| WHEN sol.status = 'created' THEN 'pending' | |||
| ELSE 'pending' | |||
| END as processingStatus | |||
| FROM fpsmsdb.pick_order po | |||
| JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id AND pol.deleted = false | |||
| JOIN fpsmsdb.items i ON i.id = pol.itemId | |||
| LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = pol.uomId | |||
| val linesResults = jdbcDao.queryForList(linesSql, mapOf("pickOrderId" to pickOrderId)) | |||
| println("🔍 Pick order $pickOrderId has ${linesResults.size} line-lot records") | |||
| LEFT JOIN ( | |||
| SELECT spl.pickOrderLineId, spl.suggestedLotLineId AS lotLineId | |||
| FROM fpsmsdb.suggested_pick_lot spl | |||
| UNION | |||
| SELECT sol.pickOrderLineId, sol.inventoryLotLineId | |||
| FROM fpsmsdb.stock_out_line sol | |||
| WHERE sol.deleted = false | |||
| ) ll ON ll.pickOrderLineId = pol.id | |||
| // ✅ 按 pickOrderLineId 分组 | |||
| val lineGroups = linesResults.groupBy { (it["pickOrderLineId"] as? Number)?.toLong() } | |||
| LEFT JOIN fpsmsdb.suggested_pick_lot spl | |||
| ON spl.pickOrderLineId = pol.id AND spl.suggestedLotLineId = ll.lotLineId | |||
| LEFT JOIN fpsmsdb.stock_out_line sol | |||
| ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ll.lotLineId AND sol.deleted = false | |||
| LEFT JOIN fpsmsdb.inventory_lot_line ill ON ill.id = ll.lotLineId AND ill.deleted = false | |||
| LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId AND il.deleted = false | |||
| LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId | |||
| val pickOrderLines = lineGroups.map { (lineId, lineRows) -> | |||
| val firstLineRow = lineRows.firstOrNull() | |||
| if (firstLineRow == null) { | |||
| null | |||
| } else { | |||
| // ✅ 构建 lots 列表(如果没有 lot,返回空数组) | |||
| val lots = if (lineRows.any { it["lotId"] != null }) { | |||
| lineRows.filter { it["lotId"] != null }.map { lotRow -> | |||
| mapOf( | |||
| "id" to lotRow["lotId"], | |||
| "lotNo" to lotRow["lotNo"], | |||
| "expiryDate" to lotRow["expiryDate"], | |||
| "location" to lotRow["location"], | |||
| "stockUnit" to lotRow["stockUnit"], | |||
| "availableQty" to lotRow["availableQty"], | |||
| "requiredQty" to lotRow["requiredQty"], | |||
| "actualPickQty" to lotRow["actualPickQty"], | |||
| "inQty" to lotRow["inQty"], | |||
| "outQty" to lotRow["outQty"], | |||
| "holdQty" to lotRow["holdQty"], | |||
| "lotStatus" to lotRow["lotStatus"], | |||
| "lotAvailability" to lotRow["lotAvailability"], | |||
| "processingStatus" to lotRow["processingStatus"], | |||
| "suggestedPickLotId" to lotRow["suggestedPickLotId"], | |||
| "stockOutLineId" to lotRow["stockOutLineId"], | |||
| "stockOutLineStatus" to lotRow["stockOutLineStatus"], | |||
| "stockOutLineQty" to lotRow["stockOutLineQty"], | |||
| "router" to mapOf( | |||
| "id" to null, | |||
| "index" to lotRow["routerIndex"], | |||
| "route" to lotRow["routerRoute"], | |||
| "area" to lotRow["routerRoute"], | |||
| "itemCode" to lotRow["itemId"], | |||
| "itemName" to lotRow["itemName"], | |||
| "uomId" to lotRow["uomCode"], | |||
| "noofCarton" to lotRow["requiredQty"] | |||
| ) | |||
| WHERE po.id = :pickOrderId | |||
| AND po.deleted = false | |||
| ORDER BY | |||
| COALESCE(w.`order`, 999999) ASC, | |||
| pol.id ASC, | |||
| il.lotNo ASC | |||
| """.trimIndent() | |||
| val linesResults = jdbcDao.queryForList(linesSql, mapOf("pickOrderId" to pickOrderId)) | |||
| println("🔍 Pick order $pickOrderId has ${linesResults.size} line-lot records") | |||
| // ✅ 按 pickOrderLineId 分组 | |||
| val lineGroups = linesResults.groupBy { (it["pickOrderLineId"] as? Number)?.toLong() } | |||
| val pickOrderLines = lineGroups.map { (lineId, lineRows) -> | |||
| val firstLineRow = lineRows.firstOrNull() | |||
| if (firstLineRow == null) { | |||
| null | |||
| } else { | |||
| // ✅ 构建 lots 列表 | |||
| val lots = if (lineRows.any { it["lotId"] != null }) { | |||
| lineRows.filter { it["lotId"] != null }.map { lotRow -> | |||
| mapOf( | |||
| "id" to lotRow["lotId"], | |||
| "lotNo" to lotRow["lotNo"], | |||
| "expiryDate" to lotRow["expiryDate"], | |||
| "location" to lotRow["location"], | |||
| "stockUnit" to lotRow["stockUnit"], | |||
| "availableQty" to lotRow["availableQty"], | |||
| "requiredQty" to lotRow["requiredQty"], | |||
| "actualPickQty" to lotRow["actualPickQty"], | |||
| "inQty" to lotRow["inQty"], | |||
| "outQty" to lotRow["outQty"], | |||
| "holdQty" to lotRow["holdQty"], | |||
| "lotStatus" to lotRow["lotStatus"], | |||
| "lotAvailability" to lotRow["lotAvailability"], | |||
| "processingStatus" to lotRow["processingStatus"], | |||
| "suggestedPickLotId" to lotRow["suggestedPickLotId"], | |||
| "stockOutLineId" to lotRow["stockOutLineId"], | |||
| "stockOutLineStatus" to lotRow["stockOutLineStatus"], | |||
| "stockOutLineQty" to lotRow["stockOutLineQty"], | |||
| "router" to mapOf( | |||
| "id" to null, | |||
| "index" to lotRow["routerIndex"], | |||
| "route" to lotRow["routerRoute"], | |||
| "area" to lotRow["routerRoute"], | |||
| "itemCode" to lotRow["itemId"], | |||
| "itemName" to lotRow["itemName"], | |||
| "uomId" to lotRow["uomCode"], | |||
| "noofCarton" to lotRow["requiredQty"] | |||
| ) | |||
| } | |||
| } else { | |||
| emptyList() // ✅ 返回空数组而不是 null | |||
| ) | |||
| } | |||
| mapOf( | |||
| "id" to lineId, | |||
| "requiredQty" to firstLineRow["pickOrderLineRequiredQty"], | |||
| "status" to firstLineRow["pickOrderLineStatus"], | |||
| "item" to mapOf( | |||
| "id" to firstLineRow["itemId"], | |||
| "code" to firstLineRow["itemCode"], | |||
| "name" to firstLineRow["itemName"], | |||
| "uomCode" to firstLineRow["uomCode"], | |||
| "uomDesc" to firstLineRow["uomDesc"], | |||
| "uomShortDesc" to firstLineRow["uomShortDesc"], | |||
| ), | |||
| "lots" to lots // ✅ 即使是空数组也返回 | |||
| ) | |||
| } else { | |||
| emptyList() | |||
| } | |||
| }.filterNotNull() | |||
| mapOf( | |||
| "pickOrderId" to pickOrderId, | |||
| "pickOrderCode" to poInfo["pick_order_code"], | |||
| "doOrderId" to poInfo["do_order_id"], | |||
| "deliveryOrderCode" to poInfo["delivery_order_code"], | |||
| "consoCode" to poInfo["consoCode"], | |||
| "status" to poInfo["status"], | |||
| "targetDate" to poInfo["targetDate"], | |||
| "pickOrderLines" to pickOrderLines | |||
| ) | |||
| } | |||
| // ✅ 构建 FG 信息 | |||
| val fgInfo = mapOf( | |||
| "doPickOrderId" to doPickOrderId, | |||
| "ticketNo" to doPickOrderInfo["ticket_no"], | |||
| "storeId" to doPickOrderInfo["store_id"], | |||
| "shopCode" to doPickOrderInfo["ShopCode"], | |||
| "shopName" to doPickOrderInfo["ShopName"], | |||
| "truckLanceCode" to doPickOrderInfo["TruckLanceCode"], | |||
| "departureTime" to doPickOrderInfo["truck_departure_time"] | |||
| ) | |||
| mapOf( | |||
| "id" to lineId, | |||
| "requiredQty" to firstLineRow["pickOrderLineRequiredQty"], | |||
| "status" to firstLineRow["pickOrderLineStatus"], | |||
| "item" to mapOf( | |||
| "id" to firstLineRow["itemId"], | |||
| "code" to firstLineRow["itemCode"], | |||
| "name" to firstLineRow["itemName"], | |||
| "uomCode" to firstLineRow["uomCode"], | |||
| "uomDesc" to firstLineRow["uomDesc"], | |||
| "uomShortDesc" to firstLineRow["uomShortDesc"], | |||
| ), | |||
| "lots" to lots | |||
| ) | |||
| } | |||
| }.filterNotNull() | |||
| return mapOf( | |||
| "fgInfo" to fgInfo, | |||
| "pickOrders" to pickOrders | |||
| // 记录该 pick order 的行数 | |||
| lineCountsPerPickOrder.add(pickOrderLines.size) | |||
| allPickOrderLines.addAll(pickOrderLines) | |||
| } | |||
| // 合并到总列表 | |||
| 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?> | |||
| (router?.get("index") as? Number)?.toInt() ?: 999999 | |||
| } | |||
| )) | |||
| // ✅ 构建 FG 信息 | |||
| val fgInfo = mapOf( | |||
| "doPickOrderId" to doPickOrderId, | |||
| "ticketNo" to doPickOrderInfo["ticket_no"], | |||
| "storeId" to doPickOrderInfo["store_id"], | |||
| "shopCode" to doPickOrderInfo["ShopCode"], | |||
| "shopName" to doPickOrderInfo["ShopName"], | |||
| "truckLanceCode" to doPickOrderInfo["TruckLanceCode"], | |||
| "departureTime" to doPickOrderInfo["truck_departure_time"] | |||
| ) | |||
| // ✅ 构建合并后的 pick order 对象 | |||
| val mergedPickOrder = if (pickOrdersInfo.isNotEmpty()) { | |||
| val firstPickOrderInfo = pickOrdersInfo.first() | |||
| mapOf( | |||
| "pickOrderIds" to pickOrderIds, | |||
| "pickOrderCodes" to pickOrderCodes, | |||
| "doOrderIds" to doOrderIds, | |||
| "deliveryOrderCodes" to deliveryOrderCodes, | |||
| "lineCountsPerPickOrder" to lineCountsPerPickOrder, | |||
| "consoCode" to firstPickOrderInfo["consoCode"], | |||
| "status" to firstPickOrderInfo["status"], | |||
| "targetDate" to firstPickOrderInfo["targetDate"], | |||
| "pickOrderLines" to allPickOrderLines | |||
| ) | |||
| } else { | |||
| null | |||
| } | |||
| return mapOf( | |||
| "fgInfo" to fgInfo, | |||
| "pickOrders" to listOfNotNull(mergedPickOrder) | |||
| ) | |||
| } | |||
| // Fix the type issues in the getPickOrdersByDateAndStore method | |||
| open fun getPickOrdersByDateAndStore(storeId: String): Map<String, Any?> { | |||
| println("=== Debug: getPickOrdersByDateAndStore ===") | |||