| @@ -436,7 +436,7 @@ open class DeliveryOrderService( | |||||
| ) | ) | ||||
| val createdPickOrder = pickOrderService.create(po) | val createdPickOrder = pickOrderService.create(po) | ||||
| println("🔍 DEBUG: Created pick order - ID: ${createdPickOrder.id}") | |||||
| println(" DEBUG: Created pick order - ID: ${createdPickOrder.id}") | |||||
| val consoCode = pickOrderService.assignConsoCode() | val consoCode = pickOrderService.assignConsoCode() | ||||
| val pickOrderEntity = pickOrderRepository.findById(createdPickOrder.id!!).orElse(null) | val pickOrderEntity = pickOrderRepository.findById(createdPickOrder.id!!).orElse(null) | ||||
| @@ -450,7 +450,7 @@ open class DeliveryOrderService( | |||||
| // Debug: Check pick order lines | // Debug: Check pick order lines | ||||
| println("�� DEBUG: Pick order has ${pickOrderEntity.pickOrderLines?.size ?: 0} pick order lines") | println("�� DEBUG: Pick order has ${pickOrderEntity.pickOrderLines?.size ?: 0} pick order lines") | ||||
| pickOrderEntity.pickOrderLines?.forEach { line -> | pickOrderEntity.pickOrderLines?.forEach { line -> | ||||
| println("🔍 DEBUG: Pick order line - Item ID: ${line.item?.id}, Qty: ${line.qty}") | |||||
| println(" DEBUG: Pick order line - Item ID: ${line.item?.id}, Qty: ${line.qty}") | |||||
| } | } | ||||
| @@ -460,7 +460,7 @@ open class DeliveryOrderService( | |||||
| ) | ) | ||||
| val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) | val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) | ||||
| println("🔍 DEBUG: Saved ${saveSuggestedPickLots.size} suggested pick lots") | |||||
| println(" DEBUG: Saved ${saveSuggestedPickLots.size} suggested pick lots") | |||||
| val insufficientCount = suggestions.suggestedList.count { it.suggestedLotLine == null } | val insufficientCount = suggestions.suggestedList.count { it.suggestedLotLine == null } | ||||
| if (insufficientCount > 0) { | if (insufficientCount > 0) { | ||||
| println("⚠️ WARNING: $insufficientCount items have insufficient stock (issues auto-created)") | println("⚠️ WARNING: $insufficientCount items have insufficient stock (issues auto-created)") | ||||
| @@ -525,11 +525,11 @@ open class DeliveryOrderService( | |||||
| val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() | val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() | ||||
| val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) | val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) | ||||
| println("🔍 DEBUG: Target date: $targetDate, Date prefix: $datePrefix") | |||||
| println(" DEBUG: Target date: $targetDate, Date prefix: $datePrefix") | |||||
| val truck = deliveryOrder.shop?.id?.let { shopId -> | val truck = deliveryOrder.shop?.id?.let { shopId -> | ||||
| println("🔍 DEBUG: Looking for truck with shop ID: $shopId") | |||||
| println(" DEBUG: Looking for truck with shop ID: $shopId") | |||||
| val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) | val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) | ||||
| println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId") | |||||
| println(" DEBUG: Found ${trucks.size} trucks for shop $shopId") | |||||
| // 移除提前返回,总是分析 items 分布 | // 移除提前返回,总是分析 items 分布 | ||||
| // 分析 DO order lines 中的 items 分布 | // 分析 DO order lines 中的 items 分布 | ||||
| @@ -553,8 +553,8 @@ open class DeliveryOrderService( | |||||
| floorItemCount[row["floor"] as? String ?: "Other"] = (row["item_count"] as? Number)?.toInt() ?: 0 | floorItemCount[row["floor"] as? String ?: "Other"] = (row["item_count"] as? Number)?.toInt() ?: 0 | ||||
| } | } | ||||
| println("🔍 DEBUG: Floor item count distribution: $floorItemCount") | |||||
| println("🔍 DEBUG: Total items: ${itemIds.size}, Items on 4F: ${floorItemCount["4F"] ?: 0}") | |||||
| 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) { | val preferredFloor = if ((floorItemCount["4F"] ?: 0) == itemIds.size && (floorItemCount["2F"] ?: 0) == 0) { | ||||
| @@ -563,13 +563,13 @@ open class DeliveryOrderService( | |||||
| "2F" // 只要有任何 item 不在 4F,就算 2F | "2F" // 只要有任何 item 不在 4F,就算 2F | ||||
| } | } | ||||
| println("🔍 DEBUG: Preferred floor: $preferredFloor (All items on 4F: ${preferredFloor == "4F"})") | |||||
| println(" DEBUG: Preferred floor: $preferredFloor (All items on 4F: ${preferredFloor == "4F"})") | |||||
| // 查找 truck | // 查找 truck | ||||
| val truck = deliveryOrder.shop?.id?.let { shopId -> | val truck = deliveryOrder.shop?.id?.let { shopId -> | ||||
| println("🔍 DEBUG: Looking for truck with shop ID: $shopId") | |||||
| println(" DEBUG: Looking for truck with shop ID: $shopId") | |||||
| val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) | val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) | ||||
| println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId") | |||||
| println(" DEBUG: Found ${trucks.size} trucks for shop $shopId") | |||||
| val preferredStoreId = when (preferredFloor) { | val preferredStoreId = when (preferredFloor) { | ||||
| @@ -586,7 +586,7 @@ open class DeliveryOrderService( | |||||
| trucks.firstOrNull() | trucks.firstOrNull() | ||||
| } | } | ||||
| println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, StoreId=${selectedTruck?.storeId}") | |||||
| println(" DEBUG: Selected truck: ID=${selectedTruck?.id}, StoreId=${selectedTruck?.storeId}") | |||||
| selectedTruck | selectedTruck | ||||
| } | } | ||||
| @@ -612,7 +612,7 @@ open class DeliveryOrderService( | |||||
| val storeId = "$preferredFloor/F" | val storeId = "$preferredFloor/F" | ||||
| val loadingSequence = truck.loadingSequence ?: 999 | val loadingSequence = truck.loadingSequence ?: 999 | ||||
| println("🔍 DEBUG: Creating DoPickOrder - Floor: $preferredFloor, Store: $storeId, Truck: ${truck.id}") | |||||
| println(" DEBUG: Creating DoPickOrder - Floor: $preferredFloor, Store: $storeId, Truck: ${truck.id}") | |||||
| val doPickOrder = DoPickOrder( | val doPickOrder = DoPickOrder( | ||||
| storeId = storeId, | storeId = storeId, | ||||
| @@ -635,7 +635,7 @@ open class DeliveryOrderService( | |||||
| ) | ) | ||||
| val savedDoPickOrder = doPickOrderService.save(doPickOrder) | val savedDoPickOrder = doPickOrderService.save(doPickOrder) | ||||
| println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}") | |||||
| println(" DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}") | |||||
| truck | truck | ||||
| } | } | ||||
| return MessageResponse( | return MessageResponse( | ||||
| @@ -1084,7 +1084,7 @@ open class DeliveryOrderService( | |||||
| @Transactional(rollbackFor = [Exception::class]) | @Transactional(rollbackFor = [Exception::class]) | ||||
| open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDoResult { | open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDoResult { | ||||
| println("🔍 DEBUG: Starting releaseDeliveryOrderWithoutTicket for DO ID: ${request.id}") | |||||
| println(" DEBUG: Starting releaseDeliveryOrderWithoutTicket for DO ID: ${request.id}") | |||||
| val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.id) | val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.id) | ||||
| ?: throw NoSuchElementException("Delivery Order not found") | ?: throw NoSuchElementException("Delivery Order not found") | ||||
| @@ -1233,7 +1233,7 @@ open class DeliveryOrderService( | |||||
| else -> "2F" // 默认 2F | else -> "2F" // 默认 2F | ||||
| } | } | ||||
| println("🔍 DEBUG: Floor calculation for DO ${deliveryOrder.id}") | |||||
| println(" DEBUG: Floor calculation for DO ${deliveryOrder.id}") | |||||
| println(" - Total items: ${itemIds.size}") | println(" - Total items: ${itemIds.size}") | ||||
| println(" - Items with store_id: $totalItemsWithStoreId") | println(" - Items with store_id: $totalItemsWithStoreId") | ||||
| println(" - Items without store_id: ${itemIds.size - totalItemsWithStoreId}") | println(" - Items without store_id: ${itemIds.size - totalItemsWithStoreId}") | ||||
| @@ -1274,15 +1274,15 @@ open class DeliveryOrderService( | |||||
| java.time.DayOfWeek.SUNDAY -> "Sun" | java.time.DayOfWeek.SUNDAY -> "Sun" | ||||
| } | } | ||||
| println("🔍 DEBUG: DO ${deliveryOrder.id} - Target date: $targetDate ($dayAbbr), Shop: $shopId") | |||||
| println("🔍 DEBUG: Found ${matchedTrucks.size} matched 4F trucks") | |||||
| println(" DEBUG: DO ${deliveryOrder.id} - Target date: $targetDate ($dayAbbr), Shop: $shopId") | |||||
| println(" DEBUG: Found ${matchedTrucks.size} matched 4F trucks") | |||||
| val dayMatchedTrucks = matchedTrucks.filter { | val dayMatchedTrucks = matchedTrucks.filter { | ||||
| it.truckLanceCode?.contains(dayAbbr, ignoreCase = true) == true | it.truckLanceCode?.contains(dayAbbr, ignoreCase = true) == true | ||||
| } | } | ||||
| println("🔍 DEBUG: Found ${dayMatchedTrucks.size} trucks matching $dayAbbr") | |||||
| println(" DEBUG: Found ${dayMatchedTrucks.size} trucks matching $dayAbbr") | |||||
| dayMatchedTrucks.forEach { t -> | dayMatchedTrucks.forEach { t -> | ||||
| println(" - Truck ID=${t.id}, Code=${t.truckLanceCode}, Time=${t.departureTime}") | println(" - Truck ID=${t.id}, Code=${t.truckLanceCode}, Time=${t.departureTime}") | ||||
| } | } | ||||
| @@ -36,22 +36,22 @@ class DoPickOrderAssignmentService( | |||||
| "4/F" -> "4/F" | "4/F" -> "4/F" | ||||
| else -> request.storeId | else -> request.storeId | ||||
| } | } | ||||
| println("🔍 DEBUG: assignByLane - Converting storeId from '${request.storeId}' to '$actualStoreId'") | |||||
| println(" DEBUG: assignByLane - Converting storeId from '${request.storeId}' to '$actualStoreId'") | |||||
| // 获取日期(如果提供) | // 获取日期(如果提供) | ||||
| val requiredDate = request.requiredDate | val requiredDate = request.requiredDate | ||||
| println("🔍 DEBUG: assignByLane - Requested date: $requiredDate") | |||||
| println(" DEBUG: assignByLane - Requested date: $requiredDate") | |||||
| // 根据是否有日期参数选择不同的查询方法 | // 根据是否有日期参数选择不同的查询方法 | ||||
| val allCandidates = if (requiredDate != null) { | val allCandidates = if (requiredDate != null) { | ||||
| println("🔍 DEBUG: Filtering by date: $requiredDate") | |||||
| println(" DEBUG: Filtering by date: $requiredDate") | |||||
| doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn( | doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn( | ||||
| actualStoreId, | actualStoreId, | ||||
| requiredDate, | requiredDate, | ||||
| listOf(DoPickOrderStatus.pending) | listOf(DoPickOrderStatus.pending) | ||||
| ) | ) | ||||
| } else { | } else { | ||||
| println("🔍 DEBUG: No date filter applied") | |||||
| println(" DEBUG: No date filter applied") | |||||
| doPickOrderRepository.findByStoreIdAndTicketStatusOrderByTruckDepartureTimeAsc( | doPickOrderRepository.findByStoreIdAndTicketStatusOrderByTruckDepartureTimeAsc( | ||||
| actualStoreId, | actualStoreId, | ||||
| DoPickOrderStatus.pending | DoPickOrderStatus.pending | ||||
| @@ -60,18 +60,18 @@ class DoPickOrderAssignmentService( | |||||
| .filter { it.truckLanceCode == request.truckLanceCode } | .filter { it.truckLanceCode == request.truckLanceCode } | ||||
| .sortedBy { it.truckDepartureTime } | .sortedBy { it.truckDepartureTime } | ||||
| println("🔍 DEBUG: Found ${allCandidates.size} candidate do_pick_orders for lane ${request.truckLanceCode}") | |||||
| 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 filteredCandidates = allCandidates.filter { doPickOrder -> | ||||
| val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) | val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) | ||||
| if (!hasNonIssueLines) { | if (!hasNonIssueLines) { | ||||
| println("🔍 DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues") | |||||
| println(" DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues") | |||||
| } | } | ||||
| hasNonIssueLines | hasNonIssueLines | ||||
| } | } | ||||
| println("🔍 DEBUG: After filtering, ${filteredCandidates.size} do_pick_orders remain") | |||||
| println(" DEBUG: After filtering, ${filteredCandidates.size} do_pick_orders remain") | |||||
| if (filteredCandidates.isEmpty()) { | if (filteredCandidates.isEmpty()) { | ||||
| return MessageResponse( | return MessageResponse( | ||||
| @@ -92,7 +92,7 @@ class DoPickOrderAssignmentService( | |||||
| // 获取这个 do_pick_order 下的所有 pick orders 并分配给用户 | // 获取这个 do_pick_order 下的所有 pick orders 并分配给用户 | ||||
| val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(firstOrder.id!!) | val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(firstOrder.id!!) | ||||
| println("🔍 DEBUG: Found ${doPickOrderLines.size} pick orders in do_pick_order ${firstOrder.id}") | |||||
| println(" DEBUG: Found ${doPickOrderLines.size} pick orders in do_pick_order ${firstOrder.id}") | |||||
| doPickOrderLines.forEach { line -> | doPickOrderLines.forEach { line -> | ||||
| if (line.pickOrderId != null) { | if (line.pickOrderId != null) { | ||||
| @@ -101,7 +101,7 @@ class DoPickOrderAssignmentService( | |||||
| pickOrder.assignTo = user | pickOrder.assignTo = user | ||||
| pickOrder.status = PickOrderStatus.RELEASED | pickOrder.status = PickOrderStatus.RELEASED | ||||
| pickOrderRepository.save(pickOrder) | pickOrderRepository.save(pickOrder) | ||||
| println("🔍 DEBUG: Assigned pick order ${line.pickOrderId} to user ${request.userId}") | |||||
| println(" DEBUG: Assigned pick order ${line.pickOrderId} to user ${request.userId}") | |||||
| } else { | } else { | ||||
| println("⚠️ WARNING: Pick order ${line.pickOrderId} not found") | println("⚠️ WARNING: Pick order ${line.pickOrderId} not found") | ||||
| } | } | ||||
| @@ -120,7 +120,7 @@ class DoPickOrderAssignmentService( | |||||
| } | } | ||||
| if (records.isNotEmpty()) { | if (records.isNotEmpty()) { | ||||
| doPickOrderRecordRepository.saveAll(records) | doPickOrderRecordRepository.saveAll(records) | ||||
| println("🔍 DEBUG: Updated ${records.size} do_pick_order_record for pick order ${line.pickOrderId}") | |||||
| println(" DEBUG: Updated ${records.size} do_pick_order_record for pick order ${line.pickOrderId}") | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -171,7 +171,7 @@ class DoPickOrderAssignmentService( | |||||
| val hasNonIssueLines = nonIssueLines > 0 | val hasNonIssueLines = nonIssueLines > 0 | ||||
| println("🔍 DEBUG: DoPickOrder $doPickOrderId - Total lines: $totalLines, Non-issue lines: $nonIssueLines, Has non-issue lines: $hasNonIssueLines") | |||||
| println(" DEBUG: DoPickOrder $doPickOrderId - Total lines: $totalLines, Non-issue lines: $nonIssueLines, Has non-issue lines: $hasNonIssueLines") | |||||
| hasNonIssueLines | hasNonIssueLines | ||||
| @@ -20,7 +20,7 @@ class DoPickOrderQueryService( | |||||
| fun getSummaryByStore(storeId: String, requiredDate: LocalDate?, releaseType: String): StoreLaneSummary { | fun getSummaryByStore(storeId: String, requiredDate: LocalDate?, releaseType: String): StoreLaneSummary { | ||||
| val targetDate = requiredDate ?: LocalDate.now() | val targetDate = requiredDate ?: LocalDate.now() | ||||
| println("🔍 DEBUG: Getting summary for store=$storeId, date=$targetDate, releaseType=$releaseType") | |||||
| println(" DEBUG: Getting summary for store=$storeId, date=$targetDate, releaseType=$releaseType") | |||||
| val actualStoreId = when (storeId) { | val actualStoreId = when (storeId) { | ||||
| "2/F" -> "2/F" | "2/F" -> "2/F" | ||||
| @@ -56,16 +56,16 @@ class DoPickOrderQueryService( | |||||
| else -> completedRecords // "all" 或其他值,不过滤 | else -> completedRecords // "all" 或其他值,不过滤 | ||||
| } | } | ||||
| println("🔍 DEBUG: Found ${activeRecords.size} active records for date $targetDate") | |||||
| println("🔍 DEBUG: After releaseType filter: ${filteredActiveRecordsByReleaseType.size} active records") | |||||
| println("🔍 DEBUG: Found ${completedRecords.size} completed records for date $targetDate") | |||||
| println("🔍 DEBUG: After releaseType filter: ${filteredCompletedRecordsByReleaseType.size} completed records") | |||||
| println(" DEBUG: Found ${activeRecords.size} active records for date $targetDate") | |||||
| println(" DEBUG: After releaseType filter: ${filteredActiveRecordsByReleaseType.size} active records") | |||||
| println(" DEBUG: Found ${completedRecords.size} completed records for date $targetDate") | |||||
| println(" DEBUG: After releaseType filter: ${filteredCompletedRecordsByReleaseType.size} completed records") | |||||
| // Filter active records (check for non-issue lines) | // Filter active records (check for non-issue lines) | ||||
| val filteredActiveRecords = filteredActiveRecordsByReleaseType.filter { doPickOrder -> | val filteredActiveRecords = filteredActiveRecordsByReleaseType.filter { doPickOrder -> | ||||
| val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) | val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) | ||||
| if (!hasNonIssueLines) { | if (!hasNonIssueLines) { | ||||
| println("🔍 DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues") | |||||
| println(" DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues") | |||||
| } | } | ||||
| hasNonIssueLines | hasNonIssueLines | ||||
| } | } | ||||
| @@ -74,7 +74,7 @@ class DoPickOrderQueryService( | |||||
| val filteredCompletedRecords = filteredCompletedRecordsByReleaseType.filter { record -> | val filteredCompletedRecords = filteredCompletedRecordsByReleaseType.filter { record -> | ||||
| val hasNonIssueLines = checkDoPickOrderRecordHasNonIssueLines(record.id!!) | val hasNonIssueLines = checkDoPickOrderRecordHasNonIssueLines(record.id!!) | ||||
| if (!hasNonIssueLines) { | if (!hasNonIssueLines) { | ||||
| println("🔍 DEBUG: Filtering out DoPickOrderRecord ${record.id} - all lines are issues") | |||||
| println(" DEBUG: Filtering out DoPickOrderRecord ${record.id} - all lines are issues") | |||||
| } | } | ||||
| hasNonIssueLines | hasNonIssueLines | ||||
| } | } | ||||
| @@ -95,7 +95,7 @@ class DoPickOrderQueryService( | |||||
| ) | ) | ||||
| } | } | ||||
| println("🔍 DEBUG: After filtering, ${allRecords.size} records remain (${filteredActiveRecords.size} active + ${filteredCompletedRecords.size} completed)") | |||||
| println(" DEBUG: After filtering, ${allRecords.size} records remain (${filteredActiveRecords.size} active + ${filteredCompletedRecords.size} completed)") | |||||
| val grouped = allRecords.groupBy { it.truckDepartureTime to it.truckLanceCode } | val grouped = allRecords.groupBy { it.truckDepartureTime to it.truckLanceCode } | ||||
| .mapValues { (_, list) -> | .mapValues { (_, list) -> | ||||
| @@ -264,8 +264,8 @@ class DoReleaseCoordinatorService( | |||||
| private fun getOrderedDeliveryOrderIds(ids: List<Long>): List<Long> { | private fun getOrderedDeliveryOrderIds(ids: List<Long>): List<Long> { | ||||
| try { | try { | ||||
| println("🔍 DEBUG: Getting ordered IDs for ${ids.size} orders") | |||||
| println("🔍 DEBUG: First 5 IDs: ${ids.take(5)}") | |||||
| println(" DEBUG: Getting ordered IDs for ${ids.size} orders") | |||||
| println(" DEBUG: First 5 IDs: ${ids.take(5)}") | |||||
| val dayOfWeekSql = getDayOfWeekAbbrSql("do.estimatedArrivalDate") | val dayOfWeekSql = getDayOfWeekAbbrSql("do.estimatedArrivalDate") | ||||
| val sql = """ | val sql = """ | ||||
| WITH DoFloorCounts AS ( | WITH DoFloorCounts AS ( | ||||
| @@ -470,24 +470,24 @@ class DoReleaseCoordinatorService( | |||||
| """.trimIndent() | """.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) | 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()) { | 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 -> | val sortedIds = results.mapNotNull { row -> | ||||
| (row["id"] as? Number)?.toLong() | (row["id"] as? Number)?.toLong() | ||||
| } | } | ||||
| println("🔍 DEBUG: Query returned ${sortedIds.size} sorted IDs") | |||||
| println("🔍 DEBUG: First 10 sorted IDs: ${sortedIds.take(10)}") | |||||
| println(" DEBUG: Query returned ${sortedIds.size} sorted IDs") | |||||
| println(" DEBUG: First 10 sorted IDs: ${sortedIds.take(10)}") | |||||
| return if (sortedIds.isEmpty()) { | return if (sortedIds.isEmpty()) { | ||||
| println("⚠️ WARNING: No sorted IDs, using original order") | println("⚠️ WARNING: No sorted IDs, using original order") | ||||
| @@ -518,7 +518,7 @@ class DoReleaseCoordinatorService( | |||||
| try { | try { | ||||
| println("📦 Starting batch release for ${ids.size} orders") | println("📦 Starting batch release for ${ids.size} orders") | ||||
| val sortedIds = getOrderedDeliveryOrderIds(ids) | val sortedIds = getOrderedDeliveryOrderIds(ids) | ||||
| println("🔍 DEBUG: Got ${sortedIds.size} sorted orders") | |||||
| println(" DEBUG: Got ${sortedIds.size} sorted orders") | |||||
| val releaseResults = mutableListOf<ReleaseDoResult>() | val releaseResults = mutableListOf<ReleaseDoResult>() | ||||
| @@ -538,7 +538,7 @@ class DoReleaseCoordinatorService( | |||||
| ) | ) | ||||
| releaseResults.add(result) | releaseResults.add(result) | ||||
| status.success.incrementAndGet() | status.success.incrementAndGet() | ||||
| println("🔍 DO $id -> Success") | |||||
| println(" DO $id -> Success") | |||||
| } catch (e: Exception) { | } catch (e: Exception) { | ||||
| synchronized(status.failed) { | synchronized(status.failed) { | ||||
| status.failed.add(id to (e.message ?: "Exception")) | status.failed.add(id to (e.message ?: "Exception")) | ||||
| @@ -587,13 +587,13 @@ class DoReleaseCoordinatorService( | |||||
| Triple(it.estimatedArrivalDate, it.preferredFloor, it.shopId) | Triple(it.estimatedArrivalDate, it.preferredFloor, it.shopId) | ||||
| } | } | ||||
| println("🔍 DEBUG: Grouped into ${grouped.size} DoPickOrders") | |||||
| println(" DEBUG: Grouped into ${grouped.size} DoPickOrders") | |||||
| // 第三步:为每组创建一个 DoPickOrder 和多条 DoPickOrderLine | // 第三步:为每组创建一个 DoPickOrder 和多条 DoPickOrderLine | ||||
| grouped.forEach { (key, group) -> | grouped.forEach { (key, group) -> | ||||
| try { | try { | ||||
| createMergedDoPickOrder(group) | createMergedDoPickOrder(group) | ||||
| println("🔍 DEBUG: Created DoPickOrder for ${group.size} DOs") | |||||
| println(" DEBUG: Created DoPickOrder for ${group.size} DOs") | |||||
| } catch (e: Exception) { | } catch (e: Exception) { | ||||
| println("❌ Error creating DoPickOrder: ${e.message}") | println("❌ Error creating DoPickOrder: ${e.message}") | ||||
| e.printStackTrace() | e.printStackTrace() | ||||
| @@ -653,7 +653,7 @@ class DoReleaseCoordinatorService( | |||||
| // 直接使用 doPickOrderRepository.save() 而不是 doPickOrderService.save() | // 直接使用 doPickOrderRepository.save() 而不是 doPickOrderService.save() | ||||
| val saved = doPickOrderRepository.save(doPickOrder) | val saved = doPickOrderRepository.save(doPickOrder) | ||||
| println("🔍 DEBUG: Saved DoPickOrder - ID: ${saved.id}, Ticket: ${saved.ticketNo}") | |||||
| println(" DEBUG: Saved DoPickOrder - ID: ${saved.id}, Ticket: ${saved.ticketNo}") | |||||
| // 创建多条 DoPickOrderLine(每个 DO 一条) | // 创建多条 DoPickOrderLine(每个 DO 一条) | ||||
| @@ -674,7 +674,7 @@ class DoReleaseCoordinatorService( | |||||
| status = "pending" // 初始状态 | status = "pending" // 初始状态 | ||||
| } | } | ||||
| doPickOrderLineRepository.save(line) | doPickOrderLineRepository.save(line) | ||||
| println("🔍 DEBUG: Created DoPickOrderLine for pick order ${result.pickOrderId}") | |||||
| println(" DEBUG: Created DoPickOrderLine for pick order ${result.pickOrderId}") | |||||
| } | } | ||||
| // 现在检查整个 DoPickOrder 是否有库存问题 | // 现在检查整个 DoPickOrder 是否有库存问题 | ||||
| @@ -686,10 +686,10 @@ class DoReleaseCoordinatorService( | |||||
| line.status = "issue" | line.status = "issue" | ||||
| } | } | ||||
| doPickOrderLineRepository.saveAll(doPickOrderLines) | doPickOrderLineRepository.saveAll(doPickOrderLines) | ||||
| println("🔍 DEBUG: Updated ${doPickOrderLines.size} DoPickOrderLine records to 'issue' status") | |||||
| println(" DEBUG: Updated ${doPickOrderLines.size} DoPickOrderLine records to 'issue' status") | |||||
| } | } | ||||
| println("🔍 DEBUG: Created ${results.size} DoPickOrderLine records") | |||||
| println(" DEBUG: Created ${results.size} DoPickOrderLine records") | |||||
| } | } | ||||
| private fun checkPickOrderHasStockIssues(doPickOrderId: Long): Boolean { | private fun checkPickOrderHasStockIssues(doPickOrderId: Long): Boolean { | ||||
| try { | try { | ||||
| @@ -724,7 +724,7 @@ class DoReleaseCoordinatorService( | |||||
| // 3. 只有当所有 pick orders 都有问题时才算 issue | // 3. 只有当所有 pick orders 都有问题时才算 issue | ||||
| val hasAllPickOrdersIssues = (totalPickOrders > 0) && (issuePickOrders == totalPickOrders) | val hasAllPickOrdersIssues = (totalPickOrders > 0) && (issuePickOrders == totalPickOrders) | ||||
| println("🔍 DEBUG: DoPickOrder $doPickOrderId - Total pick orders: $totalPickOrders, Issue pick orders: $issuePickOrders, All pick orders have issues: $hasAllPickOrdersIssues") | |||||
| println(" DEBUG: DoPickOrder $doPickOrderId - Total pick orders: $totalPickOrders, Issue pick orders: $issuePickOrders, All pick orders have issues: $hasAllPickOrdersIssues") | |||||
| return hasAllPickOrdersIssues | return hasAllPickOrdersIssues | ||||
| @@ -811,7 +811,7 @@ class DoReleaseCoordinatorService( | |||||
| status = "pending" | status = "pending" | ||||
| } | } | ||||
| doPickOrderLineRepository.save(line) | doPickOrderLineRepository.save(line) | ||||
| println("🔍 DEBUG: Created DoPickOrderLine for existing DoPickOrder ${existingDoPickOrder.id}") | |||||
| println(" DEBUG: Created DoPickOrderLine for existing DoPickOrder ${existingDoPickOrder.id}") | |||||
| } | } | ||||
| } else { | } else { | ||||
| // 如果不存在,创建新的 do_pick_order | // 如果不存在,创建新的 do_pick_order | ||||
| @@ -843,7 +843,7 @@ class DoReleaseCoordinatorService( | |||||
| status = "pending" | status = "pending" | ||||
| } | } | ||||
| doPickOrderLineRepository.save(line) | doPickOrderLineRepository.save(line) | ||||
| println("🔍 DEBUG: Created new DoPickOrder with releaseType=single") | |||||
| println(" DEBUG: Created new DoPickOrder with releaseType=single") | |||||
| } | } | ||||
| // 更新 ticket numbers(只更新 single 类型的) | // 更新 ticket numbers(只更新 single 类型的) | ||||
| @@ -873,11 +873,11 @@ class DoReleaseCoordinatorService( | |||||
| } | } | ||||
| if (tempTickets.isEmpty()) { | if (tempTickets.isEmpty()) { | ||||
| println("🔍 No single release type tickets to update") | |||||
| println(" No single release type tickets to update") | |||||
| return | return | ||||
| } | } | ||||
| println("🔍 DEBUG: Found ${tempTickets.size} single release type tickets to update") | |||||
| println(" DEBUG: Found ${tempTickets.size} single release type tickets to update") | |||||
| // 2. 按日期和 storeId 分组 | // 2. 按日期和 storeId 分组 | ||||
| val grouped = tempTickets.groupBy { ticket -> | val grouped = tempTickets.groupBy { ticket -> | ||||
| @@ -918,7 +918,7 @@ class DoReleaseCoordinatorService( | |||||
| } else null | } else null | ||||
| }.toMutableSet() | }.toMutableSet() | ||||
| println("🔍 DEBUG: Group ($date, $storeId) - Existing ticket numbers: $existingTickets, Existing numbers: $existingNumbers") | |||||
| println(" DEBUG: Group ($date, $storeId) - Existing ticket numbers: $existingTickets, Existing numbers: $existingNumbers") | |||||
| // 5. 在组内按 truckDepartureTime, truckLanceCode, loadingSequence, doOrderId 排序 | // 5. 在组内按 truckDepartureTime, truckLanceCode, loadingSequence, doOrderId 排序 | ||||
| val sortedTickets = tickets.sortedWith( | val sortedTickets = tickets.sortedWith( | ||||
| @@ -948,7 +948,7 @@ class DoReleaseCoordinatorService( | |||||
| existingNumbers.add(nextNumber) | existingNumbers.add(nextNumber) | ||||
| nextNumber++ | nextNumber++ | ||||
| println("🔍 DEBUG: Updated ticket ${ticket.id} to $newTicketNo") | |||||
| println(" DEBUG: Updated ticket ${ticket.id} to $newTicketNo") | |||||
| } | } | ||||
| } | } | ||||
| @@ -260,7 +260,7 @@ open class JoPickOrderService( | |||||
| statusList | statusList | ||||
| ).filter { it.jobOrder != null } // Only pick orders with joId | ).filter { it.jobOrder != null } // Only pick orders with joId | ||||
| println("🔍 DEBUG: Found ${allAssignedPickOrders.size} job order pick orders assigned to user $userId") | |||||
| println(" DEBUG: Found ${allAssignedPickOrders.size} job order pick orders assigned to user $userId") | |||||
| // Filter based on assignment and status | // Filter based on assignment and status | ||||
| val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) { | val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) { | ||||
| @@ -271,7 +271,7 @@ open class JoPickOrderService( | |||||
| if (assignedReleasedOrders.isNotEmpty()) { | 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 job orders, showing only those") | |||||
| println(" DEBUG: Found ${assignedReleasedOrders.size} assigned RELEASED job orders, showing only those") | |||||
| assignedReleasedOrders | assignedReleasedOrders | ||||
| } else { | } else { | ||||
| // If no assigned RELEASED orders, show only the latest COMPLETED order | // If no assigned RELEASED orders, show only the latest COMPLETED order | ||||
| @@ -279,10 +279,10 @@ open class JoPickOrderService( | |||||
| if (completedOrders.isNotEmpty()) { | if (completedOrders.isNotEmpty()) { | ||||
| val latestCompleted = | val latestCompleted = | ||||
| completedOrders.maxByOrNull { it.completeDate ?: it.modified ?: LocalDateTime.MIN } | completedOrders.maxByOrNull { it.completeDate ?: it.modified ?: LocalDateTime.MIN } | ||||
| println("🔍 DEBUG: No assigned RELEASED job orders, showing latest completed order: ${latestCompleted?.code}") | |||||
| println(" DEBUG: No assigned RELEASED job orders, showing latest completed order: ${latestCompleted?.code}") | |||||
| listOfNotNull(latestCompleted) | listOfNotNull(latestCompleted) | ||||
| } else { | } else { | ||||
| println("🔍 DEBUG: No job orders found") | |||||
| println(" DEBUG: No job orders found") | |||||
| emptyList() | emptyList() | ||||
| } | } | ||||
| } | } | ||||
| @@ -569,7 +569,7 @@ open class JoPickOrderService( | |||||
| .findAllByAssignToIdAndStatusIn(userId, listOf(PickOrderStatus.COMPLETED)) | .findAllByAssignToIdAndStatusIn(userId, listOf(PickOrderStatus.COMPLETED)) | ||||
| .filter { it.jobOrder != null } | .filter { it.jobOrder != null } | ||||
| println("🔍 DEBUG: Found ${completedPickOrders.size} completed job order pick orders assigned to user $userId") | |||||
| println(" DEBUG: Found ${completedPickOrders.size} completed job order pick orders assigned to user $userId") | |||||
| if (completedPickOrders.isEmpty()) { | if (completedPickOrders.isEmpty()) { | ||||
| return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>()) | return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>()) | ||||
| @@ -580,7 +580,7 @@ open class JoPickOrderService( | |||||
| it.completeDate ?: it.modified ?: LocalDateTime.MIN | it.completeDate ?: it.modified ?: LocalDateTime.MIN | ||||
| } ?: return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>()) | } ?: return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>()) | ||||
| println("🔍 DEBUG: Using latest completed order: ${latestCompletedOrder.code}") | |||||
| println(" DEBUG: Using latest completed order: ${latestCompletedOrder.code}") | |||||
| val pickOrder = latestCompletedOrder | val pickOrder = latestCompletedOrder | ||||
| val jobOrder = pickOrder.jobOrder!! | val jobOrder = pickOrder.jobOrder!! | ||||
| @@ -1524,8 +1524,8 @@ open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List<Map<St | |||||
| il.lotNo ASC | il.lotNo ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing SQL for Job Order pick order lot details: $sql") | |||||
| println("🔍 With parameters: pickOrderId = $pickOrderId") | |||||
| println(" Executing SQL for Job Order pick order lot details: $sql") | |||||
| println(" With parameters: pickOrderId = $pickOrderId") | |||||
| val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId)) | val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId)) | ||||
| @@ -1733,8 +1733,8 @@ open fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId: Lo | |||||
| il.lotNo ASC | il.lotNo ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing SQL for completed pick order lot details: $sql") | |||||
| println("🔍 With parameters: pickOrderId = $pickOrderId") | |||||
| println(" Executing SQL for completed pick order lot details: $sql") | |||||
| println(" With parameters: pickOrderId = $pickOrderId") | |||||
| val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId)) | val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId)) | ||||
| @@ -1286,8 +1286,8 @@ open class PickOrderService( | |||||
| doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(pickOrderId) | doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(pickOrderId) | ||||
| val doPickOrderIds = doPickOrderLines.mapNotNull { it.doPickOrderId }.distinct() | val doPickOrderIds = doPickOrderLines.mapNotNull { it.doPickOrderId }.distinct() | ||||
| println("🔍 DEBUG: Found ${doPickOrderLines.size} do_pick_order_line records for pick order $pickOrderId") | |||||
| println("🔍 DEBUG: Unique do_pick_order IDs: $doPickOrderIds") | |||||
| println(" DEBUG: Found ${doPickOrderLines.size} do_pick_order_line records for pick order $pickOrderId") | |||||
| println(" DEBUG: Unique do_pick_order IDs: $doPickOrderIds") | |||||
| if (doPickOrderIds.isEmpty()) { | if (doPickOrderIds.isEmpty()) { | ||||
| println("ℹ️ INFO: No do_pick_order records found - skipping record copying") | println("ℹ️ INFO: No do_pick_order records found - skipping record copying") | ||||
| @@ -1302,13 +1302,13 @@ open class PickOrderService( | |||||
| return@forEach | return@forEach | ||||
| } | } | ||||
| println("🔍 Processing do_pick_order ID: ${dpo.id}, ticket: ${dpo.ticketNo}") | |||||
| 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 allDoPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(dpo.id!!) | ||||
| val allPickOrderIdsInDpo = allDoPickOrderLines.mapNotNull { it.pickOrderId }.distinct() | val allPickOrderIdsInDpo = allDoPickOrderLines.mapNotNull { it.pickOrderId }.distinct() | ||||
| println("🔍 DEBUG: This do_pick_order has ${allPickOrderIdsInDpo.size} pick orders") | |||||
| println(" DEBUG: This do_pick_order has ${allPickOrderIdsInDpo.size} pick orders") | |||||
| // 检查每个 pick order 的状态 | // 检查每个 pick order 的状态 | ||||
| val pickOrderStatuses = allPickOrderIdsInDpo.map { poId -> | val pickOrderStatuses = allPickOrderIdsInDpo.map { poId -> | ||||
| @@ -1317,7 +1317,7 @@ open class PickOrderService( | |||||
| } | } | ||||
| pickOrderStatuses.forEach { (poId, status) -> | pickOrderStatuses.forEach { (poId, status) -> | ||||
| println("🔍 DEBUG: Pick order $poId status: $status") | |||||
| println(" DEBUG: Pick order $poId status: $status") | |||||
| } | } | ||||
| // 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表 | // 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表 | ||||
| @@ -1327,7 +1327,7 @@ open class PickOrderService( | |||||
| if (!allPickOrdersCompleted) { | if (!allPickOrdersCompleted) { | ||||
| println("⏳ Not all pick orders in this do_pick_order are completed, keeping do_pick_order alive") | 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}") | |||||
| println(" DEBUG: Completed pick orders: ${pickOrderStatuses.count { it.second == PickOrderStatus.COMPLETED }}/${pickOrderStatuses.size}") | |||||
| return@forEach // 跳过这个 do_pick_order,不删除它 | return@forEach // 跳过这个 do_pick_order,不删除它 | ||||
| } | } | ||||
| @@ -1654,7 +1654,7 @@ open class PickOrderService( | |||||
| // 添加检查是否需要 resuggest 的方法 | // 添加检查是否需要 resuggest 的方法 | ||||
| private fun checkIfNeedsResuggest(pickOrderLineId: Long): Boolean { | private fun checkIfNeedsResuggest(pickOrderLineId: Long): Boolean { | ||||
| println("🔍 checkIfNeedsResuggest called with pickOrderLineId: $pickOrderLineId") | |||||
| println(" checkIfNeedsResuggest called with pickOrderLineId: $pickOrderLineId") | |||||
| // 首先执行一个调试查询来查看实际的数值 | // 首先执行一个调试查询来查看实际的数值 | ||||
| val debugSql = """ | val debugSql = """ | ||||
| @@ -1680,9 +1680,9 @@ open class PickOrderService( | |||||
| WHERE spl.pickOrderLineId = :pickOrderLineId | WHERE spl.pickOrderLineId = :pickOrderLineId | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Debug SQL: $debugSql") | |||||
| println(" Debug SQL: $debugSql") | |||||
| val debugResult = jdbcDao.queryForList(debugSql, mapOf("pickOrderLineId" to pickOrderLineId)) | val debugResult = jdbcDao.queryForList(debugSql, mapOf("pickOrderLineId" to pickOrderLineId)) | ||||
| println("🔍 Debug result:") | |||||
| println(" Debug result:") | |||||
| debugResult.forEach { row -> | debugResult.forEach { row -> | ||||
| println(" SuggestedPickLotId: ${row["suggestedPickLotId"]}") | println(" SuggestedPickLotId: ${row["suggestedPickLotId"]}") | ||||
| println(" SuggestedQty: ${row["suggestedQty"]}") | println(" SuggestedQty: ${row["suggestedQty"]}") | ||||
| @@ -1730,12 +1730,12 @@ open class PickOrderService( | |||||
| WHERE spl.pickOrderLineId = :pickOrderLineId | WHERE spl.pickOrderLineId = :pickOrderLineId | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing SQL: $checkSql") | |||||
| println("🔍 With parameters: pickOrderLineId = $pickOrderLineId") | |||||
| println(" Executing SQL: $checkSql") | |||||
| println(" With parameters: pickOrderLineId = $pickOrderLineId") | |||||
| val result = jdbcDao.queryForList(checkSql, mapOf("pickOrderLineId" to pickOrderLineId)) | val result = jdbcDao.queryForList(checkSql, mapOf("pickOrderLineId" to pickOrderLineId)) | ||||
| println("🔍 SQL result size: ${result.size}") | |||||
| println(" SQL result size: ${result.size}") | |||||
| if (result.isNotEmpty()) { | if (result.isNotEmpty()) { | ||||
| val row = result[0] | val row = result[0] | ||||
| @@ -1767,7 +1767,7 @@ open class PickOrderService( | |||||
| println("Needs resuggest: $needsResuggest") | println("Needs resuggest: $needsResuggest") | ||||
| return needsResuggest | return needsResuggest | ||||
| } else { | } else { | ||||
| println("🔍 No results returned from SQL query") | |||||
| println(" No results returned from SQL query") | |||||
| } | } | ||||
| return false | return false | ||||
| @@ -1839,7 +1839,7 @@ open class PickOrderService( | |||||
| ).filter { it.deliveryOrder != null } | ).filter { it.deliveryOrder != null } | ||||
| if (userExistingOrders.isNotEmpty()) { | if (userExistingOrders.isNotEmpty()) { | ||||
| println("🔍 DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress") | |||||
| println(" DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress") | |||||
| return MessageResponse( | return MessageResponse( | ||||
| id = null, | id = null, | ||||
| name = "User already has pick orders", | name = "User already has pick orders", | ||||
| @@ -1961,14 +1961,14 @@ open class PickOrderService( | |||||
| // Update do_pick_order_record entries | // Update do_pick_order_record entries | ||||
| val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!) | val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!) | ||||
| println("🔍 DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}") | |||||
| println(" DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}") | |||||
| if (existingRecords.isNotEmpty()) { | if (existingRecords.isNotEmpty()) { | ||||
| existingRecords.forEach { record -> | existingRecords.forEach { record -> | ||||
| record.handledBy = user.id | record.handledBy = user.id | ||||
| record.ticketStatus = DoPickOrderStatus.released | 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") | |||||
| println(" DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released") | |||||
| } | } | ||||
| doPickOrderRecordRepository.saveAll(existingRecords) | doPickOrderRecordRepository.saveAll(existingRecords) | ||||
| println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") | println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") | ||||
| @@ -2108,7 +2108,7 @@ open class PickOrderService( | |||||
| i.code ASC | i.code ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing optimized SQL: $sql") | |||||
| println(" Executing optimized SQL: $sql") | |||||
| val result = jdbcDao.queryForList(sql, emptyMap<String, Any>()) | val result = jdbcDao.queryForList(sql, emptyMap<String, Any>()) | ||||
| @@ -2234,7 +2234,7 @@ open class PickOrderService( | |||||
| // 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 consoCode = pickOrder.consoCode | ||||
| if (consoCode == null) { | if (consoCode == null) { | ||||
| println("🔍 Checking pick order ${pickOrder.code} (consoCode: null)") | |||||
| println(" Checking pick order ${pickOrder.code} (consoCode: null)") | |||||
| println(" ⚠️ No consoCode - considering as active") | println(" ⚠️ No consoCode - considering as active") | ||||
| true // No consoCode means not completed | true // No consoCode means not completed | ||||
| } else { | } else { | ||||
| @@ -2501,9 +2501,9 @@ open class PickOrderService( | |||||
| ).filter { it.deliveryOrder != null } | ).filter { it.deliveryOrder != null } | ||||
| if (userExistingOrders.isNotEmpty()) { | if (userExistingOrders.isNotEmpty()) { | ||||
| println("🔍 DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress:") | |||||
| println(" DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress:") | |||||
| userExistingOrders.forEach { po -> | userExistingOrders.forEach { po -> | ||||
| println("🔍 DEBUG: Existing order ${po.id}: code=${po.code}, status=${po.status}") | |||||
| println(" DEBUG: Existing order ${po.id}: code=${po.code}, status=${po.status}") | |||||
| } | } | ||||
| return MessageResponse( | return MessageResponse( | ||||
| id = null, | id = null, | ||||
| @@ -2624,15 +2624,15 @@ open class PickOrderService( | |||||
| val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() | val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() | ||||
| val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) | val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) | ||||
| println("🔍 DEBUG: Target date: $targetDate, Date prefix: $datePrefix") | |||||
| 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 -> | val truck = deliveryOrder.shop?.id?.let { shopId -> | ||||
| println("🔍 DEBUG: Looking for truck with shop ID: $shopId") | |||||
| println(" DEBUG: Looking for truck with shop ID: $shopId") | |||||
| val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) | val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) | ||||
| println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId") | |||||
| println(" DEBUG: Found ${trucks.size} trucks for shop $shopId") | |||||
| val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX } | val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX } | ||||
| println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}") | |||||
| println(" DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}") | |||||
| selectedTruck | selectedTruck | ||||
| } | } | ||||
| @@ -2645,13 +2645,13 @@ open class PickOrderService( | |||||
| // Get next ticket number for this date and store | // Get next ticket number for this date and store | ||||
| val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, determinedStoreId) | val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, determinedStoreId) | ||||
| println("🔍 DEBUG: Next ticket number: $nextTicketNumber") | |||||
| println(" DEBUG: Next ticket number: $nextTicketNumber") | |||||
| println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines") | |||||
| 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!!) | val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!) | ||||
| println("🔍 DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}") | |||||
| println(" DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}") | |||||
| if (existingRecords.isNotEmpty()) { | if (existingRecords.isNotEmpty()) { | ||||
| // Update existing records | // Update existing records | ||||
| @@ -2664,7 +2664,7 @@ open class PickOrderService( | |||||
| record.shopCode = deliveryOrder.shop?.code | record.shopCode = deliveryOrder.shop?.code | ||||
| record.shopName = deliveryOrder.shop?.name | record.shopName = deliveryOrder.shop?.name | ||||
| record.requiredDeliveryDate = targetDate | record.requiredDeliveryDate = targetDate | ||||
| println("🔍 DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released") | |||||
| println(" DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released") | |||||
| } | } | ||||
| doPickOrderRecordRepository.saveAll(existingRecords) | doPickOrderRecordRepository.saveAll(existingRecords) | ||||
| println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") | println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") | ||||
| @@ -2672,7 +2672,7 @@ open class PickOrderService( | |||||
| // 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") | println("⚠️ No existing DoPickOrderRecord entries found, creating new ones") | ||||
| deliveryOrder.deliveryOrderLines.forEach { line -> | deliveryOrder.deliveryOrderLines.forEach { line -> | ||||
| println("🔍 DEBUG: Processing line - Store ID: $determinedStoreId") | |||||
| println(" DEBUG: Processing line - Store ID: $determinedStoreId") | |||||
| val doPickOrderRecord = DoPickOrderRecord( | val doPickOrderRecord = DoPickOrderRecord( | ||||
| id=dopickorder.id, | id=dopickorder.id, | ||||
| @@ -2691,10 +2691,10 @@ open class PickOrderService( | |||||
| requiredDeliveryDate = targetDate | requiredDeliveryDate = targetDate | ||||
| ) | ) | ||||
| println("🔍 DEBUG: Creating new DoPickOrderRecord - Store: $determinedStoreId, Ticket: $nextTicketNumber, Truck: ${truck?.id}") | |||||
| println(" DEBUG: Creating new DoPickOrderRecord - Store: $determinedStoreId, Ticket: $nextTicketNumber, Truck: ${truck?.id}") | |||||
| val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord) | val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord) | ||||
| println("🔍 DEBUG: Saved new DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}") | |||||
| println(" DEBUG: Saved new DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}") | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -2747,9 +2747,9 @@ open class PickOrderService( | |||||
| listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED) | listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED) | ||||
| ).filter { it.deliveryOrder != null } // Only pick orders with doId | ).filter { it.deliveryOrder != null } // Only pick orders with doId | ||||
| println("🔍 DEBUG: All assigned pick orders: ${allAssignedPickOrders.size}") | |||||
| println(" DEBUG: All assigned pick orders: ${allAssignedPickOrders.size}") | |||||
| val pickOrderIds = allAssignedPickOrders.map { it.id!! } | val pickOrderIds = allAssignedPickOrders.map { it.id!! } | ||||
| println("🔍 DEBUG: All assigned pick orders: ${pickOrderIds.size}") | |||||
| println(" DEBUG: All assigned pick orders: ${pickOrderIds.size}") | |||||
| println(" Pick order IDs to fetch: $pickOrderIds") | println(" Pick order IDs to fetch: $pickOrderIds") | ||||
| if (pickOrderIds.isEmpty()) { | if (pickOrderIds.isEmpty()) { | ||||
| @@ -2883,7 +2883,7 @@ open class PickOrderService( | |||||
| il.lotNo ASC | il.lotNo ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing SQL for all pick order lots with details: $sql") | |||||
| println(" Executing SQL for all pick order lots with details: $sql") | |||||
| println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") | println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") | ||||
| val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) | val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) | ||||
| @@ -2903,7 +2903,7 @@ open class PickOrderService( | |||||
| open fun getFgPickOrders(): List<Map<String, Any?>> { | open fun getFgPickOrders(): List<Map<String, Any?>> { | ||||
| try { | try { | ||||
| println("🔍 Starting getFgPickOrders method - using repository") | |||||
| println(" Starting getFgPickOrders method - using repository") | |||||
| // Use repository to find pick orders with type 'do' | // Use repository to find pick orders with type 'do' | ||||
| val pickOrders = pickOrderRepository.findAll().filter { | val pickOrders = pickOrderRepository.findAll().filter { | ||||
| @@ -2911,7 +2911,7 @@ open class PickOrderService( | |||||
| it.status?.value in listOf("assigned", "released", "picking") | it.status?.value in listOf("assigned", "released", "picking") | ||||
| } | } | ||||
| println("🔍 Found ${pickOrders.size} FG pick orders using repository") | |||||
| println(" Found ${pickOrders.size} FG pick orders using repository") | |||||
| val results = pickOrders.map { po -> | val results = pickOrders.map { po -> | ||||
| val deliveryOrder = po.deliveryOrder | val deliveryOrder = po.deliveryOrder | ||||
| @@ -2968,7 +2968,7 @@ open class PickOrderService( | |||||
| open fun getFgPickOrdersByUserId(userId: Long): List<Map<String, Any?>> { | open fun getFgPickOrdersByUserId(userId: Long): List<Map<String, Any?>> { | ||||
| try { | try { | ||||
| println("🔍 Starting getFgPickOrdersByUserId with userId: $userId") | |||||
| println(" Starting getFgPickOrdersByUserId with userId: $userId") | |||||
| // 修复:从 do_pick_order_line 获取 pick order 信息 | // 修复:从 do_pick_order_line 获取 pick order 信息 | ||||
| val sql = """ | val sql = """ | ||||
| @@ -3018,8 +3018,8 @@ open class PickOrderService( | |||||
| ORDER BY MIN(po.targetDate) DESC, MIN(po.code) ASC | ORDER BY MIN(po.targetDate) DESC, MIN(po.code) ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing SQL for FG pick orders by userId: $sql") | |||||
| println("🔍 With parameters: userId = $userId") | |||||
| println(" Executing SQL for FG pick orders by userId: $sql") | |||||
| println(" With parameters: userId = $userId") | |||||
| val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) | val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) | ||||
| @@ -3028,11 +3028,11 @@ open class PickOrderService( | |||||
| return emptyList() | return emptyList() | ||||
| } | } | ||||
| println("🔍 Found ${results.size} active FG pick orders for user: $userId") | |||||
| println(" Found ${results.size} active FG pick orders for user: $userId") | |||||
| // 添加调试信息 | // 添加调试信息 | ||||
| results.forEachIndexed { index, row -> | results.forEachIndexed { index, row -> | ||||
| println("🔍 DEBUG: Result $index:") | |||||
| println(" DEBUG: Result $index:") | |||||
| println(" - doPickOrderId: ${row["doPickOrderId"]}") | println(" - doPickOrderId: ${row["doPickOrderId"]}") | ||||
| println(" - pickOrderIds: ${row["pickOrderIds"]}") | println(" - pickOrderIds: ${row["pickOrderIds"]}") | ||||
| println(" - numberOfPickOrders: ${row["numberOfPickOrders"]}") | println(" - numberOfPickOrders: ${row["numberOfPickOrders"]}") | ||||
| @@ -3088,7 +3088,7 @@ open class PickOrderService( | |||||
| open fun getFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { | open fun getFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { | ||||
| try { | try { | ||||
| println("🔍 Starting getFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId") | |||||
| println(" Starting getFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId") | |||||
| val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) | val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) | ||||
| @@ -3097,7 +3097,7 @@ open class PickOrderService( | |||||
| return emptyList() | return emptyList() | ||||
| } | } | ||||
| println("🔍 Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}") | |||||
| println(" Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}") | |||||
| if (pickOrder.type?.value != "do") { | if (pickOrder.type?.value != "do") { | ||||
| println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}") | println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}") | ||||
| @@ -3117,16 +3117,16 @@ open class PickOrderService( | |||||
| val supplier = deliveryOrder?.supplier | val supplier = deliveryOrder?.supplier | ||||
| println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") | println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") | ||||
| println("🔍 Shop ID: ${shop?.id}") | |||||
| 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) { | val truck = if (shop?.id != null) { | ||||
| try { | try { | ||||
| println("🔍 Querying truck repository for shopId: ${shop.id}") | |||||
| println(" Querying truck repository for shopId: ${shop.id}") | |||||
| // Get all trucks for this shop | // Get all trucks for this shop | ||||
| val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id) | val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id) | ||||
| println("🔍 Trucks for shop ${shop.id}: ${trucksForShop.size}") | |||||
| println(" Trucks for shop ${shop.id}: ${trucksForShop.size}") | |||||
| trucksForShop.forEach { t -> | trucksForShop.forEach { t -> | ||||
| println(" - Truck ID: ${t.id}, truckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}") | println(" - Truck ID: ${t.id}, truckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}") | ||||
| } | } | ||||
| @@ -3153,7 +3153,7 @@ open class PickOrderService( | |||||
| val ticketNo = try { | val ticketNo = try { | ||||
| val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) | val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) | ||||
| val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: "" | val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: "" | ||||
| println("🔍 Found ticket number: $ticketNo for pick order $pickOrderId") | |||||
| println(" Found ticket number: $ticketNo for pick order $pickOrderId") | |||||
| ticketNo | ticketNo | ||||
| } catch (e: Exception) { | } catch (e: Exception) { | ||||
| println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}") | println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}") | ||||
| @@ -3200,7 +3200,7 @@ open class PickOrderService( | |||||
| open fun getnewFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { | open fun getnewFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { | ||||
| try { | try { | ||||
| println("🔍 Starting getnewFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId") | |||||
| println(" Starting getnewFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId") | |||||
| val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) | val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) | ||||
| @@ -3209,7 +3209,7 @@ open class PickOrderService( | |||||
| return emptyList() | return emptyList() | ||||
| } | } | ||||
| println("🔍 Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}") | |||||
| println(" Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}") | |||||
| if (pickOrder.type?.value != "do") { | if (pickOrder.type?.value != "do") { | ||||
| println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}") | println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}") | ||||
| @@ -3229,16 +3229,16 @@ open class PickOrderService( | |||||
| val supplier = deliveryOrder?.supplier | val supplier = deliveryOrder?.supplier | ||||
| println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") | println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") | ||||
| println("🔍 Shop ID: ${shop?.id}") | |||||
| 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) { | val truck = if (shop?.id != null) { | ||||
| try { | try { | ||||
| println("🔍 Querying truck repository for shopId: ${shop.id}") | |||||
| println(" Querying truck repository for shopId: ${shop.id}") | |||||
| // Get all trucks for this shop | // Get all trucks for this shop | ||||
| val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id) | val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id) | ||||
| println("🔍 Trucks for shop ${shop.id}: ${trucksForShop.size}") | |||||
| println(" Trucks for shop ${shop.id}: ${trucksForShop.size}") | |||||
| trucksForShop.forEach { t -> | trucksForShop.forEach { t -> | ||||
| println(" - Truck ID: ${t.id}, TruckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}") | println(" - Truck ID: ${t.id}, TruckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}") | ||||
| } | } | ||||
| @@ -3265,7 +3265,7 @@ open class PickOrderService( | |||||
| val ticketNo = try { | val ticketNo = try { | ||||
| val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) | val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) | ||||
| val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: "" | val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: "" | ||||
| println("🔍 Found ticket number: $ticketNo for pick order $pickOrderId") | |||||
| println(" Found ticket number: $ticketNo for pick order $pickOrderId") | |||||
| ticketNo | ticketNo | ||||
| } catch (e: Exception) { | } catch (e: Exception) { | ||||
| println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}") | println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}") | ||||
| @@ -3342,9 +3342,9 @@ open class PickOrderService( | |||||
| user, | user, | ||||
| listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED) | listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED) | ||||
| ).filter { it.deliveryOrder != null } // Only pick orders with doId | ).filter { it.deliveryOrder != null } // Only pick orders with doId | ||||
| println("🔍 DEBUG: Found ${allAssignedPickOrders.size} pick orders assigned to user $userId") | |||||
| println(" DEBUG: Found ${allAssignedPickOrders.size} pick orders assigned to user $userId") | |||||
| allAssignedPickOrders.forEach { po -> | allAssignedPickOrders.forEach { po -> | ||||
| println("🔍 DEBUG: Pick order ${po.id}: code=${po.code}, status=${po.status}, assignTo=${po.assignTo?.id}, doId=${po.deliveryOrder?.id}") | |||||
| 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()) { | val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) { | ||||
| @@ -3355,7 +3355,7 @@ open class PickOrderService( | |||||
| if (assignedReleasedOrders.isNotEmpty()) { | 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") | |||||
| println(" DEBUG: Found ${assignedReleasedOrders.size} assigned RELEASED orders, showing only those") | |||||
| assignedReleasedOrders | assignedReleasedOrders | ||||
| } else { | } else { | ||||
| // If no assigned RELEASED orders, show only the latest COMPLETED order | // If no assigned RELEASED orders, show only the latest COMPLETED order | ||||
| @@ -3366,7 +3366,7 @@ open class PickOrderService( | |||||
| println("�� DEBUG: No assigned RELEASED orders, showing latest completed order: ${latestCompleted?.code}") | println("�� DEBUG: No assigned RELEASED orders, showing latest completed order: ${latestCompleted?.code}") | ||||
| listOfNotNull(latestCompleted) | listOfNotNull(latestCompleted) | ||||
| } else { | } else { | ||||
| println("🔍 DEBUG: No orders found") | |||||
| println(" DEBUG: No orders found") | |||||
| emptyList() | emptyList() | ||||
| } | } | ||||
| } | } | ||||
| @@ -3523,7 +3523,7 @@ ORDER BY | |||||
| il.lotNo ASC | il.lotNo ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing SQL for all pick order lots with details (no auto-assign): $sql") | |||||
| println(" Executing SQL for all pick order lots with details (no auto-assign): $sql") | |||||
| println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") | println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") | ||||
| val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) | val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) | ||||
| @@ -3630,7 +3630,7 @@ ORDER BY | |||||
| ) | ) | ||||
| } | } | ||||
| println("🔍 Found ${userPickOrders.size} pick orders assigned to user $userId") | |||||
| println(" Found ${userPickOrders.size} pick orders assigned to user $userId") | |||||
| val pickOrderIds = userPickOrders.mapNotNull { it.id } | val pickOrderIds = userPickOrders.mapNotNull { it.id } | ||||
| // Step 2: 通过 do_pick_order_line 找到相关的 do_pick_order | // Step 2: 通过 do_pick_order_line 找到相关的 do_pick_order | ||||
| @@ -3648,7 +3648,7 @@ ORDER BY | |||||
| ) | ) | ||||
| } | } | ||||
| println("🔍 Found ${doPickOrderIds.size} do_pick_order records") | |||||
| 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) | val doPickOrder = doPickOrderRepository.findById(doPickOrderIds.first()).orElse(null) | ||||
| @@ -3661,13 +3661,13 @@ ORDER BY | |||||
| } | } | ||||
| val doPickOrderId = doPickOrder.id!! | val doPickOrderId = doPickOrder.id!! | ||||
| println("🔍 Using do_pick_order ID: $doPickOrderId") | |||||
| println(" Using do_pick_order ID: $doPickOrderId") | |||||
| // Step 4: 使用 Repository 加载 pick orders 及其关联数据 | // Step 4: 使用 Repository 加载 pick orders 及其关联数据 | ||||
| val pickOrders = pickOrderRepository.findAllById(pickOrderIds) | val pickOrders = pickOrderRepository.findAllById(pickOrderIds) | ||||
| .filter { it.deleted == false } | .filter { it.deleted == false } | ||||
| println("🔍 Loaded ${pickOrders.size} pick orders") | |||||
| println(" Loaded ${pickOrders.size} pick orders") | |||||
| // 收集所有需要的数据 | // 收集所有需要的数据 | ||||
| // 收集所有需要的数据 | // 收集所有需要的数据 | ||||
| @@ -4037,7 +4037,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String | |||||
| } | } | ||||
| val doPickOrderId = (doPickOrderInfo["do_pick_order_id"] as? Number)?.toLong() | val doPickOrderId = (doPickOrderInfo["do_pick_order_id"] as? Number)?.toLong() | ||||
| println("🔍 Found do_pick_order ID: $doPickOrderId") | |||||
| println(" Found do_pick_order ID: $doPickOrderId") | |||||
| val doTicketStatus = doPickOrderInfo["ticket_status"] | val doTicketStatus = doPickOrderInfo["ticket_status"] | ||||
| // Step 2: 获取该 do_pick_order 下的所有 pick orders | // Step 2: 获取该 do_pick_order 下的所有 pick orders | ||||
| val pickOrdersSql = """ | val pickOrdersSql = """ | ||||
| @@ -4058,7 +4058,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String | |||||
| """.trimIndent() | """.trimIndent() | ||||
| val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderId" to doPickOrderId)) | val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderId" to doPickOrderId)) | ||||
| println("🔍 Found ${pickOrdersInfo.size} pick orders") | |||||
| println(" Found ${pickOrdersInfo.size} pick orders") | |||||
| // Step 3: 为每个 pick order 获取 lines 和 lots | // Step 3: 为每个 pick order 获取 lines 和 lots | ||||
| val allPickOrderLines = mutableListOf<Map<String, Any?>>() | val allPickOrderLines = mutableListOf<Map<String, Any?>>() | ||||
| @@ -4201,7 +4201,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String | |||||
| """.trimIndent() | """.trimIndent() | ||||
| val linesResults = jdbcDao.queryForList(linesSql, mapOf("pickOrderId" to pickOrderId)) | val linesResults = jdbcDao.queryForList(linesSql, mapOf("pickOrderId" to pickOrderId)) | ||||
| println("🔍 Pick order $pickOrderId has ${linesResults.size} line-lot records") | |||||
| println(" Pick order $pickOrderId has ${linesResults.size} line-lot records") | |||||
| println("DEBUG polIds in linesResults: " + linesResults.map { it["pickOrderLineId"] }.distinct()) | println("DEBUG polIds in linesResults: " + linesResults.map { it["pickOrderLineId"] }.distinct()) | ||||
| println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["stockOutLineId"]?.let { _ -> it["pickOrderLineId"] } }.distinct()) | println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["stockOutLineId"]?.let { _ -> it["pickOrderLineId"] } }.distinct()) | ||||
| // 按 pickOrderLineId 分组 | // 按 pickOrderLineId 分组 | ||||
| @@ -4377,8 +4377,8 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto | |||||
| ORDER BY orderDate ASC | ORDER BY orderDate ASC | ||||
| """.trimIndent() | """.trimIndent() | ||||
| println("🔍 Executing SQL: $sql") | |||||
| println("🔍 With parameters: storeId = $storeId") | |||||
| println(" Executing SQL: $sql") | |||||
| println(" With parameters: storeId = $storeId") | |||||
| val results = jdbcDao.queryForList(sql, mapOf("storeId" to storeId)) | val results = jdbcDao.queryForList(sql, mapOf("storeId" to storeId)) | ||||
| println(" Found ${results.size} records") | println(" Found ${results.size} records") | ||||
| @@ -4743,7 +4743,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri | |||||
| """.trimIndent() | """.trimIndent() | ||||
| val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderRecordId" to doPickOrderRecordId)) | val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderRecordId" to doPickOrderRecordId)) | ||||
| println("🔍 Found ${pickOrdersInfo.size} pick orders in do_pick_order_record") | |||||
| println(" Found ${pickOrdersInfo.size} pick orders in do_pick_order_record") | |||||
| // Step 3: 为每个 pick order 获取 lines 和 lots | // Step 3: 为每个 pick order 获取 lines 和 lots | ||||
| val pickOrders = pickOrdersInfo.map { poInfo -> | val pickOrders = pickOrdersInfo.map { poInfo -> | ||||
| @@ -5082,7 +5082,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri | |||||
| pickOrders = emptyList() | pickOrders = emptyList() | ||||
| ) | ) | ||||
| println("🔍 Found DoPickOrderRecord: id=${dpor.id}, ticketNo=${dpor.ticketNo}") | |||||
| println(" Found DoPickOrderRecord: id=${dpor.id}, ticketNo=${dpor.ticketNo}") | |||||
| // 2) 构建 fgInfo | // 2) 构建 fgInfo | ||||
| val fgInfo = FgInfoResponse( | val fgInfo = FgInfoResponse( | ||||
| @@ -5097,7 +5097,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri | |||||
| // 3) 通过 DoPickOrderLineRecord 获取 pickOrderIds | // 3) 通过 DoPickOrderLineRecord 获取 pickOrderIds | ||||
| val lineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(dpor.recordId!!) | val lineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(dpor.recordId!!) | ||||
| println("🔍 Found ${lineRecords.size} DoPickOrderLineRecord records") | |||||
| println(" Found ${lineRecords.size} DoPickOrderLineRecord records") | |||||
| var pickOrderIds = lineRecords.mapNotNull { it.pickOrderId }.distinct() | var pickOrderIds = lineRecords.mapNotNull { it.pickOrderId }.distinct() | ||||
| @@ -5115,7 +5115,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri | |||||
| ) | ) | ||||
| } | } | ||||
| println("🔍 Using pickOrderIds: $pickOrderIds") | |||||
| println(" Using pickOrderIds: $pickOrderIds") | |||||
| // 4) 批量加载所有相关数据 | // 4) 批量加载所有相关数据 | ||||
| val pickOrders = pickOrderRepository.findAllById(pickOrderIds) | val pickOrders = pickOrderRepository.findAllById(pickOrderIds) | ||||
| @@ -5129,7 +5129,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri | |||||
| ) | ) | ||||
| } | } | ||||
| println("🔍 Found ${pickOrders.size} pick orders") | |||||
| println(" Found ${pickOrders.size} pick orders") | |||||
| // 5) 收集所有 pickOrderLineIds | // 5) 收集所有 pickOrderLineIds | ||||
| val allPickOrderLineIds = pickOrders | val allPickOrderLineIds = pickOrders | ||||
| @@ -5137,7 +5137,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri | |||||
| .filter { !it.deleted } | .filter { !it.deleted } | ||||
| .mapNotNull { it.id } | .mapNotNull { it.id } | ||||
| println("🔍 Found ${allPickOrderLineIds.size} pick order lines") | |||||
| println(" Found ${allPickOrderLineIds.size} pick order lines") | |||||
| // 6) 批量加载 suggestions 和 stock out lines | // 6) 批量加载 suggestions 和 stock out lines | ||||
| val allSuggestions = if (allPickOrderLineIds.isNotEmpty()) { | val allSuggestions = if (allPickOrderLineIds.isNotEmpty()) { | ||||
| @@ -5317,7 +5317,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri | |||||
| // 新增:从 do_pick_order_record 表查询(用于已完成的 pick orders) | // 新增:从 do_pick_order_record 表查询(用于已完成的 pick orders) | ||||
| open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { | open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { | ||||
| try { | try { | ||||
| println("🔍 Starting getFgPickOrdersFromRecordByPickOrderId with pickOrderId: $pickOrderId") | |||||
| println(" Starting getFgPickOrdersFromRecordByPickOrderId with pickOrderId: $pickOrderId") | |||||
| val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) | val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) | ||||
| if (pickOrder == null) { | if (pickOrder == null) { | ||||
| @@ -83,14 +83,14 @@ open class ProductProcessService( | |||||
| } | } | ||||
| open fun findById(id: Long): ProductProcess { | open fun findById(id: Long): ProductProcess { | ||||
| println("🔍 Service: Finding ProductProcess by ID: $id") | |||||
| println(" Service: Finding ProductProcess by ID: $id") | |||||
| return productProcessRepository.findById(id) | return productProcessRepository.findById(id) | ||||
| .orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") } | .orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") } | ||||
| } | } | ||||
| open fun findByCode(code: String): ProductProcess { | open fun findByCode(code: String): ProductProcess { | ||||
| println("🔍 Service: Finding ProductProcess by code: $code") | |||||
| println(" Service: Finding ProductProcess by code: $code") | |||||
| return productProcessRepository.findByProductProcessCode(code) | return productProcessRepository.findByProductProcessCode(code) | ||||
| .orElseThrow { IllegalArgumentException("ProductProcess not found with code: $code") } | .orElseThrow { IllegalArgumentException("ProductProcess not found with code: $code") } | ||||
| } | } | ||||
| @@ -126,7 +126,7 @@ open class ProductProcessService( | |||||
| // 4. 查询 BOM 的所有工序步骤 | // 4. 查询 BOM 的所有工序步骤 | ||||
| val bomProcesses = bomProcessRepository.findByBomIdOrderBySeqNo(request.bomId) | val bomProcesses = bomProcessRepository.findByBomIdOrderBySeqNo(request.bomId) | ||||
| println("🔍 Service: Found ${bomProcesses.size} BOM processes") | |||||
| println(" Service: Found ${bomProcesses.size} BOM processes") | |||||
| // 5. 为每个 BOM Process 创建 ProductProcessLine | // 5. 为每个 BOM Process 创建 ProductProcessLine | ||||
| bomProcesses.forEachIndexed { index, bomProcess -> // 修复 forEach | bomProcesses.forEachIndexed { index, bomProcess -> // 修复 forEach | ||||
| @@ -274,14 +274,14 @@ open class ProductProcessService( | |||||
| return issues | return issues | ||||
| } | } | ||||
| open fun findByJobOrderId(jobOrderId: Long): List<ProductProcess> { | open fun findByJobOrderId(jobOrderId: Long): List<ProductProcess> { | ||||
| println("🔍 Service: Finding ProductProcess by jobOrderId: $jobOrderId") | |||||
| println(" Service: Finding ProductProcess by jobOrderId: $jobOrderId") | |||||
| val result = productProcessRepository.findByJobOrder_Id(jobOrderId) | val result = productProcessRepository.findByJobOrder_Id(jobOrderId) | ||||
| println(" Service: Found ${result.size} processes") | println(" Service: Found ${result.size} processes") | ||||
| return result | return result | ||||
| } | } | ||||
| open fun findByJobOrderIdWithLines(jobOrderId: Long): List<ProductProcessWithLinesResponse> { | open fun findByJobOrderIdWithLines(jobOrderId: Long): List<ProductProcessWithLinesResponse> { | ||||
| println("🔍 Service: Finding ProductProcess with lines by jobOrderId: $jobOrderId") | |||||
| println(" Service: Finding ProductProcess with lines by jobOrderId: $jobOrderId") | |||||
| val processes = productProcessRepository.findByJobOrder_Id(jobOrderId) | val processes = productProcessRepository.findByJobOrder_Id(jobOrderId) | ||||
| val result = processes.map { process -> | val result = processes.map { process -> | ||||
| @@ -338,7 +338,7 @@ open class ProductProcessService( | |||||
| } | } | ||||
| open fun findByIdAsDto(id: Long): ProductProcessSimpleResponse { | open fun findByIdAsDto(id: Long): ProductProcessSimpleResponse { | ||||
| println("🔍 Service: Finding ProductProcess by ID: $id as DTO") | |||||
| println(" Service: Finding ProductProcess by ID: $id as DTO") | |||||
| val entity = productProcessRepository.findById(id) | val entity = productProcessRepository.findById(id) | ||||
| .orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") } | .orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") } | ||||
| @@ -480,7 +480,7 @@ open class ProductProcessService( | |||||
| return saved | return saved | ||||
| } | } | ||||
| open fun findPendingLinesByHandlerId(handlerId: Long): List<ProductProcessLine> { | open fun findPendingLinesByHandlerId(handlerId: Long): List<ProductProcessLine> { | ||||
| println("🔍 Service: Finding pending lines for handlerId: $handlerId") | |||||
| println(" Service: Finding pending lines for handlerId: $handlerId") | |||||
| val lines = productProcessLineRepository.findByHandler_IdAndStartTimeIsNotNullAndEndTimeIsNull(handlerId) | val lines = productProcessLineRepository.findByHandler_IdAndStartTimeIsNotNullAndEndTimeIsNull(handlerId) | ||||
| println(" Service: Found ${lines.size} pending lines") | println(" Service: Found ${lines.size} pending lines") | ||||
| return lines | return lines | ||||
| @@ -25,7 +25,7 @@ class ProductProcessController( | |||||
| @GetMapping("/{id}") | @GetMapping("/{id}") | ||||
| fun findById(@PathVariable id: Long): ProductProcessSimpleResponse { // 改为返回 DTO | fun findById(@PathVariable id: Long): ProductProcessSimpleResponse { // 改为返回 DTO | ||||
| println("🔍 Controller: GET /product-process/$id") | |||||
| println(" Controller: GET /product-process/$id") | |||||
| val result = productProcessService.findByIdAsDto(id) // 使用新方法 | val result = productProcessService.findByIdAsDto(id) // 使用新方法 | ||||
| println(" Controller: Found: ${result.productProcessCode}") | println(" Controller: Found: ${result.productProcessCode}") | ||||
| return result | return result | ||||
| @@ -33,7 +33,7 @@ class ProductProcessController( | |||||
| @GetMapping("/code/{code}") | @GetMapping("/code/{code}") | ||||
| fun findByCode(@PathVariable code: String): ProductProcess { | fun findByCode(@PathVariable code: String): ProductProcess { | ||||
| println("🔍 Controller: GET /product-process/code/$code") | |||||
| println(" Controller: GET /product-process/code/$code") | |||||
| val result = productProcessService.findByCode(code) | val result = productProcessService.findByCode(code) | ||||
| println(" Controller: Found ID: ${result.id}") | println(" Controller: Found ID: ${result.id}") | ||||
| return result | return result | ||||
| @@ -128,7 +128,7 @@ class ProductProcessController( | |||||
| @GetMapping("/by-job-order/{jobOrderId}") | @GetMapping("/by-job-order/{jobOrderId}") | ||||
| fun findByJobOrderId(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> { // 改为返回 DTO | fun findByJobOrderId(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> { // 改为返回 DTO | ||||
| println("🔍 Controller: GET /product-process/by-job-order/$jobOrderId") | |||||
| println(" Controller: GET /product-process/by-job-order/$jobOrderId") | |||||
| val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) // 直接使用 with-lines 方法 | val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) // 直接使用 with-lines 方法 | ||||
| println(" Controller: Found ${result.size} processes for Job Order $jobOrderId") | println(" Controller: Found ${result.size} processes for Job Order $jobOrderId") | ||||
| return result | return result | ||||
| @@ -137,7 +137,7 @@ class ProductProcessController( | |||||
| // 额外添加:获取带 lines 的完整数据 | // 额外添加:获取带 lines 的完整数据 | ||||
| @GetMapping("/by-job-order/{jobOrderId}/with-lines") | @GetMapping("/by-job-order/{jobOrderId}/with-lines") | ||||
| fun findByJobOrderIdWithLines(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> { | fun findByJobOrderIdWithLines(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> { | ||||
| println("🔍 Controller: GET /product-process/by-job-order/$jobOrderId/with-lines") | |||||
| println(" Controller: GET /product-process/by-job-order/$jobOrderId/with-lines") | |||||
| val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) | 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 | return result | ||||
| @@ -63,4 +63,11 @@ fun findAllByWarehouseIdInAndDeletedIsFalse(@Param("warehouseIds") warehouseIds: | |||||
| ORDER BY ill.inventoryLot.item.code, ill.inventoryLot.lotNo | ORDER BY ill.inventoryLot.item.code, ill.inventoryLot.lotNo | ||||
| """) | """) | ||||
| fun findAllByWarehouseCodeAndDeletedIsFalse(@Param("warehouseCode") warehouseCode: String): List<InventoryLotLine> | fun findAllByWarehouseCodeAndDeletedIsFalse(@Param("warehouseCode") warehouseCode: String): List<InventoryLotLine> | ||||
| @Query(""" | |||||
| SELECT COUNT(DISTINCT ill.inventoryLot.item.id) | |||||
| FROM InventoryLotLine ill | |||||
| WHERE ill.warehouse.id IN :warehouseIds | |||||
| AND ill.deleted = false | |||||
| """) | |||||
| fun countDistinctItemsByWarehouseIds(@Param("warehouseIds") warehouseIds: List<Long>): Long | |||||
| } | } | ||||
| @@ -108,6 +108,9 @@ open class StockInLine : BaseEntity<Long>() { | |||||
| @Column(name = "remarks") | @Column(name = "remarks") | ||||
| open var remarks: String? = null | open var remarks: String? = null | ||||
| @Column(name = "type") | |||||
| open var type: String? = null | |||||
| @JsonManagedReference | @JsonManagedReference | ||||
| @OneToMany(mappedBy = "stockInLine", cascade = [CascadeType.ALL], orphanRemoval = true) | @OneToMany(mappedBy = "stockInLine", cascade = [CascadeType.ALL], orphanRemoval = true) | ||||
| open var escalationLog: MutableList<EscalationLog>? = mutableListOf() | open var escalationLog: MutableList<EscalationLog>? = mutableListOf() | ||||
| @@ -45,4 +45,7 @@ open class StockOutLine: BaseEntity<Long>() { | |||||
| @ManyToOne | @ManyToOne | ||||
| @JoinColumn(name = "pickOrderLineId") | @JoinColumn(name = "pickOrderLineId") | ||||
| open var pickOrderLine: PickOrderLine? = null | open var pickOrderLine: PickOrderLine? = null | ||||
| @Column(name = "type") | |||||
| open var type: String? = null | |||||
| } | } | ||||
| @@ -97,9 +97,9 @@ class StockTakeRecordService( | |||||
| .filter { it.status == StockTakeStatus.COMPLETED && it.actualEnd != null } | .filter { it.status == StockTakeStatus.COMPLETED && it.actualEnd != null } | ||||
| .sortedByDescending { it.actualEnd } | .sortedByDescending { it.actualEnd } | ||||
| val lastStockTakeDate = completedStockTakes.firstOrNull()?.actualEnd?.toLocalDate() | |||||
| val lastStockTakeDate = completedStockTakes.firstOrNull()?.actualEnd | |||||
| // 7. 获取 status:获取最新的 stock_take 记录(按 actualStart 或 planStart 排序) | |||||
| val latestStockTake = stockTakesForSection | val latestStockTake = stockTakesForSection | ||||
| .maxByOrNull { it.actualStart ?: it.planStart ?: LocalDateTime.MIN } | .maxByOrNull { it.actualStart ?: it.planStart ?: LocalDateTime.MIN } | ||||
| @@ -108,17 +108,65 @@ class StockTakeRecordService( | |||||
| } else { | } else { | ||||
| "no_cycle" | "no_cycle" | ||||
| } | } | ||||
| val stockTakerName = if (latestStockTake != null) { | |||||
| // 从该 stock take 的 records 中获取最新的 stockTakerName | |||||
| val recordsForStockTake = allStockTakeRecords | |||||
| .filter { | |||||
| it.stockTake?.id == latestStockTake.id && | |||||
| it.stockTakeSection == stockTakeSection && | |||||
| it.stockTakerName != null | |||||
| } | |||||
| .sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN } | |||||
| recordsForStockTake.firstOrNull()?.stockTakerName | |||||
| } else { | |||||
| null | |||||
| } | |||||
| val approverName = if (latestStockTake != null) { | |||||
| // 从该 stock take 的 records 中获取最新的 approverName | |||||
| val recordsForStockTake = allStockTakeRecords | |||||
| .filter { | |||||
| it.stockTake?.id == latestStockTake.id && | |||||
| it.stockTakeSection == stockTakeSection && | |||||
| it.approverName != null | |||||
| } | |||||
| .sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN } | |||||
| recordsForStockTake.firstOrNull()?.approverName | |||||
| } else { | |||||
| null | |||||
| } | |||||
| // 9. 计算 TotalItemNumber:获取该 section 下所有 InventoryLotLine,按 item 分组,计算不同的 item 数量 | |||||
| val totalItemNumber = inventoryLotLineRepository.countDistinctItemsByWarehouseIds(warehouseIds).toInt() | |||||
| // 8. 使用 stockTakeSection 作为 stockTakeSession | // 8. 使用 stockTakeSection 作为 stockTakeSession | ||||
| val reStockTakeTrueFalse = if (latestStockTake != null) { | |||||
| // 检查该 stock take 下该 section 的记录中是否有 notMatch 状态 | |||||
| val hasNotMatch = allStockTakeRecords.any { | |||||
| !it.deleted && | |||||
| it.stockTake?.id == latestStockTake.id && | |||||
| it.stockTakeSection == stockTakeSection && | |||||
| it.status == "notMatch" | |||||
| } | |||||
| hasNotMatch | |||||
| } else { | |||||
| false | |||||
| } | |||||
| result.add( | result.add( | ||||
| AllPickedStockTakeListReponse( | AllPickedStockTakeListReponse( | ||||
| id = idCounter++, | id = idCounter++, | ||||
| stockTakeSession = stockTakeSection, | stockTakeSession = stockTakeSection, | ||||
| lastStockTakeDate = lastStockTakeDate, | |||||
| status = status, | |||||
| currentStockTakeItemNumber = 0, // 临时设为 0,测试性能 | |||||
| totalInventoryLotNumber = 0, // 临时设为 0,测试性能 | |||||
| stockTakeId = latestStockTake?.id ?: 0 | |||||
| lastStockTakeDate = latestStockTake?.actualStart?.toLocalDate(), | |||||
| status = status?:"", | |||||
| currentStockTakeItemNumber = 0, | |||||
| totalInventoryLotNumber = 0, | |||||
| stockTakeId = latestStockTake?.id ?: 0, | |||||
| stockTakerName = stockTakerName, | |||||
| TotalItemNumber = totalItemNumber, | |||||
| approverName = approverName, | |||||
| startTime = latestStockTake?.actualStart, | |||||
| endTime = latestStockTake?.actualEnd, | |||||
| ReStockTakeTrueFalse = reStockTakeTrueFalse | |||||
| ) | ) | ||||
| ) | ) | ||||
| } | } | ||||
| @@ -196,17 +244,65 @@ class StockTakeRecordService( | |||||
| } else { | } else { | ||||
| null | null | ||||
| } | } | ||||
| val stockTakerName = if (latestStockTake != null) { | |||||
| // 从该 stock take 的 records 中获取最新的 stockTakerName | |||||
| val recordsForStockTake = allStockTakeRecords | |||||
| .filter { | |||||
| it.stockTake?.id == latestStockTake.id && | |||||
| it.stockTakeSection == stockTakeSection && | |||||
| it.stockTakerName != null | |||||
| } | |||||
| .sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN } | |||||
| recordsForStockTake.firstOrNull()?.stockTakerName | |||||
| } else { | |||||
| null | |||||
| } | |||||
| val approverName = if (latestStockTake != null) { | |||||
| // 从该 stock take 的 records 中获取最新的 approverName | |||||
| val recordsForStockTake = allStockTakeRecords | |||||
| .filter { | |||||
| it.stockTake?.id == latestStockTake.id && | |||||
| it.stockTakeSection == stockTakeSection && | |||||
| it.approverName != null | |||||
| } | |||||
| .sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN } | |||||
| recordsForStockTake.firstOrNull()?.approverName | |||||
| } else { | |||||
| null | |||||
| } | |||||
| val reStockTakeTrueFalse = if (latestStockTake != null) { | |||||
| // 检查该 stock take 下该 section 的记录中是否有 notMatch 状态 | |||||
| val hasNotMatch = allStockTakeRecords.any { | |||||
| !it.deleted && | |||||
| it.stockTake?.id == latestStockTake.id && | |||||
| it.stockTakeSection == stockTakeSection && | |||||
| it.status == "notMatch" | |||||
| } | |||||
| hasNotMatch | |||||
| } else { | |||||
| false | |||||
| } | |||||
| // 9. 计算 TotalItemNumber:获取该 section 下所有 InventoryLotLine,按 item 分组,计算不同的 item 数量 | |||||
| val totalItemNumber = inventoryLotLineRepository.countDistinctItemsByWarehouseIds(warehouseIds).toInt() | |||||
| // 9. 使用 stockTakeSection 作为 stockTakeSession | // 9. 使用 stockTakeSection 作为 stockTakeSession | ||||
| result.add( | result.add( | ||||
| AllPickedStockTakeListReponse( | AllPickedStockTakeListReponse( | ||||
| id = idCounter++, | id = idCounter++, | ||||
| stockTakeSession = stockTakeSection, | stockTakeSession = stockTakeSection, | ||||
| lastStockTakeDate = lastStockTakeDate, | |||||
| lastStockTakeDate = latestStockTake?.actualStart?.toLocalDate(), | |||||
| status = status?:"", | status = status?:"", | ||||
| currentStockTakeItemNumber = 0, // 临时设为 0,测试性能 | currentStockTakeItemNumber = 0, // 临时设为 0,测试性能 | ||||
| totalInventoryLotNumber = 0, // 临时设为 0,测试性能 | totalInventoryLotNumber = 0, // 临时设为 0,测试性能 | ||||
| stockTakeId = latestStockTake?.id ?: 0 | |||||
| stockTakeId = latestStockTake?.id ?: 0, | |||||
| stockTakerName = stockTakerName, | |||||
| approverName = approverName, | |||||
| TotalItemNumber = totalItemNumber, | |||||
| startTime = latestStockTake?.actualStart, | |||||
| endTime = latestStockTake?.actualEnd, | |||||
| ReStockTakeTrueFalse = reStockTakeTrueFalse | |||||
| ) | ) | ||||
| ) | ) | ||||
| } | } | ||||
| @@ -414,11 +510,10 @@ class StockTakeRecordService( | |||||
| } | } | ||||
| existingRecord | existingRecord | ||||
| } else { | } else { | ||||
| // 创建新记录(第一次盘点) | |||||
| // 第一次盘点不验证 QTY + Bad QTY 是否匹配,允许不匹配的情况 | |||||
| // 如果匹配,status = "1",如果不匹配,status = "2" | |||||
| val totalInputQty = request.qty.add(request.badQty) | val totalInputQty = request.qty.add(request.badQty) | ||||
| val isMatched = totalInputQty.compareTo(availableQty) == 0 | val isMatched = totalInputQty.compareTo(availableQty) == 0 | ||||
| val isCompled=inventoryLotLine.inQty==inventoryLotLine.outQty | |||||
| val varianceQty = availableQty-request.qty-request.badQty | val varianceQty = availableQty-request.qty-request.badQty | ||||
| StockTakeRecord().apply { | StockTakeRecord().apply { | ||||
| this.itemId = item.id | this.itemId = item.id | ||||
| @@ -435,7 +530,7 @@ class StockTakeRecordService( | |||||
| this.varianceQty = varianceQty | this.varianceQty = varianceQty | ||||
| this.uom = inventoryLotLine.stockUom?.uom?.udfudesc | this.uom = inventoryLotLine.stockUom?.uom?.udfudesc | ||||
| this.date = java.time.LocalDate.now() | this.date = java.time.LocalDate.now() | ||||
| this.status = if (isMatched) "pass" else "notMatch" | |||||
| this.status = if (isCompled) "completed" else "pass" | |||||
| this.remarks = request.remark | this.remarks = request.remark | ||||
| this.itemCode = item.code | this.itemCode = item.code | ||||
| this.itemName = item.name | this.itemName = item.name | ||||
| @@ -447,7 +542,23 @@ class StockTakeRecordService( | |||||
| val savedRecord = stockTakeRecordRepository.save(stockTakeRecord) | val savedRecord = stockTakeRecordRepository.save(stockTakeRecord) | ||||
| if (request.stockTakeRecordId == null) { | |||||
| val existingRecordsCount = stockTakeRecordRepository.findAll() | |||||
| .filter { | |||||
| !it.deleted && | |||||
| it.stockTake?.id == stockTakeId && | |||||
| it.id != savedRecord.id // 排除刚创建的这条记录 | |||||
| } | |||||
| .count() | |||||
| if (existingRecordsCount == 0 && stockTake.actualStart == null) { | |||||
| stockTake.actualStart = java.time.LocalDateTime.now() | |||||
| stockTake.status = StockTakeStatus.STOCKTAKING | |||||
| stockTakeRepository.save(stockTake) | |||||
| println("Stock take $stockTakeId actualStart updated - first record created") | |||||
| } | |||||
| } | |||||
| val stockTakeSection = savedRecord.stockTakeSection | val stockTakeSection = savedRecord.stockTakeSection | ||||
| if (stockTakeSection != null) { | if (stockTakeSection != null) { | ||||
| @@ -541,6 +652,7 @@ open fun batchSaveStockTakeRecords( | |||||
| val totalInputQty = qty.add(badQty) | val totalInputQty = qty.add(badQty) | ||||
| val isMatched = totalInputQty.compareTo(availableQty) == 0 | val isMatched = totalInputQty.compareTo(availableQty) == 0 | ||||
| val varianceQty = availableQty-qty-badQty | val varianceQty = availableQty-qty-badQty | ||||
| val isCompleted = (ill.inQty ?: BigDecimal.ZERO) == (ill.outQty ?: BigDecimal.ZERO) | |||||
| // 创建新记录 | // 创建新记录 | ||||
| val stockTakeRecord = StockTakeRecord().apply { | val stockTakeRecord = StockTakeRecord().apply { | ||||
| this.itemId = itemEntity.id | this.itemId = itemEntity.id | ||||
| @@ -557,7 +669,7 @@ open fun batchSaveStockTakeRecords( | |||||
| this.varianceQty = varianceQty | this.varianceQty = varianceQty | ||||
| this.uom = ill.stockUom?.uom?.udfudesc | this.uom = ill.stockUom?.uom?.udfudesc | ||||
| this.date = java.time.LocalDate.now() | this.date = java.time.LocalDate.now() | ||||
| this.status = if (isMatched) "pass" else "notMatch" | |||||
| this.status = if (isCompleted) "completed" else "pass" | |||||
| this.remarks = null | this.remarks = null | ||||
| this.itemCode = itemEntity.code | this.itemCode = itemEntity.code | ||||
| this.itemName = itemEntity.name | this.itemName = itemEntity.name | ||||
| @@ -577,6 +689,12 @@ open fun batchSaveStockTakeRecords( | |||||
| } | } | ||||
| } | } | ||||
| if (successCount > 0) { | if (successCount > 0) { | ||||
| val existingRecordsCount = stockTakeRecordRepository.findAll() | |||||
| .filter { | |||||
| !it.deleted && | |||||
| it.stockTake?.id == request.stockTakeId | |||||
| } | |||||
| .count() | |||||
| checkAndUpdateStockTakeStatus(request.stockTakeId, request.stockTakeSection) | checkAndUpdateStockTakeStatus(request.stockTakeId, request.stockTakeSection) | ||||
| } | } | ||||
| println("batchSaveStockTakeRecords completed: success=$successCount, errors=$errorCount") | println("batchSaveStockTakeRecords completed: success=$successCount, errors=$errorCount") | ||||
| @@ -586,10 +704,7 @@ open fun batchSaveStockTakeRecords( | |||||
| errors = errors | errors = errors | ||||
| ) | ) | ||||
| } | } | ||||
| // ... existing code ... | |||||
| // 检查并更新 stock take 状态 | |||||
| // 检查并更新 stock take 状态 | |||||
| open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: String): Map<String, Any> { | open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: String): Map<String, Any> { | ||||
| try { | try { | ||||
| val stockTake = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId) | val stockTake = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId) | ||||
| @@ -629,20 +744,29 @@ open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: Stri | |||||
| } | } | ||||
| } | } | ||||
| // 5. 检查是否所有记录的状态都是 "pass" | |||||
| val allRecordsPassed = stockTakeRecords.isNotEmpty() && | val allRecordsPassed = stockTakeRecords.isNotEmpty() && | ||||
| stockTakeRecords.all { it.status == "pass" } | |||||
| stockTakeRecords.all { it.status == "pass" || it.status == "completed" } | |||||
| val allRecordsCompleted = stockTakeRecords.isNotEmpty() && | |||||
| stockTakeRecords.all { it.status == "completed" } | |||||
| // 6. 如果所有记录都已创建且都是 "pass",更新 stock take 状态为 "approving" | // 6. 如果所有记录都已创建且都是 "pass",更新 stock take 状态为 "approving" | ||||
| if (allLinesHaveRecords && allRecordsPassed) { | if (allLinesHaveRecords && allRecordsPassed) { | ||||
| stockTake.status = StockTakeStatus.APPROVING | stockTake.status = StockTakeStatus.APPROVING | ||||
| stockTake.actualEnd = java.time.LocalDateTime.now() | |||||
| stockTakeRepository.save(stockTake) | stockTakeRepository.save(stockTake) | ||||
| println("Stock take $stockTakeId status updated to APPROVING - all records are pass") | println("Stock take $stockTakeId status updated to APPROVING - all records are pass") | ||||
| return mapOf( | return mapOf( | ||||
| "success" to true, | "success" to true, | ||||
| "message" to "Stock take status updated to APPROVING", | "message" to "Stock take status updated to APPROVING", | ||||
| "updated" to true | "updated" to true | ||||
| ) | ) | ||||
| } else if (allLinesHaveRecords && allRecordsCompleted) { | |||||
| stockTake.status = StockTakeStatus.COMPLETED | |||||
| stockTake.planEnd = java.time.LocalDateTime.now() | |||||
| stockTakeRepository.save(stockTake) | |||||
| println("Stock take $stockTakeId status updated to COMPLETED - all records are completed") | |||||
| return mapOf("success" to true, "message" to "Stock take status updated to COMPLETED", "updated" to true) | |||||
| } else { | } else { | ||||
| return mapOf( | return mapOf( | ||||
| "success" to true, | "success" to true, | ||||
| @@ -713,58 +837,60 @@ open fun saveApproverStockTakeRecord( | |||||
| ) ?: throw IllegalArgumentException("Inventory lot not found") | ) ?: throw IllegalArgumentException("Inventory lot not found") | ||||
| if (varianceQty !=BigDecimal.ZERO ) { | if (varianceQty !=BigDecimal.ZERO ) { | ||||
| val stockTakeLine = StockTakeLine().apply { | |||||
| this.stockTake = stockTake | |||||
| this.inventoryLotLine = inventoryLotLine | |||||
| this.initialQty = stockTakeRecord.bookQty | |||||
| this.finalQty = finalQty | |||||
| this.status = StockTakeLineStatus.COMPLETED | |||||
| this.completeDate = java.time.LocalDateTime.now() | |||||
| val stockTakeLine = StockTakeLine().apply { | |||||
| this.stockTake = stockTake | |||||
| this.inventoryLotLine = inventoryLotLine | |||||
| this.initialQty = stockTakeRecord.bookQty | |||||
| this.finalQty = finalQty | |||||
| this.status = StockTakeLineStatus.COMPLETED | |||||
| this.completeDate = java.time.LocalDateTime.now() | |||||
| } | |||||
| stockTakeLineRepository.save(stockTakeLine) | |||||
| if (varianceQty < BigDecimal.ZERO ) { | |||||
| val stockOut=StockOut().apply { | |||||
| this.type="stockTake" | |||||
| this.status="completed" | |||||
| this.handler=request.approverId | |||||
| } | |||||
| stockOutRepository.save(stockOut) | |||||
| } | |||||
| stockTakeLineRepository.save(stockTakeLine) | |||||
| val stockOutLine = StockOutLine().apply { | |||||
| this.item=inventoryLot.item | |||||
| this.qty=(-varianceQty)?.toDouble() | |||||
| this.stockOut = stockOut | |||||
| this.inventoryLotLine = inventoryLotLine | |||||
| this.status = "completed" | |||||
| if (varianceQty < BigDecimal.ZERO ) { | |||||
| val stockOut=StockOut().apply { | |||||
| this.type="stockTake" | |||||
| this.status="completed" | |||||
| this.handler=request.approverId | |||||
| } | |||||
| stockOutRepository.save(stockOut) | |||||
| } | |||||
| stockOutLineRepository.save(stockOutLine) | |||||
| val stockOutLine = StockOutLine().apply { | |||||
| this.item=inventoryLot.item | |||||
| this.qty=(-varianceQty)?.toDouble() | |||||
| this.stockOut = stockOut | |||||
| this.inventoryLotLine = inventoryLotLine | |||||
| this.status = "completed" | |||||
| this.type = "ADJ" | |||||
| } | |||||
| stockOutLineRepository.save(stockOutLine) | |||||
| } | } | ||||
| if (varianceQty > BigDecimal.ZERO ) { | if (varianceQty > BigDecimal.ZERO ) { | ||||
| val stockIn=StockIn().apply { | |||||
| this.code=stockTake.code | |||||
| this.status="completed" | |||||
| this.stockTake=stockTake | |||||
| } | |||||
| stockInRepository.save(stockIn) | |||||
| val stockInLine = StockInLine().apply { | |||||
| this.stockTakeLine=stockTakeLine | |||||
| this.item=inventoryLot.item | |||||
| this.itemNo=stockTakeRecord.itemCode | |||||
| this.stockIn = stockIn | |||||
| this.demandQty=finalQty | |||||
| this.acceptedQty=finalQty | |||||
| this.expiryDate=inventoryLot.expiryDate | |||||
| this.inventoryLot=inventoryLot | |||||
| this.inventoryLotLine=inventoryLotLine | |||||
| this.lotNo=inventoryLot.lotNo | |||||
| this.status = "completed" | |||||
| val stockIn=StockIn().apply { | |||||
| this.code=stockTake.code | |||||
| this.status="completed" | |||||
| this.stockTake=stockTake | |||||
| } | |||||
| stockInRepository.save(stockIn) | |||||
| val stockInLine = StockInLine().apply { | |||||
| this.stockTakeLine=stockTakeLine | |||||
| this.item=inventoryLot.item | |||||
| this.itemNo=stockTakeRecord.itemCode | |||||
| this.stockIn = stockIn | |||||
| this.demandQty=finalQty | |||||
| this.acceptedQty=finalQty | |||||
| this.expiryDate=inventoryLot.expiryDate | |||||
| this.inventoryLot=inventoryLot | |||||
| this.inventoryLotLine=inventoryLotLine | |||||
| this.lotNo=inventoryLot.lotNo | |||||
| this.status = "completed" | |||||
| this.type = "ADJ" | |||||
| } | |||||
| stockInLineRepository.save(stockInLine) | |||||
| } | |||||
| stockInLineRepository.save(stockInLine) | |||||
| } | } | ||||
| // val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO | // val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO | ||||
| // val newInQty = currentInQty.add(variance) | // val newInQty = currentInQty.add(variance) | ||||
| @@ -782,7 +908,10 @@ open fun saveApproverStockTakeRecord( | |||||
| ) | ) | ||||
| inventoryLotLineService.saveInventoryLotLine(updateRequest) | inventoryLotLineService.saveInventoryLotLine(updateRequest) | ||||
| } | } | ||||
| val stockTakeSection = savedRecord.stockTakeSection | |||||
| if (stockTakeSection != null) { | |||||
| checkAndUpdateStockTakeStatus(stockTakeId, stockTakeSection) | |||||
| } | |||||
| return savedRecord | return savedRecord | ||||
| } | } | ||||
| @@ -797,15 +926,15 @@ open fun batchSaveApproverStockTakeRecords( | |||||
| ?: throw IllegalArgumentException("Stock take not found: ${request.stockTakeId}") | ?: throw IllegalArgumentException("Stock take not found: ${request.stockTakeId}") | ||||
| // 2. Get all stock take records for this section where: | // 2. Get all stock take records for this section where: | ||||
| // - secondStockTakeQty is null/0 (no second input) | |||||
| // - pickerFirstStockTakeQty is not 0 | // - pickerFirstStockTakeQty is not 0 | ||||
| // - approverStockTakeQty is null (not yet approved) | |||||
| val stockTakeRecords = stockTakeRecordRepository.findAll() | val stockTakeRecords = stockTakeRecordRepository.findAll() | ||||
| .filter { | .filter { | ||||
| !it.deleted && | !it.deleted && | ||||
| it.stockTake?.id == request.stockTakeId && | it.stockTake?.id == request.stockTakeId && | ||||
| it.stockTakeSection == request.stockTakeSection && | it.stockTakeSection == request.stockTakeSection && | ||||
| (it.pickerSecondStockTakeQty == null || it.pickerSecondStockTakeQty == BigDecimal.ZERO) && | |||||
| it.pickerFirstStockTakeQty != null && it.pickerFirstStockTakeQty!! > BigDecimal.ZERO | |||||
| it.pickerFirstStockTakeQty != null && it.pickerFirstStockTakeQty!! > BigDecimal.ZERO && | |||||
| it.approverStockTakeQty == null // 只处理未审批的记录 | |||||
| } | } | ||||
| println("Found ${stockTakeRecords.size} records to process") | println("Found ${stockTakeRecords.size} records to process") | ||||
| @@ -817,61 +946,47 @@ open fun batchSaveApproverStockTakeRecords( | |||||
| // 3. Process each record | // 3. Process each record | ||||
| var successCount = 0 | var successCount = 0 | ||||
| var errorCount = 0 | var errorCount = 0 | ||||
| var skippedCount = 0 | |||||
| val errors = mutableListOf<String>() | val errors = mutableListOf<String>() | ||||
| stockTakeRecords.forEach { record -> | stockTakeRecords.forEach { record -> | ||||
| try { | try { | ||||
| // Use first qty/badQty as approver selection | |||||
| val qty = record.pickerFirstStockTakeQty ?: BigDecimal.ZERO | |||||
| val badQty = record.pickerFirstBadQty ?: BigDecimal.ZERO | |||||
| // Update approver fields | |||||
| record.apply { | |||||
| this.approverId = request.approverId | |||||
| this.approverName = user?.name | |||||
| this.approverStockTakeQty = qty | |||||
| this.approverBadQty = badQty | |||||
| val qty: BigDecimal | |||||
| val badQty: BigDecimal | |||||
| if (record.pickerSecondStockTakeQty != null && record.pickerSecondStockTakeQty!! > BigDecimal.ZERO) { | |||||
| qty = record.pickerSecondStockTakeQty!! | |||||
| badQty = record.pickerSecondBadQty ?: BigDecimal.ZERO | |||||
| } else { | |||||
| qty = record.pickerFirstStockTakeQty ?: BigDecimal.ZERO | |||||
| badQty = record.pickerFirstBadQty ?: BigDecimal.ZERO | |||||
| } | } | ||||
| stockTakeRecordRepository.save(record) | |||||
| // Create stock_take_line and update inventoryLotLine | |||||
| val inventoryLotLine = record.inventoryLotId?.let { | |||||
| inventoryLotLineRepository.findByIdAndDeletedIsFalse(it) | |||||
| } ?: throw IllegalArgumentException("Inventory lot line not found") | |||||
| val bookQty = record.bookQty ?: BigDecimal.ZERO | |||||
| val varianceQty = qty.subtract(bookQty) | |||||
| // Create stock take line | |||||
| val stockTakeLine = StockTakeLine().apply { | |||||
| this.stockTake = stockTake | |||||
| this.inventoryLotLine = inventoryLotLine | |||||
| this.initialQty = record.bookQty | |||||
| this.finalQty = qty.add(badQty) | |||||
| this.status = StockTakeLineStatus.COMPLETED | |||||
| this.completeDate = java.time.LocalDateTime.now() | |||||
| this.remarks = "Batch approved by approver" | |||||
| if (varianceQty.compareTo(BigDecimal.ZERO) != 0) { | |||||
| skippedCount++ | |||||
| println("Skipping record ${record.id}: variance = $varianceQty (qty=$qty, bookQty=$bookQty)") | |||||
| return@forEach | |||||
| } | } | ||||
| stockTakeLineRepository.save(stockTakeLine) | |||||
| // Update inventoryLotLine | |||||
| val variance = qty.add(badQty).subtract(record.bookQty ?: BigDecimal.ZERO) | |||||
| if (variance.compareTo(BigDecimal.ZERO) != 0) { | |||||
| val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO | |||||
| val newInQty = currentInQty.add(variance) | |||||
| val updateRequest = SaveInventoryLotLineRequest( | |||||
| id = inventoryLotLine.id, | |||||
| inventoryLotId = inventoryLotLine.inventoryLot?.id, | |||||
| warehouseId = inventoryLotLine.warehouse?.id, | |||||
| stockUomId = inventoryLotLine.stockUom?.id, | |||||
| inQty = newInQty, | |||||
| outQty = inventoryLotLine.outQty, | |||||
| holdQty = inventoryLotLine.holdQty, | |||||
| status = inventoryLotLine.status?.value, | |||||
| remarks = inventoryLotLine.remarks | |||||
| ) | |||||
| inventoryLotLineService.saveInventoryLotLine(updateRequest) | |||||
| // variance = 0,批量保存并设置为 completed | |||||
| record.apply { | |||||
| this.approverId = request.approverId | |||||
| this.approverName = user?.name | |||||
| this.approverStockTakeQty = qty | |||||
| this.approverBadQty = badQty | |||||
| this.varianceQty = varianceQty // 应该是 0 | |||||
| this.status = "completed" | |||||
| } | } | ||||
| stockTakeRecordRepository.save(record) | |||||
| successCount++ | successCount++ | ||||
| } catch (e: Exception) { | } catch (e: Exception) { | ||||
| errorCount++ | errorCount++ | ||||
| @@ -881,14 +996,19 @@ open fun batchSaveApproverStockTakeRecords( | |||||
| } | } | ||||
| } | } | ||||
| println("batchSaveApproverStockTakeRecords completed: success=$successCount, errors=$errorCount") | |||||
| // 只在最后调用一次 checkAndUpdateStockTakeStatus | |||||
| if (successCount > 0) { | |||||
| checkAndUpdateStockTakeStatus(request.stockTakeId, request.stockTakeSection) | |||||
| } | |||||
| println("batchSaveApproverStockTakeRecords completed: success=$successCount, skipped=$skippedCount, errors=$errorCount") | |||||
| return BatchSaveApproverStockTakeRecordResponse( | return BatchSaveApproverStockTakeRecordResponse( | ||||
| successCount = successCount, | successCount = successCount, | ||||
| errorCount = errorCount, | errorCount = errorCount, | ||||
| errors = errors | errors = errors | ||||
| ) | ) | ||||
| } | } | ||||
| // 在文件末尾,batchSaveApproverStockTakeRecords 方法之后添加 | |||||
| open fun updateStockTakeRecordStatusToNotMatch(stockTakeRecordId: Long): StockTakeRecord { | open fun updateStockTakeRecordStatusToNotMatch(stockTakeRecordId: Long): StockTakeRecord { | ||||
| println("updateStockTakeRecordStatusToNotMatch called with stockTakeRecordId: $stockTakeRecordId") | println("updateStockTakeRecordStatusToNotMatch called with stockTakeRecordId: $stockTakeRecordId") | ||||
| @@ -1,16 +1,27 @@ | |||||
| // StockTakeRecordReponse.kt | // StockTakeRecordReponse.kt | ||||
| package com.ffii.fpsms.modules.stock.web.model | package com.ffii.fpsms.modules.stock.web.model | ||||
| import com.fasterxml.jackson.annotation.JsonFormat | |||||
| import java.time.LocalDate | import java.time.LocalDate | ||||
| import java.math.BigDecimal | import java.math.BigDecimal | ||||
| import java.time.LocalDateTime | |||||
| data class AllPickedStockTakeListReponse( | data class AllPickedStockTakeListReponse( | ||||
| val id: Long, | val id: Long, | ||||
| val stockTakeSession: String, | val stockTakeSession: String, | ||||
| @JsonFormat(pattern = "yyyy-MM-dd") | |||||
| val lastStockTakeDate: LocalDate?, | val lastStockTakeDate: LocalDate?, | ||||
| val status: String, | val status: String, | ||||
| val currentStockTakeItemNumber: Int, | val currentStockTakeItemNumber: Int, | ||||
| val totalInventoryLotNumber: Int, | val totalInventoryLotNumber: Int, | ||||
| @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") | |||||
| val startTime: LocalDateTime?, | |||||
| @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") | |||||
| val endTime: LocalDateTime?, | |||||
| val stockTakeId: Long, | val stockTakeId: Long, | ||||
| val stockTakerName: String?, | |||||
| val approverName: String?, | |||||
| val TotalItemNumber: Int, | |||||
| val ReStockTakeTrueFalse: Boolean, | |||||
| ) | ) | ||||
| data class InventoryLotDetailResponse( | data class InventoryLotDetailResponse( | ||||
| val id: Long, | val id: Long, | ||||
| @@ -0,0 +1,8 @@ | |||||
| --liquibase formatted sql | |||||
| --changeset author:add_time_fields_to_productprocessline | |||||
| ALTER TABLE `stock_in_line` | |||||
| ADD COLUMN `type` VARCHAR(255) NULL AFTER `remarks`; | |||||
| ALTER TABLE `stock_out_line` | |||||
| ADD COLUMN `type` VARCHAR(255) NULL AFTER `pickerId`; | |||||