|
|
|
@@ -2092,97 +2092,112 @@ open fun getCompletedJobOrderPickOrders(completedDate: LocalDate?): List<Map<Str |
|
|
|
|
|
|
|
open fun getAllJoPickOrders(bomType: String?, floor: String?): List<AllJoPickOrderResponse> { |
|
|
|
println("=== getAllJoPickOrders ===") |
|
|
|
val wallStartNs = System.nanoTime() |
|
|
|
val timing = linkedMapOf<String, Long>() |
|
|
|
fun <T> timed(name: String, block: () -> T): T { |
|
|
|
val t0 = System.nanoTime() |
|
|
|
val v = block() |
|
|
|
timing[name] = ((System.nanoTime() - t0) / 1_000_000) |
|
|
|
return v |
|
|
|
} |
|
|
|
|
|
|
|
return try { |
|
|
|
val releasedPickOrders = pickOrderRepository.findAllByStatusAndDeletedFalse( |
|
|
|
PickOrderStatus.RELEASED |
|
|
|
).filter { pickOrder -> |
|
|
|
pickOrder.jobOrder != null |
|
|
|
val releasedPickOrders = timed("loadReleasedPickOrdersMs") { |
|
|
|
pickOrderRepository.findAllReleasedJoWorkbenchPickOrders( |
|
|
|
status = PickOrderStatus.RELEASED, |
|
|
|
completedStatus = JobOrderStatus.COMPLETED, |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
println("Found ${releasedPickOrders.size} released job order pick orders") |
|
|
|
// 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 = """ |
|
|
|
SELECT |
|
|
|
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 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 |
|
|
|
AND po.id IN (${pickOrderIds.joinToString(",")}) |
|
|
|
AND w.id IS NOT NULL |
|
|
|
GROUP BY po.id, floorKey |
|
|
|
""".trimIndent() |
|
|
|
jdbcDao.queryForList(sql, emptyMap<String, Any?>()) |
|
|
|
.groupBy { (it["pickOrderId"] as? Number)?.toLong() ?: 0L } |
|
|
|
} else { |
|
|
|
emptyMap() |
|
|
|
val floorCountsByPickOrderId: Map<Long, List<Map<String, Any?>>> = timed("queryFloorCountsMs") { |
|
|
|
if (pickOrderIds.isNotEmpty()) { |
|
|
|
val sql = """ |
|
|
|
SELECT |
|
|
|
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 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 |
|
|
|
AND po.id IN (${pickOrderIds.joinToString(",")}) |
|
|
|
AND w.id IS NOT NULL |
|
|
|
GROUP BY po.id, floorKey |
|
|
|
""".trimIndent() |
|
|
|
jdbcDao.queryForList(sql, emptyMap<String, Any?>()) |
|
|
|
.groupBy { (it["pickOrderId"] as? Number)?.toLong() ?: 0L } |
|
|
|
} 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() |
|
|
|
val noLotCountsByPickOrderId: Map<Long, Map<String, Any?>> = timed("queryNoLotCountsMs") { |
|
|
|
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 suggestedFailCountByPickOrderId: Map<Long, Int> = timed("querySuggestedFailCountsMs") { |
|
|
|
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 linesByPickOrderId = |
|
|
|
val linesByPickOrderId = timed("loadPickOrderLinesMs") { |
|
|
|
if (pickOrderIds.isNotEmpty()) { |
|
|
|
pickOrderLineRepository.findAllByPickOrderIdInAndDeletedFalse(pickOrderIds) |
|
|
|
.mapNotNull { pol -> |
|
|
|
@@ -2193,138 +2208,148 @@ open fun getCompletedJobOrderPickOrders(completedDate: LocalDate?): List<Map<Str |
|
|
|
} else { |
|
|
|
emptyMap() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val jobOrderIdsForStockIn = releasedPickOrders.mapNotNull { it.jobOrder?.id }.distinct() |
|
|
|
val lotNoByJobOrderId = |
|
|
|
val lotNoByJobOrderId = timed("loadStockInLinesMs") { |
|
|
|
if (jobOrderIdsForStockIn.isNotEmpty()) { |
|
|
|
stockInLineRepository.findAllByJobOrder_IdInAndDeletedFalse(jobOrderIdsForStockIn) |
|
|
|
.mapNotNull { sil -> |
|
|
|
val joid = sil.jobOrder?.id ?: return@mapNotNull null |
|
|
|
joid to sil |
|
|
|
} |
|
|
|
.groupBy({ it.first }, { it.second }) |
|
|
|
.mapValues { (_, sils) -> |
|
|
|
sils.minByOrNull { it.id ?: Long.MAX_VALUE }?.lotNo |
|
|
|
} |
|
|
|
stockInLineRepository.findFirstLotNoByJobOrderIds(jobOrderIdsForStockIn) |
|
|
|
.associate { it.jobOrderId to it.lotNo } |
|
|
|
} else { |
|
|
|
emptyMap() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val jobTypeIds = releasedPickOrders.mapNotNull { it.jobOrder?.jobTypeId }.distinct() |
|
|
|
val jobTypesById = |
|
|
|
val jobTypesById = timed("loadJobTypesMs") { |
|
|
|
if (jobTypeIds.isNotEmpty()) { |
|
|
|
jobTypeRepository.findAllById(jobTypeIds).associateBy { it.id } |
|
|
|
} else { |
|
|
|
emptyMap() |
|
|
|
} |
|
|
|
val jobOrderPickOrders = releasedPickOrders.mapNotNull { pickOrder -> |
|
|
|
println("Processing pick order: ${pickOrder.id}, code: ${pickOrder.code}") |
|
|
|
val jobOrder = pickOrder.jobOrder |
|
|
|
if (jobOrder == null) { |
|
|
|
println("❌ Pick order ${pickOrder.id} has no job order") |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
if (jobOrder.isHidden == true) { |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
if (jobOrder.status == JobOrderStatus.COMPLETED) { |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
} |
|
|
|
val jobOrderPickOrders = timed("buildResponseMs") { |
|
|
|
releasedPickOrders.mapNotNull { pickOrder -> |
|
|
|
// println("Processing pick order: ${pickOrder.id}, code: ${pickOrder.code}") |
|
|
|
val jobOrder = pickOrder.jobOrder |
|
|
|
if (jobOrder == null) { |
|
|
|
println("❌ Pick order ${pickOrder.id} has no job order") |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
if (jobOrder.isHidden == true) { |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
if (jobOrder.status == JobOrderStatus.COMPLETED) { |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
|
|
|
|
println("Job order found: ${jobOrder.id}, code: ${jobOrder.code}") |
|
|
|
//println("Job order found: ${jobOrder.id}, code: ${jobOrder.code}") |
|
|
|
|
|
|
|
val bom = jobOrder.bom |
|
|
|
val bom = jobOrder.bom |
|
|
|
|
|
|
|
// 按 bom.type 过滤:null / blank 表示不过滤(全部) |
|
|
|
val normalizedType = bomType?.trim()?.lowercase()?.takeIf { it.isNotBlank() } |
|
|
|
if (normalizedType != null) { |
|
|
|
val currentType = bom?.type?.trim()?.lowercase() |
|
|
|
if (currentType != normalizedType) return@mapNotNull null |
|
|
|
} |
|
|
|
println("BOM found: ${bom?.id}") |
|
|
|
// 按 bom.type 过滤:null / blank 表示不过滤(全部) |
|
|
|
val normalizedType = bomType?.trim()?.lowercase()?.takeIf { it.isNotBlank() } |
|
|
|
if (normalizedType != null) { |
|
|
|
val currentType = bom?.type?.trim()?.lowercase() |
|
|
|
if (currentType != normalizedType) return@mapNotNull null |
|
|
|
} |
|
|
|
// println("BOM found: ${bom?.id}") |
|
|
|
|
|
|
|
val item = bom?.item |
|
|
|
if (item == null) { |
|
|
|
println("❌ BOM ${bom?.id} has no item") |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
val item = bom?.item |
|
|
|
if (item == null) { |
|
|
|
println("❌ BOM ${bom?.id} has no item") |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
|
|
|
|
println("Item found: ${item.id}, name: ${item.name}") |
|
|
|
//println("Item found: ${item.id}, name: ${item.name}") |
|
|
|
|
|
|
|
val uom = bom.outputQtyUom |
|
|
|
if (uom == null) { |
|
|
|
println("❌ BOM ${bom.id} has no uom") |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
val uom = bom.outputQtyUom |
|
|
|
if (uom == null) { |
|
|
|
println("❌ BOM ${bom.id} has no uom") |
|
|
|
return@mapNotNull null |
|
|
|
} |
|
|
|
|
|
|
|
// println("UOM found: ${uom.id}, code: ${uom.code}") |
|
|
|
// println("UOM found: ${uom.id}, code: ${uom.code}") |
|
|
|
|
|
|
|
val poId = pickOrder.id ?: return@mapNotNull null |
|
|
|
val pickOrderLines = linesByPickOrderId[poId].orEmpty() |
|
|
|
val finishedLines = pickOrderLines.count { it.status == PickOrderLineStatus.COMPLETED } |
|
|
|
val jobOrderType = jobOrder.jobTypeId?.let { jobTypesById[it] } |
|
|
|
val joId = jobOrder.id ?: return@mapNotNull null |
|
|
|
val lotNo = lotNoByJobOrderId[joId] |
|
|
|
println("✅ Building response for pick order ${pickOrder.id}") |
|
|
|
val floorPickCounts = floorCountsByPickOrderId[pickOrder.id]?.map { row -> |
|
|
|
com.ffii.fpsms.modules.jobOrder.web.model.FloorPickCountDto( |
|
|
|
floor = normalizeFloor((row["floorKey"] as? String).orEmpty()), |
|
|
|
finishedCount = (row["finishedCount"] as? Number)?.toInt() ?: 0, |
|
|
|
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: |
|
|
|
// - When selecting a specific floor (2F/3F/4F), show ONLY remaining on that floor. |
|
|
|
// - When selecting NO_LOT, show ONLY remaining for no-lot items. |
|
|
|
if (normalizedFloorFilter != null) { |
|
|
|
if (normalizedFloorFilter == "NO_LOT") { |
|
|
|
val hasNoLotRemaining = (noLotPickCount?.let { it.totalCount - it.finishedCount } ?: 0) > 0 |
|
|
|
if (!hasNoLotRemaining) return@mapNotNull null |
|
|
|
} else { |
|
|
|
val hasRemainingOnFloor = floorPickCounts.any { c -> |
|
|
|
c.floor == normalizedFloorFilter && (c.totalCount - c.finishedCount) > 0 |
|
|
|
val poId = pickOrder.id ?: return@mapNotNull null |
|
|
|
val pickOrderLines = linesByPickOrderId[poId].orEmpty() |
|
|
|
val finishedLines = pickOrderLines.count { it.status == PickOrderLineStatus.COMPLETED } |
|
|
|
val jobOrderType = jobOrder.jobTypeId?.let { jobTypesById[it] } |
|
|
|
val joId = jobOrder.id ?: return@mapNotNull null |
|
|
|
val lotNo = lotNoByJobOrderId[joId] |
|
|
|
// println("✅ Building response for pick order ${pickOrder.id}") |
|
|
|
val floorPickCounts = floorCountsByPickOrderId[pickOrder.id]?.map { row -> |
|
|
|
com.ffii.fpsms.modules.jobOrder.web.model.FloorPickCountDto( |
|
|
|
floor = normalizeFloor((row["floorKey"] as? String).orEmpty()), |
|
|
|
finishedCount = (row["finishedCount"] as? Number)?.toInt() ?: 0, |
|
|
|
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: |
|
|
|
// - When selecting a specific floor (2F/3F/4F), show ONLY remaining on that floor. |
|
|
|
// - When selecting NO_LOT, show ONLY remaining for no-lot items. |
|
|
|
if (normalizedFloorFilter != null) { |
|
|
|
if (normalizedFloorFilter == "NO_LOT") { |
|
|
|
val hasNoLotRemaining = (noLotPickCount?.let { it.totalCount - it.finishedCount } ?: 0) > 0 |
|
|
|
if (!hasNoLotRemaining) return@mapNotNull null |
|
|
|
} else { |
|
|
|
val hasRemainingOnFloor = floorPickCounts.any { c -> |
|
|
|
c.floor == normalizedFloorFilter && (c.totalCount - c.finishedCount) > 0 |
|
|
|
} |
|
|
|
if (!hasRemainingOnFloor) return@mapNotNull null |
|
|
|
} |
|
|
|
if (!hasRemainingOnFloor) return@mapNotNull null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val suggestedFailCount = suggestedFailCountByPickOrderId[pickOrder.id] ?: 0 |
|
|
|
AllJoPickOrderResponse( |
|
|
|
id = pickOrder.id ?: 0L, |
|
|
|
pickOrderId = pickOrder.id, |
|
|
|
pickOrderCode = pickOrder.code, |
|
|
|
jobOrderId = jobOrder.id, |
|
|
|
jobOrderCode = jobOrder.code, |
|
|
|
jobOrderTypeId = jobOrder.jobTypeId, |
|
|
|
jobOrderType = jobOrderType?.name, |
|
|
|
itemId = item.id ?: 0L, |
|
|
|
itemName = item.name ?: "", |
|
|
|
reqQty = jobOrder.reqQty ?: BigDecimal.ZERO, |
|
|
|
//uomId = bom.outputQtyUom?.id : 0L, |
|
|
|
uomId = 0, |
|
|
|
uomName = bom?.outputQtyUom ?: "", |
|
|
|
lotNo = lotNo, |
|
|
|
jobOrderStatus = jobOrder.status?.value ?: "", |
|
|
|
finishedPickOLineCount = finishedLines, |
|
|
|
floorPickCounts = floorPickCounts, |
|
|
|
noLotPickCount = noLotPickCount, |
|
|
|
suggestedFailCount = suggestedFailCount |
|
|
|
) |
|
|
|
val suggestedFailCount = suggestedFailCountByPickOrderId[pickOrder.id] ?: 0 |
|
|
|
AllJoPickOrderResponse( |
|
|
|
id = pickOrder.id ?: 0L, |
|
|
|
pickOrderId = pickOrder.id, |
|
|
|
pickOrderCode = pickOrder.code, |
|
|
|
jobOrderId = jobOrder.id, |
|
|
|
jobOrderCode = jobOrder.code, |
|
|
|
jobOrderTypeId = jobOrder.jobTypeId, |
|
|
|
jobOrderType = jobOrderType?.name, |
|
|
|
itemId = item.id ?: 0L, |
|
|
|
itemName = item.name ?: "", |
|
|
|
reqQty = jobOrder.reqQty ?: BigDecimal.ZERO, |
|
|
|
//uomId = bom.outputQtyUom?.id : 0L, |
|
|
|
uomId = 0, |
|
|
|
uomName = bom?.outputQtyUom ?: "", |
|
|
|
lotNo = lotNo, |
|
|
|
jobOrderStatus = jobOrder.status?.value ?: "", |
|
|
|
finishedPickOLineCount = finishedLines, |
|
|
|
floorPickCounts = floorPickCounts, |
|
|
|
noLotPickCount = noLotPickCount, |
|
|
|
suggestedFailCount = suggestedFailCount |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
println("Returning ${jobOrderPickOrders.size} released job order pick orders") |
|
|
|
jobOrderPickOrders.sortedByDescending { it.id } |
|
|
|
val sorted = timed("sortResponseMs") { |
|
|
|
jobOrderPickOrders.sortedByDescending { it.id } |
|
|
|
} |
|
|
|
val totalMs = (System.nanoTime() - wallStartNs) / 1_000_000 |
|
|
|
println( |
|
|
|
"JO_ALL_PICK_ORDERS_TIMING totalMs=$totalMs released=${releasedPickOrders.size} " + |
|
|
|
timing.entries.joinToString(" ") { "${it.key}=${it.value}" }, |
|
|
|
) |
|
|
|
// println("Returning ${jobOrderPickOrders.size} released job order pick orders") |
|
|
|
sorted |
|
|
|
} catch (e: Exception) { |
|
|
|
val totalMs = (System.nanoTime() - wallStartNs) / 1_000_000 |
|
|
|
println( |
|
|
|
"JO_ALL_PICK_ORDERS_TIMING totalMs=$totalMs (error) " + |
|
|
|
timing.entries.joinToString(" ") { "${it.key}=${it.value}" }, |
|
|
|
) |
|
|
|
println("❌ Error in getAllJoPickOrders: ${e.message}") |
|
|
|
e.printStackTrace() |
|
|
|
emptyList() |
|
|
|
|