|
|
|
@@ -1758,7 +1758,7 @@ private fun normalizeFloor(raw: String): String { |
|
|
|
val num = cleaned.replace(Regex("[^0-9]"), "") |
|
|
|
return if (num.isNotEmpty()) "${num}F" else cleaned |
|
|
|
} |
|
|
|
open fun getAllJoPickOrders(isDrink: Boolean?): List<AllJoPickOrderResponse> { |
|
|
|
open fun getAllJoPickOrders(isDrink: Boolean?, floor: String?): List<AllJoPickOrderResponse> { |
|
|
|
println("=== getAllJoPickOrders ===") |
|
|
|
|
|
|
|
return try { |
|
|
|
@@ -1771,6 +1771,8 @@ open fun getAllJoPickOrders(isDrink: Boolean?): List<AllJoPickOrderResponse> { |
|
|
|
println("Found ${releasedPickOrders.size} released job order pick orders") |
|
|
|
val pickOrderIds = releasedPickOrders.mapNotNull { it.id } |
|
|
|
|
|
|
|
val normalizedFloorFilter = floor?.let { normalizeFloor(it) }?.takeIf { it.isNotBlank() } |
|
|
|
|
|
|
|
// 2. 批量查询每个 pick order 的按楼层统计(若没有则跳过) |
|
|
|
val floorCountsByPickOrderId: Map<Long, List<Map<String, Any?>>> = if (pickOrderIds.isNotEmpty()) { |
|
|
|
val sql = """ |
|
|
|
@@ -1778,12 +1780,16 @@ open fun getAllJoPickOrders(isDrink: Boolean?): List<AllJoPickOrderResponse> { |
|
|
|
po.id AS pickOrderId, |
|
|
|
COALESCE(NULLIF(TRIM(w.store_id), ''), SUBSTRING_INDEX(w.code, '-', 1)) AS floorKey, |
|
|
|
COUNT(DISTINCT pol.id) AS totalCount, |
|
|
|
COUNT(DISTINCT CASE WHEN pol.status = 'COMPLETED' THEN pol.id END) AS finishedCount |
|
|
|
COUNT(DISTINCT CASE |
|
|
|
WHEN LOWER(sol.status) = 'completed' THEN pol.id |
|
|
|
WHEN pol.status = 'COMPLETED' THEN pol.id |
|
|
|
END) AS finishedCount |
|
|
|
FROM fpsmsdb.pick_order po |
|
|
|
JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id AND pol.deleted = false |
|
|
|
LEFT JOIN fpsmsdb.suggested_pick_lot spl ON pol.id = spl.pickOrderLineId AND spl.deleted = false |
|
|
|
LEFT JOIN fpsmsdb.inventory_lot_line ill ON spl.suggestedLotLineId = ill.id AND ill.deleted = false |
|
|
|
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId |
|
|
|
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.deleted = false |
|
|
|
WHERE po.deleted = false |
|
|
|
AND po.status = 'RELEASED' |
|
|
|
AND po.joId IS NOT NULL |
|
|
|
@@ -1795,6 +1801,52 @@ open fun getAllJoPickOrders(isDrink: Boolean?): List<AllJoPickOrderResponse> { |
|
|
|
} else { |
|
|
|
emptyMap() |
|
|
|
} |
|
|
|
|
|
|
|
// 2b. no-lot counts (lines with stock_out_line.inventoryLotLineId IS NULL) |
|
|
|
val noLotCountsByPickOrderId: Map<Long, Map<String, Any?>> = if (pickOrderIds.isNotEmpty()) { |
|
|
|
val sql = """ |
|
|
|
SELECT |
|
|
|
po.id AS pickOrderId, |
|
|
|
COUNT(DISTINCT pol.id) AS totalCount, |
|
|
|
COUNT(DISTINCT CASE |
|
|
|
WHEN LOWER(sol.status) = 'completed' THEN pol.id |
|
|
|
WHEN pol.status = 'COMPLETED' THEN pol.id |
|
|
|
END) AS finishedCount |
|
|
|
FROM fpsmsdb.pick_order po |
|
|
|
JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id AND pol.deleted = false |
|
|
|
JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.deleted = false |
|
|
|
WHERE po.deleted = false |
|
|
|
AND po.status = 'RELEASED' |
|
|
|
AND po.joId IS NOT NULL |
|
|
|
AND po.id IN (${pickOrderIds.joinToString(",")}) |
|
|
|
AND sol.inventoryLotLineId IS NULL |
|
|
|
GROUP BY po.id |
|
|
|
""".trimIndent() |
|
|
|
jdbcDao.queryForList(sql, emptyMap<String, Any?>()).associateBy { (it["pickOrderId"] as? Number)?.toLong() ?: 0L } |
|
|
|
} else emptyMap() |
|
|
|
|
|
|
|
// 2c. suggested fail (rejected) counts per pick order |
|
|
|
val suggestedFailCountByPickOrderId: Map<Long, Int> = if (pickOrderIds.isNotEmpty()) { |
|
|
|
val sql = """ |
|
|
|
SELECT |
|
|
|
po.id AS pickOrderId, |
|
|
|
COUNT(DISTINCT sol.id) AS rejectedCount |
|
|
|
FROM fpsmsdb.pick_order po |
|
|
|
JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id AND pol.deleted = false |
|
|
|
JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.deleted = false |
|
|
|
WHERE po.deleted = false |
|
|
|
AND po.status = 'RELEASED' |
|
|
|
AND po.joId IS NOT NULL |
|
|
|
AND po.id IN (${pickOrderIds.joinToString(",")}) |
|
|
|
AND LOWER(sol.status) = 'rejected' |
|
|
|
GROUP BY po.id |
|
|
|
""".trimIndent() |
|
|
|
jdbcDao.queryForList(sql, emptyMap<String, Any?>()).associate { row -> |
|
|
|
val id = (row["pickOrderId"] as? Number)?.toLong() ?: 0L |
|
|
|
val cnt = (row["rejectedCount"] as? Number)?.toInt() ?: 0 |
|
|
|
id to cnt |
|
|
|
} |
|
|
|
} else emptyMap() |
|
|
|
|
|
|
|
|
|
|
|
val jobOrderPickOrders = releasedPickOrders.mapNotNull { pickOrder -> |
|
|
|
@@ -1844,6 +1896,26 @@ open fun getAllJoPickOrders(isDrink: Boolean?): List<AllJoPickOrderResponse> { |
|
|
|
totalCount = (row["totalCount"] as? Number)?.toInt() ?: 0 |
|
|
|
) |
|
|
|
}.orEmpty() |
|
|
|
|
|
|
|
val noLotRow = noLotCountsByPickOrderId[pickOrder.id] |
|
|
|
val noLotPickCount = if (noLotRow != null) { |
|
|
|
com.ffii.fpsms.modules.jobOrder.web.model.FloorPickCountDto( |
|
|
|
floor = "NO_LOT", |
|
|
|
finishedCount = (noLotRow["finishedCount"] as? Number)?.toInt() ?: 0, |
|
|
|
totalCount = (noLotRow["totalCount"] as? Number)?.toInt() ?: 0 |
|
|
|
) |
|
|
|
} else null |
|
|
|
|
|
|
|
// Backend filtering by floor: include if there is remaining on that floor OR any no-lot remaining |
|
|
|
if (normalizedFloorFilter != null) { |
|
|
|
val hasRemainingOnFloor = floorPickCounts.any { c -> |
|
|
|
c.floor == normalizedFloorFilter && (c.totalCount - c.finishedCount) > 0 |
|
|
|
} |
|
|
|
val hasNoLotRemaining = (noLotPickCount?.let { it.totalCount - it.finishedCount } ?: 0) > 0 |
|
|
|
if (!hasRemainingOnFloor && !hasNoLotRemaining) return@mapNotNull null |
|
|
|
} |
|
|
|
|
|
|
|
val suggestedFailCount = suggestedFailCountByPickOrderId[pickOrder.id] ?: 0 |
|
|
|
AllJoPickOrderResponse( |
|
|
|
id = pickOrder.id ?: 0L, |
|
|
|
pickOrderId = pickOrder.id, |
|
|
|
@@ -1861,7 +1933,9 @@ open fun getAllJoPickOrders(isDrink: Boolean?): List<AllJoPickOrderResponse> { |
|
|
|
lotNo = lotNo, |
|
|
|
jobOrderStatus = jobOrder.status?.value ?: "", |
|
|
|
finishedPickOLineCount = finishedLines, |
|
|
|
floorPickCounts = floorPickCounts |
|
|
|
floorPickCounts = floorPickCounts, |
|
|
|
noLotPickCount = noLotPickCount, |
|
|
|
suggestedFailCount = suggestedFailCount |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
|