From 3b3640635484556c21073a4ccc97686d38aa198c Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Mon, 29 Sep 2025 13:53:36 +0800 Subject: [PATCH] update --- .../jobOrder/service/JoPickOrderService.kt | 210 +++++++++++++++++- .../jobOrder/web/JobOrderController.kt | 8 + 2 files changed, 217 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt index 22369e1..49d7e31 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt @@ -1039,4 +1039,212 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse ) } } -} \ No newline at end of file +open fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(userId: Long): List> { + 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> { + 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() + } +} +} diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt index 95366d9..ae085b7 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt @@ -129,4 +129,12 @@ class JobOrderController( ) return joPickOrderService.recordSecondScanIssue(request) } + @GetMapping("/completed-job-order-pick-orders-with-completed-second-scan/{userId}") + fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(@PathVariable userId: Long): List> { + return joPickOrderService.getCompletedJobOrderPickOrdersWithCompletedSecondScan(userId) + } + @GetMapping("/completed-job-order-pick-order-lot-details/{pickOrderId}") + fun getCompletedJobOrderPickOrderLotDetails(@PathVariable pickOrderId: Long): List> { + return joPickOrderService.getCompletedJobOrderPickOrderLotDetails(pickOrderId) + } } \ No newline at end of file