From 219b588e34cf914448595ff94e4b41685dbac9a4 Mon Sep 17 00:00:00 2001 From: "kelvin.yau" Date: Fri, 13 Mar 2026 15:17:07 +0800 Subject: [PATCH] A4 printer routing & register, new col "brand" is added to printer table, plz fill in with 'Zebra', 'Canon' or 'Brother' to make it works --- gradle.properties | 1 + .../com/ffii/core/utils/BrotherPrinterUtil.kt | 10 +++++++- .../service/DeliveryOrderService.kt | 22 ++++-------------- .../jobOrder/service/JobOrderService.kt | 23 ++++--------------- .../fpsms/modules/master/entity/Printer.kt | 4 ++++ .../master/entity/projections/PrinterCombo.kt | 1 + .../modules/master/print/A4PrintDriver.kt | 11 +++++++++ .../master/print/A4PrintDriverRegistry.kt | 18 +++++++++++++++ .../modules/master/print/BrotherA4Driver.kt | 10 ++++++++ .../modules/master/print/CanonA4Driver.kt | 15 ++++++++++++ .../modules/master/service/PrinterService.kt | 13 +++++++++++ .../modules/master/web/PrinterController.kt | 6 +++-- .../01_add_brand_to_printer.sql | 5 ++++ 13 files changed, 100 insertions(+), 39 deletions(-) create mode 100644 gradle.properties create mode 100644 src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriver.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriverRegistry.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/print/BrotherA4Driver.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/print/CanonA4Driver.kt create mode 100644 src/main/resources/db/changelog/changes/20260313_01_KelvinY/01_add_brand_to_printer.sql diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..f98d3ce --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +kotlin.daemon.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m \ No newline at end of file diff --git a/src/main/java/com/ffii/core/utils/BrotherPrinterUtil.kt b/src/main/java/com/ffii/core/utils/BrotherPrinterUtil.kt index 4a0a395..7908bb7 100644 --- a/src/main/java/com/ffii/core/utils/BrotherPrinterUtil.kt +++ b/src/main/java/com/ffii/core/utils/BrotherPrinterUtil.kt @@ -25,9 +25,16 @@ class BrotherPrinterUtil { fun printToBrother(pdfFile: File, printerIp: String, printerPort: Int = 9100, printQty: Int = 1) { if (!pdfFile.exists()) throw IllegalArgumentException("File not found.") + println("DEBUG: PDF file size: ${pdfFile.length()} bytes") + PDDocument.load(pdfFile).use { document -> val renderer = PDFRenderer(document) - + + val totalPages = document.numberOfPages + repeat(printQty) { copyIndex -> + println("DEBUG: Printing copy ${copyIndex + 1} of $printQty") + } + Socket(printerIp, printerPort).use { socket -> val os = socket.getOutputStream() @@ -49,6 +56,7 @@ class BrotherPrinterUtil { // 4. End Job os.write("\u001B%-12345X".toByteArray(Charsets.US_ASCII)) os.flush() + println("DEBUG: Print job sent to printer") } } } 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 53aed88..ea7d54d 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 @@ -74,7 +74,7 @@ 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.fpsms.modules.master.print.A4PrintDriverRegistry import com.ffii.core.response.RecordsRes import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Page @@ -1303,24 +1303,10 @@ open class DeliveryOrderService( val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty - val duplexMode = if (CanonPrinterUtil.isLandscape(tempPdfFile)) { - CanonPrinterUtil.DuplexMode.DUPLEX_SHORT_EDGE // Landscape: flip on short edge - } else { - CanonPrinterUtil.DuplexMode.DUPLEX_LONG_EDGE // Portrait: flip on long edge - } - - println("DEBUG: PDF orientation detected - Landscape: ${CanonPrinterUtil.isLandscape(tempPdfFile)}, Duplex mode: $duplexMode") - printer.ip?.let { ip -> - printer.port?.let { port -> - CanonPrinterUtil.printPdfToCanon( - tempPdfFile, - ip, - port, - printQty, - duplexMode - ) - } + val port = printer.port ?: 9100 + val driver = A4PrintDriverRegistry.getDriver(printer.brand) + driver.print(tempPdfFile, ip, port, printQty) } } finally { //tempPdfFile.delete() diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt index 577dca7..104f957 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt @@ -72,6 +72,7 @@ import com.ffii.fpsms.modules.master.service.ItemUomService import com.ffii.fpsms.modules.master.web.models.ConvertUomByItemRequest import com.ffii.fpsms.modules.stock.service.StockInLineService import com.ffii.fpsms.modules.stock.web.model.SaveStockInLineRequest +import com.ffii.fpsms.modules.master.print.A4PrintDriverRegistry @Service open class JobOrderService( val jobOrderRepository: JobOrderRepository, @@ -95,6 +96,7 @@ open class JobOrderService( val jobOrderBomMaterialRepository: JobOrderBomMaterialRepository, val bomMaterialRepository: BomMaterialRepository, val itemUomService: ItemUomService + ) { open fun allJobOrdersByPage(request: SearchJobOrderInfoRequest): RecordsRes { @@ -783,25 +785,10 @@ open class JobOrderService( val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty - // Auto-detect orientation and set duplex mode accordingly - val duplexMode = if (CanonPrinterUtil.isLandscape(tempPdfFile)) { - CanonPrinterUtil.DuplexMode.DUPLEX_SHORT_EDGE // Landscape: flip on short edge - } else { - CanonPrinterUtil.DuplexMode.DUPLEX_LONG_EDGE // Portrait: flip on long edge - } - - println("DEBUG: PDF orientation detected - Landscape: ${CanonPrinterUtil.isLandscape(tempPdfFile)}, Duplex mode: $duplexMode") - printer.ip?.let { ip -> - printer.port?.let { port -> - CanonPrinterUtil.printPdfToCanon( - tempPdfFile, - ip, - port, - printQty, - duplexMode - ) - } + val port = printer.port ?: 9100 + val driver = A4PrintDriverRegistry.getDriver(printer.brand) + driver.print(tempPdfFile, ip, port, printQty) } } finally { //tempPdfFile.delete() diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/Printer.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/Printer.kt index 19fc6b1..69bb267 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/Printer.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/Printer.kt @@ -22,6 +22,10 @@ open class Printer : BaseEntity() { @Column(name = "type", nullable = true, length = 255) open var type: String? = null + @Size(max = 255) + @Column(name = "brand", nullable = true, length = 255) + open var brand: String? = null + @Size(max = 500) @Column(name = "description", length = 500) open var description: String? = null diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/projections/PrinterCombo.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/projections/PrinterCombo.kt index 61ac8cc..c098af0 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/projections/PrinterCombo.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/projections/PrinterCombo.kt @@ -14,4 +14,5 @@ interface PrinterCombo { val description: String?; val ip: String?; val port: Int?; + val brand: String?; } diff --git a/src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriver.kt b/src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriver.kt new file mode 100644 index 0000000..4b5456b --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriver.kt @@ -0,0 +1,11 @@ +package com.ffii.fpsms.modules.master.print + +import java.io.File + +/** + * Abstraction for A4 (document) printing. + * Implementations send PDF to Canon, Brother, etc. via their protocol. + */ +interface A4PrintDriver { + fun print(pdfFile: File, ip: String, port: Int, printQty: Int) +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriverRegistry.kt b/src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriverRegistry.kt new file mode 100644 index 0000000..7d59bce --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/print/A4PrintDriverRegistry.kt @@ -0,0 +1,18 @@ +package com.ffii.fpsms.modules.master.print + +object A4PrintDriverRegistry { + private val drivers = mapOf( + "Canon" to CanonA4Driver(), + "Brother" to BrotherA4Driver() + ) + private val defaultDriver = CanonA4Driver() + + /** + * Returns the A4 driver for the given brand. + * Null/blank/unknown brand => Canon (backward compatible). + */ + fun getDriver(brand: String?): A4PrintDriver { + if (brand.isNullOrBlank()) return defaultDriver + return drivers[brand.trim()] ?: defaultDriver + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/print/BrotherA4Driver.kt b/src/main/java/com/ffii/fpsms/modules/master/print/BrotherA4Driver.kt new file mode 100644 index 0000000..92336d6 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/print/BrotherA4Driver.kt @@ -0,0 +1,10 @@ +package com.ffii.fpsms.modules.master.print + +import com.ffii.core.utils.BrotherPrinterUtil +import java.io.File + +class BrotherA4Driver : A4PrintDriver { + override fun print(pdfFile: File, ip: String, port: Int, printQty: Int) { + BrotherPrinterUtil.printToBrother(pdfFile, ip, port, printQty) + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/print/CanonA4Driver.kt b/src/main/java/com/ffii/fpsms/modules/master/print/CanonA4Driver.kt new file mode 100644 index 0000000..a0a031e --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/print/CanonA4Driver.kt @@ -0,0 +1,15 @@ +package com.ffii.fpsms.modules.master.print + +import com.ffii.core.utils.CanonPrinterUtil +import java.io.File + +class CanonA4Driver : A4PrintDriver { + override fun print(pdfFile: File, ip: String, port: Int, printQty: Int) { + val duplexMode = if (CanonPrinterUtil.isLandscape(pdfFile)) { + CanonPrinterUtil.DuplexMode.DUPLEX_SHORT_EDGE + } else { + CanonPrinterUtil.DuplexMode.DUPLEX_LONG_EDGE + } + CanonPrinterUtil.printPdfToCanon(pdfFile, ip, port, printQty, duplexMode) + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/PrinterService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/PrinterService.kt index 20187cf..3e57448 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/PrinterService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/PrinterService.kt @@ -40,6 +40,7 @@ open class PrinterService( name = request.name code = request.code type = request.type + brand = if (request.type == "Label") "Zebra" else request.brand description = request.description ip = request.ip port = request.port @@ -74,6 +75,18 @@ open class PrinterService( request.name?.let { printer.name = it } request.code?.let { printer.code = it } request.type?.let { printer.type = it } + request.type?.let { newType -> + printer.type = newType + if (newType == "Label") { + printer.brand = "Zebra" + } + } + + request.brand?.let { newBrand -> + if (printer.type != "Label") { + printer.brand = newBrand + } + } request.description?.let { printer.description = it } request.ip?.let { printer.ip = it } request.port?.let { printer.port = it } diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/PrinterController.kt b/src/main/java/com/ffii/fpsms/modules/master/web/PrinterController.kt index 291dc0f..481fe3b 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/web/PrinterController.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/web/PrinterController.kt @@ -65,7 +65,8 @@ data class PrinterCreateRequest( val description: String? = null, val ip: String? = null, val port: Int? = null, - val dpi: Int? = null + val dpi: Int? = null, + val brand: String? = null ) data class PrinterUpdateRequest( @@ -75,5 +76,6 @@ data class PrinterUpdateRequest( val description: String? = null, val ip: String? = null, val port: Int? = null, - val dpi: Int? = null + val dpi: Int? = null, + val brand: String? = null ) \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20260313_01_KelvinY/01_add_brand_to_printer.sql b/src/main/resources/db/changelog/changes/20260313_01_KelvinY/01_add_brand_to_printer.sql new file mode 100644 index 0000000..b993e2b --- /dev/null +++ b/src/main/resources/db/changelog/changes/20260313_01_KelvinY/01_add_brand_to_printer.sql @@ -0,0 +1,5 @@ +-- liquibase formatted sql +-- changeset KelvinY:add_brand_to_printer + +ALTER TABLE `fpsmsdb`.`printer` +ADD COLUMN `brand` VARCHAR(255) NULL; \ No newline at end of file