From 446fcca384bcc14e46213a367f6d41bdf7b5fdcd Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Thu, 6 Nov 2025 16:25:38 +0800 Subject: [PATCH] update --- .../deliveryOrder/entity/DoPickOrder.kt | 2 +- .../entity/DoPickOrderLineRecord.kt | 6 +- .../deliveryOrder/entity/DoPickOrderRecord.kt | 2 +- .../entity/DoPickOrderRecordRepository.kt | 2 + .../service/DeliveryOrderService.kt | 50 +-- .../service/DoPickOrderAssignmentService.kt | 18 +- .../service/DoPickOrderCompletionService.kt | 20 +- .../service/DoPickOrderService.kt | 111 ++--- .../service/DoReleaseCoordinatorService.kt | 32 +- .../web/DeliveryOrderController.kt | 2 +- .../web/DoPickOrderController.kt | 2 +- .../jobOrder/service/JoPickOrderService.kt | 132 +++--- .../jobOrder/service/JobOrderService.kt | 8 +- .../jobOrder/web/JobOrderController.kt | 10 +- .../web/model/SecondScanIssueRequest.kt | 4 +- .../web/model/SecondScanSubmitRequest.kt | 4 +- .../pickOrder/entity/PickExecutionIssue.kt | 2 +- .../pickOrder/entity/TruckRepository.kt | 6 +- .../service/PickExecutionIssueService.kt | 100 ++--- .../pickOrder/service/PickOrderService.kt | 396 +++++++++--------- .../web/PickExecutionIssueController.kt | 2 +- .../productProcess/entity/ProductProcess.kt | 2 +- .../entity/ProductProcessLine.kt | 6 +- .../entity/ProductProcessLineRepository.kt | 2 + .../entity/ProductionProcessIssue.kt | 4 +- .../service/ProductProcessService.kt | 113 ++--- .../web/ProductProcessController.kt | 68 +-- .../web/model/SaveProductProcessRequest.kt | 16 +- .../stock/service/InventoryLotLineService.kt | 4 +- .../stock/service/StockOutLineService.kt | 14 +- .../stock/service/SuggestedPickLotService.kt | 144 +++---- .../stock/web/InventoryLotLineController.kt | 2 +- 32 files changed, 652 insertions(+), 634 deletions(-) diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt index d5f16f9..f7c20f9 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt @@ -46,7 +46,7 @@ class DoPickOrder { @Column(name = "ticket_release_time") var ticketReleaseTime: LocalDateTime? = null - // ✅ 新增字段声明 + // 新增字段声明 @Column(name = "ticketCompleteDateTime") var ticketCompleteDateTime: LocalDateTime? = null diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderLineRecord.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderLineRecord.kt index 8e71a87..ea28ebf 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderLineRecord.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderLineRecord.kt @@ -23,13 +23,13 @@ open class DoPickOrderLineRecord: BaseEntity() { @Column(name = "do_pick_order_id", length = 100) open var doPickOrderId: Long? = null - @Column(name = "pick_order_id") // ✅ 正确:普通列 + @Column(name = "pick_order_id") // 正确:普通列 open var pickOrderId: Long? = null - @Column(name = "do_order_id") // ✅ 正确:普通列 + @Column(name = "do_order_id") // 正确:普通列 open var doOrderId: Long? = null - @Column(name = "pick_order_code") // ✅ 正确:普通列 + @Column(name = "pick_order_code") // 正确:普通列 open var pickOrderCode: String? = null @Column(name = "delivery_order_code") diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt index 4594305..9912654 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt @@ -54,7 +54,7 @@ class DoPickOrderRecord { @Column(name = "handled_by") var handledBy: Long? = null - // ✅ 新增字段声明 + // 新增字段声明 @Column(name = "ticketCompleteDateTime") var ticketCompleteDateTime: LocalDateTime? = null diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt index d75e929..23f1269 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt @@ -10,9 +10,11 @@ import org.springframework.data.jpa.repository.Query import org.springframework.stereotype.Repository import java.io.Serializable import java.time.LocalDateTime +import java.time.LocalDate @Repository interface DoPickOrderRecordRepository : JpaRepository { fun findByPickOrderId(pickOrderId: Long): List fun findByTicketNoStartingWith(ticketPrefix: String): List + fun findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(storeId: String, requiredDeliveryDate: LocalDate, ticketStatus: List): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt index 7c6bba8..ccc4ff2 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt @@ -71,11 +71,11 @@ import com.ffii.fpsms.modules.stock.service.InventoryLotService import net.sf.jasperreports.engine.JasperPrintManager import net.sf.jasperreports.engine.JRPrintPage import com.ffii.fpsms.modules.stock.entity.SuggestPickLotRepository -import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService // ✅ 添加这行 +import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService // 添加这行 import com.ffii.fpsms.modules.deliveryOrder.web.models.* -import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssue // ✅ 添加 -import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository // ✅ 添加 -import com.ffii.fpsms.modules.pickOrder.entity.IssueCategory // ✅ 添加 +import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssue // 添加 +import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository // 添加 +import com.ffii.fpsms.modules.pickOrder.entity.IssueCategory // 添加 import com.ffii.fpsms.modules.pickOrder.entity.HandleStatus @Service open class DeliveryOrderService( @@ -310,7 +310,7 @@ open class DeliveryOrderService( return null } - // ✅ 新增方法2:获取 warehouse 的 code 字段(用于显示路由) + // 新增方法2:获取 warehouse 的 code 字段(用于显示路由) open fun getWarehouseCodeByItemId(itemId: Long): String? { val inventoryLots = inventoryLotService.findByItemId(itemId) if (inventoryLots.isNotEmpty()) { @@ -451,7 +451,7 @@ open class DeliveryOrderService( pickOrderRepository.saveAndFlush(pickOrderEntity) println("�� DEBUG: Assigned consoCode $consoCode to pick order ${createdPickOrder.id}") - // ✅ Debug: Check pick order lines + // Debug: Check pick order lines println("�� DEBUG: Pick order has ${pickOrderEntity.pickOrderLines?.size ?: 0} pick order lines") pickOrderEntity.pickOrderLines?.forEach { line -> println("🔍 DEBUG: Pick order line - Item ID: ${line.item?.id}, Qty: ${line.qty}") @@ -470,7 +470,7 @@ open class DeliveryOrderService( println("⚠️ WARNING: $insufficientCount items have insufficient stock (issues auto-created)") } - // ✅ Hold inventory quantities + // Hold inventory quantities val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn( saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id } ) @@ -486,7 +486,7 @@ open class DeliveryOrderService( } inventoryLotLineRepository.saveAll(inventoryLotLines) - // ✅ Create stock out record and pre-create stock out lines + // Create stock out record and pre-create stock out lines val stockOut = StockOut().apply { this.type = "do" this.consoPickOrderCode = consoCode @@ -495,7 +495,7 @@ open class DeliveryOrderService( } val savedStockOut = stockOutRepository.saveAndFlush(stockOut) - // ✅ Pre-create stock out lines for suggested lots + // Pre-create stock out lines for suggested lots saveSuggestedPickLots.forEach { lot -> val polId = lot.pickOrderLine?.id val illId = lot.suggestedLotLine?.id @@ -522,10 +522,10 @@ open class DeliveryOrderService( } } - // ✅ CREATE do_pick_order_record entries + // CREATE do_pick_order_record entries // 第 471-555 行附近 - 修复创建逻辑 -// ✅ CREATE do_pick_order_record entries +// CREATE do_pick_order_record entries val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) @@ -535,9 +535,9 @@ open class DeliveryOrderService( val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId") - // ✅ 移除提前返回,总是分析 items 分布 + // 移除提前返回,总是分析 items 分布 // 分析 DO order lines 中的 items 分布 - // ✅ 分析 items 来确定 storeId + // 分析 items 来确定 storeId val itemIds = deliveryOrder.deliveryOrderLines.mapNotNull { it.item?.id }.distinct() val inventoryQuery = """ SELECT @@ -560,7 +560,7 @@ open class DeliveryOrderService( println("🔍 DEBUG: Floor item count distribution: $floorItemCount") println("🔍 DEBUG: Total items: ${itemIds.size}, Items on 4F: ${floorItemCount["4F"] ?: 0}") -// ✅ 新逻辑:只有所有 items 都在 4F,才算 4F,否则算 2F +// 新逻辑:只有所有 items 都在 4F,才算 4F,否则算 2F val preferredFloor = if ((floorItemCount["4F"] ?: 0) == itemIds.size && (floorItemCount["2F"] ?: 0) == 0) { "4F" // 所有 items 都在 4F } else { @@ -569,7 +569,7 @@ open class DeliveryOrderService( println("🔍 DEBUG: Preferred floor: $preferredFloor (All items on 4F: ${preferredFloor == "4F"})") -// ✅ 查找 truck +// 查找 truck val truck = deliveryOrder.shop?.id?.let { shopId -> println("🔍 DEBUG: Looking for truck with shop ID: $shopId") val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) @@ -593,7 +593,7 @@ open class DeliveryOrderService( selectedTruck } -// ✅ 检查 truck 和 preferredFloor 是否匹配 +// 检查 truck 和 preferredFloor 是否匹配 val truckStoreId = truck?.storeId val expectedStoreId = when (preferredFloor) { "2F" -> 2 @@ -608,9 +608,9 @@ open class DeliveryOrderService( throw IllegalStateException(errorMsg) // 或返回错误响应 } - println("✅ DEBUG: Truck matches preferred floor - Truck Store: $truckStoreId, Preferred: $preferredFloor") + println(" DEBUG: Truck matches preferred floor - Truck Store: $truckStoreId, Preferred: $preferredFloor") - // ✅ storeId 基于 items 的 preferredFloor + // storeId 基于 items 的 preferredFloor val storeId = "$preferredFloor/F" val loadingSequence = truck.loadingSequence ?: 999 @@ -922,12 +922,12 @@ open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDo val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.id) ?: throw NoSuchElementException("Delivery Order not found") - // ✅ 检查状态,跳过已完成或已发布的DO + // 检查状态,跳过已完成或已发布的DO if (deliveryOrder.status == DeliveryOrderStatus.COMPLETED || deliveryOrder.status == DeliveryOrderStatus.RECEIVING) { throw IllegalStateException("Delivery Order ${deliveryOrder.id} is already ${deliveryOrder.status?.value}, skipping release") } - // ✅ 更新状态为released (使用RECEIVING表示已发布) + // 更新状态为released (使用RECEIVING表示已发布) deliveryOrder.apply { status = DeliveryOrderStatus.RECEIVING // 使用RECEIVING表示已发布状态 } @@ -1004,7 +1004,7 @@ open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDo this.pickOrderLine = pickOrderLine this.inventoryLotLine = inventoryLotLine // 可能为 null this.item = pickOrderLine.item - // ✅ 修复:根据是否有 inventoryLotLine 设置状态 + // 修复:根据是否有 inventoryLotLine 设置状态 this.status = if (inventoryLotLine == null) { StockOutLineStatus.PARTIALLY_COMPLETE.status // 没有库存批次时使用 PARTIALLY_COMPLETE } else { @@ -1046,7 +1046,7 @@ open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDo "2F" } - // ✅ 查找匹配 preferred floor 的 truck + // 查找匹配 preferred floor 的 truck val truck = deliveryOrder.shop?.id?.let { shopId -> val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) val preferredStoreId = when (preferredFloor) { @@ -1065,14 +1065,14 @@ open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDo } } - // ✅ 如果没有匹配的 truck,抛出异常跳过 + // 如果没有匹配的 truck,抛出异常跳过 if (truck == null) { val errorMsg = "No matching truck found for preferredFloor ($preferredFloor). Skipping DO ${deliveryOrder.id}." println("⚠️ $errorMsg") throw IllegalStateException(errorMsg) } - println("✅ DEBUG: Matched truck - ID=${truck.id}, Store=${truck.storeId}, Floor=$preferredFloor") + println(" DEBUG: Matched truck - ID=${truck.id}, Store=${truck.storeId}, Floor=$preferredFloor") return ReleaseDoResult( deliveryOrderId = deliveryOrder.id!!, @@ -1087,7 +1087,7 @@ open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDo truckId = truck.id, truckDepartureTime = truck.departureTime, truckLanceCode = truck.truckLanceCode, - loadingSequence = truck.loadingSequence // ✅ 直接使用 truck 的值 + loadingSequence = truck.loadingSequence // 直接使用 truck 的值 ) } diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderAssignmentService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderAssignmentService.kt index b467c7d..c861ae4 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderAssignmentService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderAssignmentService.kt @@ -20,7 +20,7 @@ class DoPickOrderAssignmentService( private val doPickOrderRecordRepository: DoPickOrderRecordRepository, private val pickOrderRepository: PickOrderRepository, private val userRepository: UserRepository, - private val jdbcDao: JdbcDao // ✅ 添加 JdbcDao + private val jdbcDao: JdbcDao // 添加 JdbcDao ) { fun assignByLane(request: AssignByLaneRequest): MessageResponse { @@ -30,7 +30,7 @@ class DoPickOrderAssignmentService( message = "User not found", errorPosition = null, entity = null ) - // ✅ 转换 storeId 格式 + // 转换 storeId 格式 val actualStoreId = when (request.storeId) { "2/F" -> "2/F" "4/F" -> "4/F" @@ -38,11 +38,11 @@ class DoPickOrderAssignmentService( } println("🔍 DEBUG: assignByLane - Converting storeId from '${request.storeId}' to '$actualStoreId'") - // ✅ 获取日期(如果提供) + // 获取日期(如果提供) val requiredDate = request.requiredDate println("🔍 DEBUG: assignByLane - Requested date: $requiredDate") - // ✅ 根据是否有日期参数选择不同的查询方法 + // 根据是否有日期参数选择不同的查询方法 val allCandidates = if (requiredDate != null) { println("🔍 DEBUG: Filtering by date: $requiredDate") doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn( @@ -62,7 +62,7 @@ class DoPickOrderAssignmentService( println("🔍 DEBUG: Found ${allCandidates.size} candidate do_pick_orders for lane ${request.truckLanceCode}") - // ✅ 过滤掉所有 pick orders 都是 issue 的记录 + // 过滤掉所有 pick orders 都是 issue 的记录 val filteredCandidates = allCandidates.filter { doPickOrder -> val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) if (!hasNonIssueLines) { @@ -83,14 +83,14 @@ class DoPickOrderAssignmentService( val firstOrder = filteredCandidates.first() - // ✅ 更新 do_pick_order + // 更新 do_pick_order firstOrder.handledBy = request.userId firstOrder.handlerName = user.name firstOrder.ticketStatus = DoPickOrderStatus.released firstOrder.ticketReleaseTime = LocalDateTime.now() doPickOrderRepository.save(firstOrder) - // ✅ 获取这个 do_pick_order 下的所有 pick orders 并分配给用户 + // 获取这个 do_pick_order 下的所有 pick orders 并分配给用户 val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(firstOrder.id!!) println("🔍 DEBUG: Found ${doPickOrderLines.size} pick orders in do_pick_order ${firstOrder.id}") @@ -108,7 +108,7 @@ class DoPickOrderAssignmentService( } } - // ✅ 同步更新 do_pick_order_record(如果有的话) + // 同步更新 do_pick_order_record(如果有的话) doPickOrderLines.forEach { line -> if (line.pickOrderId != null) { val records = doPickOrderRecordRepository.findByPickOrderId(line.pickOrderId!!) @@ -141,7 +141,7 @@ class DoPickOrderAssignmentService( ) } - // ✅ 添加过滤方法(和 DoPickOrderQueryService 中相同的逻辑) + // 添加过滤方法(和 DoPickOrderQueryService 中相同的逻辑) private fun checkDoPickOrderHasNonIssueLines(doPickOrderId: Long): Boolean { return try { val totalLinesSql = """ diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderCompletionService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderCompletionService.kt index 8ec3105..6ce1977 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderCompletionService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderCompletionService.kt @@ -25,14 +25,14 @@ open class DoPickOrderCompletionService( } val savedDoPickOrders = doPickOrderRepository.saveAll(doPickOrders) - // ✅ 同步更新相关的delivery_order状态 + // 同步更新相关的delivery_order状态 savedDoPickOrders.forEach { doPickOrder -> if (doPickOrder.doOrderId != null) { val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(doPickOrder.doOrderId!!) if (deliveryOrder != null && deliveryOrder.status != DeliveryOrderStatus.COMPLETED) { deliveryOrder.status = DeliveryOrderStatus.COMPLETED deliveryOrderRepository.save(deliveryOrder) - println("✅ Updated delivery order ${doPickOrder.doOrderId} status to completed") + println(" Updated delivery order ${doPickOrder.doOrderId} status to completed") } } } @@ -46,7 +46,7 @@ open class DoPickOrderCompletionService( var deletedCount = 0 doPickOrders.forEach { doPickOrder -> - // ✅ 第一步:复制 do_pick_order 到 do_pick_order_record + // 第一步:复制 do_pick_order 到 do_pick_order_record val doPickOrderRecord = DoPickOrderRecord( storeId = doPickOrder.storeId ?: "", @@ -70,9 +70,9 @@ open class DoPickOrderCompletionService( requiredDeliveryDate = doPickOrder.requiredDeliveryDate ) val savedRecord = doPickOrderRecordRepository.save(doPickOrderRecord) - println("✅ Copied do_pick_order ${doPickOrder.id} to do_pick_order_record") + println(" Copied do_pick_order ${doPickOrder.id} to do_pick_order_record") - // ✅ 第二步:复制 do_pick_order_line 到 do_pick_order_line_record + // 第二步:复制 do_pick_order_line 到 do_pick_order_line_record val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrder.id!!) doPickOrderLines.forEach { line -> val doPickOrderLineRecord = DoPickOrderLineRecord() @@ -83,19 +83,19 @@ open class DoPickOrderCompletionService( doPickOrderLineRecord.deliveryOrderCode = line.deliveryOrderCode doPickOrderLineRecord.status = line.status doPickOrderLineRecordRepository.save(doPickOrderLineRecord) - println("✅ Copied do_pick_order_line ${line.id} to do_pick_order_line_record") + println(" Copied do_pick_order_line ${line.id} to do_pick_order_line_record") } - // ✅ 第三步:删除原始的 do_pick_order_line 记录 + // 第三步:删除原始的 do_pick_order_line 记录 if (doPickOrderLines.isNotEmpty()) { doPickOrderLineRepository.deleteAll(doPickOrderLines) - println("✅ Deleted ${doPickOrderLines.size} do_pick_order_line records") + println(" Deleted ${doPickOrderLines.size} do_pick_order_line records") } - // ✅ 第四步:删除原始的 do_pick_order 记录 + // 第四步:删除原始的 do_pick_order 记录 doPickOrderRepository.delete(doPickOrder) deletedCount++ - println("✅ Deleted do_pick_order ${doPickOrder.id}") + println(" Deleted do_pick_order ${doPickOrder.id}") } return deletedCount diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt index c2c8272..e9f6c40 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt @@ -33,7 +33,7 @@ import java.time.LocalDateTime import com.ffii.fpsms.modules.deliveryOrder.web.models.AssignByStoreRequest import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecord import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository -import com.ffii.fpsms.modules.deliveryOrder.web.models.* // ✅ 导入 +import com.ffii.fpsms.modules.deliveryOrder.web.models.* // 导入 import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus import com.ffii.fpsms.modules.pickOrder.entity.TruckRepository @@ -52,7 +52,7 @@ open class DoPickOrderService( private val doPickOrderRecordRepository: DoPickOrderRecordRepository, private val userRepository: UserRepository, private val pickOrderRepository: PickOrderRepository, - private val jdbcDao: JdbcDao, // ✅ 添加这行 + private val jdbcDao: JdbcDao, // 添加这行 private val truckRepository: TruckRepository, private val doPickOrderLineRepository: DoPickOrderLineRepository, @Lazy private val deliveryOrderRepository: DeliveryOrderRepository, @@ -73,7 +73,7 @@ open class DoPickOrderService( } else { datePrefix } - // ✅ 修改搜索模式为新格式 + // 修改搜索模式为新格式 val searchPattern = "TI-${shortDatePrefix}-${sanitizedStoreId}-" // T-20250915-4F- val todayTickets = doPickOrderRepository.findByTicketNoStartingWith(searchPattern) println("🔍 DEBUG: Found ${todayTickets.size} existing tickets with prefix $searchPattern") @@ -81,7 +81,7 @@ open class DoPickOrderService( println("🔍 DEBUG: Existing ticket: ${ticket.ticketNo}, Status: ${ticket.ticketStatus}") } val nextNumber = (todayTickets.size + 1).toString().padStart(3, '0') - // ✅ 修改生成格式 + // 修改生成格式 val ticketNumber = "TI-${datePrefix}-${sanitizedStoreId}-${nextNumber}" // T-20250915-4F-001 println("🔍 DEBUG: Generated ticket number: $ticketNumber") return ticketNumber @@ -129,10 +129,10 @@ open class DoPickOrderService( ) } - // ✅ Updated method to set ticketReleaseTime when assigning order to user + // Updated method to set ticketReleaseTime when assigning order to user open fun updateHandledByForPickOrder(pickOrderId: Long, userId: Long): List { val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) - val user = userRepository.findById(userId).orElse(null) // ✅ 改用 orElse(null) + val user = userRepository.findById(userId).orElse(null) // 改用 orElse(null) val handlerName = user?.name ?: "Unknown" doPickOrders.forEach { it.handledBy = userId @@ -151,14 +151,14 @@ open class DoPickOrderService( } val savedDoPickOrders = doPickOrderRepository.saveAll(doPickOrders) - // ✅ 同步更新相关的delivery_order状态 + // 同步更新相关的delivery_order状态 savedDoPickOrders.forEach { doPickOrder -> if (doPickOrder.doOrderId != null) { val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(doPickOrder.doOrderId!!) if (deliveryOrder != null && deliveryOrder.status != DeliveryOrderStatus.COMPLETED) { deliveryOrder.status = DeliveryOrderStatus.COMPLETED deliveryOrderRepository.save(deliveryOrder) - println("✅ Updated delivery order ${doPickOrder.doOrderId} status to completed") + println(" Updated delivery order ${doPickOrder.doOrderId} status to completed") } } } @@ -166,15 +166,15 @@ open class DoPickOrderService( return savedDoPickOrders } - // ✅ New method to remove do_pick_order records when auto-assigning by store - // ✅ 修改方法:先复制记录到record表,再删除原记录 + // New method to remove do_pick_order records when auto-assigning by store + // 修改方法:先复制记录到record表,再删除原记录 @Transactional open fun removeDoPickOrdersForPickOrder(pickOrderId: Long): Int { val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) var deletedCount = 0 doPickOrders.forEach { doPickOrder -> - // ✅ 第一步:复制 do_pick_order 到 do_pick_order_record + // 第一步:复制 do_pick_order 到 do_pick_order_record val doPickOrderRecord = DoPickOrderRecord( recordId = doPickOrder.id, storeId = doPickOrder.storeId?: "", @@ -198,34 +198,34 @@ open class DoPickOrderService( requiredDeliveryDate = doPickOrder.requiredDeliveryDate ) val savedRecord = doPickOrderRecordRepository.save(doPickOrderRecord) - println("✅ Copied do_pick_order ${doPickOrder.id} to do_pick_order_record") + println(" Copied do_pick_order ${doPickOrder.id} to do_pick_order_record") - // ✅ 第二步:复制 do_pick_order_line 到 do_pick_order_line_record - // ✅ 第二步:复制 do_pick_order_line 到 do_pick_order_line_record + // 第二步:复制 do_pick_order_line 到 do_pick_order_line_record + // 第二步:复制 do_pick_order_line 到 do_pick_order_line_record val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrder.id!!) doPickOrderLines.forEach { line -> val doPickOrderLineRecord = DoPickOrderLineRecord() - doPickOrderLineRecord.recordId = line.id // ✅ 使用默认构造函数 - doPickOrderLineRecord.doPickOrderId = savedRecord.id // ✅ 设置属性 + doPickOrderLineRecord.recordId = line.id // 使用默认构造函数 + doPickOrderLineRecord.doPickOrderId = savedRecord.id // 设置属性 doPickOrderLineRecord.pickOrderId = line.pickOrderId doPickOrderLineRecord.doOrderId = line.doOrderId doPickOrderLineRecord.pickOrderCode = line.pickOrderCode doPickOrderLineRecord.deliveryOrderCode = line.deliveryOrderCode doPickOrderLineRecord.status = line.status doPickOrderLineRecordRepository.save(doPickOrderLineRecord) - println("✅ Copied do_pick_order_line ${line.id} to do_pick_order_line_record") + println(" Copied do_pick_order_line ${line.id} to do_pick_order_line_record") } - // ✅ 第三步:删除原始的 do_pick_order_line 记录 + // 第三步:删除原始的 do_pick_order_line 记录 if (doPickOrderLines.isNotEmpty()) { doPickOrderLineRepository.deleteAll(doPickOrderLines) - println("✅ Deleted ${doPickOrderLines.size} do_pick_order_line records") + println(" Deleted ${doPickOrderLines.size} do_pick_order_line records") } - // ✅ 第四步:删除原始的 do_pick_order 记录 + // 第四步:删除原始的 do_pick_order 记录 doPickOrderRepository.delete(doPickOrder) deletedCount++ - println("✅ Deleted do_pick_order ${doPickOrder.id}") + println(" Deleted do_pick_order ${doPickOrder.id}") } return deletedCount @@ -235,10 +235,10 @@ open class DoPickOrderService( return doPickOrderRecordRepository.save(record) } - // ✅ Add method to update DoPickOrderRecord status + // Add method to update DoPickOrderRecord status open fun updateRecordHandledByForPickOrder(pickOrderId: Long, userId: Long): List { val doPickOrderRecords = doPickOrderRecordRepository.findByPickOrderId(pickOrderId) - val user = userRepository.findById(userId).orElse(null) // ✅ 改用 orElse(null) + val user = userRepository.findById(userId).orElse(null) // 改用 orElse(null) val handlerName = user?.name ?: "Unknown" doPickOrderRecords.forEach { it.handledBy = userId @@ -249,12 +249,12 @@ open class DoPickOrderService( return doPickOrderRecordRepository.saveAll(doPickOrderRecords) } - // ✅ Add method to complete DoPickOrderRecord + // Add method to complete DoPickOrderRecord open fun completeDoPickOrderRecordsForPickOrder(pickOrderId: Long): List { val doPickOrderRecords = doPickOrderRecordRepository.findByPickOrderId(pickOrderId) doPickOrderRecords.forEach { it.ticketStatus = DoPickOrderStatus.completed - it.ticketCompleteDateTime = LocalDateTime.now() // ✅ 设置完成时间 + it.ticketCompleteDateTime = LocalDateTime.now() // 设置完成时间 } return doPickOrderRecordRepository.saveAll(doPickOrderRecords) } @@ -271,29 +271,32 @@ open class DoPickOrderService( } return doPickOrderRepository.saveAll(doPickOrders) } - open fun getSummaryByStore(storeId: String, requiredDate: LocalDate?): StoreLaneSummary { + fun getSummaryByStore(storeId: String, requiredDate: LocalDate?): StoreLaneSummary { val targetDate = requiredDate ?: LocalDate.now() println("🔍 DEBUG: Getting summary for store=$storeId, date=$targetDate") - // ✅ 修复格式转换:保持原始格式 val actualStoreId = when (storeId) { - "2/F" -> "2/F" // ✅ 保持原格式 - "4/F" -> "4/F" // ✅ 保持原格式 + "2/F" -> "2/F" + "4/F" -> "4/F" else -> storeId } - println("🔍 DEBUG: Using storeId: '$actualStoreId'") - // ✅ 直接查询 do_pick_order 表 val allRecords = doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn( actualStoreId, targetDate, listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released, DoPickOrderStatus.completed) ) - + + // 添加 finishedRecords 查询 + val finishedRecords = doPickOrderRecordRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn( + actualStoreId, + targetDate, + listOf(DoPickOrderStatus.completed) + ) + println("🔍 DEBUG: Found ${allRecords.size} records for date $targetDate") + println("🔍 DEBUG: Found ${finishedRecords.size} finished records for date $targetDate") - // ✅ 过滤掉所有 do_pick_order_line 都是 "issue" 状态的 shop - /* val filteredRecords = allRecords.filter { doPickOrder -> val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) if (!hasNonIssueLines) { @@ -301,19 +304,27 @@ open class DoPickOrderService( } hasNonIssueLines } - */ - // println("🔍 DEBUG: After filtering, ${filteredRecords.size} records remain") - // ✅ 使用过滤后的记录 - val grouped = allRecords.groupBy { it.truckDepartureTime to it.truckLanceCode } - .mapValues { (_, list) -> + println("🔍 DEBUG: After filtering, ${filteredRecords.size} records remain") + + val grouped = filteredRecords.groupBy { it.truckDepartureTime to it.truckLanceCode } + .mapValues { (key, list) -> + val (truckDepartureTime, truckLanceCode) = key + // 计算匹配的 finishedRecords 数量 + val matchingFinishedCount = finishedRecords.count { record -> + (record.truckDepartureTime == truckDepartureTime) && + (record.truckLanceCode == truckLanceCode) + } + println("🔍 DEBUG: Group key - truckDepartureTime: $truckDepartureTime, truckLanceCode: $truckLanceCode") + println("🔍 DEBUG: Found ${list.size} active records in this group") + println("🔍 DEBUG: Found $matchingFinishedCount finished records matching this group") LaneBtn( truckLanceCode = list.first().truckLanceCode ?: "", unassigned = list.count { it.handledBy == null }, - total = list.size + total = list.size + matchingFinishedCount // 添加 finishedRecords 计数 ) } - + val timeGroups = grouped.entries .groupBy { it.key.first } .mapValues { (_, entries) -> @@ -330,7 +341,7 @@ open class DoPickOrderService( lanes = lanes ) } - + return StoreLaneSummary(storeId = storeId, rows = timeGroups) } private fun checkDoPickOrderHasNonIssueLines(doPickOrderId: Long): Boolean { @@ -374,7 +385,7 @@ open class DoPickOrderService( return true // 出错时不过滤 } } - // ✅ 修复:把 assignByLane 移到类里面 + // 修复:把 assignByLane 移到类里面 open fun assignByLane(request: AssignByLaneRequest): MessageResponse { val user = userRepository.findById(request.userId).orElse(null) ?: return MessageResponse( @@ -382,10 +393,10 @@ open class DoPickOrderService( message = "User not found", errorPosition = null, entity = null ) - // ✅ 转换 storeId 格式:'2/F' -> '2F/F', '4/F' -> '4F/F' + // 转换 storeId 格式:'2/F' -> '2F/F', '4/F' -> '4F/F' val actualStoreId = when (request.storeId) { - "2/F" -> "2/F" // ✅ 保持原格式 - "4/F" -> "4/F" // ✅ 保持原格式 + "2/F" -> "2/F" // 保持原格式 + "4/F" -> "4/F" // 保持原格式 else -> request.storeId } println("🔍 DEBUG: assignByLane - Converting storeId from '${request.storeId}' to '$actualStoreId'") @@ -406,14 +417,14 @@ open class DoPickOrderService( val firstOrder = candidates.first() - // ✅ 更新 do_pick_order + // 更新 do_pick_order firstOrder.handledBy = request.userId firstOrder.handlerName = user.name firstOrder.ticketStatus = DoPickOrderStatus.released firstOrder.ticketReleaseTime = LocalDateTime.now() doPickOrderRepository.save(firstOrder) - // ✅ 关键修改:获取这个 do_pick_order 下的所有 pick orders 并分配给用户 + // 关键修改:获取这个 do_pick_order 下的所有 pick orders 并分配给用户 val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(firstOrder.id!!) println("🔍 DEBUG: Found ${doPickOrderLines.size} pick orders in do_pick_order ${firstOrder.id}") @@ -431,7 +442,7 @@ open class DoPickOrderService( } } - // ✅ 同步更新 do_pick_order_record(如果有的话) + // 同步更新 do_pick_order_record(如果有的话) doPickOrderLines.forEach { line -> if (line.pickOrderId != null) { val records = doPickOrderRecordRepository.findByPickOrderId(line.pickOrderId!!) @@ -588,4 +599,4 @@ open class DoPickOrderService( open fun getTicketReleaseTable(): List{ return doPickOrderRepository.findAllByDeletedFalseOrderByTicketReleaseTimeDesc() } -}// ✅ 类结束 \ No newline at end of file +}// 类结束 \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt index 60f02bf..727363f 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt @@ -183,7 +183,7 @@ class DoReleaseCoordinatorService( """.trimIndent() val rowsUpdated = jdbcDao.executeUpdate(updateSql, emptyMap()) - println("✅ Updated $rowsUpdated ticket numbers") + println(" Updated $rowsUpdated ticket numbers") } catch (e: Exception) { println("❌ Error updating ticket numbers: ${e.message}") e.printStackTrace() @@ -332,16 +332,16 @@ class DoReleaseCoordinatorService( """.trimIndent() - println("🔍 DEBUG: SQL length: ${sql.length} characters") // ✅ 添加这行 - println("🔍 DEBUG: SQL first 500 chars: ${sql.take(500)}") // ✅ 添加这行 + println("🔍 DEBUG: SQL length: ${sql.length} characters") // 添加这行 + println("🔍 DEBUG: SQL first 500 chars: ${sql.take(500)}") // 添加这行 val results = jdbcDao.queryForList(sql) - println("🔍 DEBUG: Results type: ${results.javaClass.name}") // ✅ 添加这行 - println("🔍 DEBUG: Results size: ${results.size}") // ✅ 添加这行 + println("🔍 DEBUG: Results type: ${results.javaClass.name}") // 添加这行 + println("🔍 DEBUG: Results size: ${results.size}") // 添加这行 if (results.isNotEmpty()) { - println("🔍 DEBUG: First result keys: ${results[0].keys}") // ✅ 添加这行 - println("🔍 DEBUG: First result: ${results[0]}") // ✅ 添加这行 + println("🔍 DEBUG: First result keys: ${results[0].keys}") // 添加这行 + println("🔍 DEBUG: First result: ${results[0]}") // 添加这行 } val sortedIds = results.mapNotNull { row -> @@ -359,7 +359,7 @@ class DoReleaseCoordinatorService( } } catch (e: Exception) { println("❌ ERROR: ${e.message}") - println("❌ ERROR Stack Trace:") // ✅ 添加这行 + println("❌ ERROR Stack Trace:") // 添加这行 e.printStackTrace() return ids } @@ -407,7 +407,7 @@ class DoReleaseCoordinatorService( } println("❌ DO $id skipped: ${e.message}") - // ✅ 调用 PickExecutionIssueService 创建 issue 记录 + // 调用 PickExecutionIssueService 创建 issue 记录 try { val issueCategory = when { e.message?.contains("Unable to find") == true && @@ -430,9 +430,9 @@ class DoReleaseCoordinatorService( println("⚠️ Failed to create issue for DO $id: ${issueException.message}") } } - } // ✅ forEach 循环在这里结束 + } // forEach 循环在这里结束 - // ✅ 第二步:按日期、楼层、店铺分组(在 forEach 之后) + // 第二步:按日期、楼层、店铺分组(在 forEach 之后) val sortedResults = releaseResults.sortedWith( compareBy( { it.estimatedArrivalDate }, @@ -444,7 +444,7 @@ class DoReleaseCoordinatorService( ) ) - // ✅ 然后按正确的顺序分组(保持排序后的顺序) + // 然后按正确的顺序分组(保持排序后的顺序) val grouped = sortedResults.groupBy { Triple(it.estimatedArrivalDate, it.preferredFloor, it.shopId) } @@ -468,7 +468,7 @@ class DoReleaseCoordinatorService( updateBatchTicketNumbers() } - println("✅ Batch completed: ${status.success.get()} success, ${status.failed.size} failed") + println(" Batch completed: ${status.success.get()} success, ${status.failed.size} failed") } catch (e: Exception) { println("❌ Batch release exception: ${e.javaClass.simpleName} - ${e.message}") @@ -511,7 +511,7 @@ class DoReleaseCoordinatorService( requiredDeliveryDate = first.estimatedArrivalDate ) - // ✅ 直接使用 doPickOrderRepository.save() 而不是 doPickOrderService.save() + // 直接使用 doPickOrderRepository.save() 而不是 doPickOrderService.save() val saved = doPickOrderRepository.save(doPickOrder) println("🔍 DEBUG: Saved DoPickOrder - ID: ${saved.id}, Ticket: ${saved.ticketNo}") @@ -524,7 +524,7 @@ class DoReleaseCoordinatorService( return@forEach // 跳过这个 } - // ✅ 先创建 DoPickOrderLine,然后检查库存问题 + // 先创建 DoPickOrderLine,然后检查库存问题 val line = DoPickOrderLine().apply { doPickOrderId = saved.id pickOrderId = result.pickOrderId @@ -537,7 +537,7 @@ class DoReleaseCoordinatorService( println("🔍 DEBUG: Created DoPickOrderLine for pick order ${result.pickOrderId}") } - // ✅ 现在检查整个 DoPickOrder 是否有库存问题 + // 现在检查整个 DoPickOrder 是否有库存问题 val hasStockIssues = checkPickOrderHasStockIssues(saved.id!!) if (hasStockIssues) { // 更新所有相关的 DoPickOrderLine 状态为 "issue" diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt index 2eb7873..635a574 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt @@ -180,7 +180,7 @@ class DeliveryOrderController( @PostMapping("/release") fun releaseDeliveryOrder(@RequestBody request: ReleaseDoRequest): MessageResponse { - // ✅ Simply pass the request directly - userId comes from frontend session + // Simply pass the request directly - userId comes from frontend session return deliveryOrderService.releaseDeliveryOrder(request) } diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt index cd89860..4ab0d6c 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt @@ -75,7 +75,7 @@ class DoPickOrderController( } @PostMapping("/assign-by-lane") fun assignByLane(@RequestBody request: AssignByLaneRequest): MessageResponse { - return doPickOrderAssignmentService.assignByLane(request) // ✅ 使用新的 Service + return doPickOrderAssignmentService.assignByLane(request) // 使用新的 Service } @PostMapping("/batch-release/async") 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 393b977..2b382d8 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 @@ -44,7 +44,7 @@ open class JoPickOrderService( return joPickOrderRecordRepository.save(record) } - // ✅ Update JoPickOrder status to released + // Update JoPickOrder status to released open fun updateHandledByForPickOrder(pickOrderId: Long, userId: Long): List { val joPickOrders = joPickOrderRepository.findByPickOrderId(pickOrderId) @@ -68,7 +68,7 @@ open class JoPickOrderService( } return joPickOrderRepository.saveAll(joPickOrders) } - // ✅ Complete JoPickOrder + // Complete JoPickOrder open fun completeJoPickOrdersForPickOrder(pickOrderId: Long): List { val joPickOrders = joPickOrderRepository.findByPickOrderId(pickOrderId) joPickOrders.forEach { @@ -78,7 +78,7 @@ open class JoPickOrderService( return joPickOrderRepository.saveAll(joPickOrders) } - // ✅ Update JoPickOrderRecord status to released + // Update JoPickOrderRecord status to released open fun updateRecordHandledByForPickOrder(pickOrderId: Long, userId: Long): List { val joPickOrderRecords = joPickOrderRecordRepository.findByPickOrderId(pickOrderId) @@ -103,7 +103,7 @@ open class JoPickOrderService( return joPickOrderRecordRepository.saveAll(joPickOrderRecords) } - // ✅ Complete JoPickOrderRecord + // Complete JoPickOrderRecord open fun completeJoPickOrderRecordsForPickOrder(pickOrderId: Long): List { val joPickOrderRecords = joPickOrderRecordRepository.findByPickOrderId(pickOrderId) joPickOrderRecords.forEach { @@ -113,17 +113,17 @@ open class JoPickOrderService( return joPickOrderRecordRepository.saveAll(joPickOrderRecords) } - // ✅ Find JoPickOrder records by pick order ID + // Find JoPickOrder records by pick order ID open fun findByPickOrderId(pickOrderId: Long): List { return joPickOrderRepository.findByPickOrderId(pickOrderId) } - // ✅ Find JoPickOrderRecord records by pick order ID + // Find JoPickOrderRecord records by pick order ID open fun findRecordsByPickOrderId(pickOrderId: Long): List { return joPickOrderRecordRepository.findByPickOrderId(pickOrderId) } - // ✅ Create JoPickOrder records for a pick order + // Create JoPickOrder records for a pick order @Transactional open fun createJoPickOrdersForPickOrder(pickOrderId: Long, itemIds: List): List { // Get pick order and item details @@ -155,7 +155,7 @@ open class JoPickOrderService( } return joPickOrderRepository.saveAll(joPickOrders) } - // ✅ Create JoPickOrderRecord records for a pick order + // Create JoPickOrderRecord records for a pick order @Transactional open fun createJoPickOrderRecordsForPickOrder(pickOrderId: Long, itemIds: List): List { // Get pick order and item details @@ -248,7 +248,7 @@ open class JoPickOrderService( ) } - // ✅ 修复:简化 SQL 查询,移除不存在的字段 + // 修复:简化 SQL 查询,移除不存在的字段 val pickOrderIdsStr = pickOrderIds.joinToString(",") val sql = """ @@ -286,7 +286,7 @@ open class JoPickOrderService( w.name as location, COALESCE(uc.udfudesc, 'N/A') as stockUnit, - -- ✅ Simplified Router Information using warehouse + -- Simplified Router Information using warehouse w.`order` as routerIndex, w.code as routerRoute, w.code as routerArea, @@ -363,7 +363,7 @@ open class JoPickOrderService( 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 -- ✅ 直接关联 warehouse + LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId -- 直接关联 warehouse 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 @@ -376,7 +376,7 @@ open class JoPickOrderService( 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(w.`order`, 999999) ASC, -- ✅ 使用 warehouse.order 排序 + COALESCE(w.`order`, 999999) ASC, -- 使用 warehouse.order 排序 po.code ASC, i.code ASC, il.expiryDate ASC, @@ -386,7 +386,7 @@ open class JoPickOrderService( println("🔍 Executing SQL for job order hierarchical structure: $sql") println("🔍 With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") - // ✅ 修复:直接执行 SQL 查询并构建分层结构 + // 修复:直接执行 SQL 查询并构建分层结构 try { val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) @@ -410,7 +410,7 @@ open class JoPickOrderService( "jobOrder" to mapOf( "id" to firstRow["jobOrderId"], "code" to firstRow["jobOrderCode"], - "name" to "Job Order ${firstRow["jobOrderCode"]}" // ✅ 使用生成的名称 + "name" to "Job Order ${firstRow["jobOrderCode"]}" // 使用生成的名称 ) ) } @@ -474,7 +474,7 @@ open class JoPickOrderService( } // Get completed job order pick orders (for second tab) - // ✅ Fix the getCompletedJobOrderLotsHierarchical method + // Fix the getCompletedJobOrderLotsHierarchical method open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map { println("=== Debug: getCompletedJobOrderLotsHierarchical ===") println("today: ${LocalDate.now()}") @@ -520,7 +520,7 @@ open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map { println("🔍 DEBUG: Using latest completed order: ${latestCompletedOrder.code}") - // ✅ Use the same SQL query approach as getAllJobOrderLotsWithDetailsHierarchical + // Use the same SQL query approach as getAllJobOrderLotsWithDetailsHierarchical val pickOrderIds = listOf(latestCompletedOrder.id!!) val pickOrderIdsStr = pickOrderIds.joinToString(",") @@ -657,7 +657,7 @@ open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map { println("🔍 Executing SQL for completed job order hierarchical structure: $sql") println("🔍 With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") - // ✅ Execute SQL query and build hierarchical structure + // Execute SQL query and build hierarchical structure try { val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) @@ -799,7 +799,7 @@ open fun getUnassignedJobOrderPickOrders(): List> { println("=== getUnassignedJobOrderPickOrders ===") return try { - // ✅ 修复:使用正确的 repository 方法 + // 修复:使用正确的 repository 方法 val unassignedPickOrders = pickOrderRepository.findAllByStatusAndAssignToIsNullAndDeletedFalse( com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus.RELEASED ).filter { pickOrder -> @@ -840,7 +840,7 @@ open fun getUnassignedJobOrderPickOrders(): List> { } } -// ✅ 修复:assignJobOrderPickOrderToUser 方法中的自引用问题 +// 修复:assignJobOrderPickOrderToUser 方法中的自引用问题 @Transactional open fun assignJobOrderPickOrderToUser(pickOrderId: Long, userId: Long): MessageResponse { println("=== assignJobOrderPickOrderToUser ===") @@ -874,7 +874,7 @@ open fun assignJobOrderPickOrderToUser(pickOrderId: Long, userId: Long): Message pickOrder.assignTo = userService.find(userId).orElse(null) pickOrderRepository.save(pickOrder) - // ✅ 修复:使用 this 而不是 joPickOrderService + // 修复:使用 this 而不是 joPickOrderService this.updateHandledByForPickOrder(pickOrderId, userId) this.updateRecordHandledByForPickOrder(pickOrderId, userId) MessageResponse( @@ -898,7 +898,7 @@ open fun assignJobOrderPickOrderToUser(pickOrderId: Long, userId: Long): Message ) } } - // ✅ Fix the updateMatchStatus method + // Fix the updateMatchStatus method open fun updateMatchStatus(pickOrderId: Long, itemId: Long, userId: Long, qty: Int): MessageResponse { try { println("=== Debug: updateMatchStatus ===") @@ -919,23 +919,23 @@ open fun assignJobOrderPickOrderToUser(pickOrderId: Long, userId: Long): Message val joPickOrderEntity = joPickOrder.get() - // ✅ 设置扫描状态和相关字段 + // 设置扫描状态和相关字段 joPickOrderEntity.matchStatus = JoPickOrderStatus.scanned joPickOrderEntity.matchBy = userId - joPickOrderEntity.matchQty = qty // ✅ 使用传递的 qty + joPickOrderEntity.matchQty = qty // 使用传递的 qty joPickOrderRepository.save(joPickOrderEntity) - // ✅ 同时更新 jo_pick_order_record + // 同时更新 jo_pick_order_record val joPickOrderRecord = joPickOrderRecordRepository.findByPickOrderIdAndItemId(pickOrderId, itemId) if (joPickOrderRecord.isPresent) { val recordEntity = joPickOrderRecord.get() recordEntity.matchStatus = JoPickOrderStatus.scanned recordEntity.matchBy = userId - recordEntity.matchQty = qty // ✅ 使用相同的 qty + recordEntity.matchQty = qty // 使用相同的 qty joPickOrderRecordRepository.save(recordEntity) } - println("✅ Updated match status: pickOrderId=$pickOrderId, itemId=$itemId, matchQty=$qty") + println(" Updated match status: pickOrderId=$pickOrderId, itemId=$itemId, matchQty=$qty") return MessageResponse( id = null, @@ -979,17 +979,17 @@ open fun submitSecondScanQty(request: SecondScanSubmitRequest): MessageResponse val joPickOrderEntity = joPickOrder.get() joPickOrderEntity.matchQty = request.qty.toInt() - // ✅ Set status to completed when submitting quantity + // Set status to completed when submitting quantity joPickOrderEntity.matchStatus = JoPickOrderStatus.completed - // ✅ 添加:如果 ticketCompleteTime 还没设置,现在设置(通常已经在拣货完成时设置了) + // 添加:如果 ticketCompleteTime 还没设置,现在设置(通常已经在拣货完成时设置了) if (joPickOrderEntity.ticketCompleteTime == null) { joPickOrderEntity.ticketCompleteTime = LocalDateTime.now() } joPickOrderRepository.save(joPickOrderEntity) - println("✅ Updated jo_pick_order: status=${joPickOrderEntity.matchStatus}, qty=${joPickOrderEntity.matchQty}, completeTime=${joPickOrderEntity.ticketCompleteTime}") + println(" Updated jo_pick_order: status=${joPickOrderEntity.matchStatus}, qty=${joPickOrderEntity.matchQty}, completeTime=${joPickOrderEntity.ticketCompleteTime}") return MessageResponse( id = null, @@ -1014,7 +1014,7 @@ open fun submitSecondScanQty(request: SecondScanSubmitRequest): MessageResponse } -// ✅ Fix the recordSecondScanIssue method +// Fix the recordSecondScanIssue method open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse { try { println("=== Debug: recordSecondScanIssue ===") @@ -1033,7 +1033,7 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse ) } - // ✅ Get pick order and pick order line details with item and lot information + // Get pick order and pick order line details with item and lot information val pickOrderDetails = jdbcDao.queryForList( """ SELECT @@ -1060,7 +1060,7 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse ) ) - // ✅ 修复:使用正确的变量名 pickOrderDetails + // 修复:使用正确的变量名 pickOrderDetails if (pickOrderDetails.isEmpty()) { return MessageResponse( id = null, @@ -1072,7 +1072,7 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse ) } - // ✅ 修复:使用正确的变量名 pickOrderDetails + // 修复:使用正确的变量名 pickOrderDetails val orderData = pickOrderDetails.first() val pickOrderCode = orderData["pickOrderCode"] as String? val pickOrderCreateDate = orderData["pickOrderCreateDate"]?.let { @@ -1086,7 +1086,7 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse BigDecimal(it.toString()) } - // ✅ 获取 suggested lot 信息(用于 lot_id, lot_no, store_location) + // 获取 suggested lot 信息(用于 lot_id, lot_no, store_location) val lotResults = jdbcDao.queryForList( """ SELECT @@ -1127,41 +1127,41 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse joPickOrderRepository.save(joPickOrderEntity) - // ✅ 生成 issueNo + // 生成 issueNo val issueNo = generateIssueNoForJo() - // ✅ Create pick execution issue with complete data - // ✅ Create pick execution issue with complete data + // Create pick execution issue with complete data + // Create pick execution issue with complete data val pickExecutionIssue = PickExecutionIssue( - id = null, // ✅ 1 - pickOrderId = request.pickOrderId, // ✅ 2 - pickOrderCode = pickOrderCode ?: "PI-${request.pickOrderId}", // ✅ 3 - pickOrderCreateDate = pickOrderCreateDate, // ✅ 4 - pickExecutionDate = LocalDate.now(), // ✅ 5 - pickOrderLineId = pickOrderLineId, // ✅ 6 - issueNo = issueNo, // ✅ 7 - issueCategory = IssueCategory.match_issue, // ✅ 8 - 因为这是 JO 的 match 问题 - itemId = request.itemId, // ✅ 9 - itemCode = itemCode, // ✅ 10 - itemDescription = itemName, // ✅ 11 - lotId = lotId, // ✅ 12 - lotNo = lotNo, // ✅ 13 - storeLocation = storeLocation, // ✅ 14 - requiredQty = requiredQty, // ✅ 15 - actualPickQty = request.qty.toBigDecimal(), // ✅ 16 - missQty = request.missQty.toBigDecimal(), // ✅ 17 - badItemQty = request.badItemQty.toBigDecimal(), // ✅ 18 - issueRemark = request.reason, // ✅ 19 - pickerName = pickerName, // ✅ 20 - handleStatus = HandleStatus.pending, // ✅ 21 - handleDate = null, // ✅ 22 - handledBy = null, // ✅ 23 - created = LocalDateTime.now(), // ✅ 24 - createdBy = request.createdBy.toString(), // ✅ 25 - version = 0, // ✅ 26 - modified = LocalDateTime.now(), // ✅ 27 - modifiedBy = null, // ✅ 28 - deleted = false // ✅ 29 + id = null, // 1 + pickOrderId = request.pickOrderId, // 2 + pickOrderCode = pickOrderCode ?: "PI-${request.pickOrderId}", // 3 + pickOrderCreateDate = pickOrderCreateDate, // 4 + pickExecutionDate = LocalDate.now(), // 5 + pickOrderLineId = pickOrderLineId, // 6 + issueNo = issueNo, // 7 + issueCategory = IssueCategory.match_issue, // 8 - 因为这是 JO 的 match 问题 + itemId = request.itemId, // 9 + itemCode = itemCode, // 10 + itemDescription = itemName, // 11 + lotId = lotId, // 12 + lotNo = lotNo, // 13 + storeLocation = storeLocation, // 14 + requiredQty = requiredQty, // 15 + actualPickQty = request.qty.toBigDecimal(), // 16 + missQty = request.missQty.toBigDecimal(), // 17 + badItemQty = request.badItemQty.toBigDecimal(), // 18 + issueRemark = request.reason, // 19 + pickerName = pickerName, // 20 + handleStatus = HandleStatus.pending, // 21 + handleDate = null, // 22 + handledBy = null, // 23 + created = LocalDateTime.now(), // 24 + createdBy = request.createdBy.toString(), // 25 + version = 0, // 26 + modified = LocalDateTime.now(), // 27 + modifiedBy = null, // 28 + deleted = false // 29 ) pickExecutionIssueRepository.save(pickExecutionIssue) diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt index 63b2f37..31d54ab 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt @@ -244,7 +244,7 @@ open class JobOrderService( pickOrderEntity.status = com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus.RELEASED pickOrderRepository.saveAndFlush(pickOrderEntity) - // ✅ 添加 suggested pick lots 创建逻辑 + // 添加 suggested pick lots 创建逻辑 val lines = pickOrderLineRepository.findAllByPickOrderId(pickOrderEntity.id!!) if (lines.isNotEmpty()) { val suggestions = suggestedPickLotService.suggestionForPickOrderLines( @@ -253,7 +253,7 @@ open class JobOrderService( val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) - // ✅ Hold inventory quantities + // Hold inventory quantities val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn( saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id } ) @@ -269,7 +269,7 @@ open class JobOrderService( } inventoryLotLineRepository.saveAll(inventoryLotLines) - // ✅ Create stock out record and pre-create stock out lines + // Create stock out record and pre-create stock out lines val stockOut = StockOut().apply { this.type = "job" this.consoPickOrderCode = consoCode @@ -278,7 +278,7 @@ open class JobOrderService( } val savedStockOut = stockOutRepository.saveAndFlush(stockOut) - // ✅ Pre-create stock out lines for suggested lots + // Pre-create stock out lines for suggested lots saveSuggestedPickLots.forEach { lot -> val polId = lot.pickOrderLine?.id val illId = lot.suggestedLotLine?.id 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 18f0b2a..189cf8e 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 @@ -134,8 +134,8 @@ class JobOrderController( @RequestBody data: Map ): MessageResponse { val request = SecondScanSubmitRequest( - pickOrderId = pickOrderId, // ✅ Use path variable - itemId = itemId, // ✅ Use path variable + pickOrderId = pickOrderId, // Use path variable + itemId = itemId, // Use path variable qty = (data["qty"] as Number).toDouble(), isMissing = data["isMissing"] as? Boolean ?: false, isBad = data["isBad"] as? Boolean ?: false @@ -150,10 +150,10 @@ fun recordSecondScanIssue( @RequestBody data: Map ): MessageResponse { val request = SecondScanIssueRequest( - pickOrderId = pickOrderId, // ✅ path 变量 - itemId = itemId, // ✅ path 变量 + pickOrderId = pickOrderId, // path 变量 + itemId = itemId, // path 变量 qty = (data["qty"] as Number).toDouble(), - // ✅ 新增:安全读取 missQty/badItemQty/type,默认 0/"match" + // 新增:安全读取 missQty/badItemQty/type,默认 0/"match" missQty = (data["missQty"] as? Number)?.toDouble() ?: 0.0, badItemQty = (data["badItemQty"] as? Number)?.toDouble() ?: 0.0, isMissing = data["isMissing"] as? Boolean ?: false, diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt index 936bd5d..8f5d4f6 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt @@ -4,8 +4,8 @@ data class SecondScanIssueRequest( val pickOrderId: Long, val itemId: Long, val qty: Double, // 这是 actual pick qty (verified qty) - val missQty: Double = 0.0, // ✅ 添加:单独的 miss qty - val badItemQty: Double = 0.0, // ✅ 添加:单独的 bad item qty + val missQty: Double = 0.0, // 添加:单独的 miss qty + val badItemQty: Double = 0.0, // 添加:单独的 bad item qty val isMissing: Boolean, val isBad: Boolean, val reason: String, diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanSubmitRequest.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanSubmitRequest.kt index 9c46e3e..30ee7bb 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanSubmitRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanSubmitRequest.kt @@ -4,9 +4,9 @@ import jakarta.validation.constraints.NotNull data class SecondScanSubmitRequest( @NotNull - val pickOrderId: Long, // ✅ Add missing property + val pickOrderId: Long, // Add missing property @NotNull - val itemId: Long, // ✅ Add missing property + val itemId: Long, // Add missing property @NotNull val qty: Double, val isMissing: Boolean = false, diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt index cefb95c..f904ca7 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt @@ -103,7 +103,7 @@ val doPickOrderId: Long? = null, @Column(name = "deleted", nullable = false) val deleted: Boolean = false ) { - // ✅ 添加默认构造函数 + // 添加默认构造函数 constructor() : this( pickOrderId = null, pickOrderCode = "", diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/TruckRepository.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/TruckRepository.kt index 3071714..b701482 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/TruckRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/TruckRepository.kt @@ -13,15 +13,15 @@ interface TruckRepository : AbstractRepository { @Query("SELECT t FROM Truck t WHERE t.shop.id = :shopId AND t.deleted = false ORDER BY t.id ASC") fun findFirstByShopIdAndDeletedFalse(@Param("shopId") shopId: Long): List - // ✅ 使用新的 TruckLanceCode 字段名 + // 使用新的 TruckLanceCode 字段名 @Query("SELECT t FROM Truck t WHERE t.truckLanceCode = :truckLanceCode AND t.deleted = false") fun findByTruckLanceCodeAndDeletedFalse(@Param("truckLanceCode") truckLanceCode: String): Truck? - // ✅ 按 ShopCode 查询 + // 按 ShopCode 查询 @Query("SELECT t FROM Truck t WHERE t.shopCode = :shopCode AND t.deleted = false") fun findByShopCodeAndDeletedFalse(@Param("shopCode") shopCode: String): List - // ✅ 按 Store_id 查询 + // 按 Store_id 查询 fun findByStoreIdAndDeletedFalse(storeId: Int): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt index 42fd4ae..040ff1a 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt @@ -5,7 +5,7 @@ import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssue import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository import com.ffii.fpsms.modules.stock.entity.StockOutLine -import com.ffii.fpsms.modules.pickOrder.entity.IssueCategory // ✅ 添加这行 +import com.ffii.fpsms.modules.pickOrder.entity.IssueCategory // 添加这行 import com.ffii.fpsms.modules.pickOrder.entity.HandleStatus import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository import com.ffii.fpsms.modules.stock.entity.InventoryLotLine @@ -70,15 +70,15 @@ open class PickExecutionIssueService( val pickOrder = pickOrderRepository.findById(request.pickOrderId).orElse(null) // 2. 创建 pick execution issue 记录 val pickExecutionIssue = PickExecutionIssue( - id = null, // ✅ 添加 id + id = null, // 添加 id pickOrderId = request.pickOrderId, pickOrderCode = request.pickOrderCode, pickOrderCreateDate = request.pickOrderCreateDate, pickExecutionDate = request.pickExecutionDate ?: LocalDate.now(), pickOrderLineId = request.pickOrderLineId, issueNo = generateIssueNo(), - joPickOrderId = pickOrder?.jobOrder?.id, // ✅ 添加 - doPickOrderId = if (pickOrder?.type?.value == "do") pickOrder.id else null, // ✅ 添加 + joPickOrderId = pickOrder?.jobOrder?.id, // 添加 + doPickOrderId = if (pickOrder?.type?.value == "do") pickOrder.id else null, // 添加 issueCategory = IssueCategory.valueOf( request.issueCategory ?: "lot_issue" ), @@ -93,16 +93,16 @@ open class PickExecutionIssueService( missQty = request.missQty, badItemQty = request.badItemQty, issueRemark = request.issueRemark, - pickerName = request.pickerName, // ✅ 确保从 request 中获取 - handleStatus = HandleStatus.pending, // ✅ 添加 - handleDate = null, // ✅ 添加 + pickerName = request.pickerName, // 确保从 request 中获取 + handleStatus = HandleStatus.pending, // 添加 + handleDate = null, // 添加 handledBy = request.handledBy, created = LocalDateTime.now(), createdBy = "system", - version = 0, // ✅ 添加 + version = 0, // 添加 modified = LocalDateTime.now(), modifiedBy = "system", - deleted = false // ✅ 添加 + deleted = false // 添加 ) val savedIssue = pickExecutionIssueRepository.save(pickExecutionIssue) @@ -139,7 +139,7 @@ open class PickExecutionIssueService( handleBothMissAndBadItem(request, missQty, badItemQty) } - // ✅ 修复:情况4: 有 miss item 的情况(无论 actualPickQty 是多少) + // 修复:情况4: 有 miss item 的情况(无论 actualPickQty 是多少) missQty > BigDecimal.ZERO -> { handleMissItemWithPartialPick(request, actualPickQty, missQty) } @@ -264,7 +264,7 @@ private fun checkAndCompletePickOrder(consoCode: String) { // 4. 如果所有行都完成或被拒绝,则完成 pick order if (unfinishedLines.isEmpty()) { - println("✅ All stock out lines completed or rejected, completing pick order...") + println(" All stock out lines completed or rejected, completing pick order...") // 4.1 更新 StockOut 状态 stockOut.status = StockOutStatus.COMPLETE.status @@ -281,7 +281,7 @@ private fun checkAndCompletePickOrder(consoCode: String) { println("Updated pick order line ${line.id} to COMPLETED") } pickOrderLineRepository.saveAll(pickOrderLines) - println("✅ Updated ${pickOrderLines.size} pick order lines to COMPLETED status") + println(" Updated ${pickOrderLines.size} pick order lines to COMPLETED status") // 4.3 获取所有受影响的 pick orders val pickOrderIds = pickOrderLines.mapNotNull { it.pickOrder?.id }.distinct() @@ -302,15 +302,15 @@ private fun checkAndCompletePickOrder(consoCode: String) { pickOrder.status = PickOrderStatus.COMPLETED pickOrder.completeDate = LocalDateTime.now() pickOrderRepository.save(pickOrder) - println("✅ Updated pick order ${pickOrder.code} to COMPLETED status") + println(" Updated pick order ${pickOrder.code} to COMPLETED status") // 4.5 处理 DO pick order 相关记录 try { val removedCount = doPickOrderService.removeDoPickOrdersForPickOrder(pickOrderId) - println("✅ Removed $removedCount do_pick_order records for completed pick order ${pickOrderId}") + println(" Removed $removedCount do_pick_order records for completed pick order ${pickOrderId}") doPickOrderService.completeDoPickOrderRecordsForPickOrder(pickOrderId) - println("✅ Updated do_pick_order_record status to COMPLETED for pick order ${pickOrderId}") + println(" Updated do_pick_order_record status to COMPLETED for pick order ${pickOrderId}") } catch (e: Exception) { println("⚠️ Error updating DO pick order records: ${e.message}") } @@ -330,7 +330,7 @@ private fun checkAndCompletePickOrder(consoCode: String) { } joPickOrderRecordRepository.saveAll(joPickOrderRecords) - println("✅ Set jo_pick_order ticketCompleteTime for pick order ${pickOrderId}") + println(" Set jo_pick_order ticketCompleteTime for pick order ${pickOrderId}") } catch (e: Exception) { println("⚠️ Error updating JO pick order records: ${e.message}") } @@ -346,7 +346,7 @@ private fun checkAndCompletePickOrder(consoCode: String) { } } // FPSMS-backend/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt -// ✅ 修复:处理有部分拣货但有 miss item 的情况 +// 修复:处理有部分拣货但有 miss item 的情况 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) private fun handleMissItemWithPartialPick(request: PickExecutionIssueRequest, actualPickQty: BigDecimal, missQty: BigDecimal) { println("=== HANDLING MISS ITEM WITH PARTIAL PICK (FIXED LOGIC) ===") @@ -358,16 +358,16 @@ private fun handleMissItemWithPartialPick(request: PickExecutionIssueRequest, ac val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null) if (inventoryLotLine != null) { - // ✅ 修复1:只处理已拣货的部分:更新 outQty + // 修复1:只处理已拣货的部分:更新 outQty val currentOutQty = inventoryLotLine.outQty ?: BigDecimal.ZERO val newOutQty = currentOutQty.add(actualPickQty) inventoryLotLine.outQty = newOutQty - // ✅ 修复2:Miss item 不减少 inQty,而是标记为 unavailable + // 修复2:Miss item 不减少 inQty,而是标记为 unavailable // 因为 miss item 意味着这些物品实际上不存在或找不到 // 所以应该标记整个批次为 unavailable,而不是减少 inQty - // ✅ 修复3:如果 missQty > 0,标记批次为 unavailable + // 修复3:如果 missQty > 0,标记批次为 unavailable if (missQty > BigDecimal.ZERO) { inventoryLotLine.status = InventoryLotLineStatus.UNAVAILABLE } @@ -381,11 +381,11 @@ private fun handleMissItemWithPartialPick(request: PickExecutionIssueRequest, ac println(" - Set status to UNAVAILABLE due to missQty: ${missQty}") } - // ✅ 修复4:更新 inventory 表的 unavailableQty + // 修复4:更新 inventory 表的 unavailableQty // 对于 miss item,应该将 missQty 计入 unavailableQty updateInventoryUnavailableQty(itemId, missQty) - // ✅ 修复5:更新 stock_out_line 状态为 rejected(因为还有 miss item) + // 修复5:更新 stock_out_line 状态为 rejected(因为还有 miss item) updateStockOutLineStatus(request, "rejected") // 重新建议拣货批次(针对 miss 的数量) @@ -397,7 +397,7 @@ private fun handleMissItemWithPartialPick(request: PickExecutionIssueRequest, ac } } -// ✅ 修复:Miss item 处理逻辑 +// 修复:Miss item 处理逻辑 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) private fun handleMissItemOnly(request: PickExecutionIssueRequest, missQty: BigDecimal) { println("=== HANDLING MISS ITEM ONLY (FIXED LOGIC) ===") @@ -408,7 +408,7 @@ private fun handleMissItemOnly(request: PickExecutionIssueRequest, missQty: BigD val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null) if (inventoryLotLine != null) { - // ✅ 修复:Miss item 意味着剩余的所有物品都找不到 + // 修复:Miss item 意味着剩余的所有物品都找不到 val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO val currentOutQty = inventoryLotLine.outQty ?: BigDecimal.ZERO val remainingQty = currentInQty.minus(currentOutQty) @@ -425,16 +425,16 @@ private fun handleMissItemOnly(request: PickExecutionIssueRequest, missQty: BigD println(" - Unavailable qty (should be remaining qty): ${remainingQty}") } - // ✅ 修复:更新 inventory 表的 unavailableQty + // 修复:更新 inventory 表的 unavailableQty // 应该是剩余的数量,而不是 missQty val currentInQty = inventoryLotLine?.inQty ?: BigDecimal.ZERO val currentOutQty = inventoryLotLine?.outQty ?: BigDecimal.ZERO val remainingQty = currentInQty.minus(currentOutQty) - // ✅ 修复:只增加剩余数量,不要重复计算 missQty + // 修复:只增加剩余数量,不要重复计算 missQty updateInventoryUnavailableQty(itemId, remainingQty) - // ✅ 修复:更新 stock_out_line 状态为 rejected + // 修复:更新 stock_out_line 状态为 rejected updateStockOutLineStatus(request, "rejected") // 重新建议拣货批次 @@ -446,7 +446,7 @@ private fun handleMissItemOnly(request: PickExecutionIssueRequest, missQty: BigD } } -// ✅ 修复:Bad item 处理逻辑 +// 修复:Bad item 处理逻辑 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) private fun handleBadItemOnly(request: PickExecutionIssueRequest, badItemQty: BigDecimal) { println("=== HANDLING BAD ITEM ONLY (FIXED LOGIC) ===") @@ -457,7 +457,7 @@ private fun handleBadItemOnly(request: PickExecutionIssueRequest, badItemQty: Bi val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null) if (inventoryLotLine != null) { - // ✅ 修复:Bad item 不减少 inQty,而是标记为 unavailable + // 修复:Bad item 不减少 inQty,而是标记为 unavailable // 因为 bad item 意味着这些物品质量有问题,不能使用 inventoryLotLine.status = InventoryLotLineStatus.UNAVAILABLE inventoryLotLine.modified = LocalDateTime.now() @@ -467,10 +467,10 @@ private fun handleBadItemOnly(request: PickExecutionIssueRequest, badItemQty: Bi println("Bad item only: Set lot ${lotId} status to UNAVAILABLE") } - // ✅ 修复:更新 inventory 表的 unavailableQty + // 修复:更新 inventory 表的 unavailableQty updateInventoryUnavailableQty(itemId, badItemQty) - // ✅ 修复:更新 stock_out_line 状态为 rejected + // 修复:更新 stock_out_line 状态为 rejected updateStockOutLineStatus(request, "rejected") // 重新建议拣货批次 @@ -482,7 +482,7 @@ private fun handleBadItemOnly(request: PickExecutionIssueRequest, badItemQty: Bi } } -// ✅ 修复:Both miss and bad item 处理逻辑 +// 修复:Both miss and bad item 处理逻辑 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty: BigDecimal, badItemQty: BigDecimal) { println("=== HANDLING BOTH MISS AND BAD ITEM (FIXED LOGIC) ===") @@ -494,7 +494,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty val totalUnavailableQty = missQty.add(badItemQty) if (inventoryLotLine != null) { - // ✅ 修复:Miss + Bad item 不减少 inQty,而是标记为 unavailable + // 修复:Miss + Bad item 不减少 inQty,而是标记为 unavailable inventoryLotLine.status = InventoryLotLineStatus.UNAVAILABLE inventoryLotLine.modified = LocalDateTime.now() inventoryLotLine.modifiedBy = "system" @@ -506,10 +506,10 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty println(" - Total Unavailable Qty: ${totalUnavailableQty}") } - // ✅ 修复:更新 inventory 表的 unavailableQty + // 修复:更新 inventory 表的 unavailableQty updateInventoryUnavailableQty(itemId, totalUnavailableQty) - // ✅ 修复:更新 stock_out_line 状态为 rejected + // 修复:更新 stock_out_line 状态为 rejected updateStockOutLineStatus(request, "rejected") // 重新建议拣货批次 @@ -521,19 +521,19 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty } } - // ✅ 修复:正常拣货处理逻辑 + // 修复:正常拣货处理逻辑 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) private fun handleNormalPick(request: PickExecutionIssueRequest, actualPickQty: BigDecimal) { println("=== HANDLING NORMAL PICK ===") - // ✅ 修复:更新 stock_out_line,但不要累积 qty + // 修复:更新 stock_out_line,但不要累积 qty val stockOutLines = stockOutLineRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse( request.pickOrderLineId, request.lotId ?: 0L ) stockOutLines.forEach { stockOutLine -> - // ✅ 修复:直接设置 qty 为 actualPickQty,不要累积 + // 修复:直接设置 qty 为 actualPickQty,不要累积 val requiredQty = request.requiredQty?.toDouble() ?: 0.0 val actualPickQtyDouble = actualPickQty.toDouble() val newStatus = if (actualPickQtyDouble >= requiredQty) { @@ -543,7 +543,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty } stockOutLine.status = newStatus - stockOutLine.qty = actualPickQtyDouble // ✅ 直接设置,不累积 + stockOutLine.qty = actualPickQtyDouble // 直接设置,不累积 stockOutLine.modified = LocalDateTime.now() stockOutLine.modifiedBy = "system" stockOutLineRepository.save(stockOutLine) @@ -551,11 +551,11 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty println("Updated stock out line ${stockOutLine.id}: status=${newStatus}, qty=${actualPickQtyDouble}") } - // ✅ 修复:更新 inventory_lot_line 的 outQty + // 修复:更新 inventory_lot_line 的 outQty val lotId = request.lotId ?: return val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null) if (inventoryLotLine != null) { - // ✅ 修复:计算新的 outQty,考虑之前的 outQty + // 修复:计算新的 outQty,考虑之前的 outQty val currentOutQty = inventoryLotLine.outQty ?: BigDecimal.ZERO val previousPickedQty = currentOutQty.minus(actualPickQty) // 计算之前已拣的数量 val newOutQty = previousPickedQty.add(actualPickQty) // 更新为新的总拣货数量 @@ -569,7 +569,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty } } - // ✅ 新方法:统一更新 inventory 表的 unavailableQty + // 新方法:统一更新 inventory 表的 unavailableQty private fun updateInventoryUnavailableQty(itemId: Long, unavailableQty: BigDecimal) { try { println("=== INVENTORY UNAVAILABLE QTY UPDATE (TRIGGER HANDLED) ===") @@ -582,7 +582,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty } } - // ✅ 修复:更新 stock_out_line 状态 + // 修复:更新 stock_out_line 状态 private fun updateStockOutLineStatus(request: PickExecutionIssueRequest, status: String) { val stockOutLines = stockOutLineRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse( request.pickOrderLineId, @@ -592,7 +592,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty stockOutLines.forEach { stockOutLine -> stockOutLine.status = status - // ✅ FIX: Update qty to actualPickQty before setting status to rejected + // FIX: Update qty to actualPickQty before setting status to rejected if (status == "rejected" && request.actualPickQty != null) { stockOutLine.qty = request.actualPickQty.toDouble() println("Updated stock out line ${stockOutLine.id} qty to: ${request.actualPickQty}") @@ -605,7 +605,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty println("Updated stock out line ${stockOutLine.id} status to: ${status}") } } - // ✅ 修复:使用 REQUIRES_NEW 传播级别,避免事务冲突 + // 修复:使用 REQUIRES_NEW 传播级别,避免事务冲突 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) private fun resuggestPickOrder(pickOrderId: Long?) { if (pickOrderId != null) { @@ -639,7 +639,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty "jo" -> { // Case 1: 只返回 Job Order 的 issues val joIssues = pickExecutionIssueRepository.findJoIssues() - println("✅ Finding JO issues: ${joIssues.size} records") + println(" Finding JO issues: ${joIssues.size} records") joIssues.forEach { println(" - ID=${it.id}, joPickOrderId=${it.joPickOrderId}, doPickOrderId=${it.doPickOrderId}") } @@ -648,7 +648,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty "do" -> { // Case 2: 只返回 Delivery Order 的 issues val doIssues = pickExecutionIssueRepository.findDoIssues() - println("✅ Finding DO issues: ${doIssues.size} records") + println(" Finding DO issues: ${doIssues.size} records") doIssues.forEach { println(" - ID=${it.id}, joPickOrderId=${it.joPickOrderId}, doPickOrderId=${it.doPickOrderId}") } @@ -657,7 +657,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty "material" -> { // Case 3: 只返回 Material 的 issues (普通 pick order) val materialIssues = pickExecutionIssueRepository.findMaterialIssues() - println("✅ Finding Material issues: ${materialIssues.size} records") + println(" Finding Material issues: ${materialIssues.size} records") materialIssues.forEach { println(" - ID=${it.id}, joPickOrderId=${it.joPickOrderId}, doPickOrderId=${it.doPickOrderId}") } @@ -666,7 +666,7 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty else -> { // Case 4: 返回所有 issues val allIssues = pickExecutionIssueRepository.findByDeletedFalse() - println("✅ Finding ALL issues: ${allIssues.size} records") + println(" Finding ALL issues: ${allIssues.size} records") allIssues } } @@ -772,7 +772,7 @@ open fun createBatchReleaseIssue( createdCount++ } - println("✅ Created $createdCount ${issueCategory.name} issues for DO $deliveryOrderId") + println(" Created $createdCount ${issueCategory.name} issues for DO $deliveryOrderId") return createdCount } catch (e: Exception) { diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt index 7bc79e6..a7af020 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt @@ -66,8 +66,8 @@ import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecord import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLine import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus -import com.ffii.fpsms.modules.stock.entity.SuggestPickLotRepository // ✅ 添加这行 -import com.ffii.fpsms.modules.stock.entity.projection.StockOutLineInfo // ✅ 添加这行 +import com.ffii.fpsms.modules.stock.entity.SuggestPickLotRepository // 添加这行 +import com.ffii.fpsms.modules.stock.entity.projection.StockOutLineInfo // 添加这行 import com.ffii.fpsms.modules.stock.entity.SuggestedPickLot @Service open class PickOrderService( @@ -94,7 +94,7 @@ open class PickOrderService( private val doPickOrderRecordRepository: DoPickOrderRecordRepository, private val doPickOrderRepository: DoPickOrderRepository, private val userRepository: UserRepository, - private val joPickOrderRepository: JoPickOrderRepository, // ✅ 添加这行 + private val joPickOrderRepository: JoPickOrderRepository, // 添加这行 private val joPickOrderRecordRepository: JoPickOrderRecordRepository, private val doPickOrderLineRepository: DoPickOrderLineRepository, @@ -708,7 +708,7 @@ open class PickOrderService( val suggestions = suggestedPickLotService.suggestionForPickOrders(SuggestedPickLotForPoRequest(pickOrders = pos)) - // ✅ Get stock out line data for each pick order line + // Get stock out line data for each pick order line val pickOrderLineIds = pos.flatMap { it.pickOrderLines }.mapNotNull { it.id } val stockOutLinesByPickOrderLineId = if (pickOrderLineIds.isNotEmpty()) { pickOrderLineIds.associateWith { pickOrderLineId -> @@ -718,7 +718,7 @@ open class PickOrderService( emptyMap() } - // ✅ Pre-calculate available quantities for each item ONCE + // Pre-calculate available quantities for each item ONCE val itemAvailableQtyMap = mutableMapOf() itemIds.forEach { itemId -> val inventory = inventories[itemId] @@ -738,10 +738,10 @@ open class PickOrderService( val itemId = pol.item?.id val availableQty = itemId?.let { itemAvailableQtyMap[it] } ?: zero - // ✅ Move stockOutLines declaration inside the pol loop + // Move stockOutLines declaration inside the pol loop val stockOutLines = stockOutLinesByPickOrderLineId[pol.id] ?: emptyList() - // ✅ Calculate total picked quantity from stock out lines + // Calculate total picked quantity from stock out lines println("=== PICKED QTY DEBUG: Line ${pol.id} ===") println("Stock Out Lines: ${stockOutLines.map { "${it.id}(status=${it.status}, qty=${it.qty})" }}") @@ -757,7 +757,7 @@ open class PickOrderService( itemId = pol.item?.id, itemCode = pol.item?.code, itemName = pol.item?.name, - availableQty = availableQty, // ✅ Use pre-calculated value + availableQty = availableQty, // Use pre-calculated value requiredQty = pol.qty, uomCode = pol.uom?.code, uomDesc = pol.uom?.udfudesc, @@ -810,7 +810,7 @@ open class PickOrderService( val allPickOrders = pickOrderRepository.findAll() val releasedPickOrderIds = allPickOrders .filter { it.status == PickOrderStatus.RELEASED } - .filter { userId == null || it.assignTo?.id == userId } // ✅ Fixed: now userId is a parameter + .filter { userId == null || it.assignTo?.id == userId } // Fixed: now userId is a parameter .map { it.id!! } println("All released pick order IDs for user $userId: $releasedPickOrderIds") @@ -843,19 +843,19 @@ open class PickOrderService( w.name as location, COALESCE(uc.udfudesc, 'N/A') as stockUnit, (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as availableQty, - COALESCE(spl.qty, 0) as requiredQty, -- ✅ 使用COALESCE处理null值 + COALESCE(spl.qty, 0) as requiredQty, -- 使用COALESCE处理null值 COALESCE(ill.inQty, 0) as inQty, COALESCE(ill.outQty, 0) as outQty, COALESCE(ill.holdQty, 0) as holdQty, COALESCE(sol.qty, 0) as actualPickQty, - COALESCE(spl.id, 0) as suggestedPickLotId, -- ✅ 使用COALESCE处理null值 + COALESCE(spl.id, 0) as suggestedPickLotId, -- 使用COALESCE处理null值 ill.status as lotStatus, sol.id as stockOutLineId, sol.status as stockOutLineStatus, sol.qty as stockOutLineQty, - COALESCE(spl.suggestedLotLineId, ill.id) as debugSuggestedLotLineId, -- ✅ 使用COALESCE处理null值 + COALESCE(spl.suggestedLotLineId, ill.id) as debugSuggestedLotLineId, -- 使用COALESCE处理null值 ill.inventoryLotId as debugInventoryLotId, - -- ✅ Calculate total picked quantity by ALL pick orders for this lot + -- Calculate total picked quantity by ALL pick orders for this lot COALESCE(( SELECT SUM(sol_all.qty) FROM fpsmsdb.stock_out_line sol_all @@ -863,24 +863,24 @@ open class PickOrderService( AND sol_all.deleted = false AND sol_all.status IN ('pending', 'checked', 'partially_completed', 'completed') ), 0) as totalPickedByAllPickOrders, - -- ✅ FIXED: Calculate remaining available quantity correctly + -- FIXED: Calculate remaining available quantity correctly (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as remainingAfterAllPickOrders, - -- ✅ Add detailed debug fields for lotAvailability calculation + -- Add detailed debug fields for lotAvailability calculation ill.status as debug_ill_status, (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) as debug_is_expired, sol.status as debug_sol_status, (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as debug_remaining_stock, (COALESCE(spl.qty, 0) - COALESCE(sol.qty, 0)) as debug_required_after_picked, CASE - -- ✅ FIXED: Check if lot is expired + -- FIXED: Check if lot is expired WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 'expired' - -- ✅ FIXED: Check if lot has rejected stock out line for this pick order + -- FIXED: Check if lot has rejected stock out line for this pick order WHEN sol.status = 'rejected' THEN 'rejected' - -- ✅ FIXED: Check if lot is unavailable due to insufficient stock + -- FIXED: Check if lot is unavailable due to insufficient stock WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) <= 0 THEN 'insufficient_stock' - -- ✅ FIXED: Check if lot status is unavailable + -- FIXED: Check if lot status is unavailable WHEN ill.status = 'unavailable' THEN 'status_unavailable' - -- ✅ Default to available + -- Default to available ELSE 'available' END as lotAvailability FROM fpsmsdb.inventory_lot_line ill @@ -888,16 +888,16 @@ open class PickOrderService( LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId LEFT JOIN fpsmsdb.item_uom sales_iu ON sales_iu.itemId = il.itemId AND sales_iu.salesUnit = true AND sales_iu.deleted = false LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = sales_iu.uomId - -- ✅ FIXED: Include both suggested lots AND lots with stock out lines for this pick order + -- FIXED: Include both suggested lots AND lots with stock out lines for this pick order LEFT JOIN fpsmsdb.suggested_pick_lot spl ON spl.suggestedLotLineId = ill.id AND spl.pickOrderLineId = :pickOrderLineId LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = :pickOrderLineId AND sol.inventoryLotLineId = ill.id AND sol.deleted = false - -- ✅ FIXED: Only include lots that are either suggested OR have stock out lines for this pick order + -- FIXED: Only include lots that are either suggested OR have stock out lines for this pick order WHERE (spl.pickOrderLineId = :pickOrderLineId OR sol.pickOrderLineId = :pickOrderLineId) AND(sol.status IS NULL OR sol.status != 'completed') AND ill.deleted = false AND il.deleted = false ORDER BY - CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END, -- ✅ Show rejected lots first + CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END, -- Show rejected lots first il.expiryDate ASC, il.lotNo ASC """.trimIndent() @@ -907,7 +907,7 @@ open class PickOrderService( val result = jdbcDao.queryForList(sql, mapOf("pickOrderLineId" to pickOrderLineId)) - // ✅ Add detailed debug output for each lot + // Add detailed debug output for each lot println("=== DETAILED LOT AVAILABILITY DEBUG ===") result.forEach { row -> val lotId = row["lotId"] @@ -923,19 +923,19 @@ open class PickOrderService( println(" sol.status: $solStatus") println(" lotAvailability: $lotAvailability") - // ✅ Check each condition step by step + // Check each condition step by step if (isExpired == true) { println(" ❌ FAILED: lot is expired") } else if (solStatus == "rejected") { println(" ❌ FAILED: sol.status = 'rejected'") } else { - println(" ✅ PASSED: All conditions met, should be 'available'") + println(" PASSED: All conditions met, should be 'available'") } println(" ---") } println("=== END DETAILED DEBUG ===") - // ✅ Filter out completed lots + // Filter out completed lots val filteredResult = result.filter { row -> val stockOutLineStatus = row["stockOutLineStatus"] as String? val stockOutLineQty = row["stockOutLineQty"] as Number? @@ -1097,7 +1097,7 @@ open class PickOrderService( this.stockOut = savedStockOut this.pickOrderLine = pickOrderLine this.inventoryLotLine = inventoryLotLine - this.item = pickOrderLine.item // ✅ Add the required item field + this.item = pickOrderLine.item // Add the required item field this.status = com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus.PENDING.status this.qty = 0.0 @@ -1145,7 +1145,7 @@ open class PickOrderService( val stockOut = stockOutRepository.findByConsoPickOrderCode(consoCode).orElseThrow() println("StockOut ID: ${stockOut.id}") - // ✅ FIXED: 直接通过 consoCode 查找相关的 stock out lines,而不依赖 stockOutId 关联 + // FIXED: 直接通过 consoCode 查找相关的 stock out lines,而不依赖 stockOutId 关联 val stockOutLinesSql = """ SELECT sol.* FROM stock_out_line sol @@ -1161,7 +1161,7 @@ open class PickOrderService( println("StockOutLine ID: ${row["id"]}, stockOutId: ${row["stockOutId"]}, status: ${row["status"]}, qty: ${row["qty"]}, pickOrderLineId: ${row["pickOrderLineId"]}") } - // ✅ 将结果转换为 StockOutLine 对象 + // 将结果转换为 StockOutLine 对象 val stockOutLineIds = stockOutLinesResult.mapNotNull { row -> val id = row["id"] println("Raw ID value: $id (type: ${id?.javaClass?.simpleName})") @@ -1199,7 +1199,7 @@ open class PickOrderService( } val savedStockOut = stockOutRepository.saveAndFlush(stockOut) - // ✅ NEW APPROACH: Update through relationship chain + // NEW APPROACH: Update through relationship chain // 1. Get all pick order lines from completed stock out lines val completedPickOrderLineIds = stockOutLines.mapNotNull { it.pickOrderLine?.id } println("Completed pick order line IDs: $completedPickOrderLineIds") @@ -1212,7 +1212,7 @@ open class PickOrderService( println("Updated pick order line ${line.id} to COMPLETED") } pickOrderLineRepository.saveAll(pickOrderLines) - println("✅ Updated ${pickOrderLines.size} pick order lines to COMPLETED status") + println(" Updated ${pickOrderLines.size} pick order lines to COMPLETED status") // 3. Get all unique pick order IDs from the lines val pickOrderIds = pickOrderLines.mapNotNull { it.pickOrder?.id }.distinct() @@ -1233,9 +1233,9 @@ open class PickOrderService( pickOrder.status = PickOrderStatus.COMPLETED pickOrder.completeDate = LocalDateTime.now() pickOrderRepository.save(pickOrder) - println("✅ Updated pick order ${pickOrder.code} to COMPLETED status") + println(" Updated pick order ${pickOrder.code} to COMPLETED status") - // ✅ 修改:通过 do_pick_order_line 查询(因为 do_pick_order.pick_order_id 可能为 null) + // 修改:通过 do_pick_order_line 查询(因为 do_pick_order.pick_order_id 可能为 null) val doPickOrderLines = doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(pickOrderId) val doPickOrderIds = doPickOrderLines.mapNotNull { it.doPickOrderId }.distinct() @@ -1258,13 +1258,13 @@ open class PickOrderService( println("🔍 Processing do_pick_order ID: ${dpo.id}, ticket: ${dpo.ticketNo}") - // ✅ 新增:检查这个 do_pick_order 下是否还有其他未完成的 pick orders + // 新增:检查这个 do_pick_order 下是否还有其他未完成的 pick orders val allDoPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(dpo.id!!) val allPickOrderIdsInDpo = allDoPickOrderLines.mapNotNull { it.pickOrderId }.distinct() println("🔍 DEBUG: This do_pick_order has ${allPickOrderIdsInDpo.size} pick orders") - // ✅ 检查每个 pick order 的状态 + // 检查每个 pick order 的状态 val pickOrderStatuses = allPickOrderIdsInDpo.map { poId -> val po = pickOrderRepository.findById(poId).orElse(null) poId to po?.status @@ -1274,7 +1274,7 @@ open class PickOrderService( println("🔍 DEBUG: Pick order $poId status: $status") } - // ✅ 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表 + // 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表 val allPickOrdersCompleted = pickOrderStatuses.all { (_, status) -> status == PickOrderStatus.COMPLETED } @@ -1282,10 +1282,10 @@ open class PickOrderService( if (!allPickOrdersCompleted) { println("⏳ Not all pick orders in this do_pick_order are completed, keeping do_pick_order alive") println("🔍 DEBUG: Completed pick orders: ${pickOrderStatuses.count { it.second == PickOrderStatus.COMPLETED }}/${pickOrderStatuses.size}") - return@forEach // ✅ 跳过这个 do_pick_order,不删除它 + return@forEach // 跳过这个 do_pick_order,不删除它 } - println("✅ All pick orders in this do_pick_order are completed, moving to record table") + println(" All pick orders in this do_pick_order are completed, moving to record table") // 2) 先复制 do_pick_order -> do_pick_order_record val dpoRecord = DoPickOrderRecord( @@ -1341,14 +1341,14 @@ open class PickOrderService( if (deliveryOrder != null && deliveryOrder.status != DeliveryOrderStatus.COMPLETED) { deliveryOrder.status = DeliveryOrderStatus.COMPLETED deliveryOrderRepository.save(deliveryOrder) - println("✅ Updated delivery order $doId to COMPLETED") + println(" Updated delivery order $doId to COMPLETED") } } } - println("✅ Copied $copied do_pick_order to record and deleted $deleted original(s)") + println(" Copied $copied do_pick_order to record and deleted $deleted original(s)") } - // ✅ 添加:直接使用 Repository 处理 JO pick order(避免循环依赖) + // 添加:直接使用 Repository 处理 JO pick order(避免循环依赖) if (pickOrder.jobOrder != null) { val joPickOrders = joPickOrderRepository.findByPickOrderId(pickOrderId) joPickOrders.forEach { @@ -1364,7 +1364,7 @@ open class PickOrderService( } joPickOrderRecordRepository.saveAll(joPickOrderRecords) - println("✅ Set jo_pick_order ticketCompleteTime for pick order ${pickOrderId}, waiting for second scan") + println(" Set jo_pick_order ticketCompleteTime for pick order ${pickOrderId}, waiting for second scan") } } } @@ -1443,7 +1443,7 @@ open class PickOrderService( println("📊 Stock out lines: ${stockOutLines.size}, Unfinished: ${unfinishedLines.size}") if (unfinishedLines.isEmpty()) { - println("✅ All stock out lines completed, updating pick order statuses...") + println(" All stock out lines completed, updating pick order statuses...") return completeStockOut(consoCode) } else { println("⏳ Still have ${unfinishedLines.size} unfinished lines") @@ -1588,7 +1588,7 @@ open class PickOrderService( ) } - // ✅ 添加缺失的方法:从 pick order line ID 获取 pick order ID + // 添加缺失的方法:从 pick order line ID 获取 pick order ID private fun getPickOrderIdFromPickOrderLineId(pickOrderLineId: Long): Long? { val sql = """ SELECT po.id as pickOrderId @@ -1606,11 +1606,11 @@ open class PickOrderService( } } - // ✅ 添加检查是否需要 resuggest 的方法 + // 添加检查是否需要 resuggest 的方法 private fun checkIfNeedsResuggest(pickOrderLineId: Long): Boolean { println("🔍 checkIfNeedsResuggest called with pickOrderLineId: $pickOrderLineId") - // ✅ 首先执行一个调试查询来查看实际的数值 + // 首先执行一个调试查询来查看实际的数值 val debugSql = """ SELECT spl.id as suggestedPickLotId, @@ -1647,7 +1647,7 @@ open class PickOrderService( println(" RatioN: ${row["ratioN"]}") println(" RatioD: ${row["ratioD"]}") println(" ConvertedAvailableQty: ${row["convertedAvailableQty"]}") - // ✅ 修复:正确处理 Number 类型转换 + // 修复:正确处理 Number 类型转换 val convertedAvailableQty = (row["convertedAvailableQty"] as Number).toDouble() val suggestedQty = (row["suggestedQty"] as Number).toDouble() println(" Is Insufficient: ${convertedAvailableQty < suggestedQty}") @@ -1659,7 +1659,7 @@ open class PickOrderService( COUNT(*) as totalSuggestions, COUNT(CASE WHEN ill.status != 'available' THEN 1 END) as unavailableLots, COUNT(CASE WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 1 END) as expiredLots, - -- ✅ 修复:使用销售单位进行比较 + -- 修复:使用销售单位进行比较 -- COUNT(CASE WHEN -- CASE -- WHEN sales_iu.ratioN IS NOT NULL AND sales_iu.ratioD IS NOT NULL AND sales_iu.ratioD != 0 @@ -1671,13 +1671,13 @@ open class PickOrderService( (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) < spl.qty THEN 1 END) as insufficientStockLots, COUNT(CASE WHEN sol.status IN ('rejected', 'lot-change', 'determine1') THEN 1 END) as problematicStockOutLines, - -- ✅ 检查单位不一致问题 + -- 检查单位不一致问题 COUNT(CASE WHEN spl.qty > pol.qty * 100 THEN 1 END) as unitMismatchLots FROM fpsmsdb.suggested_pick_lot spl JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId JOIN fpsmsdb.pick_order_line pol ON pol.id = spl.pickOrderLineId - -- ✅ 添加销售单位转换 + -- 添加销售单位转换 LEFT JOIN fpsmsdb.item_uom sales_iu ON sales_iu.itemId = il.itemId AND sales_iu.salesUnit = true AND sales_iu.deleted = false LEFT JOIN fpsmsdb.stock_out_line sol ON sol.inventoryLotLineId = ill.id AND sol.pickOrderLineId = spl.pickOrderLineId @@ -1714,7 +1714,7 @@ open class PickOrderService( expiredLots > 0 || insufficientStockLots > 0 || problematicStockOutLines > 0 || - unitMismatchLots > 0 || // ✅ 单位不一致检查 + unitMismatchLots > 0 || // 单位不一致检查 totalSuggestions == 0 // 没有建议也需要 resuggest ) @@ -1921,15 +1921,15 @@ open class PickOrderService( existingRecords.forEach { record -> record.handledBy = user.id record.ticketStatus = DoPickOrderStatus.released - record.ticketReleaseTime = LocalDateTime.now() // ✅ 添加这行 + record.ticketReleaseTime = LocalDateTime.now() // 添加这行 println("🔍 DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released") } doPickOrderRecordRepository.saveAll(existingRecords) - println("✅ Updated ${existingRecords.size} existing DoPickOrderRecord entries") + println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") } doPickOrderService.updateHandledByForPickOrder(selected.id!!, user.id!!) - println("✅ Updated DoPickOrder handledBy to user $userId for pick order ${selected.id}") + println(" Updated DoPickOrder handledBy to user $userId for pick order ${selected.id}") return MessageResponse( id = null, @@ -1996,7 +1996,7 @@ open class PickOrderService( uc.code as uomCode, uc.udfudesc as uomDesc, - -- ✅ Calculate total picked quantity from stock_out_line table + -- Calculate total picked quantity from stock_out_line table COALESCE(( SELECT SUM(sol_picked.qty) FROM fpsmsdb.stock_out_line sol_picked @@ -2005,7 +2005,7 @@ open class PickOrderService( AND sol_picked.status IN ('completed', 'COMPLETE', 'partially_completed','rejected') ), 0) as totalPickedQty, - -- ✅ Calculate available quantity from inventory + -- Calculate available quantity from inventory COALESCE(( SELECT inv.onHandQty - inv.onHoldQty - inv.unavailableQty FROM fpsmsdb.inventory inv @@ -2013,7 +2013,7 @@ open class PickOrderService( AND inv.deleted = false ), 0) as availableQty, - -- ✅ Check if all stock out lines for this pick order line are completed + -- Check if all stock out lines for this pick order line are completed CASE WHEN EXISTS ( SELECT 1 @@ -2039,8 +2039,8 @@ open class PickOrderService( AND po.id IN ($pickOrderIdsStr) AND pol.deleted = false AND po.status = 'RELEASED' - AND po.type NOT IN ('do', 'job') -- ✅ 排除 do 和 job 类型 - -- ✅ Only include lines that have incomplete stock out lines + AND po.type NOT IN ('do', 'job') -- 排除 do 和 job 类型 + -- Only include lines that have incomplete stock out lines AND ( NOT EXISTS ( SELECT 1 @@ -2066,17 +2066,17 @@ open class PickOrderService( val result = jdbcDao.queryForList(sql, emptyMap()) - println("✅ Optimized result count: ${result.size}") + println(" Optimized result count: ${result.size}") - // ✅ Transform the flat data into the expected nested structure + // Transform the flat data into the expected nested structure val pickOrdersMap = mutableMapOf() - var consoCode: String? = null // ✅ 用于存储 consoCode + var consoCode: String? = null // 用于存储 consoCode result.forEach { row -> val pickOrderId = (row["pickOrderId"] as Number).toLong() val pickOrderLineId = (row["pickOrderLineId"] as Number).toLong() - // ✅ 获取 consoCode(所有行应该有相同的 consoCode) + // 获取 consoCode(所有行应该有相同的 consoCode) if (consoCode == null) { consoCode = row["pickOrderConsoCode"] as String? } @@ -2087,7 +2087,7 @@ open class PickOrderService( id = pickOrderId, code = row["pickOrderCode"] as String, consoCode = row["pickOrderConsoCode"] as String?, - targetDate = row["pickOrderTargetDate"] as LocalDateTime?, // ✅ Convert to LocalDateTime + targetDate = row["pickOrderTargetDate"] as LocalDateTime?, // Convert to LocalDateTime type = row["pickOrderType"] as String, status = row["pickOrderStatus"] as String, assignTo = (row["pickOrderAssignTo"] as Number?)?.toLong(), @@ -2104,21 +2104,21 @@ open class PickOrderService( itemId = (row["itemId"] as Number).toLong(), itemCode = row["itemCode"] as String, itemName = row["itemName"] as String, - availableQty = (row["availableQty"] as Number).toDouble().toBigDecimal(), // ✅ Convert to BigDecimal + availableQty = (row["availableQty"] as Number).toDouble().toBigDecimal(), // Convert to BigDecimal requiredQty = (row["pickOrderLineRequiredQty"] as Number).toDouble() - .toBigDecimal(), // ✅ Convert to BigDecimal + .toBigDecimal(), // Convert to BigDecimal uomCode = row["uomCode"] as String?, uomDesc = row["uomDesc"] as String?, suggestedList = emptyList(), - pickedQty = (row["totalPickedQty"] as Number).toDouble().toBigDecimal() // ✅ Convert to BigDecimal + pickedQty = (row["totalPickedQty"] as Number).toDouble().toBigDecimal() // Convert to BigDecimal ) - // ✅ Fix the add method call + // Fix the add method call (pickOrder.pickOrderLines as MutableList).add(pickOrderLine) } return GetPickOrderInfoResponse( - consoCode = consoCode, // ✅ 使用获取到的 consoCode + consoCode = consoCode, // 使用获取到的 consoCode pickOrders = pickOrdersMap.values.toList(), items = emptyList() ) @@ -2133,7 +2133,7 @@ open class PickOrderService( val releasedPickOrderIds = allPickOrders .filter { it.status == PickOrderStatus.RELEASED } .filter { it.assignTo?.id == userId } - .filter { it.type?.value != "do" && it.type?.value != "jo" } // ✅ 排除 do 和 job 类型 + .filter { it.type?.value != "do" && it.type?.value != "jo" } // 排除 do 和 job 类型 .map { it.id!! } if (releasedPickOrderIds.isEmpty()) { @@ -2173,7 +2173,7 @@ open class PickOrderService( ) } - println("✅ User found: ${user.name} (ID: ${user.id})") + println(" User found: ${user.name} (ID: ${user.id})") // Check if user already has pending/released pick orders that are not completed val existingPickOrders = pickOrderRepository.findAllByAssignToAndStatusIn( @@ -2185,7 +2185,7 @@ open class PickOrderService( // Filter out completed pick orders by checking stock_out status val activePickOrders = existingPickOrders.filter { pickOrder -> - // ✅ Fix: Store consoCode in local variable to avoid smart cast issues + // Fix: Store consoCode in local variable to avoid smart cast issues val consoCode = pickOrder.consoCode if (consoCode == null) { println("🔍 Checking pick order ${pickOrder.code} (consoCode: null)") @@ -2201,7 +2201,7 @@ open class PickOrderService( } else { println(" 📦 Stock_out status: ${stockOut.status}") val isActive = stockOut.status != StockOutStatus.COMPLETE.status - println(" ${if (isActive) "🟡 Active" else "✅ Completed"}") + println(" ${if (isActive) "🟡 Active" else " Completed"}") isActive } } @@ -2247,9 +2247,9 @@ open class PickOrderService( ) } - println("✅ Found available pick order: ${availablePickOrders.first().code}") + println(" Found available pick order: ${availablePickOrders.first().code}") - // ✅ Add the complete assignment logic here + // Add the complete assignment logic here val availablePickOrder = availablePickOrders.first() // Generate consoCode early and save immediately @@ -2297,7 +2297,7 @@ open class PickOrderService( inventoryLotLineRepository.saveAll(inventoryLotLines) - println("✅ Successfully assigned pick order ${availablePickOrder.code}") + println(" Successfully assigned pick order ${availablePickOrder.code}") return MessageResponse( id = null, @@ -2349,7 +2349,7 @@ open class PickOrderService( ) val completionStatus = userPickOrders.map { pickOrder -> - // ✅ Fix: Store consoCode in local variable to avoid smart cast issues + // Fix: Store consoCode in local variable to avoid smart cast issues val consoCode = pickOrder.consoCode val stockOut = if (consoCode != null) { stockOutRepository.findByConsoPickOrderCode(consoCode).orElse(null) @@ -2448,7 +2448,7 @@ open class PickOrderService( ) } - // ✅ Check if user already has pick orders in progress + // Check if user already has pick orders in progress val userExistingOrders = pickOrderRepository.findAllByAssignToAndStatusIn( user, listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED) @@ -2572,7 +2572,7 @@ open class PickOrderService( selected.assignTo = user pickOrderRepository.saveAndFlush(selected) - // ✅ 更新 DoPickOrderRecord,填充新字段 + // 更新 DoPickOrderRecord,填充新字段 val deliveryOrder = selected.deliveryOrder if (deliveryOrder != null) { val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() @@ -2580,7 +2580,7 @@ open class PickOrderService( println("🔍 DEBUG: Target date: $targetDate, Date prefix: $datePrefix") - // ✅ Find truck by shop ID with earliest departure time + // Find truck by shop ID with earliest departure time val truck = deliveryOrder.shop?.id?.let { shopId -> println("🔍 DEBUG: Looking for truck with shop ID: $shopId") val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) @@ -2590,7 +2590,7 @@ open class PickOrderService( selectedTruck } - // ✅ 根据 truck 的 Store_id 字段确定 storeId + // 根据 truck 的 Store_id 字段确定 storeId val determinedStoreId = when (truck?.storeId) { 4 -> "4/F" 2 -> "2/F" @@ -2603,17 +2603,17 @@ open class PickOrderService( println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines") - // ✅ UPDATE existing do_pick_order_record entries instead of creating new ones + // UPDATE existing do_pick_order_record entries instead of creating new ones val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!) println("🔍 DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}") if (existingRecords.isNotEmpty()) { - // ✅ Update existing records + // Update existing records existingRecords.forEach { record -> record.handledBy = user.id record.ticketStatus = DoPickOrderStatus.released - record.ticketReleaseTime = LocalDateTime.now() // ✅ 设置 release time - // ✅ 填充新字段 + record.ticketReleaseTime = LocalDateTime.now() // 设置 release time + // 填充新字段 record.truckLanceCode = truck?.truckLanceCode record.shopCode = deliveryOrder.shop?.code record.shopName = deliveryOrder.shop?.name @@ -2621,9 +2621,9 @@ open class PickOrderService( println("🔍 DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released") } doPickOrderRecordRepository.saveAll(existingRecords) - println("✅ Updated ${existingRecords.size} existing DoPickOrderRecord entries") + println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") } else { - // ✅ Only create new records if none exist (fallback) + // Only create new records if none exist (fallback) println("⚠️ No existing DoPickOrderRecord entries found, creating new ones") deliveryOrder.deliveryOrderLines.forEach { line -> println("🔍 DEBUG: Processing line - Store ID: $determinedStoreId") @@ -2638,7 +2638,7 @@ open class PickOrderService( truckDepartureTime = truck?.departureTime, shopId = deliveryOrder.shop?.id, handledBy = user.id, - // ✅ 填充新增字段 + // 填充新增字段 truckLanceCode = truck?.truckLanceCode, shopCode = deliveryOrder.shop?.code, shopName = deliveryOrder.shop?.name, @@ -2654,8 +2654,8 @@ open class PickOrderService( } doPickOrderService.updateHandledByForPickOrder(selected.id!!, user.id!!) - doPickOrderService.updateRecordHandledByForPickOrder(selected.id!!, user.id!!) // ✅ 添加这行 - println("✅ Updated DoPickOrder and DoPickOrderRecord handledBy to user $userId for pick order ${selected.id}") + doPickOrderService.updateRecordHandledByForPickOrder(selected.id!!, user.id!!) // 添加这行 + println(" Updated DoPickOrder and DoPickOrderRecord handledBy to user $userId for pick order ${selected.id}") return MessageResponse( id = null, @@ -2684,7 +2684,7 @@ open class PickOrderService( println("today: ${LocalDate.now()}") println("userId filter: $userId") - // ✅ First attempt auto-assignment for the user + // First attempt auto-assignment for the user println("🎯 Attempting auto-assignment for user $userId") val assignedPickOrderResponse = autoAssignAndReleasePickOrder(userId) @@ -2710,7 +2710,7 @@ open class PickOrderService( return emptyList() } - // ✅ Use SQL query approach similar to getPickOrderLineLotDetails for detailed lot information + // Use SQL query approach similar to getPickOrderLineLotDetails for detailed lot information val pickOrderIdsStr = pickOrderIds.joinToString(",") val sql = """ @@ -2743,7 +2743,7 @@ open class PickOrderService( w.name as location, COALESCE(uc.udfudesc, 'N/A') as stockUnit, - -- ✅ FIXED: Set quantities to NULL for rejected lots + -- FIXED: 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)) @@ -2841,7 +2841,7 @@ open class PickOrderService( println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) - println("✅ Total result count: ${results.size}") + println(" Total result count: ${results.size}") // Filter out lots with null availableQty (rejected lots) val filteredResults = results.filter { row -> @@ -2849,7 +2849,7 @@ open class PickOrderService( availableQty != null } - println("✅ Filtered result count: ${filteredResults.size}") + println(" Filtered result count: ${filteredResults.size}") val enrichedResults = filteredResults return enrichedResults @@ -2872,7 +2872,7 @@ open class PickOrderService( val shop = deliveryOrder?.shop val supplier = deliveryOrder?.supplier - // ✅ Get truck information for this shop - handle Optional properly + // Get truck information for this shop - handle Optional properly val truckInfo = if (shop?.id != null) { try { jdbcDao.queryForMap( @@ -2904,13 +2904,13 @@ open class PickOrderService( "shopAddress" to buildShopAddress(shop), "shopPoNo" to (supplier?.code ?: ""), "numberOfCartons" to (po.pickOrderLines.size), - "TruckLanceCode" to (truckInfo?.get("TruckLanceCode") ?: ""), // ✅ Add truck number - "DepartureTime" to (truckInfo?.get("DepartureTime") ?: ""), // ✅ Add departure time + "TruckLanceCode" to (truckInfo?.get("TruckLanceCode") ?: ""), // Add truck number + "DepartureTime" to (truckInfo?.get("DepartureTime") ?: ""), // Add departure time "qrCodeData" to (po.id ?: 0L) ) } - println("✅ FG Pick Orders result count: ${results.size}") + println(" FG Pick Orders result count: ${results.size}") return results } catch (e: Exception) { @@ -2924,7 +2924,7 @@ open class PickOrderService( try { println("🔍 Starting getFgPickOrdersByUserId with userId: $userId") - // ✅ 修复:从 do_pick_order_line 获取 pick order 信息 + // 修复:从 do_pick_order_line 获取 pick order 信息 val sql = """ SELECT dpo.id as doPickOrderId, @@ -2937,12 +2937,12 @@ open class PickOrderService( s.id as shopId, s.name as shopNameFromShop, CONCAT_WS(', ', s.addr1, s.addr2, s.addr3, s.addr4, s.district) as shopAddress, - -- ✅ 从 do_pick_order_line 获取所有关联的 pick orders 和 delivery orders + -- 从 do_pick_order_line 获取所有关联的 pick orders 和 delivery orders GROUP_CONCAT(DISTINCT dpol.pick_order_id ORDER BY dpol.pick_order_id) as pickOrderIds, GROUP_CONCAT(DISTINCT dpol.pick_order_code ORDER BY dpol.pick_order_id SEPARATOR ', ') as pickOrderCodes, GROUP_CONCAT(DISTINCT dpol.do_order_id ORDER BY dpol.do_order_id) as deliveryOrderIds, GROUP_CONCAT(DISTINCT dpol.delivery_order_code ORDER BY dpol.do_order_id SEPARATOR ', ') as deliveryNos, - -- ✅ 获取第一个 pick order 的详细信息(用于兼容性) + -- 获取第一个 pick order 的详细信息(用于兼容性) (SELECT po2.consoCode FROM pick_order po2 WHERE po2.id = MIN(dpol.pick_order_id) LIMIT 1) as pickOrderConsoCode, (SELECT po2.targetDate FROM pick_order po2 WHERE po2.id = MIN(dpol.pick_order_id) LIMIT 1) as pickOrderTargetDate, (SELECT po2.status FROM pick_order po2 WHERE po2.id = MIN(dpol.pick_order_id) LIMIT 1) as pickOrderStatus, @@ -2959,7 +2959,7 @@ open class PickOrderService( ) as numberOfCartons FROM do_pick_order dpo INNER JOIN do_pick_order_line dpol ON dpol.do_pick_order_id = dpo.id AND dpol.deleted = 0 - -- ✅ JOIN pick_order 以检查用户分配 + -- JOIN pick_order 以检查用户分配 INNER JOIN pick_order po ON po.id = dpol.pick_order_id LEFT JOIN shop s ON s.id = dpo.shop_id WHERE po.assignTo = :userId @@ -2984,7 +2984,7 @@ open class PickOrderService( println("🔍 Found ${results.size} active FG pick orders for user: $userId") - // ✅ 添加调试信息 + // 添加调试信息 results.forEachIndexed { index, row -> println("🔍 DEBUG: Result $index:") println(" - doPickOrderId: ${row["doPickOrderId"]}") @@ -2994,7 +2994,7 @@ open class PickOrderService( } val formattedResults = results.map { row -> - // ✅ 解析 pick order IDs 列表 + // 解析 pick order IDs 列表 val pickOrderIdsStr = row["pickOrderIds"] as? String ?: "" val pickOrderIds = if (pickOrderIdsStr.isNotEmpty()) { pickOrderIdsStr.split(",").mapNotNull { it.toLongOrNull() } @@ -3004,10 +3004,10 @@ open class PickOrderService( mapOf( "doPickOrderId" to (row["doPickOrderId"] ?: 0L), - "pickOrderIds" to pickOrderIds, // ✅ 返回所有 pick order IDs - "pickOrderId" to (pickOrderIds.firstOrNull() ?: 0L), // ✅ 兼容:返回第一个 + "pickOrderIds" to pickOrderIds, // 返回所有 pick order IDs + "pickOrderId" to (pickOrderIds.firstOrNull() ?: 0L), // 兼容:返回第一个 "pickOrderCodes" to (row["pickOrderCodes"] ?: ""), - "pickOrderCode" to ((row["pickOrderCodes"] as? String)?.split(", ")?.firstOrNull() ?: ""), // ✅ 兼容 + "pickOrderCode" to ((row["pickOrderCodes"] as? String)?.split(", ")?.firstOrNull() ?: ""), // 兼容 "deliveryOrderIds" to (row["deliveryOrderIds"] as? String ?: "").split(",") .mapNotNull { it.toLongOrNull() }, "deliveryNos" to (row["deliveryNos"] ?: ""), @@ -3020,17 +3020,17 @@ open class PickOrderService( "shopName" to (row["shopName"] ?: row["shopNameFromShop"] ?: ""), "shopAddress" to (row["shopAddress"] ?: ""), "shopPoNo" to "", - "numberOfPickOrders" to (row["numberOfPickOrders"] ?: 0), // ✅ 新增:pick order 数量 + "numberOfPickOrders" to (row["numberOfPickOrders"] ?: 0), // 新增:pick order 数量 "numberOfCartons" to (row["numberOfCartons"] ?: 0), "truckLanceCode" to (row["truckLanceCode"] ?: ""), "DepartureTime" to (row["DepartureTime"]?.toString() ?: ""), "ticketNo" to (row["ticketNo"] ?: ""), "storeId" to (row["storeId"] ?: ""), - "qrCodeData" to (row["doPickOrderId"] ?: 0L) // ✅ 改为 doPickOrderId + "qrCodeData" to (row["doPickOrderId"] ?: 0L) // 改为 doPickOrderId ) } - println("✅ Built ${formattedResults.size} FG pick orders for user: $userId") + println(" Built ${formattedResults.size} FG pick orders for user: $userId") return formattedResults } catch (e: Exception) { @@ -3073,7 +3073,7 @@ open class PickOrderService( println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") println("🔍 Shop ID: ${shop?.id}") - // ✅ Get truck information using repository with detailed debugging + // Get truck information using repository with detailed debugging val truck = if (shop?.id != null) { try { println("🔍 Querying truck repository for shopId: ${shop.id}") @@ -3089,7 +3089,7 @@ open class PickOrderService( val selectedTruck = trucksForShop.firstOrNull() if (selectedTruck != null) { - println("✅ Selected truck: ID=${selectedTruck.id}, truckLanceCode=${selectedTruck.truckLanceCode}, DepartureTime=${selectedTruck.departureTime}") + println(" Selected truck: ID=${selectedTruck.id}, truckLanceCode=${selectedTruck.truckLanceCode}, DepartureTime=${selectedTruck.departureTime}") } else { println("❌ No truck found for shopId ${shop.id}") } @@ -3135,14 +3135,14 @@ open class PickOrderService( "shopAddress" to buildShopAddress(shop), "shopPoNo" to (supplier?.code ?: ""), "numberOfCartons" to (pickOrder.pickOrderLines.size), - "truckLanceCode" to (truck?.truckLanceCode ?: ""), // ✅ Use entity property + "truckLanceCode" to (truck?.truckLanceCode ?: ""), // Use entity property "DepartureTime" to (truck?.departureTime?.toString() ?: ""), "ticketNo" to ticketNo, "storeId" to dpoStoreId, "qrCodeData" to (pickOrder.id ?: 0L) ) - println("✅ FG Pick Orders by ID result count: 1") + println(" FG Pick Orders by ID result count: 1") return listOf(result) } catch (e: Exception) { @@ -3185,7 +3185,7 @@ open class PickOrderService( println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") println("🔍 Shop ID: ${shop?.id}") - // ✅ Get truck information using repository with detailed debugging + // Get truck information using repository with detailed debugging val truck = if (shop?.id != null) { try { println("🔍 Querying truck repository for shopId: ${shop.id}") @@ -3201,7 +3201,7 @@ open class PickOrderService( val selectedTruck = trucksForShop.firstOrNull() if (selectedTruck != null) { - println("✅ Selected truck: ID=${selectedTruck.id}, TruckLanceCode=${selectedTruck.truckLanceCode}, DepartureTime=${selectedTruck.departureTime}") + println(" Selected truck: ID=${selectedTruck.id}, TruckLanceCode=${selectedTruck.truckLanceCode}, DepartureTime=${selectedTruck.departureTime}") } else { println("❌ No truck found for shopId ${shop.id}") } @@ -3247,14 +3247,14 @@ open class PickOrderService( "shopAddress" to buildShopAddress(shop), "shopPoNo" to (supplier?.code ?: ""), "numberOfCartons" to (pickOrder.pickOrderLines.size), - "TruckLanceCode" to (truck?.truckLanceCode ?: ""), // ✅ Use entity property + "TruckLanceCode" to (truck?.truckLanceCode ?: ""), // Use entity property "DepartureTime" to (truck?.departureTime?.toString() ?: ""), "ticketNo" to ticketNo, "storeId" to dpoStoreId, "qrCodeData" to (pickOrder.id ?: 0L) ) - println("✅ FG Pick Orders by ID result count: 1") + println(" FG Pick Orders by ID result count: 1") return listOf(result) } catch (e: Exception) { @@ -3300,7 +3300,7 @@ open class PickOrderService( allAssignedPickOrders.forEach { po -> println("🔍 DEBUG: Pick order ${po.id}: code=${po.code}, status=${po.status}, assignTo=${po.assignTo?.id}, doId=${po.deliveryOrder?.id}") } - // ✅ NEW LOGIC: Filter based on assignment and status + // NEW LOGIC: Filter based on assignment and status val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) { // Check if there are any RELEASED orders assigned to this user (active work) val assignedReleasedOrders = allAssignedPickOrders.filter { @@ -3308,11 +3308,11 @@ open class PickOrderService( } if (assignedReleasedOrders.isNotEmpty()) { - // ✅ If there are assigned RELEASED orders, show only those + // If there are assigned RELEASED orders, show only those println("🔍 DEBUG: Found ${assignedReleasedOrders.size} assigned RELEASED orders, showing only those") assignedReleasedOrders } else { - // ✅ If no assigned RELEASED orders, show only the latest COMPLETED order + // If no assigned RELEASED orders, show only the latest COMPLETED order val completedOrders = allAssignedPickOrders.filter { it.status == PickOrderStatus.COMPLETED } if (completedOrders.isNotEmpty()) { val latestCompleted = @@ -3382,7 +3382,7 @@ open class PickOrderService( - -- ✅ FIXED: Set quantities to NULL for rejected lots + -- FIXED: 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)) @@ -3470,7 +3470,7 @@ 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(w.`order`, 999999) ASC, -- ✅ 改用 warehouse.order + COALESCE(w.`order`, 999999) ASC, -- 改用 warehouse.order po.code ASC, i.code ASC, il.expiryDate ASC, @@ -3481,7 +3481,7 @@ ORDER BY println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) - println("✅ Total result count: ${results.size}") + println(" Total result count: ${results.size}") // Filter out lots with null availableQty (rejected lots) val filteredResults = results.filter { row -> @@ -3489,9 +3489,9 @@ ORDER BY availableQty != null } - println("✅ Filtered result count: ${filteredResults.size}") + println(" Filtered result count: ${filteredResults.size}") /* - // ✅ Add router information for each lot + // Add router information for each lot val enrichedResults = filteredResults.map { row -> val inventoryLotId = row["debugInventoryLotId"] as? Number @@ -3564,7 +3564,7 @@ ORDER BY return emptyMap() } - // ✅ Step 1: 先找到分配给该用户的所有 pick orders + // Step 1: 先找到分配给该用户的所有 pick orders val userPickOrders = pickOrderRepository.findAll() .filter { it.deleted == false && @@ -3584,7 +3584,7 @@ ORDER BY println("🔍 Found ${userPickOrders.size} pick orders assigned to user $userId") val pickOrderIds = userPickOrders.mapNotNull { it.id } - // ✅ Step 2: 通过 do_pick_order_line 找到相关的 do_pick_order + // Step 2: 通过 do_pick_order_line 找到相关的 do_pick_order val doPickOrderLineRecords = pickOrderIds.flatMap { poId -> doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(poId) } @@ -3601,7 +3601,7 @@ ORDER BY println("🔍 Found ${doPickOrderIds.size} do_pick_order records") - // ✅ Step 3: 获取第一个 do_pick_order 的详细信息(用于构建 fgInfo) + // Step 3: 获取第一个 do_pick_order 的详细信息(用于构建 fgInfo) val doPickOrder = doPickOrderRepository.findById(doPickOrderIds.first()).orElse(null) if (doPickOrder == null) { println("❌ do_pick_order not found: ${doPickOrderIds.first()}") @@ -3614,32 +3614,32 @@ ORDER BY val doPickOrderId = doPickOrder.id!! println("🔍 Using do_pick_order ID: $doPickOrderId") - // ✅ Step 4: 使用 Repository 加载 pick orders 及其关联数据 + // Step 4: 使用 Repository 加载 pick orders 及其关联数据 val pickOrders = pickOrderRepository.findAllById(pickOrderIds) .filter { it.deleted == false } println("🔍 Loaded ${pickOrders.size} pick orders") - // ✅ 收集所有需要的数据 - // ✅ 收集所有需要的数据 + // 收集所有需要的数据 + // 收集所有需要的数据 val allPickOrderLineIds = pickOrders.flatMap { it.pickOrderLines }.mapNotNull { it.id } - // ✅ 使用 Repository 批量加载所有 suggestions 和 stock out lines - // ✅ 使用 Repository 批量加载所有 suggestions 和 stock out lines - val allSuggestions = suggestPickLotRepository.findAllByPickOrderLineIdIn(allPickOrderLineIds) // ✅ 修复:使用 suggestPickLotRepository + // 使用 Repository 批量加载所有 suggestions 和 stock out lines + // 使用 Repository 批量加载所有 suggestions 和 stock out lines + val allSuggestions = suggestPickLotRepository.findAllByPickOrderLineIdIn(allPickOrderLineIds) // 修复:使用 suggestPickLotRepository val allStockOutLines = allPickOrderLineIds.flatMap { lineId -> stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(lineId) } - // ✅ 按 pickOrderLineId 分组 - val suggestionsByLineId = allSuggestions.groupBy { spl: SuggestedPickLot -> // ✅ 修复:明确类型 + // 按 pickOrderLineId 分组 + val suggestionsByLineId = allSuggestions.groupBy { spl: SuggestedPickLot -> // 修复:明确类型 spl.pickOrderLine?.id } - val stockOutLinesByLineId = allStockOutLines.groupBy { sol: StockOutLineInfo -> // ✅ 修复:明确类型 + val stockOutLinesByLineId = allStockOutLines.groupBy { sol: StockOutLineInfo -> // 修复:明确类型 sol.pickOrderLineId } - // ✅ 构建层级数据结构 + // 构建层级数据结构 val allPickOrderLines = mutableListOf>() val lineCountsPerPickOrder = mutableListOf() val pickOrderIdsList = mutableListOf() @@ -3664,14 +3664,14 @@ ORDER BY val zero = BigDecimal.ZERO val today = LocalDate.now() - // ✅ 使用 Repository 获取该 line 的 suggestions 和 stock out lines - val suggestions = suggestionsByLineId[lineId] ?: emptyList() // ✅ 修复:明确类型 - val stockOutLines = stockOutLinesByLineId[lineId] ?: emptyList() // ✅ 修复:明确类型 - // ✅ 合并 suggestions 和 stock out lines,按 (lotId, stockOutLineId) 去重 - // ✅ 合并 suggestions 和 stock out lines,按 lotId 去重(合并相同 lot 的多个条目) + // 使用 Repository 获取该 line 的 suggestions 和 stock out lines + val suggestions = suggestionsByLineId[lineId] ?: emptyList() // 修复:明确类型 + val stockOutLines = stockOutLinesByLineId[lineId] ?: emptyList() // 修复:明确类型 + // 合并 suggestions 和 stock out lines,按 (lotId, stockOutLineId) 去重 + // 合并 suggestions 和 stock out lines,按 lotId 去重(合并相同 lot 的多个条目) val lotMap = mutableMapOf>() - // ✅ 第一步:处理 suggestions,构建基础数据 + // 第一步:处理 suggestions,构建基础数据 suggestions.forEach { spl: SuggestedPickLot -> val ill = spl.suggestedLotLine if (ill != null) { @@ -3683,19 +3683,19 @@ ORDER BY .minus(ill.outQty ?: zero) .minus(ill.holdQty ?: zero) - // ✅ 查找对应的 stock out line(通过 lotId 查找,而不是通过 suggestion.stockOutLine) + // 查找对应的 stock out line(通过 lotId 查找,而不是通过 suggestion.stockOutLine) val stockOutLine = stockOutLines.find { sol: StockOutLineInfo -> sol.inventoryLotLineId == lotId } if (lotMap.containsKey(lotId)) { - // ✅ 如果已存在,合并 requiredQty(累加) + // 如果已存在,合并 requiredQty(累加) val existing = lotMap[lotId]!! val existingRequiredQty = (existing["requiredQty"] as? BigDecimal) ?: zero val newRequiredQty = spl.qty ?: zero existing["requiredQty"] = existingRequiredQty.plus(newRequiredQty) - // ✅ 如果当前有 stockOutLine 但 existing 没有,更新 stockOutLine 信息 + // 如果当前有 stockOutLine 但 existing 没有,更新 stockOutLine 信息 if (stockOutLine != null && existing["stockOutLineId"] == null) { existing["stockOutLineId"] = stockOutLine.id existing["stockOutLineStatus"] = stockOutLine.status @@ -3715,7 +3715,7 @@ ORDER BY } } } else { - // ✅ 首次遇到,创建新条目 + // 首次遇到,创建新条目 lotMap[lotId] = mutableMapOf( "id" to lotId, "lotNo" to il?.lotNo, @@ -3760,15 +3760,15 @@ ORDER BY } } - // ✅ 第二步:处理 stock out lines(包括没有 suggestion 的,或更新已存在的) + // 第二步:处理 stock out lines(包括没有 suggestion 的,或更新已存在的) stockOutLines.forEach { sol: StockOutLineInfo -> val inventoryLotLineId = sol.inventoryLotLineId val stockOutLineId = sol.id if (inventoryLotLineId != null) { - // ✅ 有 lot 的 stock out line + // 有 lot 的 stock out line if (lotMap.containsKey(inventoryLotLineId)) { - // ✅ 如果 lot 已存在,更新 stockOutLine 信息(如果还没有) + // 如果 lot 已存在,更新 stockOutLine 信息(如果还没有) val existing = lotMap[inventoryLotLineId]!! if (existing["stockOutLineId"] == null) { existing["stockOutLineId"] = stockOutLineId @@ -3781,13 +3781,13 @@ ORDER BY else -> "pending" } - // ✅ 更新 lotAvailability(如果 stockOutLine 是 rejected) + // 更新 lotAvailability(如果 stockOutLine 是 rejected) if (sol.status == "rejected") { existing["lotAvailability"] = "rejected" } } } else { - // ✅ lot 不存在,创建新条目(没有 suggestion 的情况) + // lot 不存在,创建新条目(没有 suggestion 的情况) val ill = inventoryLotLineRepository.findById(inventoryLotLineId).orElse(null) if (ill != null) { val il = ill.inventoryLot @@ -3797,7 +3797,7 @@ ORDER BY .minus(ill.outQty ?: zero) .minus(ill.holdQty ?: zero) - // ✅ 查找对应的 suggestion(如果有) + // 查找对应的 suggestion(如果有) val suggestion = suggestions.find { spl: SuggestedPickLot -> spl.suggestedLotLine?.id == inventoryLotLineId } @@ -3849,7 +3849,7 @@ ORDER BY val lots = lotMap.values.toList() - // ✅ 处理没有 lot 的 stock out lines(noLot = true) + // 处理没有 lot 的 stock out lines(noLot = true) val stockouts = stockOutLines .filter { sol: StockOutLineInfo -> sol.inventoryLotLineId == null } .map { sol: StockOutLineInfo -> @@ -3886,14 +3886,14 @@ ORDER BY allPickOrderLines.addAll(lineDtos) } - // ✅ 按 router index 排序 + // 按 router index 排序 allPickOrderLines.sortWith(compareBy( { line -> val lots = line["lots"] as? List> val firstLot = lots?.firstOrNull() val router = firstLot?.get("router") as? Map val indexValue = router?.get("index") - // ✅ 修复:支持字符串和数字两种格式 + // 修复:支持字符串和数字两种格式 when (indexValue) { is Number -> indexValue.toInt() is String -> indexValue.toIntOrNull() ?: 999999 @@ -3902,7 +3902,7 @@ ORDER BY } )) - // ✅ 构建 FG 信息 + // 构建 FG 信息 val fgInfo = mapOf( "doPickOrderId" to doPickOrderId, "ticketNo" to doPickOrder.ticketNo, @@ -3913,7 +3913,7 @@ ORDER BY "departureTime" to doPickOrder.truckDepartureTime?.toString() ) - // ✅ 构建合并后的 pick order 对象 + // 构建合并后的 pick order 对象 val mergedPickOrder = if (pickOrders.isNotEmpty()) { val firstPickOrder = pickOrders.first() mapOf( @@ -3946,7 +3946,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map>() val lineCountsPerPickOrder = mutableListOf() val pickOrderIds = mutableListOf() @@ -4029,7 +4029,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map it["pickOrderLineId"] } }.distinct()) - // ✅ 按 pickOrderLineId 分组 + // 按 pickOrderLineId 分组 val lineGroups = linesResults.groupBy { (it["pickOrderLineId"] as? Number)?.toLong() } val pickOrderLines = lineGroups.map { (lineId, lineRows) -> @@ -4162,7 +4162,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto if (firstLineRow == null) { null } else { - // ✅ lots:仍然是“有批次”的明细(保留你当前的逻辑) + // lots:仍然是“有批次”的明细(保留你当前的逻辑) val lots = if (lineRows.any { it["lotId"] != null }) { lineRows.filter { it["lotId"] != null }.map { lotRow -> mapOf( @@ -4200,7 +4200,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto emptyList() } - // ✅ 新增:stockouts(包括 inventoryLotLineId 为 null 的出库行) + // 新增:stockouts(包括 inventoryLotLineId 为 null 的出库行) // stockouts:包含所有出库行(即使 lot 为空) val stockouts = lineRows .filter { it["stockOutLineId_any"] != null } @@ -4233,7 +4233,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto "uomShortDesc" to firstLineRow["uomShortDesc"], ), "lots" to lots, - // ✅ 新增字段 + // 新增字段 "stockouts" to stockouts ) } @@ -4254,7 +4254,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto )) - // ✅ 构建 FG 信息 + // 构建 FG 信息 val fgInfo = mapOf( "doPickOrderId" to doPickOrderId, "ticketNo" to doPickOrderInfo["ticket_no"], @@ -4266,7 +4266,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto ) val allConsoCodes = pickOrdersInfo.mapNotNull { it["consoCode"] as? String }.distinct() - // ✅ 构建合并后的 pick order 对象 + // 构建合并后的 pick order 对象 val mergedPickOrder = if (pickOrdersInfo.isNotEmpty()) { val firstPickOrderInfo = pickOrdersInfo.first() mapOf( @@ -4330,7 +4330,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto println("🔍 With parameters: storeId = $storeId") val results = jdbcDao.queryForList(sql, mapOf("storeId" to storeId)) - println("✅ Found ${results.size} records") + println(" Found ${results.size} records") if (results.isEmpty()) { return mapOf( @@ -4418,7 +4418,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto ) } - println("✅ Final orders to return: ${finalOrders.size}") + println(" Final orders to return: ${finalOrders.size}") finalOrders.forEach { order -> println(" 📅 Date: ${order["orderDate"]}, Total: ${order["orderTotal"]}, Completed: ${order["orderCompleted"]}") } @@ -4542,7 +4542,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto println("=== getCompletedDoPickOrders (from record table) ===") println("userId: $userId") - // ✅ 从 do_pick_order_record 表查询已完成的订单 + // 从 do_pick_order_record 表查询已完成的订单 val sql = """ SELECT DISTINCT dpor.id as doPickOrderRecordId, @@ -4554,18 +4554,18 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto dpor.TruckLanceCode as truckLanceCode, dpor.truck_departure_time as departureTime, - -- ✅ 聚合该 do_pick_order_record 下的所有 pick orders + -- 聚合该 do_pick_order_record 下的所有 pick orders GROUP_CONCAT(DISTINCT dpolr.pick_order_id ORDER BY dpolr.pick_order_id) as pickOrderIds, GROUP_CONCAT(DISTINCT dpolr.pick_order_code ORDER BY dpolr.pick_order_id SEPARATOR ', ') as pickOrderCodes, GROUP_CONCAT(DISTINCT dpolr.do_order_id ORDER BY dpolr.do_order_id) as deliveryOrderIds, GROUP_CONCAT(DISTINCT dpolr.delivery_order_code ORDER BY dpolr.do_order_id SEPARATOR ', ') as deliveryNos, - -- ✅ 获取第一个 pick order 的详细信息(用于显示) + -- 获取第一个 pick order 的详细信息(用于显示) (SELECT po.consoCode FROM pick_order po WHERE po.id = MIN(dpolr.pick_order_id) LIMIT 1) as pickOrderConsoCode, (SELECT po.status FROM pick_order po WHERE po.id = MIN(dpolr.pick_order_id) LIMIT 1) as pickOrderStatus, (SELECT do.orderDate FROM delivery_order do WHERE do.id = MIN(dpolr.do_order_id) LIMIT 1) as deliveryDate, - -- ✅ 计算总箱数 + -- 计算总箱数 (SELECT SUM(pol_count.line_count) FROM ( SELECT COUNT(*) as line_count @@ -4588,7 +4588,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto AND dpor.ticket_status = 'completed' """.trimIndent() - // ✅ 添加搜索过滤条件 + // 添加搜索过滤条件 val conditions = mutableListOf() val params = mutableMapOf("userId" to userId) @@ -4625,11 +4625,11 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto println("🔍 Executing SQL: $finalSql") val results = jdbcDao.queryForList(finalSql, params) - println("✅ Found ${results.size} completed do_pick_order_record entries") + println(" Found ${results.size} completed do_pick_order_record entries") - // ✅ 格式化返回数据 + // 格式化返回数据 val formattedResults = results.map { row -> - // ✅ 解析 pick order IDs 列表 + // 解析 pick order IDs 列表 val pickOrderIdsStr = row["pickOrderIds"] as? String ?: "" val pickOrderIds = if (pickOrderIdsStr.isNotEmpty()) { pickOrderIdsStr.split(",").mapNotNull { it.trim().toLongOrNull() } @@ -4637,7 +4637,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto emptyList() } - // ✅ 解析 delivery order IDs 列表 + // 解析 delivery order IDs 列表 val deliveryOrderIdsStr = row["deliveryOrderIds"] as? String ?: "" val deliveryOrderIds = if (deliveryOrderIdsStr.isNotEmpty()) { deliveryOrderIdsStr.split(",").mapNotNull { it.trim().toLongOrNull() } @@ -4676,8 +4676,8 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto ) } - println("✅ Formatted ${formattedResults.size} results") - formattedResults // ✅ 返回格式化后的结果 + println(" Formatted ${formattedResults.size} results") + formattedResults // 返回格式化后的结果 } catch (e: Exception) { println("❌ Error in getCompletedDoPickOrders: ${e.message}") e.printStackTrace() @@ -4689,7 +4689,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map val pickOrderId = (poInfo["pick_order_id"] as? Number)?.toLong() - // ✅ 查询该 pick order 的所有 lines 和 lots(复用之前的 SQL) + // 查询该 pick order 的所有 lines 和 lots(复用之前的 SQL) val linesSql = """ SELECT po.id as pickOrderId, @@ -4830,7 +4830,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map @@ -5069,7 +5069,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map> { try { println("🔍 Starting getFgPickOrdersFromRecordByPickOrderId with pickOrderId: $pickOrderId") @@ -5084,7 +5084,7 @@ open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List() { - + @Size(max = 50) @NotNull @Column(name = "productprocesscode", nullable = false, unique = true, length = 50) diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt index 4698df6..0f054e3 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt @@ -14,12 +14,12 @@ import com.ffii.fpsms.modules.master.entity.BomProcess open class ProductProcessLine : BaseEntity() { - // ✅ 添加 @ManyToOne + // 添加 @ManyToOne @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "operatorId") open var operator: User? = null - // ✅ 添加 @ManyToOne + // 添加 @ManyToOne @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "equipmentId") open var equipment: Equipment? = null @@ -35,7 +35,7 @@ open class ProductProcessLine : BaseEntity() { @Column(name = "equipment_name", length = 100) open var equipmentType: String? = null - // ✅ 添加 @ManyToOne + // 添加 @ManyToOne @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "byproductId") open var byproduct: Items? = null diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLineRepository.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLineRepository.kt index f0d572e..74ea89b 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLineRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLineRepository.kt @@ -8,4 +8,6 @@ interface ProductProcessLineRepository : JpaRepository fun findByProductProcess_Id(productProcessId: Long): List fun findByProductProcess_IdAndHandler_Id(productProcessId: Long, handlerId: Long): List fun findByHandler_IdAndStartTimeIsNotNullAndEndTimeIsNull(handlerId: Long): List + fun findByProductProcess_IdIn(ids: List): List + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductionProcessIssue.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductionProcessIssue.kt index ecd8db1..4eccc5b 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductionProcessIssue.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductionProcessIssue.kt @@ -8,8 +8,8 @@ import jakarta.validation.constraints.Size import java.time.LocalDateTime @Entity -@Table(name = "productionprocessissue") // ✅ 修复:改为正确的表名 -open class ProductionProcessIssue : BaseEntity() { // ✅ 修复:改为正确的类名 +@Table(name = "productionprocessissue") // 修复:改为正确的表名 +open class ProductionProcessIssue : BaseEntity() { // 修复:改为正确的类名 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "productprocessid", nullable = false) 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 f85b5a8..c3aaae7 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 @@ -45,7 +45,7 @@ open class ProductProcessService( open fun findAll(pageable: Pageable): Page { println("📋 Service: Finding all ProductProcess with page: ${pageable.pageNumber}, size: ${pageable.pageSize}") val result = productProcessRepository.findAll(pageable) - println("✅ Service: Found ${result.totalElements} records") + println(" Service: Found ${result.totalElements} records") return result } @@ -89,14 +89,14 @@ open class ProductProcessService( } val savedProcess = productProcessRepository.save(productProcess) - println("✅ Service: ProductProcess created with ID: ${savedProcess.id}") + println(" Service: ProductProcess created with ID: ${savedProcess.id}") // 4. 查询 BOM 的所有工序步骤 val bomProcesses = bomProcessRepository.findByBomIdOrderBySeqNo(request.bomId) println("🔍 Service: Found ${bomProcesses.size} BOM processes") // 5. 为每个 BOM Process 创建 ProductProcessLine - bomProcesses.forEachIndexed { index, bomProcess -> // ✅ 修复 forEach + bomProcesses.forEachIndexed { index, bomProcess -> // 修复 forEach val line = ProductProcessLine().apply { this.productProcess = savedProcess this.bomProcess = bomProcess @@ -109,7 +109,7 @@ open class ProductProcessService( println("➕ Service: Created line ${index + 1} - seq: ${line.seqNo}, name: ${line.name}") } - println("✅ Service: All ${bomProcesses.size} lines created automatically") + println(" Service: All ${bomProcesses.size} lines created automatically") return SaveProductProcessResponse( id = savedProcess.id!!, @@ -126,11 +126,11 @@ open class ProductProcessService( } - // ✅ 添加:查询工序的所有步骤 + // 添加:查询工序的所有步骤 open fun getLines(productProcessId: Long): List { println("📋 Service: Getting lines for process ID: $productProcessId") val lines = productProcessLineRepository.findByProductProcess_Id(productProcessId) - println("✅ Service: Found ${lines.size} lines") + println(" Service: Found ${lines.size} lines") return lines } @@ -140,7 +140,7 @@ open class ProductProcessService( productProcess.status = ProductProcessStatus.IN_PROGRESS productProcess.startTime = LocalDateTime.now() val saved = productProcessRepository.save(productProcess) - println("✅ Service: Process started, status: ${saved.status}") + println(" Service: Process started, status: ${saved.status}") return saved } @@ -160,7 +160,7 @@ open class ProductProcessService( productProcessRepository.save(productProcess) val savedIssue = productionProcessIssueRepository.save(issue) - println("✅ Service: Process stopped, issue ID: ${savedIssue.id}") + println(" Service: Process stopped, issue ID: ${savedIssue.id}") return savedIssue } @@ -178,7 +178,7 @@ open class ProductProcessService( productProcessRepository.save(productProcess) val savedIssue = productionProcessIssueRepository.save(issue) - println("✅ Service: Process resumed, total stop time: ${savedIssue.totalTime} minutes") + println(" Service: Process resumed, total stop time: ${savedIssue.totalTime} minutes") return savedIssue } @@ -188,7 +188,7 @@ open class ProductProcessService( productProcess.status = ProductProcessStatus.COMPLETED productProcess.endTime = LocalDateTime.now() val saved = productProcessRepository.save(productProcess) - println("✅ Service: Process completed") + println(" Service: Process completed") return saved } @@ -206,7 +206,7 @@ open class ProductProcessService( } val saved = productProcessLineRepository.save(line) - println("✅ Service: Line added with ID: ${saved.id}") + println(" Service: Line added with ID: ${saved.id}") return SaveProductProcessLineResponse(saved.id!!) } @@ -230,20 +230,20 @@ open class ProductProcessService( } val saved = productProcessLineRepository.save(line) - println("✅ Service: Line output updated") + println(" Service: Line output updated") return saved } open fun getIssues(productProcessId: Long): List { println("📋 Service: Getting issues for ProductProcess ID: $productProcessId") val issues = productionProcessIssueRepository.findByProductProcess_Id(productProcessId) - println("✅ Service: Found ${issues.size} issues") + println(" Service: Found ${issues.size} issues") return issues } open fun findByJobOrderId(jobOrderId: Long): List { println("🔍 Service: Finding ProductProcess by jobOrderId: $jobOrderId") val result = productProcessRepository.findByJobOrder_Id(jobOrderId) - println("✅ Service: Found ${result.size} processes") + println(" Service: Found ${result.size} processes") return result } @@ -280,7 +280,7 @@ open class ProductProcessService( ) } - println("✅ Service: Returning ${result.size} processes with ${result.sumOf { it.lines.size }} total lines") + println(" Service: Returning ${result.size} processes with ${result.sumOf { it.lines.size }} total lines") return result } open fun findAllAsDto(pageable: Pageable): Page { @@ -300,7 +300,7 @@ open class ProductProcessService( ) } - println("✅ Service: Converted ${dtoList.size} entities to DTOs") + println(" Service: Converted ${dtoList.size} entities to DTOs") return org.springframework.data.domain.PageImpl(dtoList, pageable, entityPage.totalElements) } @@ -435,7 +435,7 @@ open class ProductProcessService( val line = productProcessLineRepository.findById(lineId) .orElseThrow { IllegalArgumentException("Line not found") } - // ✅ 修复:使用 UserRepository 获取 User 对象 + // 修复:使用 UserRepository 获取 User 对象 val user = userRepository.findById(userId) .orElseThrow { IllegalArgumentException("User not found with id: $userId") } @@ -443,13 +443,13 @@ open class ProductProcessService( line.startTime = LocalDateTime.now() val saved = productProcessLineRepository.save(line) - println("✅ Service: Line started, handlerId: ${saved.handler?.id}") + println(" Service: Line started, handlerId: ${saved.handler?.id}") return saved } open fun findPendingLinesByHandlerId(handlerId: Long): List { println("🔍 Service: Finding pending lines for handlerId: $handlerId") val lines = productProcessLineRepository.findByHandler_IdAndStartTimeIsNotNullAndEndTimeIsNull(handlerId) - println("✅ Service: Found ${lines.size} pending lines") + println(" Service: Found ${lines.size} pending lines") return lines } @@ -753,42 +753,45 @@ open fun updateProductProcessLineQty(request: UpdateProductProcessLineQtyRequest errorPosition = null, ) } -/* -open fun getAllJoborderProductProcessInfo(): List { - val productProcesses = productProcessRepository.findAllByDeletedIsFalse() - val productProcessId=productProcesses.map { it.id } - val productProcessLines = productProcessLineRepository.findByProductProcess_Id(productProcessId.map { it.id }) - return productProcesses.map { process -> - AllJoborderProductProcessInfoResponse( - id = productProcesses.id, - productProcessCode = productProcesses.productProcessCode, - status = productProcesses.status, - startTime = productProcesses.startTime, - endTime = productProcesses.endTime, - date = productProcesses.date, - bomId = productProcesses.bom.id, - bomName = productProcesses.bom.name, - jobOrderId = productProcesses.jobOrder.id, - lines = productProcessLines.map { line -> - ProductProcessInfoResponse( - id = line.id?:0, - productProcessCode = process.productProcessCode?:"", - operatorId = process.operator?.id?:0, - operatorName = process.operator?.name?:"", - equipmentId = line.equipment?.id?:0, - equipmentName = process.equipment?.name?:"", - startTime = line.startTime?:LocalDateTime.now(), - endTime = line.endTime?:LocalDateTime.now(), - date = line.date?:LocalDate.now(), - status = line.status?:"", - bomId = process.bom?.id?:0, - bomName = process.bom?.name?:"", - jobOrderId = process.jobOrder?.id?:0 - ) - } - ) + + open fun getAllJoborderProductProcessInfo(): List { + val productProcesses = productProcessRepository.findAllByDeletedIsFalse() + val productProcessIds = productProcesses.map { it.id } + + + return productProcesses.map { productProcesses -> + val productProcessLines = productProcessLineRepository.findByProductProcess_Id(productProcesses.id?:0L) + val jobOrder = jobOrderRepository.findById(productProcesses.jobOrder?.id?:0L).orElse(null) + val FinishedProductProcessLineCount = productProcessLineRepository.findByProductProcess_Id(productProcesses.id?:0L).count { it.status == "Completed" } + AllJoborderProductProcessInfoResponse( + id = productProcesses.id ?: 0L, + productProcessCode = productProcesses.productProcessCode, + status = productProcesses.status.value, + startTime = productProcesses.startTime, + endTime = productProcesses.endTime, + date = productProcesses.date, + bomId = productProcesses.bom?.id, + itemName = productProcesses.item?.name, + jobOrderId = productProcesses.jobOrder?.id, + jobOrderCode = jobOrder?.code, + productProcessLineCount = productProcessLines.size, + FinishedProductProcessLineCount = FinishedProductProcessLineCount, + lines = productProcessLines + .map { line -> + ProductProcessInfoResponse( + id = line.id ?: 0, + operatorId = line.operator?.id, + operatorName = line.operator?.name ?: "", + equipmentId = line.equipment?.id, + equipmentName = line.equipmentType?: "", + startTime = line.startTime, + endTime = line.endTime, + status = line.status ?: "" + ) + } + ) + } } -} -*/ + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt index 84f888e..163905b 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt @@ -16,18 +16,18 @@ class ProductProcessController( ) { @GetMapping - fun findAll(pageable: Pageable): Page { // ✅ 改为返回 DTO + fun findAll(pageable: Pageable): Page { // 改为返回 DTO println("📋 Controller: GET /product-process - Finding all") - val result = productProcessService.findAllAsDto(pageable) // ✅ 使用新方法 - println("✅ Controller: Returning ${result.totalElements} records") + val result = productProcessService.findAllAsDto(pageable) // 使用新方法 + println(" Controller: Returning ${result.totalElements} records") return result } @GetMapping("/{id}") - fun findById(@PathVariable id: Long): ProductProcessSimpleResponse { // ✅ 改为返回 DTO + fun findById(@PathVariable id: Long): ProductProcessSimpleResponse { // 改为返回 DTO println("🔍 Controller: GET /product-process/$id") - val result = productProcessService.findByIdAsDto(id) // ✅ 使用新方法 - println("✅ Controller: Found: ${result.productProcessCode}") + val result = productProcessService.findByIdAsDto(id) // 使用新方法 + println(" Controller: Found: ${result.productProcessCode}") return result } @@ -35,24 +35,24 @@ class ProductProcessController( fun findByCode(@PathVariable code: String): ProductProcess { println("🔍 Controller: GET /product-process/code/$code") val result = productProcessService.findByCode(code) - println("✅ Controller: Found ID: ${result.id}") + println(" Controller: Found ID: ${result.id}") return result } @PostMapping fun create(@RequestBody request: SaveProductProcessRequest): SaveProductProcessResponse { println("💾 Controller: POST /product-process - Creating ProductProcess") - //println("📦 Controller: Request - bomId: ${request.bomId}, jobOrderId: ${request.jobOrderId}, date: ${request.date}") // ✅ 修复 + //println("📦 Controller: Request - bomId: ${request.bomId}, jobOrderId: ${request.jobOrderId}, date: ${request.date}") // 修复 val result = productProcessService.create(request) - println("✅ Controller: Created ProductProcess - ID: ${result.id}, Code: ${result.productProcessCode}, Lines: ${result.linesCreated}") // ✅ 改进日志 + println(" Controller: Created ProductProcess - ID: ${result.id}, Code: ${result.productProcessCode}, Lines: ${result.linesCreated}") // 改进日志 return result } @PostMapping("/{id}/start") fun startProcess(@PathVariable id: Long, @RequestParam operatorId: Long): ProductProcessSimpleResponse { println("▶️ Controller: POST /product-process/$id/start - operatorId: $operatorId") - val result = productProcessService.startProcessAsDto(id, operatorId) // ✅ 改用 AsDto 方法 - println("✅ Controller: Process started") + val result = productProcessService.startProcessAsDto(id, operatorId) // 改用 AsDto 方法 + println(" Controller: Process started") return result } @@ -60,11 +60,11 @@ class ProductProcessController( fun stopProcess( @PathVariable id: Long, @RequestBody request: StopProcessRequest - ): ProductionProcessIssueResponse { // ✅ 改为 Issue Response + ): ProductionProcessIssueResponse { // 改为 Issue Response println("⏸️ Controller: POST /product-process/$id/stop") println("📦 Controller: Reason: ${request.reason}") - val result = productProcessService.stopProcessAsDto(id, request) // ✅ 使用返回 DTO 的方法 - println("✅ Controller: Process stopped, issue ID: ${result.id}") + val result = productProcessService.stopProcessAsDto(id, request) // 使用返回 DTO 的方法 + println(" Controller: Process stopped, issue ID: ${result.id}") return result } @@ -72,18 +72,18 @@ class ProductProcessController( fun resumeProcess( @PathVariable id: Long, @PathVariable issueId: Long - ): ProductionProcessIssueResponse { // ✅ 改为 Issue Response + ): ProductionProcessIssueResponse { // 改为 Issue Response println("▶️ Controller: POST /product-process/$id/resume/$issueId") - val result = productProcessService.resumeProcessAsDto(id, issueId) // ✅ 使用返回 DTO 的方法 - println("✅ Controller: Process resumed, stop duration: ${result.totalTime} min") + val result = productProcessService.resumeProcessAsDto(id, issueId) // 使用返回 DTO 的方法 + println(" Controller: Process resumed, stop duration: ${result.totalTime} min") return result } @PostMapping("/{id}/complete") fun completeProcess(@PathVariable id: Long): ProductProcessSimpleResponse { println("✔️ Controller: POST /product-process/$id/complete") - val result = productProcessService.completeProcessAsDto(id) // ✅ 改用 AsDto 方法 - println("✅ Controller: Process completed") + val result = productProcessService.completeProcessAsDto(id) // 改用 AsDto 方法 + println(" Controller: Process completed") return result } @@ -95,7 +95,7 @@ class ProductProcessController( println("➕ Controller: POST /product-process/$id/lines") println("📦 Controller: Line - name: ${request.name}, equipment: ${request.equipmentType}") val result = productProcessService.addLine(id, request) - println("✅ Controller: Line added with ID: ${result.id}") + println(" Controller: Line added with ID: ${result.id}") return result } @@ -103,10 +103,10 @@ class ProductProcessController( fun updateLineOutput( @PathVariable lineId: Long, @RequestBody request: UpdateLineOutputRequest - ): ProductProcessLineResponse { // ✅ 改为 ProductProcessLineResponse + ): ProductProcessLineResponse { // 改为 ProductProcessLineResponse println("📊 Controller: PUT /lines/$lineId/output") val result = productProcessService.updateLineOutputAsDto(lineId, request) - println("✅ Controller: Line output updated") + println(" Controller: Line output updated") return result } @@ -114,32 +114,32 @@ class ProductProcessController( fun getLines(@PathVariable id: Long): List { println("📋 Controller: GET /product-process/$id/lines") val result = productProcessService.getLinesAsDto(id) - println("✅ Controller: Found ${result.size} lines") + println(" Controller: Found ${result.size} lines") return result } @GetMapping("/{id}/issues") - fun getIssues(@PathVariable id: Long): List { // ✅ 改为 Issue Response List + fun getIssues(@PathVariable id: Long): List { // 改为 Issue Response List println("📋 Controller: GET /product-process/$id/issues") - val result = productProcessService.getIssuesAsDto(id) // ✅ 使用返回 DTO 的方法 - println("✅ Controller: Found ${result.size} issues") + val result = productProcessService.getIssuesAsDto(id) // 使用返回 DTO 的方法 + println(" Controller: Found ${result.size} issues") return result } @GetMapping("/by-job-order/{jobOrderId}") - fun findByJobOrderId(@PathVariable jobOrderId: Long): List { // ✅ 改为返回 DTO + fun findByJobOrderId(@PathVariable jobOrderId: Long): List { // 改为返回 DTO println("🔍 Controller: GET /product-process/by-job-order/$jobOrderId") - val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) // ✅ 直接使用 with-lines 方法 - println("✅ Controller: Found ${result.size} processes for Job Order $jobOrderId") + val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) // 直接使用 with-lines 方法 + println(" Controller: Found ${result.size} processes for Job Order $jobOrderId") return result } - // ✅ 额外添加:获取带 lines 的完整数据 + // 额外添加:获取带 lines 的完整数据 @GetMapping("/by-job-order/{jobOrderId}/with-lines") fun findByJobOrderIdWithLines(@PathVariable jobOrderId: Long): List { println("🔍 Controller: GET /product-process/by-job-order/$jobOrderId/with-lines") val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) - println("✅ Controller: Found ${result.size} processes with lines for Job Order $jobOrderId") + println(" Controller: Found ${result.size} processes with lines for Job Order $jobOrderId") return result } @@ -147,7 +147,7 @@ class ProductProcessController( fun startLine(@PathVariable lineId: Long, @RequestParam userId: Long): ProductProcessLineResponse { println("▶️ Controller: POST /product-process/lines/$lineId/start - userId: $userId") val entity = productProcessService.startLine(lineId, userId) - // ✅ 修复:返回正确的 DTO + // 修复:返回正确的 DTO return productProcessService.getLinesAsDto(entity.productProcess?.id!!).find { it.id == entity.id!! }!! } @@ -183,10 +183,10 @@ class ProductProcessController( fun demoupdateqty(@PathVariable lineId: Long, @RequestBody request: UpdateProductProcessLineQtyRequest): MessageResponse { return productProcessService.updateProductProcessLineQty(request) } - /* + @GetMapping("/Demo/Process/all") fun demoprocessall(): List { return productProcessService.getAllJoborderProductProcessInfo() } - */ + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt index bc9848c..84c0a52 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt @@ -27,8 +27,8 @@ data class ProductionProcessIssueResponse( ) data class SaveProductProcessResponse( val id: Long, - val productProcessCode: String? = null, // ✅ 添加 - val linesCreated: Int = 0 // ✅ 添加 + val productProcessCode: String? = null, // 添加 + val linesCreated: Int = 0 // 添加 ) data class ProductProcessWithLinesResponse( val id: Long, @@ -142,22 +142,22 @@ data class AllJoborderProductProcessInfoResponse( val endTime: LocalDateTime?, val date: LocalDate?, val bomId: Long?, - val bomName: String?, + val itemName: String?, val jobOrderId: Long?, + val jobOrderCode: String?, + val productProcessLineCount: Int, + val FinishedProductProcessLineCount: Int, + val lines: List ) data class ProductProcessInfoResponse( val id: Long, - val productProcessCode: String?, val operatorId: Long?, val operatorName: String?, val equipmentId: Long?, val equipmentName: String?, val startTime: LocalDateTime?, val endTime: LocalDateTime?, - val date: LocalDate?, val status: String, - val bomId: Long?, - val bomName: String?, - val jobOrderId: Long? + ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt index 1e984ed..3eb2a75 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt @@ -121,7 +121,7 @@ open class InventoryLotLineService( val updatedLotLine = saveInventoryLotLine(updateRequest) - // ✅ ADD THIS: Update inventory table after lot line status change + // ADD THIS: Update inventory table after lot line status change updateInventoryTable(updatedLotLine) return MessageResponse( @@ -134,7 +134,7 @@ open class InventoryLotLineService( ) } - // ✅ ADD THIS: New method to update inventory table + // ADD THIS: New method to update inventory table private fun updateInventoryTable(inventoryLotLine: InventoryLotLine) { try { // Get the item ID from the inventory lot diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt index f789652..b875ac6 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt @@ -97,7 +97,7 @@ val existingStockOutLine = stockOutLineRepository.findByPickOrderLineIdAndInvent ) if (existingStockOutLine.isNotEmpty()) { - // ✅ 如果已存在,返回 null 表示不需要创建 + // 如果已存在,返回 null 表示不需要创建 return MessageResponse( id = null, name = "Stock out line already exists", @@ -189,7 +189,7 @@ fun handleQc(stockOutLine: StockOutLine, request: UpdateStockOutLineRequest): Li @Transactional open fun createWithoutConso(request: CreateStockOutLineWithoutConsoRequest): MessageResponse { try { - // ✅ Get stockOutId from pickOrderLineId with detailed error + // Get stockOutId from pickOrderLineId with detailed error val stockOutId = getStockOutIdFromPickOrderLine(request.pickOrderLineId) println("Found stockOutId: $stockOutId for pickOrderLineId: ${request.pickOrderLineId}") @@ -253,16 +253,16 @@ open fun createWithoutConso(request: CreateStockOutLineWithoutConsoRequest): Mes } } -// ✅ Update helper method with detailed error messages +// Update helper method with detailed error messages private fun getStockOutIdFromPickOrderLine(pickOrderLineId: Long): Long { println("Getting stockOutId for pickOrderLineId: $pickOrderLineId") - // ✅ Fixed: Use poId instead of pick_order_id + // Fixed: Use poId instead of pick_order_id val sql = """ SELECT so.id as stockOutId, so.consoPickOrderCode, po.consoCode FROM stock_out so JOIN pick_order po ON po.consoCode = so.consoPickOrderCode - JOIN pick_order_line pol ON pol.poId = po.id -- ✅ Fixed: Use poId + JOIN pick_order_line pol ON pol.poId = po.id -- Fixed: Use poId WHERE pol.id = :pickOrderLineId """.trimIndent() @@ -569,7 +569,7 @@ private fun getStockOutIdFromPickOrderLine(pickOrderLineId: Long): Long { throw e } } - // ✅ ADD THIS: Handle lot rejection when stock out line is rejected + // ADD THIS: Handle lot rejection when stock out line is rejected private fun handleLotRejectionFromStockOutLine(stockOutLine: StockOutLine) { try { println("=== HANDLING LOT REJECTION FROM STOCK OUT LINE ===") @@ -612,7 +612,7 @@ private fun getStockOutIdFromPickOrderLine(pickOrderLineId: Long): Long { } } -// ✅ ADD THIS: Update inventory table after lot rejection +// ADD THIS: Update inventory table after lot rejection private fun updateInventoryTableAfterLotRejection(inventoryLotLine: InventoryLotLine) { try { println("=== UPDATING INVENTORY TABLE ===") diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt index 163e53d..d3887c0 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt @@ -5,9 +5,9 @@ import com.ffii.fpsms.modules.pickOrder.entity.PickOrder import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository -import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssue // ✅ 添加 +import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssue // 添加 import com.ffii.fpsms.modules.pickOrder.entity.IssueCategory -import com.ffii.fpsms.modules.pickOrder.entity.HandleStatus // ✅ 添加 +import com.ffii.fpsms.modules.pickOrder.entity.HandleStatus // 添加 import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository import com.ffii.fpsms.modules.stock.entity.* import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus @@ -20,8 +20,8 @@ import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotResponse import org.springframework.stereotype.Service import java.math.BigDecimal import java.time.LocalDate -import java.time.LocalDateTime // ✅ 添加 -import java.time.format.DateTimeFormatter // ✅ 添加 +import java.time.LocalDateTime // 添加 +import java.time.format.DateTimeFormatter // 添加 import kotlin.jvm.optionals.getOrDefault import kotlin.jvm.optionals.getOrNull import org.springframework.transaction.annotation.Transactional @@ -46,7 +46,7 @@ open class SuggestedPickLotService( val pickOrderLineRepository: PickOrderLineRepository, val inventoryLotLineService: InventoryLotLineService, val itemUomService: ItemUomService, - val pickExecutionIssueRepository: PickExecutionIssueRepository, // ✅ 添加逗号 + val pickExecutionIssueRepository: PickExecutionIssueRepository, // 添加逗号 val pickOrderRepository: PickOrderRepository, val inventoryRepository: InventoryRepository, val failInventoryLotLineRepository: FailInventoryLotLineRepository, @@ -114,13 +114,13 @@ open class SuggestedPickLotService( val lotLines = availableInventoryLotLines[line.item?.id].orEmpty() val ratio = one // (salesUnit?.ratioN ?: one).divide(salesUnit?.ratioD ?: one, 10, RoundingMode.HALF_UP) - // ✅ FIX: Calculate remaining quantity needed (not the full required quantity) + // FIX: Calculate remaining quantity needed (not the full required quantity) val stockOutLines = stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(line.id!!) val totalPickedQty = stockOutLines .filter { it.status == "completed" || it.status == "partially_completed" || - (it.status == "rejected" && (it.qty ?: zero) > zero) // ✅ 包含已 picked 的 rejected + (it.status == "rejected" && (it.qty ?: zero) > zero) // 包含已 picked 的 rejected } .sumOf { it.qty ?: zero } val requiredQty = line.qty ?: zero @@ -132,7 +132,7 @@ open class SuggestedPickLotService( println("Remaining qty needed: $remainingQty") println("Stock out lines: ${stockOutLines.map { "${it.id}(status=${it.status}, qty=${it.qty})" }}") - // ✅ FIX: Use remainingQty instead of line.qty + // FIX: Use remainingQty instead of line.qty var remainingQtyToAllocate = remainingQty println("remaining1 $remainingQtyToAllocate (sales units)") val updatedLotLines = mutableListOf() @@ -142,7 +142,7 @@ open class SuggestedPickLotService( println("calculateRemainingQtyForInfo(lotLine) ${calculateRemainingQtyForInfo(lotLine)}") - // ✅ 修复:计算可用数量,转换为销售单位 + // 修复:计算可用数量,转换为销售单位 val availableQtyInBaseUnits = calculateRemainingQtyForInfo(lotLine) val holdQtyInBaseUnits = holdQtyMap[lotLine.id] ?: zero val availableQtyInSalesUnits = availableQtyInBaseUnits @@ -159,11 +159,11 @@ open class SuggestedPickLotService( val inventoryLotLine = lotLine.id?.let { inventoryLotLineService.findById(it).getOrNull() } val originalHoldQty = inventoryLotLine?.holdQty - // ✅ 修复:在销售单位中计算分配数量 + // 修复:在销售单位中计算分配数量 val assignQtyInSalesUnits = minOf(availableQtyInSalesUnits, remainingQtyToAllocate) remainingQtyToAllocate = remainingQtyToAllocate.minus(assignQtyInSalesUnits) val newHoldQtyInBaseUnits = holdQtyMap[lotLine.id] ?: zero - // ✅ 修复:将销售单位转换为基础单位来更新 holdQty + // 修复:将销售单位转换为基础单位来更新 holdQty val assignQtyInBaseUnits = assignQtyInSalesUnits.multiply(ratio) holdQtyMap[lotLine.id] = (holdQtyMap[lotLine.id] ?: zero).plus(assignQtyInBaseUnits) @@ -171,10 +171,10 @@ open class SuggestedPickLotService( type = SuggestedPickLotType.PICK_ORDER suggestedLotLine = inventoryLotLine pickOrderLine = line - qty = assignQtyInSalesUnits // ✅ 保存销售单位 + qty = assignQtyInSalesUnits // 保存销售单位 } } - // ✅ 修复:计算现有 suggestions 中 pending/checked 状态满足的数量 + // 修复:计算现有 suggestions 中 pending/checked 状态满足的数量 var existingSatisfiedQty = BigDecimal.ZERO // 查询现有的 suggestions 用于这个 pick order line @@ -194,7 +194,7 @@ open class SuggestedPickLotService( } } - // ✅ 调整 remainingQtyToAllocate,减去已经通过现有 suggestions 满足的数量 + // 调整 remainingQtyToAllocate,减去已经通过现有 suggestions 满足的数量 remainingQtyToAllocate = remainingQtyToAllocate.minus(existingSatisfiedQty) println("Existing satisfied qty: $existingSatisfiedQty") println("Adjusted remaining qty: $remainingQtyToAllocate") @@ -209,7 +209,7 @@ open class SuggestedPickLotService( type = SuggestedPickLotType.PICK_ORDER suggestedLotLine = null pickOrderLine = line - qty = remainingQtyToAllocate // ✅ 保存销售单位 + qty = remainingQtyToAllocate // 保存销售单位 } try { /* @@ -337,7 +337,7 @@ open class SuggestedPickLotService( } val savedStockOutLine = stockOutLIneRepository.saveAndFlush(stockOutLine) - println("✅ Created stock out line ID: ${savedStockOutLine.id} for suggestion ID: ${suggestion.id}") + println(" Created stock out line ID: ${savedStockOutLine.id} for suggestion ID: ${suggestion.id}") return savedStockOutLine @@ -357,7 +357,7 @@ open class SuggestedPickLotService( println("Pick Order Code: ${pickOrder.code}") println("Pick Order Status: ${pickOrder.status}") - // ✅ NEW: Get ALL pick orders for the same items + // NEW: Get ALL pick orders for the same items val itemIds = pickOrder.pickOrderLines.mapNotNull { it.item?.id }.distinct() println("Item IDs in current pick order: $itemIds") @@ -373,7 +373,7 @@ open class SuggestedPickLotService( allCompetingPickOrders.addAll(competingOrders) } - // ✅ FIX: Only resuggest pick orders that have rejected stock out lines + // FIX: Only resuggest pick orders that have rejected stock out lines val allPickOrdersToResuggest = (listOf(pickOrder) + allCompetingPickOrders) .filter { pickOrderToCheck -> // Only resuggest if the pick order has rejected stock out lines @@ -397,7 +397,7 @@ open class SuggestedPickLotService( println("Filtered pick orders to resuggest: ${allPickOrdersToResuggest.size}") println("Pick orders being resuggested: ${allPickOrdersToResuggest.map { "${it.code}(${it.status})" }}") - // ✅ FIX: Only resuggest if there are actually pick orders with rejected lots + // FIX: Only resuggest if there are actually pick orders with rejected lots if (allPickOrdersToResuggest.isEmpty()) { println("No pick orders need resuggesting - no rejected lots found") return MessageResponse( @@ -410,21 +410,21 @@ open class SuggestedPickLotService( ) } - // ✅ FIX: Get all pick order line IDs for the orders to resuggest + // FIX: Get all pick order line IDs for the orders to resuggest val allPickOrderLineIds = allPickOrdersToResuggest .flatMap { it.pickOrderLines } .mapNotNull { it.id } println("All pick order line IDs to resuggest: $allPickOrderLineIds") - // ✅ FIX: Get all existing suggestions for these pick order lines + // FIX: Get all existing suggestions for these pick order lines val allSuggestions = suggestedPickLotRepository.findAllByPickOrderLineIdIn(allPickOrderLineIds) println("Found ${allSuggestions.size} existing suggestions") - // ✅ 删除第 376-395 行的旧代码,替换为: -// ✅ FIX: Separate suggestions to keep (those WITHOUT rejected stock out lines) and delete + // 删除第 376-395 行的旧代码,替换为: +// FIX: Separate suggestions to keep (those WITHOUT rejected stock out lines) and delete val suggestionsToKeep = allSuggestions.filter { suggestion -> val pickOrderLineId = suggestion.pickOrderLine?.id val suggestedLotLineId = suggestion.suggestedLotLine?.id @@ -434,14 +434,14 @@ val suggestionsToKeep = allSuggestions.filter { suggestion -> pickOrderLineId, suggestedLotLineId ) - // ✅ 保留没有 rejected stock out lines 的 suggestions + // 保留没有 rejected stock out lines 的 suggestions !stockOutLines.any { it.status == "rejected" } } else { true // 保留有问题的 suggestions 用于调试 } } -// ✅ 只删除有 rejected stock out lines 的 suggestions +// 只删除有 rejected stock out lines 的 suggestions val suggestionsToDelete = allSuggestions.filter { suggestion -> val pickOrderLineId = suggestion.pickOrderLine?.id val suggestedLotLineId = suggestion.suggestedLotLine?.id @@ -451,7 +451,7 @@ val suggestionsToDelete = allSuggestions.filter { suggestion -> pickOrderLineId, suggestedLotLineId ) - stockOutLines.any { it.status == "rejected" } // ✅ 只删除 rejected 的 + stockOutLines.any { it.status == "rejected" } // 只删除 rejected 的 } else { suggestedLotLineId == null } @@ -461,7 +461,7 @@ val suggestionsToDelete = allSuggestions.filter { suggestion -> println("Suggestions to keep (with rejected stock out lines): ${suggestionsToKeep.size}") println("Suggestions to delete: ${suggestionsToDelete.size}") - // ✅ FIX: Clear holdQty ONLY for lots that have rejected stock out lines + // FIX: Clear holdQty ONLY for lots that have rejected stock out lines val rejectedLotIds = suggestionsToDelete.mapNotNull { it.suggestedLotLine?.id }.distinct() println("Rejected lot IDs (clearing holdQty only): $rejectedLotIds") @@ -477,7 +477,7 @@ val suggestionsToDelete = allSuggestions.filter { suggestion -> println("Keeping all suggestions (including rejected ones for display)") - // ✅ NEW: Build holdQtyMap with existing holdQty from other pick orders + // NEW: Build holdQtyMap with existing holdQty from other pick orders val existingHoldQtyMap = mutableMapOf() // Get all lots that are being used by other pick orders (including those NOT being resuggested) @@ -507,9 +507,9 @@ println("Keeping all suggestions (including rejected ones for display)") println("Final existing holdQtyMap: $existingHoldQtyMap") - // ✅ FIX: Create new suggestions for all pick orders to resuggest + // FIX: Create new suggestions for all pick orders to resuggest allPickOrdersToResuggest.forEach { pickOrderToResuggest -> - // ✅ 只获取有 rejected stock out lines 的 pick order lines + // 只获取有 rejected stock out lines 的 pick order lines val problematicPickOrderLines = pickOrderToResuggest.pickOrderLines.filter { pol -> val stockOutLines = stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(pol.id!!) stockOutLines.any { it.status == "rejected" } @@ -518,7 +518,7 @@ println("Keeping all suggestions (including rejected ones for display)") if (problematicPickOrderLines.isNotEmpty()) { println("=== Creating new suggestions for pick order: ${pickOrderToResuggest.code} ===") - // ✅ 调用 suggestionForPickOrderLines 生成新的 suggestions + // 调用 suggestionForPickOrderLines 生成新的 suggestions val request = SuggestedPickLotForPolRequest( pickOrderLines = problematicPickOrderLines, holdQtyMap = existingHoldQtyMap.toMutableMap() @@ -533,24 +533,24 @@ println("Keeping all suggestions (including rejected ones for display)") if (response.suggestedList.isNotEmpty()) { println("Saving ${response.suggestedList.size} new suggestions") - // ✅ 获取现有的 pending/checked 状态的 suggestions(可以更新的) + // 获取现有的 pending/checked 状态的 suggestions(可以更新的) val existingUpdatableSuggestions = suggestionsToKeep .filter { it.suggestedLotLine?.id != null } .groupBy { it.pickOrderLine?.id to it.suggestedLotLine?.id } .mapValues { it.value.first() } // 每个 (lineId, lotId) 只取第一个 - // ✅ 处理新的 suggestions:更新现有的或创建新的 + // 处理新的 suggestions:更新现有的或创建新的 val suggestionsToSave = response.suggestedList.mapNotNull { newSugg -> val key = newSugg.pickOrderLine?.id to newSugg.suggestedLotLine?.id val lineId = newSugg.pickOrderLine?.id val lotId = newSugg.suggestedLotLine?.id if (lineId != null && lotId != null) { - // ✅ 检查这个 lot 是否已有 suggestion + // 检查这个 lot 是否已有 suggestion val existingSugg = existingUpdatableSuggestions[key] if (existingSugg != null) { - // ✅ 检查现有 suggestion 的 stock_out_line 状态 + // 检查现有 suggestion 的 stock_out_line 状态 val stockOutLines = stockOutLIneRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse( lineId, lotId ) @@ -560,23 +560,23 @@ println("Keeping all suggestions (including rejected ones for display)") } if (canUpdate) { - // ✅ Case 1: 更新现有的 suggestion + // Case 1: 更新现有的 suggestion existingSugg.qty = newSugg.qty existingSugg.modified = LocalDateTime.now() existingSugg.modifiedBy = "system" println("⚠️ Updated existing suggestion ${existingSugg.id} for lot $lotId: new qty=${newSugg.qty}") existingSugg } else { - // ✅ Case 2: 已完成/拒绝,跳过(不更新,也不创建新的) + // Case 2: 已完成/拒绝,跳过(不更新,也不创建新的) println("⏭️ Skipping lot $lotId - already ${stockOutLines.first().status}") null } } else { - // ✅ 没有现有的 suggestion,创建新的 + // 没有现有的 suggestion,创建新的 newSugg } } else if (lotId == null) { - // ✅ lotId=null:检查是否已有 resuggest_issue + // lotId=null:检查是否已有 resuggest_issue val existingResuggestIssues = pickExecutionIssueRepository .findByPickOrderLineIdAndDeletedFalse(lineId ?: 0L) .filter { it.issueCategory.name == "resuggest_issue" } @@ -601,20 +601,20 @@ println("Keeping all suggestions (including rejected ones for display)") if (updatedSuggestions.isNotEmpty()) { val savedUpdated = suggestedPickLotRepository.saveAllAndFlush(updatedSuggestions) allSavedSuggestions.addAll(savedUpdated) - println("✅ Updated ${savedUpdated.size} existing suggestions") + println(" Updated ${savedUpdated.size} existing suggestions") } // 保存新的 suggestions if (newSuggestions.isNotEmpty()) { val savedNew = suggestedPickLotRepository.saveAllAndFlush(newSuggestions) allSavedSuggestions.addAll(savedNew) - println("✅ Created ${savedNew.size} new suggestions") + println(" Created ${savedNew.size} new suggestions") } val savedSuggestions = allSavedSuggestions println("Saved/Updated ${savedSuggestions.size} suggestions") - // ✅ 为每个新 suggestion 创建 stock out line 或 issue + // 为每个新 suggestion 创建 stock out line 或 issue savedSuggestions.forEach { suggestion -> if (suggestion.suggestedLotLine != null) { val isNewSuggestion = response.suggestedList.any { @@ -624,10 +624,10 @@ println("Keeping all suggestions (including rejected ones for display)") } val stockOutLine = createStockOutLineForSuggestion(suggestion, pickOrderToResuggest) if (stockOutLine != null) { - println("✅ Created stock out line ${stockOutLine.id} for suggestion ${suggestion.id}") + println(" Created stock out line ${stockOutLine.id} for suggestion ${suggestion.id}") } } else { - // ✅ 如果 lot 是 null,表示没有可用的 lot,创建 resuggest_issue + // 如果 lot 是 null,表示没有可用的 lot,创建 resuggest_issue println("❌ No available lot for pick order line ${suggestion.pickOrderLine?.id}, creating resuggest_issue") val pickOrderLine = suggestion.pickOrderLine @@ -637,7 +637,7 @@ println("Keeping all suggestions (including rejected ones for display)") .findAllByPickOrderLineIdAndDeletedFalse(pickOrderLine.id!!) .filter { it.status == "rejected" } println("Rejected stock out lines: ${rejectedStockOutLines.size}") - // ✅ 修复:只创建一个 resuggest_issue(如果有 rejected lines) + // 修复:只创建一个 resuggest_issue(如果有 rejected lines) if (rejectedStockOutLines.isNotEmpty()) { println("Creating resuggest failure issue") createResuggestFailureIssue( @@ -653,7 +653,7 @@ println("Keeping all suggestions (including rejected ones for display)") } } - // ✅ 更新 holdQty + // 更新 holdQty response.holdQtyMap.forEach { (lotId, newHoldQty) -> if (lotId != null && newHoldQty != null && newHoldQty > BigDecimal.ZERO) { val lot = inventoryLotLineRepository.findById(lotId).orElse(null) @@ -670,7 +670,7 @@ println("Keeping all suggestions (including rejected ones for display)") } } } else { - // ✅ 如果完全没有生成任何 suggestions + // 如果完全没有生成任何 suggestions println("No suggestions generated at all for pick order: ${pickOrderToResuggest.code}") problematicPickOrderLines.forEach { pickOrderLine -> @@ -693,7 +693,7 @@ println("Keeping all suggestions (including rejected ones for display)") } } } - // ✅ FIX: Update inventory table for each pick order + // FIX: Update inventory table for each pick order allPickOrdersToResuggest.forEach { pickOrderToUpdate -> println("=== Updating inventory table for pick order: ${pickOrderToUpdate.code} ===") updateInventoryTableAfterResuggest(pickOrderToUpdate) @@ -727,12 +727,12 @@ println("Keeping all suggestions (including rejected ones for display)") private fun createResuggestFailureIssue( pickOrder: PickOrder, pickOrderLine: PickOrderLine, - rejectedStockOutLine: StockOutLineInfo // ✅ 使用 StockOutLineInfo + rejectedStockOutLine: StockOutLineInfo // 使用 StockOutLineInfo ) { try { val item = pickOrderLine.item - // ✅ 从 StockOutLineInfo 获取 inventoryLotLineId + // 从 StockOutLineInfo 获取 inventoryLotLineId val inventoryLotLineId = rejectedStockOutLine.inventoryLotLineId val inventoryLotLine = if (inventoryLotLineId != null) { inventoryLotLineRepository.findById(inventoryLotLineId).orElse(null) @@ -758,8 +758,8 @@ println("Keeping all suggestions (including rejected ones for display)") lotNo = inventoryLotLine?.inventoryLot?.lotNo, storeLocation = inventoryLotLine?.warehouse?.name, requiredQty = pickOrderLine.qty, - actualPickQty = rejectedStockOutLine.qty ?: BigDecimal.ZERO, // ✅ 直接使用,不需要 toBigDecimal() - missQty = (pickOrderLine.qty ?: BigDecimal.ZERO).minus(rejectedStockOutLine.qty ?: BigDecimal.ZERO), // ✅ 直接使用 + actualPickQty = rejectedStockOutLine.qty ?: BigDecimal.ZERO, // 直接使用,不需要 toBigDecimal() + missQty = (pickOrderLine.qty ?: BigDecimal.ZERO).minus(rejectedStockOutLine.qty ?: BigDecimal.ZERO), // 直接使用 badItemQty = BigDecimal.ZERO, issueRemark = "Resuggest failed: No alternative lots available for rejected lot ${inventoryLotLine?.inventoryLot?.lotNo}", pickerName = null, @@ -775,7 +775,7 @@ println("Keeping all suggestions (including rejected ones for display)") ) pickExecutionIssueRepository.save(issue) - println("✅ Created resuggest_issue: ${issue.issueNo} for pick order ${pickOrder.code}") + println(" Created resuggest_issue: ${issue.issueNo} for pick order ${pickOrder.code}") } catch (e: Exception) { println("❌ Error creating resuggest_issue: ${e.message}") @@ -849,16 +849,16 @@ private fun generateOptimalSuggestionsForAllPickOrders( .filter { it.expiryDate.isAfter(today) || it.expiryDate.isEqual(today) } .sortedBy { it.expiryDate } - // ✅ FIX: Get fresh lot data and reset holdQty to 0 for calculation + // FIX: Get fresh lot data and reset holdQty to 0 for calculation val lotEntities = inventoryLotLineRepository.findAllByIdIn(availableLots.mapNotNull { it.id }) lotEntities.forEach { lot -> lot.holdQty = BigDecimal.ZERO } - // ✅ FIX: Calculate remaining quantity for each pick order line - // ✅ FIX: Calculate remaining quantity for each pick order line + // FIX: Calculate remaining quantity for each pick order line + // FIX: Calculate remaining quantity for each pick order line val remainingQtyPerLine = pickOrderLines.associate { pol -> val stockOutLines = stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(pol.id!!) - // ✅ FIX: Count picked qty from ALL statuses except 'rejected' + // FIX: Count picked qty from ALL statuses except 'rejected' // This includes 'completed', 'pending', 'checked', 'partially_completed' val totalPickedQty = stockOutLines .sumOf { it.qty ?: BigDecimal.ZERO } @@ -872,7 +872,7 @@ private fun generateOptimalSuggestionsForAllPickOrders( pol.id to remainingQty }.toMutableMap() - // ✅ FIX: Filter out pick order lines that don't need more qty + // FIX: Filter out pick order lines that don't need more qty val remainingPickOrderLines = pickOrderLines.filter { pol -> val remainingQty = remainingQtyPerLine[pol.id] ?: zero remainingQty > zero @@ -915,7 +915,7 @@ private fun generateOptimalSuggestionsForAllPickOrders( } } - // ✅ FIX: Create insufficient stock suggestions for remaining quantities + // FIX: Create insufficient stock suggestions for remaining quantities remainingQtyPerLine.forEach { (lineId, remainingQty) -> if (remainingQty > zero) { val pickOrderLine = pickOrderLines.find { it.id == lineId } @@ -939,11 +939,11 @@ private fun updateInventoryTableAfterResuggest(pickOrder: PickOrder) { val itemIds = pickOrder.pickOrderLines.mapNotNull { it.item?.id }.distinct() itemIds.forEach { itemId -> - // ✅ FIX: Calculate onHoldQty for ALL pick orders that use this item, not just the current one + // FIX: Calculate onHoldQty for ALL pick orders that use this item, not just the current one val onHoldQty = inventoryLotLineRepository.findAllByInventoryLotItemIdAndStatus(itemId, InventoryLotLineStatus.AVAILABLE) .sumOf { it.holdQty ?: BigDecimal.ZERO } - // ✅ FIX: Use enum method instead of string method + // FIX: Use enum method instead of string method val unavailableQty = inventoryLotLineRepository.findAllByInventoryLotItemIdAndStatus(itemId, InventoryLotLineStatus.UNAVAILABLE) .sumOf { val inQty = it.inQty ?: BigDecimal.ZERO @@ -1110,17 +1110,17 @@ private fun generateCorrectSuggestionsWithExistingHolds(pickOrder: PickOrder): L val salesUnit = itemUomService.findSalesUnitByItemId(itemId) val ratio = one - // ✅ FIX: Get ALL inventory lots (both available and unavailable) + // FIX: Get ALL inventory lots (both available and unavailable) val allLots = inventoryLotLineService .allInventoryLotLinesByItemIdIn(listOf(itemId)) .filter { it.expiryDate.isAfter(today) || it.expiryDate.isEqual(today) } .sortedBy { it.expiryDate } - // ✅ FIX: Separate available and unavailable lots + // FIX: Separate available and unavailable lots val availableLots = allLots.filter { it.status == InventoryLotLineStatus.AVAILABLE.value } val unavailableLots = allLots.filter { it.status == InventoryLotLineStatus.UNAVAILABLE.value } - // ✅ FIX: Calculate total quantity that was previously held by unavailable lots + // FIX: Calculate total quantity that was previously held by unavailable lots var totalUnavailableHoldQty = BigDecimal.ZERO val modifiedUnavailableLots = mutableListOf() @@ -1128,19 +1128,19 @@ private fun generateCorrectSuggestionsWithExistingHolds(pickOrder: PickOrder): L val lot = lotInfo.id?.let { inventoryLotLineRepository.findById(it).orElse(null) } lot?.let { totalUnavailableHoldQty = totalUnavailableHoldQty.plus(it.holdQty ?: zero) - // ✅ Reset holdQty for unavailable lots + // Reset holdQty for unavailable lots it.holdQty = BigDecimal.ZERO - modifiedUnavailableLots.add(it) // ✅ Keep reference to modified entity + modifiedUnavailableLots.add(it) // Keep reference to modified entity } } - // ✅ FIX: Save the modified entities (not fresh ones from database) + // FIX: Save the modified entities (not fresh ones from database) if (modifiedUnavailableLots.isNotEmpty()) { inventoryLotLineRepository.saveAll(modifiedUnavailableLots) println("Reset holdQty for ${modifiedUnavailableLots.size} unavailable lots") } - // ✅ FIX: Add the unavailable hold quantity to the required quantity + // FIX: Add the unavailable hold quantity to the required quantity //val totalRequiredQty = requiredQty.plus(totalUnavailableHoldQty.divide(ratio, 2, RoundingMode.HALF_UP)) val totalRequiredQty = requiredQty var remainingQtyInSalesUnits = totalRequiredQty @@ -1222,7 +1222,7 @@ private fun generateCorrectSuggestionsWithOriginalHolds( .filter { it.expiryDate.isAfter(today) || it.expiryDate.isEqual(today) } .sortedBy { it.expiryDate } - // ✅ Calculate total quantity that needs to be redistributed + // Calculate total quantity that needs to be redistributed var totalRedistributeQty = requiredQty originalHoldQtyMap.forEach { (lotId, originalHoldQty) -> if (originalHoldQty > zero) { @@ -1478,7 +1478,7 @@ open fun updateSuggestedLotLineId(suggestedPickLotId: Long, newLotLineId: Long): suggestedPickLot.suggestedLotLine = newInventoryLotLine val savedSuggestedPickLot = suggestedPickLotRepository.save(suggestedPickLot) - println("✅ Successfully updated suggested pick lot ${suggestedPickLotId} to use lot line ${newLotLineId}") + println(" Successfully updated suggested pick lot ${suggestedPickLotId} to use lot line ${newLotLineId}") return MessageResponse( id = savedSuggestedPickLot.id, @@ -1509,7 +1509,7 @@ private fun createInsufficientStockIssue( insufficientQty: BigDecimal ) { try { - // ✅ 检查是否已存在相同的 issue(避免重复创建) + // 检查是否已存在相同的 issue(避免重复创建) val existingIssues = pickExecutionIssueRepository .findByPickOrderLineIdAndDeletedFalse(pickOrderLine.id ?: 0L) .filter { @@ -1557,7 +1557,7 @@ private fun createInsufficientStockIssue( ) pickExecutionIssueRepository.save(issue) - println("✅ Auto-created issue ${issue.issueNo} for insufficient stock (line ${pickOrderLine.id}, qty ${insufficientQty})") + println(" Auto-created issue ${issue.issueNo} for insufficient stock (line ${pickOrderLine.id}, qty ${insufficientQty})") } catch (e: Exception) { println("❌ Error creating insufficient stock issue: ${e.message}") diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt index 421112d..6558153 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt @@ -89,7 +89,7 @@ class InventoryLotLineController ( try { val result = inventoryLotLineService.updateInventoryLotLineStatus(request) - println("✅ Controller: Update successful - $result") + println(" Controller: Update successful - $result") return result } catch (e: Exception) { println("❌ Controller: Update failed - ${e.message}")