From 373f3d844d948381287436edece8394a629b6c53 Mon Sep 17 00:00:00 2001 From: "kelvin.yau" Date: Thu, 4 Dec 2025 19:44:49 +0800 Subject: [PATCH] updated import stock take function, supporting function to print all QR codes by searching DO ID --- .../web/DeliveryOrderController.kt | 8 +++++ .../modules/master/service/ItemsService.kt | 23 +++++++++++--- .../stock/entity/StockInLineRepository.kt | 4 +++ .../stock/service/StockInLineService.kt | 30 ++++++++++++++++++- .../web/model/PrintQrCodeForDoRequest.kt | 7 +++++ 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/ffii/fpsms/modules/stock/web/model/PrintQrCodeForDoRequest.kt diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt index 635a574..5812e5e 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt @@ -33,11 +33,14 @@ import java.io.OutputStream import java.io.UnsupportedEncodingException import java.text.ParseException import java.time.LocalDateTime +import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintQrCodeForDoRequest +import com.ffii.fpsms.modules.stock.service.StockInLineService @RequestMapping("/do") @RestController class DeliveryOrderController( private val deliveryOrderService: DeliveryOrderService, + private val stockInLineService: StockInLineService, ) { @GetMapping("/list") fun getDoList(): List { @@ -217,4 +220,9 @@ class DeliveryOrderController( fun printDN(@ModelAttribute request: PrintDNLabelsRequest) { deliveryOrderService.printDNLabels(request) } + + @GetMapping("/batchPrintQrCode") + fun printQrCodeForDeliveryOrder(@ModelAttribute request: PrintQrCodeForDoRequest) { + stockInLineService.printQrCodeForDeliveryOrder(request) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt index 92cadca..50c8652 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt @@ -25,6 +25,7 @@ import java.io.FileInputStream import java.math.BigDecimal import com.ffii.fpsms.modules.stock.entity.Inventory import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository +import com.ffii.fpsms.modules.stock.entity.InventoryLotRepository import com.ffii.fpsms.modules.stock.entity.InventoryRepository import com.ffii.fpsms.modules.stock.entity.StockIn import com.ffii.fpsms.modules.stock.entity.StockInLineRepository @@ -61,6 +62,7 @@ open class ItemsService( private val stockInLineService: StockInLineService, private val stockInLineRepository: StockInLineRepository, private val inventoryLotLineRepository: InventoryLotLineRepository, + private val inventoryLotRepository: InventoryLotRepository, ): AbstractBaseEntityService(jdbcDao, itemsRepository) { private val excelImportPath: String = System.getProperty("user.home") + "/Downloads/StockTakeImport/" @@ -908,9 +910,12 @@ open class ItemsService( // Calculate expiry date (+30 days) val expiryDate = LocalDateTime.now().plusDays(30).toLocalDate() - // Generate lotNo: LT-YYYYMMDD-itemCode + // Generate productLotNo: LT-YYYYMMDD-itemCode (for productLotNo field) val dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) - val lotNo = "LT-$dateStr-$itemCode" + val productLotNo = "LT-$dateStr-$itemCode" + + // Generate lotNo: LT-YYYYMMDD-XXXX (sequential number, same for StockInLine and InventoryLot) + val lotNo = stockInLineService.assignLotNo() // Generate dnNo: DN-YYYYMMDD-itemCode val dnNo = "DN-$dateStr-$itemCode" @@ -924,7 +929,8 @@ open class ItemsService( expiryDate = expiryDate, warehouseId = warehouse?.id, stockTakeLineId = savedStockTakeLine.id, - dnNo = dnNo, // Set dnNo + dnNo = dnNo, + productLotNo = productLotNo, // LT-YYYYMMDD-itemCode qcAccept = true, status = StockInLineStatus.PENDING.status ) @@ -970,6 +976,7 @@ open class ItemsService( id = savedStockInLine.id status = StockInLineStatus.PENDING.status this.dnNo = dnNo + this.productLotNo = lotNo this.qcAccept = true this.acceptedQty = qty this.acceptQty = qty @@ -1002,7 +1009,14 @@ open class ItemsService( logger.warn("Row ${i + 1}: InventoryLot was not created for StockInLine ${updatedForLot.id}") logWriter.writeRowError(i, "InventoryLot was not created") } else { - logger.info("Row ${i + 1}: InventoryLot created (ID: ${refreshedStockInLine.inventoryLot?.id}, lotNo: ${refreshedStockInLine.inventoryLot?.lotNo})") + // Update InventoryLot's lotNo to match StockInLine's lotNo (LT-YYYYMMDD-XXXX format) + val inventoryLot = refreshedStockInLine.inventoryLot!! + if (inventoryLot.lotNo != lotNo) { + inventoryLot.lotNo = lotNo + inventoryLotRepository.saveAndFlush(inventoryLot) + logger.info("Row ${i + 1}: Updated InventoryLot lotNo to '$lotNo' to match StockInLine (InventoryLot ID: ${inventoryLot.id})") + } + logger.info("Row ${i + 1}: InventoryLot created (ID: ${inventoryLot.id}, lotNo: ${inventoryLot.lotNo})") } // Step 7b: Second update to RECEIVED with inventoryLotLines to create InventoryLotLine @@ -1017,6 +1031,7 @@ open class ItemsService( id = savedStockInLine.id status = StockInLineStatus.RECEIVED.status // Explicitly set to RECEIVED this.dnNo = dnNo + this.productLotNo = productLotNo this.acceptedQty = qty this.acceptQty = qty this.inventoryLotLines = inventoryLotLines // REQUIRED for InventoryLotLine creation diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockInLineRepository.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockInLineRepository.kt index 6d38b50..f81d440 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockInLineRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockInLineRepository.kt @@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.stock.entity import com.ffii.core.support.AbstractRepository import com.ffii.fpsms.modules.stock.entity.projection.QrCodeInfo import com.ffii.fpsms.modules.stock.entity.projection.StockInLineInfo +import org.springframework.data.jpa.repository.Query import org.springframework.stereotype.Repository import java.util.Optional @@ -19,4 +20,7 @@ interface StockInLineRepository : AbstractRepository { fun findAllByPurchaseOrderIdAndDeletedFalse(purchaseOrderId: Long): Optional> fun findStockInLineInfoByInventoryLotLineId(inventoryLotLineId: Long): Optional fun findStockInLineInfoById(id: Long): Optional + + @Query("SELECT sil FROM StockInLine sil WHERE sil.item.id = :itemId AND sil.deleted = false") + fun findAllByItemIdAndDeletedFalse(itemId: Long): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt index 226aff1..f776758 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt @@ -46,7 +46,8 @@ import net.sf.jasperreports.engine.JasperExportManager import net.sf.jasperreports.engine.JasperPrint import java.io.File import kotlin.jvm.optionals.getOrNull -import kotlin.math.max +import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderRepository +import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintQrCodeForDoRequest @Serializable data class QrContent(val itemId: Long, val stockInLineId: Long) @@ -71,6 +72,7 @@ open class StockInLineService( private val itemUomRepository: ItemUomRespository, private val printerService: PrinterService, private val stockTakeLineRepository: StockTakeLineRepository, + private val deliveryOrderRepository: DeliveryOrderRepository, ): AbstractBaseEntityService(jdbcDao, stockInLineRepository) { open fun getStockInLineInfo(stockInLineId: Long): StockInLineInfo { @@ -577,4 +579,30 @@ open class StockInLineService( tempPdfFile.delete() } } + + @Transactional + open fun printQrCodeForDeliveryOrder(request: PrintQrCodeForDoRequest) { + // Get delivery order by ID + val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.deliveryOrderId) + ?: throw NoSuchElementException("Delivery order not found with ID: ${request.deliveryOrderId}") + + // Loop through delivery order lines + deliveryOrder.deliveryOrderLines.forEach { deliveryOrderLine -> + val itemId = deliveryOrderLine.item?.id + ?: throw IllegalStateException("Delivery order line ${deliveryOrderLine.id} has no item") + + // Find all stock in lines matching this itemId + val stockInLines = stockInLineRepository.findAllByItemIdAndDeletedFalse(itemId) + + // Print QR code for each stock in line + stockInLines.forEach { stockInLine -> + val printRequest = PrintQrCodeForSilRequest( + stockInLineId = stockInLine.id!!, + printerId = request.printerId, + printQty = request.printQty + ) + printQrCode(printRequest) + } + } + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/model/PrintQrCodeForDoRequest.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/model/PrintQrCodeForDoRequest.kt new file mode 100644 index 0000000..7d55449 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/model/PrintQrCodeForDoRequest.kt @@ -0,0 +1,7 @@ +package com.ffii.fpsms.modules.deliveryOrder.web.models + +data class PrintQrCodeForDoRequest( + val deliveryOrderId: Long, + val printerId: Long, + val printQty: Int?, +) \ No newline at end of file