From ec6d52b0d001335e37b275bb47a0fe66d52c7ead Mon Sep 17 00:00:00 2001 From: "MSI\\derek" Date: Wed, 21 May 2025 18:33:59 +0800 Subject: [PATCH] update po --- .../java/com/ffii/core/utils/PdfUtils.java | 32 +++ .../java/com/ffii/core/utils/QrCodeUtil.kt | 18 ++ .../service/PurchaseOrderService.kt | 2 + .../ffii/fpsms/modules/qc/entity/QcResult.kt | 2 +- .../modules/qc/entity/QcResultRepository.kt | 2 + .../qc/entity/projection/QcResultInfo.kt | 14 ++ .../modules/qc/service/QcResultService.kt | 4 + .../modules/qc/web/QcResultController.kt | 11 +- .../stock/entity/StockInLineRepository.kt | 2 + .../stock/entity/projection/QrCodeInfo.kt | 27 +++ .../stock/service/StockInLineService.kt | 86 +++++--- .../ffii/fpsms/modules/stock/sql/StockSql.kt | 4 +- .../stock/web/StockInLineController.kt | 25 ++- .../stock/web/model/ExportQrCodeRequest.kt | 5 + .../resources/qrCodeLabel/poItemPDF.jrxml | 196 ++++++++++++++++++ 15 files changed, 396 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/ffii/core/utils/PdfUtils.java create mode 100644 src/main/java/com/ffii/core/utils/QrCodeUtil.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/stock/entity/projection/QrCodeInfo.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/stock/web/model/ExportQrCodeRequest.kt create mode 100644 src/main/resources/qrCodeLabel/poItemPDF.jrxml diff --git a/src/main/java/com/ffii/core/utils/PdfUtils.java b/src/main/java/com/ffii/core/utils/PdfUtils.java new file mode 100644 index 0000000..5a36a44 --- /dev/null +++ b/src/main/java/com/ffii/core/utils/PdfUtils.java @@ -0,0 +1,32 @@ +package com.ffii.core.utils; + +import org.springframework.util.ResourceUtils; +import java.io.File; +import net.sf.jasperreports.engine.JasperCompileManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import java.util.Map; +import java.util.List; + +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JREmptyDataSource; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; + +public class PdfUtils { + + public static JasperReport loadJasperReport(String path) throws Exception { + File file = ResourceUtils.getFile(path); + JasperReport reportTemplate = JasperCompileManager.compileReport(file.getAbsolutePath()); + return reportTemplate; + } + + public static JasperPrint fillReport(JasperReport report, List loopList, Map params) + throws Exception { + JRDataSource dataSources = loopList.size() > 0 ? new JRBeanCollectionDataSource(loopList) + : new JREmptyDataSource(); + JasperPrint jasperPrint = JasperFillManager.fillReport(report, params, dataSources); + return jasperPrint; + } + +} \ No newline at end of file diff --git a/src/main/java/com/ffii/core/utils/QrCodeUtil.kt b/src/main/java/com/ffii/core/utils/QrCodeUtil.kt new file mode 100644 index 0000000..11f0554 --- /dev/null +++ b/src/main/java/com/ffii/core/utils/QrCodeUtil.kt @@ -0,0 +1,18 @@ +package com.ffii.core.utils + +import com.google.zxing.BarcodeFormat +import java.awt.image.BufferedImage +import com.google.zxing.client.j2se.MatrixToImageWriter; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; + +open class QrCodeUtil { + companion object { + fun generateQRCodeImage(barcodeText: String?): BufferedImage { + val barcodeWriter = QRCodeWriter() + val bitMatrix: BitMatrix = barcodeWriter.encode(barcodeText, BarcodeFormat.QR_CODE, 250, 250) + val img: BufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix) + return img + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt index fd41b1d..cb9358a 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt @@ -113,4 +113,6 @@ open class PurchaseOrderService( return savedPurchaseOrder } + + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResult.kt b/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResult.kt index b8ac868..fcc4a13 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResult.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResult.kt @@ -10,7 +10,7 @@ import jakarta.validation.constraints.NotNull @Entity @Table(name = "qc_result") -class QcResult: BaseEntity() { +open class QcResult: BaseEntity() { @NotNull @ManyToOne @JoinColumn(name = "qcItemId") diff --git a/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt b/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt index a2b7a6f..1784a10 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt @@ -1,8 +1,10 @@ package com.ffii.fpsms.modules.qc.entity import com.ffii.core.support.AbstractRepository +import com.ffii.fpsms.modules.qc.entity.projection.QcResultInfo import org.springframework.stereotype.Repository @Repository interface QcResultRepository: AbstractRepository { + fun findAllQcResultInfoByStockInLineIdAndDeletedFalse(stockInLineId: Long): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt b/src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt new file mode 100644 index 0000000..dd472ab --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt @@ -0,0 +1,14 @@ +package com.ffii.fpsms.modules.qc.entity.projection + +import org.springframework.beans.factory.annotation.Value + +interface QcResultInfo { + val id: Long + @get:Value("#{target.qcItem.name}") + val name: String + @get:Value("#{target.qcItem.code}") + val code: String + @get:Value("#{target.stockInLine.id}") + val stockInLineId: Long + val failQty: Double +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt b/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt index a459a90..f60b2d6 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt @@ -8,6 +8,7 @@ import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLineRepository import com.ffii.fpsms.modules.qc.entity.QcResult import com.ffii.fpsms.modules.qc.entity.QcResultRepository +import com.ffii.fpsms.modules.qc.entity.projection.QcResultInfo import com.ffii.fpsms.modules.qc.web.model.SaveQcResultRequest import com.ffii.fpsms.modules.stock.entity.StockInLine import com.ffii.fpsms.modules.stock.entity.StockInLineRepository @@ -54,4 +55,7 @@ open class QcResultService( ) } + fun getAllQcResultInfoByStockInLineId(stockInLineId: Long): List { + return qcResultRepository.findAllQcResultInfoByStockInLineIdAndDeletedFalse(stockInLineId) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt b/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt index 8069203..c004a1c 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt @@ -2,13 +2,11 @@ package com.ffii.fpsms.modules.qc.web import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.master.web.models.NewItemRequest +import com.ffii.fpsms.modules.qc.entity.projection.QcResultInfo import com.ffii.fpsms.modules.qc.service.QcResultService import com.ffii.fpsms.modules.qc.web.model.SaveQcResultRequest import jakarta.validation.Valid -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/qcResult") @@ -20,4 +18,9 @@ class QcResultController( fun saveItem(@Valid @RequestBody request: SaveQcResultRequest): MessageResponse { return qcResultService.createOrUpdate(request) } + + @GetMapping("/{stockInLineId}") + fun getAllQcResultInfoByStockInLineId(@PathVariable stockInLineId: Long): List { + return qcResultService.getAllQcResultInfoByStockInLineId(stockInLineId) + } } \ No newline at end of file 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 d5fbad0..5a3ee06 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 @@ -1,6 +1,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.stereotype.Repository @@ -10,4 +11,5 @@ interface StockInLineRepository : AbstractRepository { fun findAllStockInLineInfoByStockInIdAndDeletedFalse(stockInId: Long): List fun findStockInLineInfoByIdAndDeletedFalse(id: Long): StockInLineInfo fun findStockInLineInfoByIdInAndDeletedFalse(id: List): List + fun findQrCodeInfoByIdInAndDeletedFalse(id: List): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/QrCodeInfo.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/QrCodeInfo.kt new file mode 100644 index 0000000..6b9680c --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/QrCodeInfo.kt @@ -0,0 +1,27 @@ +package com.ffii.fpsms.modules.stock.entity.projection + +import org.springframework.beans.factory.annotation.Value +import java.awt.image.BufferedImage +import java.math.BigDecimal +import java.time.LocalDate +import java.time.LocalDateTime + +interface QrCodeInfo { // stockInLine + val id: Long // stockInLineId + @get:Value("#{target.item?.id}") + val itemId: Long + @get:Value("#{target.item?.name}") + val itemName: String + val itemNo: String + @get:Value("#{target.stockIn?.purchaseOrder.code}") + val poCode: String + @get:Value("#{target.item?.type}") + val itemType: String + val acceptedQty: BigDecimal + val productionDate: LocalDateTime? + val expiryDate: LocalDate? + val lotNo: String? + @get:Value("#{target.stockIn?.purchaseOrder?.shop?.name}") + val supplier: String? + var qrCode: BufferedImage? +} \ 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 9c87629..65797d1 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 @@ -2,6 +2,7 @@ package com.ffii.fpsms.modules.stock.service import com.ffii.core.support.AbstractBaseEntityService import com.ffii.core.support.JdbcDao +import com.ffii.core.utils.QrCodeUtil import com.ffii.fpsms.modules.common.CodeGenerator import com.ffii.fpsms.modules.master.entity.ItemsRepository import com.ffii.fpsms.modules.master.entity.QcItemRepository @@ -10,17 +11,21 @@ import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLineRepository import com.ffii.fpsms.modules.qc.entity.QcResult import com.ffii.fpsms.modules.qc.entity.QcResultRepository import com.ffii.fpsms.modules.stock.entity.* +import com.ffii.fpsms.modules.stock.sql.StockSql.SQL.INVENTORY_COUNT +import com.ffii.fpsms.modules.stock.web.model.ExportQrCodeRequest import com.ffii.fpsms.modules.stock.web.model.SaveStockInLineRequest import com.ffii.fpsms.modules.stock.web.model.SaveStockInRequest import com.ffii.fpsms.modules.stock.web.model.StockInLineStatus -import com.ffii.fpsms.modules.stock.sql.StockSql.SQL.INVENTORY_COUNT -import com.ffii.fpsms.modules.stock.web.model.SaveInventoryRequest +import net.sf.jasperreports.engine.JasperCompileManager +import org.springframework.core.io.ClassPathResource import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.io.IOException import java.math.BigDecimal import java.time.LocalDate import java.time.LocalDateTime +import com.ffii.core.utils.PdfUtils; + @Service open class StockInLineService( @@ -83,7 +88,8 @@ open class StockInLineService( expiryDate = request.expiryDate// frontend form input lotNo = newLotNo } - return inventoryLotRepository.saveAndFlush(inventoryLot) + val savedInventoryLot = inventoryLotRepository.saveAndFlush(inventoryLot) + return savedInventoryLot } @Throws(IOException::class) @@ -127,18 +133,19 @@ open class StockInLineService( if (request.acceptedQty.compareTo(stockInLine.acceptedQty) == 0) { var savedInventoryLot: InventoryLot? = null saveQcResultWhenStockIn(request, stockInLine) - if (request.status == StockInLineStatus.RECEIVED.status) { - if (request.expiryDate == null) { - return MessageResponse( - id = null, - code = null, - name = null, - type = "Found Null", - message = "missing expiry", - errorPosition = "expiryDate", - ) - } + if (request.status == StockInLineStatus.COMPLETE.status) { +// if (request.expiryDate == null) { +// return MessageResponse( +// id = null, +// code = null, +// name = null, +// type = "Found Null", +// message = "missing expiry", +// errorPosition = "expiryDate", +// ) +// } savedInventoryLot = saveInventoryLotWhenStockIn(request = request, stockInLine = stockInLine) + println(savedInventoryLot) } stockInLine.apply { // user = null @@ -188,18 +195,19 @@ open class StockInLineService( } saveQcResultWhenStockIn(request, stockInLine) var savedInventoryLot: InventoryLot? = null - if (request.status == StockInLineStatus.RECEIVED.status) { - if (request.expiryDate == null) { - return MessageResponse( - id = null, - code = null, - name = null, - type = "Found Null", - message = "missing expiry", - errorPosition = "expiryDate", - ) - } + if (request.status == StockInLineStatus.COMPLETE.status) { +// if (request.expiryDate == null) { +// return MessageResponse( +// id = null, +// code = null, +// name = null, +// type = "Found Null", +// message = "missing expiry", +// errorPosition = "expiryDate", +// ) +// } savedInventoryLot = saveInventoryLotWhenStockIn(request = request, stockInLine = stockInLine) + println(savedInventoryLot) } stockInLine.apply { receiptDate = request.receiptDate?.atStartOfDay() @@ -228,4 +236,32 @@ open class StockInLineService( } } + @Throws(IOException::class) + @Transactional + open fun exportStockInLineQrcode(request: ExportQrCodeRequest): Map { + val QRCODE_PDF = "qrCodeLabel/poItemPDF.jrxml" + val resource = ClassPathResource(QRCODE_PDF) + val inputStream = resource.inputStream + val poLabel = JasperCompileManager.compileReport(inputStream) + val stockInLineInfo = stockInLineRepository.findQrCodeInfoByIdInAndDeletedFalse(request.stockInLineIds).toMutableList() + for (lineInfo in stockInLineInfo) { + val field = mutableMapOf() + val qrCodeContent = ( + "itemId:${lineInfo.itemId}" + + ",stockInLineId:${lineInfo.id}" + ) + val image = QrCodeUtil.generateQRCodeImage(qrCodeContent) + lineInfo.apply { + this.qrCode = image + } + } + val params: MutableMap = mutableMapOf( + "poCode" to stockInLineInfo[0].poCode + ) + return mapOf( + "report" to PdfUtils.fillReport(poLabel,stockInLineInfo, params), + "fileName" to stockInLineInfo[0].poCode + ); + } + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/sql/StockSql.kt b/src/main/java/com/ffii/fpsms/modules/stock/sql/StockSql.kt index 9ae949d..191c38a 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/sql/StockSql.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/sql/StockSql.kt @@ -5,8 +5,8 @@ open class StockSql { val INVENTORY_COUNT = StringBuilder("select" + " count(id) " + " from inventory_lot i " - + " where i.stockInDate <= :from " - + " and i.stockInDate < :to " + + " where i.stockInDate > :from " + + " and i.stockInDate <= :to " + " and i.itemId = :itemId" ) } diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/StockInLineController.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/StockInLineController.kt index d351156..137b02c 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/StockInLineController.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/StockInLineController.kt @@ -1,15 +1,22 @@ package com.ffii.fpsms.modules.stock.web import com.ffii.fpsms.modules.master.web.models.MessageResponse -import com.ffii.fpsms.modules.master.web.models.NewItemRequest import com.ffii.fpsms.modules.stock.service.StockInLineService +import com.ffii.fpsms.modules.stock.web.model.ExportQrCodeRequest import com.ffii.fpsms.modules.stock.web.model.SaveStockInLineRequest +import jakarta.servlet.http.HttpServletResponse import jakarta.validation.Valid -import org.springframework.web.bind.annotation.GetMapping +import net.sf.jasperreports.engine.JasperExportManager +import net.sf.jasperreports.engine.JasperPrint +import org.springframework.context.NoSuchMessageException import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController +import java.io.OutputStream +import java.io.UnsupportedEncodingException +import java.text.ParseException + @RestController @RequestMapping("/stockInLine") @@ -25,4 +32,18 @@ class StockInLineController( fun update(@Valid @RequestBody newItem: SaveStockInLineRequest): MessageResponse { return stockInLineService.update(newItem) } + + @PostMapping("/print-label") + @Throws(UnsupportedEncodingException::class, NoSuchMessageException::class, ParseException::class, Exception::class) + fun printLabel(@Valid @RequestBody request: ExportQrCodeRequest, response: HttpServletResponse) { + response.characterEncoding = "utf-8"; + response.contentType = "application/pdf"; + val out: OutputStream = response.outputStream + val pdf: Map = stockInLineService.exportStockInLineQrcode(request) + val jasperPrint = pdf["report"] as JasperPrint + response.setHeader("Content-Disposition", "attachment; filename=" + pdf["fileName"] + ".pdf"); + out.write(JasperExportManager.exportReportToPdf(jasperPrint)); + } + + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/model/ExportQrCodeRequest.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/model/ExportQrCodeRequest.kt new file mode 100644 index 0000000..6bf9170 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/model/ExportQrCodeRequest.kt @@ -0,0 +1,5 @@ +package com.ffii.fpsms.modules.stock.web.model + +data class ExportQrCodeRequest ( + val stockInLineIds: List +) \ No newline at end of file diff --git a/src/main/resources/qrCodeLabel/poItemPDF.jrxml b/src/main/resources/qrCodeLabel/poItemPDF.jrxml new file mode 100644 index 0000000..e217e8d --- /dev/null +++ b/src/main/resources/qrCodeLabel/poItemPDF.jrxml @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +