| @@ -34,49 +34,129 @@ class DoReleaseCoordinatorService( | |||||
| val updateSql = """ | val updateSql = """ | ||||
| UPDATE fpsmsdb.do_pick_order dpo | UPDATE fpsmsdb.do_pick_order dpo | ||||
| INNER JOIN ( | INNER JOIN ( | ||||
| WITH DoWarehouseFloor AS ( | |||||
| WITH DoFloorCounts AS ( | |||||
| SELECT | SELECT | ||||
| dol.deliveryOrderId, | dol.deliveryOrderId, | ||||
| w.store_id, | w.store_id, | ||||
| COUNT(DISTINCT dol.itemId) AS item_count | COUNT(DISTINCT dol.itemId) AS item_count | ||||
| FROM fpsmsdb.delivery_order_line dol | FROM fpsmsdb.delivery_order_line dol | ||||
| LEFT JOIN fpsmsdb.inventory_lot il ON il.itemId = dol.itemId AND il.deleted = 0 | |||||
| LEFT JOIN fpsmsdb.inventory_lot_line ill ON ill.inventoryLotId = il.id AND ill.deleted = 0 | |||||
| LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId AND w.deleted = 0 | |||||
| INNER JOIN fpsmsdb.inventory i ON i.itemId = dol.itemId | |||||
| AND i.deleted = 0 | |||||
| AND i.onHandQty > 0 | |||||
| INNER JOIN fpsmsdb.inventory_lot il ON il.itemId = i.itemId | |||||
| AND il.deleted = 0 | |||||
| INNER JOIN fpsmsdb.inventory_lot_line ill ON ill.inventoryLotId = il.id | |||||
| AND ill.deleted = 0 | |||||
| INNER JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId | |||||
| AND w.deleted = 0 | |||||
| AND w.store_id IN ('2F', '4F') | |||||
| WHERE dol.deleted = 0 | WHERE dol.deleted = 0 | ||||
| GROUP BY dol.deliveryOrderId, w.store_id | GROUP BY dol.deliveryOrderId, w.store_id | ||||
| ), | ), | ||||
| DoFloorSummary AS ( | |||||
| SELECT | |||||
| do.id AS deliveryOrderId, | |||||
| COALESCE(SUM(CASE WHEN dfc.store_id = '2F' THEN dfc.item_count ELSE 0 END), 0) AS count_2f, | |||||
| COALESCE(SUM(CASE WHEN dfc.store_id = '4F' THEN dfc.item_count ELSE 0 END), 0) AS count_4f | |||||
| FROM fpsmsdb.delivery_order do | |||||
| LEFT JOIN DoFloorCounts dfc ON dfc.deliveryOrderId = do.id | |||||
| WHERE do.deleted = 0 | |||||
| GROUP BY do.id | |||||
| ), | |||||
| PreferredFloor AS ( | PreferredFloor AS ( | ||||
| SELECT | SELECT | ||||
| deliveryOrderId, | deliveryOrderId, | ||||
| store_id, | |||||
| ROW_NUMBER() OVER ( | |||||
| PARTITION BY deliveryOrderId | |||||
| ORDER BY item_count DESC, store_id ASC | |||||
| ) AS rn | |||||
| FROM DoWarehouseFloor | |||||
| WHERE store_id IS NOT NULL | |||||
| CASE | |||||
| WHEN count_2f > count_4f THEN '2F' | |||||
| WHEN count_4f > count_2f THEN '4F' | |||||
| ELSE '2F' | |||||
| END AS preferred_floor, | |||||
| CASE | |||||
| WHEN count_2f > count_4f THEN 2 | |||||
| WHEN count_4f > count_2f THEN 4 | |||||
| ELSE 2 | |||||
| END AS preferred_store_id | |||||
| FROM DoFloorSummary | |||||
| ), | |||||
| TruckSelection AS ( | |||||
| SELECT | |||||
| do.id AS delivery_order_id, | |||||
| do.estimatedArrivalDate, | |||||
| pf.preferred_floor, | |||||
| CASE | |||||
| WHEN (SELECT COUNT(*) FROM fpsmsdb.truck t WHERE t.shopId = do.shopId AND t.deleted = 0) > 1 THEN | |||||
| COALESCE( | |||||
| (SELECT t.DepartureTime FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| AND t.Store_id = pf.preferred_store_id | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| (SELECT t.DepartureTime FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| '23:59:59' | |||||
| ) | |||||
| ELSE | |||||
| COALESCE( | |||||
| (SELECT t.DepartureTime FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| '23:59:59' | |||||
| ) | |||||
| END AS selected_departure_time, | |||||
| CASE | |||||
| WHEN (SELECT COUNT(*) FROM fpsmsdb.truck t WHERE t.shopId = do.shopId AND t.deleted = 0) > 1 THEN | |||||
| COALESCE( | |||||
| (SELECT t.TruckLanceCode FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| AND t.Store_id = pf.preferred_store_id | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| (SELECT t.TruckLanceCode FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| 'ZZ' | |||||
| ) | |||||
| ELSE | |||||
| COALESCE( | |||||
| (SELECT t.TruckLanceCode FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| 'ZZ' | |||||
| ) | |||||
| END AS selected_truck_lance, | |||||
| COALESCE( | |||||
| (SELECT t.LoadingSequence FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| AND t.Store_id = pf.preferred_store_id | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| (SELECT t.LoadingSequence FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| 999 | |||||
| ) AS loading_sequence | |||||
| FROM fpsmsdb.delivery_order do | |||||
| LEFT JOIN PreferredFloor pf ON pf.deliveryOrderId = do.id | |||||
| WHERE do.deleted = 0 | |||||
| ) | ) | ||||
| SELECT | SELECT | ||||
| dpo2.id, | dpo2.id, | ||||
| CONCAT('TI-', | CONCAT('TI-', | ||||
| DATE_FORMAT(dpo2.RequiredDeliveryDate, '%Y%m%d'), | DATE_FORMAT(dpo2.RequiredDeliveryDate, '%Y%m%d'), | ||||
| '-', | '-', | ||||
| COALESCE(pf.store_id, '2F'), | |||||
| COALESCE(ts.preferred_floor, '2F'), | |||||
| '-', | '-', | ||||
| LPAD( | LPAD( | ||||
| ROW_NUMBER() OVER ( | ROW_NUMBER() OVER ( | ||||
| PARTITION BY DATE(dpo2.RequiredDeliveryDate), COALESCE(pf.store_id, '2F') | |||||
| ORDER BY COALESCE(dpo2.truck_departure_time, '23:59:59'), | |||||
| COALESCE(dpo2.TruckLanceCode, 'ZZ'), | |||||
| COALESCE(dpo2.loading_sequence, 999), | |||||
| dpo2.id | |||||
| PARTITION BY DATE(dpo2.RequiredDeliveryDate), COALESCE(ts.preferred_floor, '2F') | |||||
| ORDER BY COALESCE(ts.selected_departure_time, '23:59:59'), | |||||
| COALESCE(ts.selected_truck_lance, 'ZZ'), | |||||
| COALESCE(ts.loading_sequence, 999), | |||||
| dpo2.do_order_id | |||||
| ), | ), | ||||
| 3, '0' | 3, '0' | ||||
| ) | ) | ||||
| ) AS new_ticket_no | ) AS new_ticket_no | ||||
| FROM fpsmsdb.do_pick_order dpo2 | FROM fpsmsdb.do_pick_order dpo2 | ||||
| LEFT JOIN PreferredFloor pf ON pf.deliveryOrderId = dpo2.do_order_id AND pf.rn = 1 | |||||
| LEFT JOIN TruckSelection ts ON ts.delivery_order_id = dpo2.do_order_id | |||||
| WHERE dpo2.ticket_no LIKE 'TEMP-%' | WHERE dpo2.ticket_no LIKE 'TEMP-%' | ||||
| AND dpo2.deleted = 0 | AND dpo2.deleted = 0 | ||||
| ) AS ticket_mapping ON dpo.id = ticket_mapping.id | ) AS ticket_mapping ON dpo.id = ticket_mapping.id | ||||
| @@ -93,7 +173,7 @@ class DoReleaseCoordinatorService( | |||||
| private fun getOrderedDeliveryOrderIds(ids: List<Long>): List<Long> { | private fun getOrderedDeliveryOrderIds(ids: List<Long>): List<Long> { | ||||
| try { | try { | ||||
| println("🔍 DEBUG: Getting ordered IDs for ${ids.size} orders") | println("🔍 DEBUG: Getting ordered IDs for ${ids.size} orders") | ||||
| println("🔍 DEBUG: First 5 IDs: ${ids.take(5)}") | |||||
| val sql = """ | val sql = """ | ||||
| WITH DoFloorCounts AS ( | WITH DoFloorCounts AS ( | ||||
| SELECT | SELECT | ||||
| @@ -202,8 +282,18 @@ class DoReleaseCoordinatorService( | |||||
| 'ZZ' | 'ZZ' | ||||
| ) | ) | ||||
| END AS selected_truck_lance, | END AS selected_truck_lance, | ||||
| (SELECT COUNT(*) FROM fpsmsdb.delivery_order_line dol | |||||
| WHERE dol.deliveryOrderId = do.id AND dol.deleted = 0) AS loading_sequence | |||||
| COALESCE( | |||||
| (SELECT t.LoadingSequence | |||||
| FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| AND t.Store_id = pf.preferred_store_id | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| (SELECT t.LoadingSequence | |||||
| FROM fpsmsdb.truck t | |||||
| WHERE t.shopId = do.shopId AND t.deleted = 0 | |||||
| ORDER BY t.DepartureTime ASC LIMIT 1), | |||||
| 999 | |||||
| ) AS loading_sequence | |||||
| FROM fpsmsdb.delivery_order do | FROM fpsmsdb.delivery_order do | ||||
| LEFT JOIN PreferredFloor pf ON pf.deliveryOrderId = do.id | LEFT JOIN PreferredFloor pf ON pf.deliveryOrderId = do.id | ||||
| WHERE do.id IN (${ids.joinToString(",")}) | WHERE do.id IN (${ids.joinToString(",")}) | ||||
| @@ -218,26 +308,42 @@ class DoReleaseCoordinatorService( | |||||
| selected_truck_lance, | selected_truck_lance, | ||||
| loading_sequence ASC, | loading_sequence ASC, | ||||
| delivery_order_id ASC | delivery_order_id ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| val results = jdbcDao.queryForList(sql) | |||||
| val sortedIds = results.mapNotNull { it["id"] as? Long } | |||||
| println("🔍 DEBUG: Query returned ${sortedIds.size} sorted IDs") | |||||
| println("🔍 DEBUG: First 10 sorted IDs: ${sortedIds.take(10)}") | |||||
| return if (sortedIds.isEmpty()) { | |||||
| println("⚠️ WARNING: No sorted IDs, using original order") | |||||
| ids | |||||
| } else { | |||||
| sortedIds | |||||
| } | |||||
| } catch (e: Exception) { | |||||
| println("❌ ERROR: ${e.message}") | |||||
| e.printStackTrace() | |||||
| return ids | |||||
| println("🔍 DEBUG: SQL length: ${sql.length} characters") // ✅ 添加这行 | |||||
| println("🔍 DEBUG: SQL first 500 chars: ${sql.take(500)}") // ✅ 添加这行 | |||||
| val results = jdbcDao.queryForList(sql) | |||||
| println("🔍 DEBUG: Results type: ${results.javaClass.name}") // ✅ 添加这行 | |||||
| println("🔍 DEBUG: Results size: ${results.size}") // ✅ 添加这行 | |||||
| if (results.isNotEmpty()) { | |||||
| println("🔍 DEBUG: First result keys: ${results[0].keys}") // ✅ 添加这行 | |||||
| println("🔍 DEBUG: First result: ${results[0]}") // ✅ 添加这行 | |||||
| } | |||||
| val sortedIds = results.mapNotNull { row -> | |||||
| (row["id"] as? Number)?.toLong() | |||||
| } | |||||
| println("🔍 DEBUG: Query returned ${sortedIds.size} sorted IDs") | |||||
| println("🔍 DEBUG: First 10 sorted IDs: ${sortedIds.take(10)}") | |||||
| return if (sortedIds.isEmpty()) { | |||||
| println("⚠️ WARNING: No sorted IDs, using original order") | |||||
| ids | |||||
| } else { | |||||
| sortedIds | |||||
| } | } | ||||
| } catch (e: Exception) { | |||||
| println("❌ ERROR: ${e.message}") | |||||
| println("❌ ERROR Stack Trace:") // ✅ 添加这行 | |||||
| e.printStackTrace() | |||||
| return ids | |||||
| } | } | ||||
| } | |||||
| fun startBatchReleaseAsync(ids: List<Long>, userId: Long): MessageResponse { | fun startBatchReleaseAsync(ids: List<Long>, userId: Long): MessageResponse { | ||||
| if (ids.isEmpty()) { | if (ids.isEmpty()) { | ||||
| return MessageResponse(id = null, code = "NO_IDS", name = null, type = null, | return MessageResponse(id = null, code = "NO_IDS", name = null, type = null, | ||||