diff --git a/src/main/java/com/ffii/fpsms/modules/common/internalSetup/SetupController.kt b/src/main/java/com/ffii/fpsms/modules/common/internalSetup/SetupController.kt index dc03097..7abefa6 100644 --- a/src/main/java/com/ffii/fpsms/modules/common/internalSetup/SetupController.kt +++ b/src/main/java/com/ffii/fpsms/modules/common/internalSetup/SetupController.kt @@ -134,8 +134,10 @@ class SetupController( @PostMapping("/inventory/print-all-lot-stockin-labels") fun printAllLotStockInLabels(@RequestBody request: Map): ResponseEntity> { - val printerId = request["printerId"] as? Long + val printerId = (request["printerId"] as? Number)?.toLong() val printQty = (request["printQty"] as? Number)?.toInt() ?: 1 + val fromIndex = (request["fromIndex"] as? Number)?.toInt() + val toIndex = (request["toIndex"] as? Number)?.toInt() if (printerId == null) { val errorResponse = mapOf( @@ -145,10 +147,30 @@ class SetupController( return ResponseEntity.badRequest().body(errorResponse) } + // Validate range if provided + if (fromIndex != null && toIndex != null) { + if (fromIndex < 0 || toIndex < 0) { + val errorResponse = mapOf( + "success" to false, + "error" to "fromIndex and toIndex must be >= 0" + ) + return ResponseEntity.badRequest().body(errorResponse) + } + if (fromIndex > toIndex) { + val errorResponse = mapOf( + "success" to false, + "error" to "fromIndex must be <= toIndex" + ) + return ResponseEntity.badRequest().body(errorResponse) + } + } + try { val printedCount = inventorySetup.printAllLotStockInLabels( printerId = printerId, - printQty = printQty + printQty = printQty, + fromIndex = fromIndex, + toIndex = toIndex ) val response = mapOf( "success" to true, diff --git a/src/main/java/com/ffii/fpsms/modules/common/internalSetup/inventorySetup.kt b/src/main/java/com/ffii/fpsms/modules/common/internalSetup/inventorySetup.kt index 5eb4dfb..3e90cc4 100644 --- a/src/main/java/com/ffii/fpsms/modules/common/internalSetup/inventorySetup.kt +++ b/src/main/java/com/ffii/fpsms/modules/common/internalSetup/inventorySetup.kt @@ -226,7 +226,12 @@ open class InventorySetup { @Autowired private lateinit var inventoryLotLineRepository: InventoryLotLineRepository @Transactional(rollbackFor = [Exception::class]) - open fun printAllLotStockInLabels(printerId: Long, printQty: Int = 1): Int { + open fun printAllLotStockInLabels( + printerId: Long, + printQty: Int = 1, + fromIndex: Int? = null, + toIndex: Int? = null + ): Int { println("=== Starting to print stock in labels for all lots ===") // Get all inventory lot lines that are not deleted and have stock in lines @@ -243,13 +248,28 @@ open class InventorySetup { return 0 } - println("Found ${allInventoryLotLines.size} inventory lot lines to print") + // Apply range filter if provided + val inventoryLotLinesToPrint = if (fromIndex != null && toIndex != null) { + val startIndex = fromIndex.coerceAtLeast(0) + val endIndex = toIndex.coerceAtMost(allInventoryLotLines.size - 1) + if (startIndex > endIndex || startIndex >= allInventoryLotLines.size) { + println("Invalid range: fromIndex=$fromIndex, toIndex=$toIndex, total items=${allInventoryLotLines.size}") + return 0 + } + println("Printing range: index $startIndex to $endIndex (out of ${allInventoryLotLines.size} total items)") + allInventoryLotLines.subList(startIndex, endIndex + 1) + } else { + println("Printing all ${allInventoryLotLines.size} inventory lot lines") + allInventoryLotLines + } + + println("Found ${inventoryLotLinesToPrint.size} inventory lot lines to print") var printedCount = 0 var errorCount = 0 // Loop through each inventory lot line - for ((index, inventoryLotLine) in allInventoryLotLines.withIndex()) { + for ((index, inventoryLotLine) in inventoryLotLinesToPrint.withIndex()) { try { // Get the associated stock in line val stockInLine = inventoryLotLine.inventoryLot?.stockInLine @@ -258,7 +278,8 @@ open class InventorySetup { val stockInLineId = stockInLine.id ?: throw IllegalArgumentException("Stock in line has no ID") - println("Processing lot ${index + 1}/${allInventoryLotLines.size}: Lot No: ${inventoryLotLine.inventoryLot?.lotNo}, StockInLineId: $stockInLineId") + val actualIndex = if (fromIndex != null) fromIndex + index else index + println("Processing lot ${actualIndex + 1}/${allInventoryLotLines.size}: Lot No: ${inventoryLotLine.inventoryLot?.lotNo}, StockInLineId: $stockInLineId") // Create print request val printRequest = PrintQrCodeForSilRequest( @@ -283,7 +304,7 @@ open class InventorySetup { } println("=== Printing finished ===") - println("Total processed: ${allInventoryLotLines.size}") + println("Total processed: ${inventoryLotLinesToPrint.size}") println("Successfully printed: $printedCount") println("Errors: $errorCount") diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt index 3562303..6349300 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt @@ -72,6 +72,9 @@ import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService // 添加 import com.ffii.fpsms.modules.deliveryOrder.web.models.* import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository // 添加 import com.ffii.core.utils.CanonPrinterUtil +import com.ffii.fpsms.modules.master.entity.ItemsRepository +import kotlin.collections.emptyMap + import com.ffii.core.response.RecordsRes import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Page @@ -106,7 +109,8 @@ open class DeliveryOrderService( private val pickExecutionIssueRepository: PickExecutionIssueRepository, private val doPickOrderRepository: DoPickOrderRepository, private val doPickOrderLineRepository: DoPickOrderLineRepository, - private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository + private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository, + private val itemsRepository: ItemsRepository ) { open fun searchDoLiteByPage( code: String?, @@ -116,16 +120,16 @@ open class DeliveryOrderService( pageNum: Int?, pageSize: Int? ): RecordsRes { - + val page = (pageNum ?: 1) - 1 // 如果你前端是 1-based;如果前端本来就是 0-based 就不要 -1 val size = pageSize ?: 10 val pageable = PageRequest.of(page.coerceAtLeast(0), size) - + val statusEnum = status?.let { s -> DeliveryOrderStatus.entries.find { it.value == s } } - + val etaStart = estimatedArrivalDate val etaEnd = estimatedArrivalDate?.plusDays(1) - + val result = deliveryOrderRepository.searchDoLitePage( code = code?.ifBlank { null }, shopName = shopName?.ifBlank { null }, @@ -134,7 +138,7 @@ open class DeliveryOrderService( etaEnd = etaEnd, pageable = pageable ) - + val records = result.content.map { DeliveryOrderInfoLiteDto( id = it.id, @@ -147,12 +151,12 @@ open class DeliveryOrderService( shopAddress = it.shopAddress ) } - + return RecordsRes(records, result.totalElements.toInt()) } - + open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? { return deliveryOrderRepository.findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18DataLogId) } @@ -281,7 +285,7 @@ open class DeliveryOrderService( etaTo: LocalDateTime?, ): Page { - + val page = deliveryOrderRepository.search( code = if (code.isNullOrBlank()) null else code, shopName = if (shopName.isNullOrBlank()) null else shopName, @@ -292,7 +296,7 @@ open class DeliveryOrderService( etaTo = etaTo, pageable = pageable ) - + return page.map { d -> DoSearchRow( id = d.id!!, @@ -384,7 +388,32 @@ open class DeliveryOrderService( """.trimIndent() val result = jdbcDao.queryForList(sql, mapOf("lotId" to lotId)) if (result.isNotEmpty()) { - (result.first()["warehouseOrder"] as Number?)?.toInt() + val orderString = result.first()["warehouseOrder"] as? String + // Extract the last 3 digits from format like "2F-001" + orderString?.let { order -> + // Try to extract numeric part after the last "-" + val parts = order.split("-") + if (parts.isNotEmpty()) { + val lastPart = parts.last().trim() + // Take last 3 characters if they are all digits + if (lastPart.length >= 3) { + val lastThreeDigits = lastPart.takeLast(3) + if (lastThreeDigits.all { it.isDigit() }) { + return lastThreeDigits.toIntOrNull() + } + } + // Fallback: try to parse the last part as Int + lastPart.toIntOrNull() + } else { + // Fallback: try to extract any 3-digit sequence from the end + val lastThreeDigits = order.takeLast(3) + if (lastThreeDigits.all { it.isDigit() }) { + lastThreeDigits.toIntOrNull() + } else { + null + } + } + } } else null } } @@ -840,6 +869,12 @@ open class DeliveryOrderService( getWarehouseOrderByItemId(itemId) } ?: Int.MAX_VALUE } + val uniqueItemIds = sortedLines.mapNotNull { it.itemId }.distinct() + val itemsMap = if (uniqueItemIds.isNotEmpty()) { + itemsRepository.findAllById(uniqueItemIds).associateBy { it.id } + } else { + emptyMap() + } sortedLines.forEach { line -> val field = mutableMapOf() @@ -864,6 +899,17 @@ open class DeliveryOrderService( }.distinct().joinToString(", ") }?.ifBlank { "沒有庫存" } ?: "沒有庫存" field["lotNo"] = lotNo + + val signOff = line.itemId?.let { itemId -> + val item = itemsMap[itemId] + if (item?.isEgg == true) { + "簽署: ________" + } else { + "" + } + } ?: "" + field["signOff"] = signOff + fields.add(field) } @@ -885,6 +931,9 @@ open class DeliveryOrderService( params["truckNo"] = truckNo params["ShopPurchaseOrderNo"] = doPickOrder.deliveryOrderCode ?: deliveryNoteInfo.joinToString(", ") { it.code } params["FGPickOrderNo"] = doPickOrder.pickOrderCode ?: selectedPickOrder?.code ?: "" + params["loadingSequence"] = doPickOrder.loadingSequence?.let { + "裝載順序:$it" + } ?: "" return mapOf( "report" to PdfUtils.fillReport(deliveryNote, fields, params), @@ -950,6 +999,13 @@ open class DeliveryOrderService( } ?: Int.MAX_VALUE } + val uniqueItemIds = sortedLines.mapNotNull { it.itemId }.distinct() + val itemsMap = if (uniqueItemIds.isNotEmpty()) { + itemsRepository.findAllById(uniqueItemIds).associateBy { it.id } + } else { + emptyMap() + } + sortedLines.forEach { line -> val field = mutableMapOf() @@ -991,6 +1047,17 @@ open class DeliveryOrderService( } ?: "沒有庫存" field["lotNo"] = lotNo + + val signOff = line.itemId?.let { itemId -> + val item = itemsMap[itemId] + if (item?.isEgg == true) { + "簽署: ________" + } else { + "" + } + } ?: "" + field["signOff"] = signOff + fields.add(field) } @@ -1013,6 +1080,9 @@ open class DeliveryOrderService( params["ShopPurchaseOrderNo"] = doPickOrderRecord.deliveryOrderCode ?: deliveryNoteInfo.joinToString(", ") { it.code } params["FGPickOrderNo"] = doPickOrderRecord.pickOrderCode ?: selectedPickOrder?.code ?: "" + params["loadingSequence"] = doPickOrderRecord.loadingSequence?.let { + "裝載順序:$it" + } ?: "" return mapOf( "report" to PdfUtils.fillReport(deliveryNote, fields, params), diff --git a/src/main/resources/DeliveryNote/DeliveryNotePDF.jrxml b/src/main/resources/DeliveryNote/DeliveryNotePDF.jrxml index 3efb01e..c3ef3bc 100644 --- a/src/main/resources/DeliveryNote/DeliveryNotePDF.jrxml +++ b/src/main/resources/DeliveryNote/DeliveryNotePDF.jrxml @@ -1,381 +1,404 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <band/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +