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 b81ae5a..c2085c3 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 @@ -414,7 +414,14 @@ open class JoPickOrderService( val uom = pol.uom val lineId = pol.id!! val lineSuggestedLots = suggestedPickLots.filter { it.pickOrderLine?.id == pol.id } - + val jpo = joPickOrders.firstOrNull { it.itemId == item?.id } + println("jpo: $jpo") + val user = userService.find(jpo?.handledBy?:0L) + println("user: $user") + val handlerName = jpo?.handledBy?.let { uid -> + userService.find(uid).orElse(null)?.name + } + println("handlerName: $handlerName") // 构建 lots 数据 val lots = lineSuggestedLots.mapNotNull { spl -> val ill = spl.suggestedLotLine @@ -428,7 +435,10 @@ open class JoPickOrderService( it.pickOrderLine?.id == pol.id && it.inventoryLotLine?.id == ill.id } val jpo = joPickOrders.firstOrNull { it.itemId == item?.id } - + val handlerName = jpo?.handledBy?.let { uid -> + userService.find(uid).orElse(null)?.name + } + println("handlerName: $handlerName") val availableQty = if (sol?.status == "rejected") { null } else { @@ -490,7 +500,8 @@ open class JoPickOrderService( uomCode = uom?.code, uomDesc = uom?.udfudesc, status = pol.status?.value, - lots = lots + lots = lots, + handler = handlerName ) } @@ -536,273 +547,194 @@ open class JoPickOrderService( } // Get completed job order pick orders (for second tab) // Fix the getCompletedJobOrderLotsHierarchical method -open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map { - println("=== Debug: getCompletedJobOrderLotsHierarchical ===") - println("today: ${LocalDate.now()}") - println("userId filter: $userId") + open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map { + println("=== Debug: getCompletedJobOrderLotsHierarchical (repo version) ===") + println("today: ${LocalDate.now()}") + println("userId filter: $userId") - // Get all COMPLETED pick orders assigned to the user with joId - val user = userService.find(userId).orElse(null) - if (user == null) { - println("❌ User not found: $userId") - return emptyMap() - } + val user = userService.find(userId).orElse(null) + if (user == null) { + println("❌ User not found: $userId") + return mapOf("pickOrder" to null, "pickOrderLines" to emptyList>()) + } - // 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("🔍 DEBUG: Found ${completedPickOrders.size} completed job order pick orders assigned to user $userId") - - val visiblePickOrders = completedPickOrders + // 1. 找出当前用户所有 COMPLETED 的 JO pick order + val completedPickOrders = pickOrderRepository + .findAllByAssignToIdAndStatusIn(userId, listOf(PickOrderStatus.COMPLETED)) + .filter { it.jobOrder != null } - if (visiblePickOrders.isEmpty()) { - println("🔍 DEBUG: No visible completed job orders found") - return mapOf( - "pickOrder" to null as Any?, - "pickOrderLines" to emptyList>() as Any? - ) - } + println("🔍 DEBUG: Found ${completedPickOrders.size} completed job order pick orders assigned to user $userId") - // For completed orders, show the latest one - val latestCompletedOrder = visiblePickOrders.maxByOrNull { - it.completeDate ?: it.modified ?: LocalDateTime.MIN - } + if (completedPickOrders.isEmpty()) { + return mapOf("pickOrder" to null, "pickOrderLines" to emptyList>()) + } - if (latestCompletedOrder == null) { - println("🔍 DEBUG: No latest completed order found") - return mapOf( - "pickOrder" to null as Any?, - "pickOrderLines" to emptyList>() as Any? - ) - } + // 2. 取最新的一张 + val latestCompletedOrder = completedPickOrders.maxByOrNull { + it.completeDate ?: it.modified ?: LocalDateTime.MIN + } ?: return mapOf("pickOrder" to null, "pickOrderLines" to emptyList>()) - println("🔍 DEBUG: Using latest completed order: ${latestCompletedOrder.code}") + println("🔍 DEBUG: Using latest completed order: ${latestCompletedOrder.code}") - // Use the same SQL query approach as getAllJobOrderLotsWithDetailsHierarchical - val pickOrderIds = listOf(latestCompletedOrder.id!!) - val pickOrderIdsStr = pickOrderIds.joinToString(",") + val pickOrder = latestCompletedOrder + val jobOrder = pickOrder.jobOrder!! - 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, - 'jo' as pickOrderType, - po.status as pickOrderStatus, - po.assignTo as pickOrderAssignTo, - - -- 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 - w.`order` as routerIndex, - w.code as routerRoute, - w.code as routerArea, - 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, - COALESCE(spl.suggestedLotLineId, ill.id) as debugSuggestedLotLineId, - ill.inventoryLotId as debugInventoryLotId, - - -- 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.match_status as match_status, - jpo.match_by as match_by, - jpo.match_qty as match_qty - - 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.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 IN ($pickOrderIdsStr) - AND pol.deleted = false - AND po.status = 'COMPLETED' - AND po.assignTo = :userId - AND ill.deleted = false - AND il.deleted = false - AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL) - AND (jpo.match_status = 'pending' OR jpo.match_status = 'scanned') - ORDER BY - CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END, - COALESCE(w.`order`, 999999) ASC, - po.code ASC, - i.code ASC, - il.expiryDate ASC, - il.lotNo ASC - """.trimIndent() + // 3. 组装 pickOrder 信息 + val pickOrderInfo = mapOf( + "id" to pickOrder.id, + "code" to pickOrder.code, + "consoCode" to pickOrder.consoCode, + "targetDate" to pickOrder.targetDate?.let { + "${it.year}-${"%02d".format(it.monthValue)}-${"%02d".format(it.dayOfMonth)}" + }, + "type" to "jo", + "status" to pickOrder.status?.value, + "assignTo" to pickOrder.assignTo?.id, + "jobOrder" to mapOf( + "id" to jobOrder.id, + "code" to jobOrder.code, + "name" to "Job Order ${jobOrder.code}" + ) + ) - println("🔍 Executing SQL for completed job order hierarchical structure: $sql") - println("🔍 With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") + // 4. 找出所有 pick order line + val pickOrderLines = pickOrderLineRepository + .findAllByPickOrderId(pickOrder.id!!) + .filter { it.deleted == false } - // Execute SQL query and build hierarchical structure - try { - val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) - - if (results.isEmpty()) { - return mapOf( - "pickOrder" to null as Any?, - "pickOrderLines" to emptyList>() as Any? - ) + if (pickOrderLines.isEmpty()) { + return mapOf("pickOrder" to pickOrderInfo, "pickOrderLines" to emptyList>()) } - - // Build hierarchical structure - val pickOrderInfo = results.firstOrNull()?.let { firstRow: Map -> - mapOf( - "id" to firstRow["pickOrderId"], - "code" to firstRow["pickOrderCode"], - "consoCode" to firstRow["pickOrderConsoCode"], - "targetDate" to firstRow["pickOrderTargetDate"], - "type" to firstRow["pickOrderType"], - "status" to firstRow["pickOrderStatus"], - "assignTo" to firstRow["pickOrderAssignTo"], - "jobOrder" to mapOf( - "id" to firstRow["jobOrderId"], - "code" to firstRow["jobOrderCode"], - "name" to "Job Order ${firstRow["jobOrderCode"]}" + + val pickOrderLineIds = pickOrderLines.mapNotNull { it.id } + + // 5. 建议拣货 lot + val suggestedPickLots = if (pickOrderLineIds.isNotEmpty()) { + suggestPickLotRepository + .findAllByPickOrderLineIdIn(pickOrderLineIds) + .filter { it.deleted == false } + } else emptyList() + + val inventoryLotLineIds = suggestedPickLots.mapNotNull { it.suggestedLotLine?.id } + + val inventoryLotLines = if (inventoryLotLineIds.isNotEmpty()) { + inventoryLotLineRepository + .findAllByIdIn(inventoryLotLineIds) + .filter { it.deleted == false } + } else emptyList() + + val inventoryLotIds = inventoryLotLines.mapNotNull { it.inventoryLot?.id }.distinct() + val inventoryLots = if (inventoryLotIds.isNotEmpty()) { + inventoryLotRepository + .findAllByIdIn(inventoryLotIds) + .filter { it.deleted == false } + } else emptyList() + + // 6. stock_out_line(含所有状态) + val stockOutLines = if (pickOrderLineIds.isNotEmpty() && inventoryLotLineIds.isNotEmpty()) { + pickOrderLineIds.flatMap { polId -> + inventoryLotLineIds.flatMap { illId -> + stockOutLineRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(polId, illId) + } + } + } else emptyList() + + // 7. 对应的 jo_pick_order(用于 match_* 和 handler) + val joPickOrders = joPickOrderRepository.findByPickOrderId(pickOrder.id!!) + + // 8. 组装每一行 + lots + val pickOrderLinesResult = pickOrderLines.map { pol -> + val item = pol.item + val uom = pol.uom + val lineSuggestedLots = suggestedPickLots.filter { it.pickOrderLine?.id == pol.id } + + val jpo = joPickOrders.firstOrNull { it.itemId == item?.id } + val handlerName = jpo?.matchBy?.let { uid -> + userService.find(uid).orElse(null)?.name + } + + val lots = lineSuggestedLots.mapNotNull { spl -> + val ill = spl.suggestedLotLine ?: return@mapNotNull null + if (ill.deleted == true) return@mapNotNull null + + val il = ill.inventoryLot ?: return@mapNotNull null + if (il.deleted == true) return@mapNotNull null + + val warehouse = ill.warehouse + val sol = stockOutLines.firstOrNull { + it.pickOrderLine?.id == pol.id && it.inventoryLotLine?.id == ill.id + } + + val availableQty = if (sol?.status == "rejected") { + null + } else { + (ill.inQty ?: BigDecimal.ZERO) - + (ill.outQty ?: BigDecimal.ZERO) - + (ill.holdQty ?: BigDecimal.ZERO) + } + + val lotAvailability = when { + il.expiryDate != null && il.expiryDate!!.isBefore(LocalDate.now()) -> "expired" + sol?.status == "rejected" -> "rejected" + availableQty != null && availableQty <= BigDecimal.ZERO -> "insufficient_stock" + ill.status == InventoryLotLineStatus.UNAVAILABLE -> "status_unavailable" + else -> "available" + } + + val processingStatus = when (sol?.status) { + "completed" -> "completed" + "rejected" -> "rejected" + "created" -> "pending" + else -> "pending" + } + + mapOf( + "lotId" to ill.id, + "lotNo" to il.lotNo, + "expiryDate" to il.expiryDate?.let { + "${it.year}-${"%02d".format(it.monthValue)}-${"%02d".format(it.dayOfMonth)}" + }, + "location" to warehouse?.name, + "availableQty" to availableQty?.toDouble(), + "requiredQty" to (spl.qty?.toDouble() ?: 0.0), + "actualPickQty" to (sol?.qty ?: 0.0), + "processingStatus" to processingStatus, + "lotAvailability" to lotAvailability, + "pickOrderId" to pickOrder.id, + "pickOrderCode" to pickOrder.code, + "pickOrderConsoCode" to pickOrder.consoCode, + "pickOrderLineId" to pol.id, + "stockOutLineId" to sol?.id, + "stockOutLineStatus" to sol?.status, + "stockOutLineQty" to (sol?.qty ?: 0.0), + "routerIndex" to warehouse?.order, + "routerArea" to warehouse?.code, + "routerRoute" to warehouse?.code, + "uomShortDesc" to uom?.udfShortDesc, + "matchStatus" to jpo?.matchStatus?.value, + "matchBy" to jpo?.matchBy, + "matchQty" to jpo?.matchQty, + "handler" to handlerName ) - ) - } - - // Group by pick order line - val groupedByLine = results.groupBy { row: Map -> row["pickOrderLineId"] } - val pickOrderLines = groupedByLine.map { (lineId: Any?, lineRows: List>) -> - val firstLineRow = lineRows.first() + } + mapOf( - "id" to lineId, - "itemId" to firstLineRow["itemId"], - "itemCode" to firstLineRow["itemCode"], - "itemName" to firstLineRow["itemName"], - "requiredQty" to firstLineRow["pickOrderLineRequiredQty"], - "uomCode" to firstLineRow["uomCode"], - "uomDesc" to firstLineRow["uomDesc"], - "lots" to lineRows.map { row: Map -> - mapOf( - "lotId" to row["lotId"], - "lotNo" to row["lotNo"], - "expiryDate" to row["expiryDate"], - "location" to row["location"], - "availableQty" to row["availableQty"], - "requiredQty" to row["requiredQty"], - "actualPickQty" to row["actualPickQty"], - "processingStatus" to row["processingStatus"], - "lotAvailability" to row["lotAvailability"], - "pickOrderId" to row["pickOrderId"], - "pickOrderCode" to row["pickOrderCode"], - "suggestedPickLotId" to row["suggestedPickLotId"], - "stockOutLineQty" to row["stockOutLineQty"], - "pickOrderConsoCode" to row["pickOrderConsoCode"], - "pickOrderLineId" to row["pickOrderLineId"], - "stockOutLineId" to row["stockOutLineId"], - "stockOutLineStatus" to row["stockOutLineStatus"], - "routerIndex" to row["routerIndex"], - "routerArea" to row["routerArea"], - "routerRoute" to row["routerRoute"], - "uomShortDesc" to row["uomShortDesc"], - "matchStatus" to row["match_status"], - "matchBy" to row["match_by"], - "matchQty" to row["match_qty"] - ) - } + "id" to pol.id, + "itemId" to item?.id, + "itemCode" to item?.code, + "itemName" to item?.name, + "requiredQty" to pol.qty?.toDouble(), + "uomCode" to uom?.code, + "uomDesc" to uom?.udfudesc, + "handler" to handlerName, + "lots" to lots ) } - - return mapOf( - "pickOrder" to pickOrderInfo as Any?, - "pickOrderLines" to pickOrderLines as Any? - ) - - } catch (e: Exception) { - println("❌ Error executing completed Job Order SQL: ${e.message}") - e.printStackTrace() + return mapOf( - "pickOrder" to null as Any?, - "pickOrderLines" to emptyList>() as Any? + "pickOrder" to pickOrderInfo, + "pickOrderLines" to pickOrderLinesResult ) - } } // Get completed job order pick order records (for third tab) @@ -1310,40 +1242,35 @@ private fun generateIssueNoForJo(): String { return "SKO-${yearMonth}-${nextSequence.toString().padStart(3, '0')}" } -open fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(userId: Long): List> { +open fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(): 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 + // 1. 先找出所有 COMPLETED 的 JO pick order(不再依赖 assignTo / userId) + val completedPickOrders = pickOrderRepository + .findAllByStatusIn(listOf(PickOrderStatus.COMPLETED)) + .filter { it.jobOrder != null } // 只要有 jobOrder 的 - println("Found ${completedPickOrders.size} completed job order pick orders for user $userId") + println("Found ${completedPickOrders.size} completed job order pick orders (all users)") + // 2. 只保留「所有 item 的 second scan 都完成」的 pick order 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.matchStatus == JoPickOrderStatus.completed } - + val allSecondScanCompleted = joPickOrders.isNotEmpty() && + joPickOrders.all { it.matchStatus == 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)}" - }, + "pickOrderTargetDate" to pickOrder.targetDate, "pickOrderStatus" to pickOrder.status, - "completedDate" to pickOrder.completeDate?.let { - "${it.year}-${String.format("%02d", it.monthValue)}-${String.format("%02d", it.dayOfMonth)}" - }, + // ✅ 完成时间改用 jobOrder.planEnd + "completedDate" to jobOrder.planEnd, "jobOrderId" to jobOrder.id, "jobOrderCode" to jobOrder.code, "jobOrderName" to jobOrder.bom?.name, @@ -1537,30 +1464,25 @@ open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List> { - println("=== getCompletedJobOrderPickOrders ===") - println("userId: $userId") +open fun getCompletedJobOrderPickOrders(): List> { + println("=== getCompletedJobOrderPickOrders (no user filter) ===") return try { - // 修复:先查找所有 COMPLETED 状态的 job order pick orders(不限制 assignTo) - val allCompletedPickOrders = pickOrderRepository.findAllByStatusIn( - listOf(PickOrderStatus.COMPLETED) - ).filter { - it.jobOrder != null && // 只查找有 job order 的 - (it.assignTo?.id == userId || it.assignTo == null) // 分配给当前用户或未分配 - } - - println("Found ${allCompletedPickOrders.size} completed job order pick orders (including unassigned)") + // 1. 找出所有 COMPLETED 状态、且有关联 JobOrder 的 pick order(不再按 assignTo 过滤) + val allCompletedPickOrders = pickOrderRepository + .findAllByStatusIn(listOf(PickOrderStatus.COMPLETED)) + .filter { it.jobOrder != null } + println("Found ${allCompletedPickOrders.size} completed job order pick orders") + + // 2. 组装返回数据 val completedJobOrderPickOrders = allCompletedPickOrders.mapNotNull { pickOrder -> val jobOrder = pickOrder.jobOrder if (jobOrder != null) { - // Get JoPickOrder records for this pick order + // 对应的 JoPickOrder 记录(用于 second scan 状态统计) val joPickOrders = findByPickOrderId(pickOrder.id!!) - println("Pick Order ${pickOrder.code}: joPickOrders.size=${joPickOrders.size}") - // Calculate second scan completion status val secondScanCompleted = joPickOrders.isNotEmpty() && joPickOrders.all { it.matchStatus == JoPickOrderStatus.completed } @@ -1570,12 +1492,11 @@ open fun getCompletedJobOrderPickOrders(userId: Long): List> { "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)}" + "${it.year}-${"%02d".format(it.monthValue)}-${"%02d".format(it.dayOfMonth)}" }, "pickOrderStatus" to pickOrder.status, - "completedDate" to pickOrder.completeDate?.let { - "${it.year}-${String.format("%02d", it.monthValue)}-${String.format("%02d", it.dayOfMonth)}" - }, + // 完成时间:按你的需求用 jobOrder.planEnd + "completedDate" to jobOrder.planEnd, "jobOrderId" to jobOrder.id, "jobOrderCode" to jobOrder.code, "jobOrderName" to jobOrder.bom?.name, @@ -1944,7 +1865,10 @@ open fun getJobOrderLotsHierarchicalByPickOrderId(pickOrderId: Long): JobOrderLo val uom = pol.uom val lineId = pol.id!! val lineSuggestedLots = suggestedPickLots.filter { it.pickOrderLine?.id == pol.id } - + val jpo = joPickOrders.firstOrNull { it.itemId == item?.id } + val handlerName = jpo?.handledBy?.let { uid -> + userService.find(uid).orElse(null)?.name + } // 构建 lots 数据 val lots = lineSuggestedLots.mapNotNull { spl -> val ill = spl.suggestedLotLine @@ -1958,7 +1882,10 @@ open fun getJobOrderLotsHierarchicalByPickOrderId(pickOrderId: Long): JobOrderLo it.pickOrderLine?.id == pol.id && it.inventoryLotLine?.id == ill.id } val jpo = joPickOrders.firstOrNull { it.itemId == item?.id } - + val handlerName = jpo?.handledBy?.let { uid -> + userService.find(uid).orElse(null)?.name + } + println("handlerName: $handlerName") val availableQty = if (sol?.status == "rejected") { null } else { @@ -2019,7 +1946,8 @@ open fun getJobOrderLotsHierarchicalByPickOrderId(pickOrderId: Long): JobOrderLo uomCode = uom?.code, uomDesc = uom?.udfudesc, status = pol.status?.value, - lots = lots + lots = lots, + handler=handlerName ) } 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 778475c..3602c62 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 @@ -180,10 +180,12 @@ fun recordSecondScanIssue( ) 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-orders-with-completed-second-scan") + fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(): List> { + return joPickOrderService.getCompletedJobOrderPickOrdersWithCompletedSecondScan() } + */ @GetMapping("/completed-job-order-pick-order-lot-details/{pickOrderId}") fun getCompletedJobOrderPickOrderLotDetails(@PathVariable pickOrderId: Long): List> { return joPickOrderService.getCompletedJobOrderPickOrderLotDetails(pickOrderId) @@ -224,9 +226,9 @@ fun recordSecondScanIssue( } - @GetMapping("/completed-job-order-pick-orders-only/{userId}") - fun getCompletedJobOrderPickOrders(@PathVariable userId: Long): List> { - return joPickOrderService.getCompletedJobOrderPickOrders(userId) + @GetMapping("/completed-job-order-pick-orders-only") + fun getCompletedJobOrderPickOrders(): List> { + return joPickOrderService.getCompletedJobOrderPickOrders() } @GetMapping("/completed-job-order-pick-order-lot-details-completed-pick/{pickOrderId}") diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt index f2b9a07..3561e2d 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt @@ -89,7 +89,8 @@ data class PickOrderLineWithLotsResponse( val uomCode: String?, val uomDesc: String?, val status: String?, - val lots: List + val lots: List, + val handler: String? ) data class LotDetailResponse( diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt index fd205ca..e9a50d6 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt @@ -1121,7 +1121,7 @@ open class ProductProcessService( // 过滤掉已完成上架的 job order val jobOrder = jobOrderRepository.findById(response.jobOrderId ?: 0L).orElse(null) val stockInLineStatus = jobOrder?.stockInLines?.firstOrNull()?.status - stockInLineStatus != "completed" + stockInLineStatus != "completed" && jobOrder?.status != JobOrderStatus.PLANNING } }