|
|
|
@@ -1039,4 +1039,212 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
open fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(userId: Long): List<Map<String, Any?>> { |
|
|
|
println("=== getCompletedJobOrderPickOrdersWithCompletedSecondScan ===") |
|
|
|
println("userId: $userId") |
|
|
|
|
|
|
|
return try { |
|
|
|
// Get all completed pick orders assigned to user that have joId |
|
|
|
val completedPickOrders = pickOrderRepository.findAllByAssignToIdAndStatusIn( |
|
|
|
userId, |
|
|
|
listOf(PickOrderStatus.COMPLETED) |
|
|
|
).filter { it.jobOrder != null } // Only pick orders with joId |
|
|
|
|
|
|
|
println("Found ${completedPickOrders.size} completed job order pick orders for user $userId") |
|
|
|
|
|
|
|
val completedJobOrderPickOrders = completedPickOrders.mapNotNull { pickOrder -> |
|
|
|
val jobOrder = pickOrder.jobOrder |
|
|
|
if (jobOrder != null) { |
|
|
|
// Check if all items in this pick order have completed second scan |
|
|
|
val joPickOrders = findByPickOrderId(pickOrder.id!!) |
|
|
|
val allSecondScanCompleted = joPickOrders.isNotEmpty() && |
|
|
|
joPickOrders.all { it.second_qr_scan_status == JoPickOrderStatus.completed } |
|
|
|
|
|
|
|
if (allSecondScanCompleted) { |
|
|
|
mapOf( |
|
|
|
"id" to pickOrder.id, |
|
|
|
"pickOrderId" to pickOrder.id, |
|
|
|
"pickOrderCode" to pickOrder.code, |
|
|
|
"pickOrderConsoCode" to pickOrder.consoCode, |
|
|
|
"pickOrderTargetDate" to pickOrder.targetDate?.let { |
|
|
|
"${it.year}-${String.format("%02d", it.monthValue)}-${String.format("%02d", it.dayOfMonth)}" |
|
|
|
}, |
|
|
|
"pickOrderStatus" to pickOrder.status, |
|
|
|
"completedDate" to pickOrder.completeDate?.let { |
|
|
|
"${it.year}-${String.format("%02d", it.monthValue)}-${String.format("%02d", it.dayOfMonth)}" |
|
|
|
}, |
|
|
|
"jobOrderId" to jobOrder.id, |
|
|
|
"jobOrderCode" to jobOrder.code, |
|
|
|
"jobOrderName" to jobOrder.bom?.name, |
|
|
|
"reqQty" to jobOrder.reqQty, |
|
|
|
"uom" to jobOrder.bom?.uom?.code, |
|
|
|
"planStart" to jobOrder.planStart, |
|
|
|
"planEnd" to jobOrder.planEnd, |
|
|
|
"secondScanCompleted" to true, |
|
|
|
"totalItems" to joPickOrders.size, |
|
|
|
"completedItems" to joPickOrders.count { it.second_qr_scan_status == JoPickOrderStatus.completed } |
|
|
|
) |
|
|
|
} else { |
|
|
|
println("❌ Pick order ${pickOrder.id} has incomplete second scan, skipping.") |
|
|
|
null |
|
|
|
} |
|
|
|
} else { |
|
|
|
println("❌ Pick order ${pickOrder.id} has no job order, skipping.") |
|
|
|
null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
println("Returning ${completedJobOrderPickOrders.size} completed job order pick orders with completed second scan") |
|
|
|
completedJobOrderPickOrders |
|
|
|
} catch (e: Exception) { |
|
|
|
println("❌ Error in getCompletedJobOrderPickOrdersWithCompletedSecondScan: ${e.message}") |
|
|
|
e.printStackTrace() |
|
|
|
emptyList() |
|
|
|
} |
|
|
|
} |
|
|
|
open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List<Map<String, Any?>> { |
|
|
|
println("=== getCompletedJobOrderPickOrderLotDetails ===") |
|
|
|
println("pickOrderId: $pickOrderId") |
|
|
|
|
|
|
|
return try { |
|
|
|
val sql = """ |
|
|
|
SELECT |
|
|
|
-- Pick Order Information |
|
|
|
po.id as pickOrderId, |
|
|
|
po.code as pickOrderCode, |
|
|
|
po.consoCode as pickOrderConsoCode, |
|
|
|
DATE_FORMAT(po.targetDate, '%Y-%m-%d') as pickOrderTargetDate, |
|
|
|
po.status as pickOrderStatus, |
|
|
|
|
|
|
|
-- Job Order Information |
|
|
|
jo.id as jobOrderId, |
|
|
|
jo.code as jobOrderCode, |
|
|
|
|
|
|
|
-- Pick Order Line Information |
|
|
|
pol.id as pickOrderLineId, |
|
|
|
pol.qty as pickOrderLineRequiredQty, |
|
|
|
pol.status as pickOrderLineStatus, |
|
|
|
|
|
|
|
-- Item Information |
|
|
|
i.id as itemId, |
|
|
|
i.code as itemCode, |
|
|
|
i.name as itemName, |
|
|
|
uc.code as uomCode, |
|
|
|
uc.udfudesc as uomDesc, |
|
|
|
uc.udfShortDesc as uomShortDesc, |
|
|
|
|
|
|
|
-- Lot Information |
|
|
|
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, |
|
|
|
|
|
|
|
-- Router Information |
|
|
|
r.id as routerId, |
|
|
|
r.index as routerIndex, |
|
|
|
r.route as routerRoute, |
|
|
|
r.area as routerArea, |
|
|
|
|
|
|
|
-- Set quantities to NULL for rejected lots |
|
|
|
CASE |
|
|
|
WHEN sol.status = 'rejected' THEN NULL |
|
|
|
ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) |
|
|
|
END as availableQty, |
|
|
|
|
|
|
|
-- Required quantity for this lot |
|
|
|
COALESCE(spl.qty, 0) as requiredQty, |
|
|
|
|
|
|
|
-- Actual picked quantity |
|
|
|
COALESCE(sol.qty, 0) as actualPickQty, |
|
|
|
|
|
|
|
-- Suggested pick lot information |
|
|
|
spl.id as suggestedPickLotId, |
|
|
|
ill.status as lotStatus, |
|
|
|
|
|
|
|
-- Stock out line information |
|
|
|
sol.id as stockOutLineId, |
|
|
|
sol.status as stockOutLineStatus, |
|
|
|
COALESCE(sol.qty, 0) as stockOutLineQty, |
|
|
|
|
|
|
|
-- Additional detailed fields |
|
|
|
COALESCE(ill.inQty, 0) as inQty, |
|
|
|
COALESCE(ill.outQty, 0) as outQty, |
|
|
|
COALESCE(ill.holdQty, 0) as holdQty, |
|
|
|
|
|
|
|
-- Calculate total picked quantity by ALL pick orders for this lot |
|
|
|
COALESCE(( |
|
|
|
SELECT SUM(sol_all.qty) |
|
|
|
FROM fpsmsdb.stock_out_line sol_all |
|
|
|
WHERE sol_all.inventoryLotLineId = ill.id |
|
|
|
AND sol_all.deleted = false |
|
|
|
AND sol_all.status IN ('pending', 'checked', 'partially_completed', 'completed') |
|
|
|
), 0) as totalPickedByAllPickOrders, |
|
|
|
|
|
|
|
-- Calculate remaining available quantity correctly |
|
|
|
(COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as remainingAfterAllPickOrders, |
|
|
|
|
|
|
|
-- Lot availability status |
|
|
|
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, |
|
|
|
|
|
|
|
-- Processing status |
|
|
|
CASE |
|
|
|
WHEN sol.status = 'completed' THEN 'completed' |
|
|
|
WHEN sol.status = 'rejected' THEN 'rejected' |
|
|
|
WHEN sol.status = 'created' THEN 'pending' |
|
|
|
ELSE 'pending' |
|
|
|
END as processingStatus, |
|
|
|
|
|
|
|
-- JoPickOrder second scan status |
|
|
|
jpo.second_qr_scan_status as secondQrScanStatus, |
|
|
|
jpo.second_qr_scan_by as secondQrScanBy, |
|
|
|
jpo.second_qr_scan_qty as secondQrScanQty |
|
|
|
|
|
|
|
FROM fpsmsdb.pick_order po |
|
|
|
JOIN fpsmsdb.job_order jo ON jo.id = po.joId |
|
|
|
JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id |
|
|
|
JOIN fpsmsdb.items i ON i.id = pol.itemId |
|
|
|
LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = pol.uomId |
|
|
|
LEFT JOIN fpsmsdb.suggested_pick_lot spl ON pol.id = spl.pickOrderLineId |
|
|
|
LEFT JOIN fpsmsdb.inventory_lot_line ill ON spl.suggestedLotLineId = ill.id |
|
|
|
LEFT JOIN fpsmsdb.router r ON r.inventoryLotId = ill.id AND r.deleted = false |
|
|
|
LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId |
|
|
|
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId |
|
|
|
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ill.id AND sol.deleted = false |
|
|
|
LEFT JOIN fpsmsdb.jo_pick_order jpo ON jpo.pick_order_id = po.id AND jpo.item_id = pol.itemId |
|
|
|
WHERE po.deleted = false |
|
|
|
AND po.id = :pickOrderId |
|
|
|
AND pol.deleted = false |
|
|
|
AND po.status = 'COMPLETED' |
|
|
|
AND ill.deleted = false |
|
|
|
AND il.deleted = false |
|
|
|
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL) |
|
|
|
ORDER BY |
|
|
|
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END, |
|
|
|
COALESCE(r.index, 0) ASC, |
|
|
|
po.code ASC, |
|
|
|
i.code ASC, |
|
|
|
il.expiryDate ASC, |
|
|
|
il.lotNo ASC |
|
|
|
""".trimIndent() |
|
|
|
|
|
|
|
println("🔍 Executing SQL for Job Order pick order lot details: $sql") |
|
|
|
println("🔍 With parameters: pickOrderId = $pickOrderId") |
|
|
|
|
|
|
|
val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId)) |
|
|
|
|
|
|
|
println("Found ${results.size} lot details for pick order $pickOrderId") |
|
|
|
results |
|
|
|
} catch (e: Exception) { |
|
|
|
println("❌ Error in getCompletedJobOrderPickOrderLotDetails: ${e.message}") |
|
|
|
e.printStackTrace() |
|
|
|
emptyList() |
|
|
|
} |
|
|
|
} |
|
|
|
} |