| @@ -35,7 +35,6 @@ open class ZebraPrinterUtil { | |||||
| * @param printDirection Valid values: N (Normal), R (Rotated 90), I (Inverted 180), B (Bottom-up 270) | * @param printDirection Valid values: N (Normal), R (Rotated 90), I (Inverted 180), B (Bottom-up 270) | ||||
| * @throws Exception if there is an error during file processing or printing. | * @throws Exception if there is an error during file processing or printing. | ||||
| */ | */ | ||||
| @JvmStatic | |||||
| fun printPdfToZebra(pdfFile: File, printerIp: String, printerPort: Int, printQty: Int? = 1, printDirection: PrintDirection = PrintDirection.NORMAL) { | fun printPdfToZebra(pdfFile: File, printerIp: String, printerPort: Int, printQty: Int? = 1, printDirection: PrintDirection = PrintDirection.NORMAL) { | ||||
| // Check if the file exists and is readable | // Check if the file exists and is readable | ||||
| @@ -47,22 +46,36 @@ open class ZebraPrinterUtil { | |||||
| // 1. Load the PDF document | // 1. Load the PDF document | ||||
| PDDocument.load(pdfFile).use { document -> | PDDocument.load(pdfFile).use { document -> | ||||
| val renderer = PDFRenderer(document) | val renderer = PDFRenderer(document) | ||||
| val totalPages = document.numberOfPages | |||||
| // 2. Render the first page of the PDF as a monochrome image | |||||
| // The '300 / 72f' scales the image to 300 DPI. | |||||
| val image = renderer.renderImage(0, 300 / 72f, ImageType.BINARY) | |||||
| println("DEBUG: PDF has $totalPages pages") | |||||
| // 3. Convert the image to a ZPL format string | |||||
| val zplCommand = convertImageToZpl(image, printDirection) | |||||
| // Print each page for the specified quantity | |||||
| repeat(printQty ?: 1) { copyIndex -> | |||||
| println("DEBUG: Printing copy ${copyIndex + 1} of ${printQty ?: 1}") | |||||
| // 4. Send the ZPL command to the printer via a network socket | |||||
| val printData = zplCommand.toByteArray() | |||||
| Socket(printerIp, printerPort).use { socket -> | |||||
| val os: OutputStream = socket.getOutputStream() | |||||
| repeat(printQty ?: 1) { index -> | |||||
| // Iterate through all pages in the PDF | |||||
| for (pageIndex in 0 until totalPages) { | |||||
| println("DEBUG: Processing page ${pageIndex + 1} of $totalPages") | |||||
| // 2. Render each page of the PDF as a monochrome image | |||||
| val image = renderer.renderImage(pageIndex, 300 / 72f, ImageType.BINARY) | |||||
| // 3. Convert the image to a ZPL format string | |||||
| val zplCommand = convertImageToZpl(image, printDirection) | |||||
| // 4. Send each page as a separate print job | |||||
| Socket(printerIp, printerPort).use { socket -> | |||||
| val os: OutputStream = socket.getOutputStream() | |||||
| val printData = zplCommand.toByteArray() | |||||
| os.write(printData) | os.write(printData) | ||||
| os.flush() | os.flush() | ||||
| println("DEBUG: Page ${pageIndex + 1} sent to printer") | |||||
| } | } | ||||
| // Small delay between pages to ensure printer can process each page | |||||
| Thread.sleep(100) | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } catch (e: Exception) { | } catch (e: Exception) { | ||||
| @@ -695,7 +695,7 @@ open class DeliveryOrderService( | |||||
| //Print Delivery Note | //Print Delivery Note | ||||
| @Transactional | @Transactional | ||||
| open fun printDeliveryNote(request: PrintDeliveryNoteRequest){ | open fun printDeliveryNote(request: PrintDeliveryNoteRequest){ | ||||
| //val printer = printerService.findById(request.printerId) ?: throw java.util.NoSuchElementException("No such printer") | |||||
| val printer = printerService.findById(request.printerId) ?: throw java.util.NoSuchElementException("No such printer") | |||||
| val pdf = exportDeliveryNote( | val pdf = exportDeliveryNote( | ||||
| ExportDeliveryNoteRequest( | ExportDeliveryNoteRequest( | ||||
| @@ -713,12 +713,12 @@ open class DeliveryOrderService( | |||||
| try{ | try{ | ||||
| JasperExportManager.exportReportToPdfFile(jasperPrint,tempPdfFile.absolutePath) | JasperExportManager.exportReportToPdfFile(jasperPrint,tempPdfFile.absolutePath) | ||||
| // val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty | |||||
| // printer.ip?.let { ip -> printer.port?.let { port -> | |||||
| // ZebraPrinterUtil.printPdfToZebra(tempPdfFile, ip, port, printQty, ZebraPrinterUtil.PrintDirection.ROTATED) | |||||
| // }} | |||||
| val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty | |||||
| printer.ip?.let { ip -> printer.port?.let { port -> | |||||
| ZebraPrinterUtil.printPdfToZebra(tempPdfFile, ip, port, printQty, ZebraPrinterUtil.PrintDirection.ROTATED) | |||||
| }} | |||||
| } finally { | } finally { | ||||
| // tempPdfFile.delete() | |||||
| //tempPdfFile.delete() | |||||
| } | } | ||||
| } | } | ||||
| @@ -754,14 +754,15 @@ open class DeliveryOrderService( | |||||
| "filename" to "${cartonLabelInfo[0].code}_carton_labels" | "filename" to "${cartonLabelInfo[0].code}_carton_labels" | ||||
| ) | ) | ||||
| } | } | ||||
| //Print Carton Labels | //Print Carton Labels | ||||
| @Transactional | @Transactional | ||||
| open fun printDNLabels(request: PrintDNLabelsRequest){ | open fun printDNLabels(request: PrintDNLabelsRequest){ | ||||
| //val printer = printerService.findById(request.printerId) ?: throw java.util.NoSuchElementException("No such printer") | |||||
| val printer = printerService.findById(request.printerId) ?: throw java.util.NoSuchElementException("No such printer") | |||||
| val pdf = exportDNLabels( | val pdf = exportDNLabels( | ||||
| ExportDNLabelsRequest( | ExportDNLabelsRequest( | ||||
| @@ -778,10 +779,10 @@ open class DeliveryOrderService( | |||||
| JasperExportManager.exportReportToPdfFile(jasperPrint,tempPdfFile.absolutePath) | JasperExportManager.exportReportToPdfFile(jasperPrint,tempPdfFile.absolutePath) | ||||
| //val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty | |||||
| //printer.ip?.let { ip -> printer.port?.let { port -> | |||||
| // ZebraPrinterUtil.printPdfToZebra(tempPdfFile, ip, port, printQty, ZebraPrinterUtil.PrintDirection.ROTATED) | |||||
| //}} | |||||
| val printQty = if (request.printQty == null || request.printQty <= 0) 1 else request.printQty | |||||
| printer.ip?.let { ip -> printer.port?.let { port -> | |||||
| ZebraPrinterUtil.printPdfToZebra(tempPdfFile, ip, port, printQty, ZebraPrinterUtil.PrintDirection.ROTATED) | |||||
| }} | |||||
| println("Test PDF saved to: ${tempPdfFile.absolutePath}") | println("Test PDF saved to: ${tempPdfFile.absolutePath}") | ||||
| @@ -21,6 +21,7 @@ import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintDNLabelsRequest | |||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintDeliveryNoteRequest | import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintDeliveryNoteRequest | ||||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.ReleaseDoRequest | import com.ffii.fpsms.modules.deliveryOrder.web.models.ReleaseDoRequest | ||||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | import com.ffii.fpsms.modules.master.web.models.MessageResponse | ||||
| import com.ffii.fpsms.modules.stock.web.model.PrintQrCodeForSilRequest | |||||
| import jakarta.servlet.http.HttpServletResponse | import jakarta.servlet.http.HttpServletResponse | ||||
| import jakarta.validation.Valid | import jakarta.validation.Valid | ||||
| import net.sf.jasperreports.engine.JasperExportManager | import net.sf.jasperreports.engine.JasperExportManager | ||||
| @@ -195,8 +196,8 @@ class DeliveryOrderController( | |||||
| out.write(JasperExportManager.exportReportToPdf(jasperPrint)) | out.write(JasperExportManager.exportReportToPdf(jasperPrint)) | ||||
| } | } | ||||
| @GetMapping("print-DN") | |||||
| fun printDN(@RequestBody request: PrintDeliveryNoteRequest) { | |||||
| @GetMapping("/print-DN") | |||||
| fun printDN(@ModelAttribute request: PrintDeliveryNoteRequest) { | |||||
| deliveryOrderService.printDeliveryNote(request) | deliveryOrderService.printDeliveryNote(request) | ||||
| } | } | ||||
| @@ -213,7 +214,7 @@ class DeliveryOrderController( | |||||
| } | } | ||||
| @GetMapping("print-DNLabels") | @GetMapping("print-DNLabels") | ||||
| fun printDN(@RequestBody request: PrintDNLabelsRequest) { | |||||
| fun printDN(@ModelAttribute request: PrintDNLabelsRequest) { | |||||
| deliveryOrderService.printDNLabels(request) | deliveryOrderService.printDNLabels(request) | ||||
| } | } | ||||
| } | } | ||||
| @@ -13,30 +13,32 @@ interface InventoryInfo{ | |||||
| val itemName: String? | val itemName: String? | ||||
| @get:Value("#{target.item.type}") | @get:Value("#{target.item.type}") | ||||
| val itemType: String? | val itemType: String? | ||||
| // @get:Value("#{target.qty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{target.qty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{target.onHandQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | // @get:Value("#{target.onHandQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | ||||
| @get:Value("#{target.onHandQty}") | @get:Value("#{target.onHandQty}") | ||||
| val onHandQty: BigDecimal? | val onHandQty: BigDecimal? | ||||
| // @get:Value("#{target.onHoldQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{target.onHoldQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{target.onHoldQty}") | @get:Value("#{target.onHoldQty}") | ||||
| val onHoldQty: BigDecimal? | val onHoldQty: BigDecimal? | ||||
| // @get:Value("#{target.unavailableQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{target.unavailableQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{target.unavailableQty}") | @get:Value("#{target.unavailableQty}") | ||||
| val unavailableQty: BigDecimal? | val unavailableQty: BigDecimal? | ||||
| // @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty) / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty) / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty)}") | @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty)}") | ||||
| val availableQty: BigDecimal? | val availableQty: BigDecimal? | ||||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom.code}") | @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom.code}") | ||||
| val uomCode: String? | val uomCode: String? | ||||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom?.udfudesc}") | @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom?.udfudesc}") | ||||
| val uomUdfudesc: String? | val uomUdfudesc: String? | ||||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom?.udfShortDesc}") | |||||
| val uomShortDesc: String? | |||||
| // @get:Value("#{target.qty * target.uom.gramPerSmallestUnit}") | // @get:Value("#{target.qty * target.uom.gramPerSmallestUnit}") | ||||
| // val germPerSmallestUnit: BigDecimal? | // val germPerSmallestUnit: BigDecimal? | ||||
| @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty)}") | @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty)}") | ||||
| val qtyPerSmallestUnit: BigDecimal? | val qtyPerSmallestUnit: BigDecimal? | ||||
| @get:Value("#{target.item.itemUoms.^[baseUnit == true && deleted == false]?.uom?.udfudesc}") | @get:Value("#{target.item.itemUoms.^[baseUnit == true && deleted == false]?.uom?.udfudesc}") | ||||
| val baseUom: String? | val baseUom: String? | ||||
| // @get:Value("#{target.qty * (target.uom.unit4 != '' ? target.uom.unit4Qty " + | |||||
| // @get:Value("#{target.qty * (target.uom.unit4 != '' ? target.uom.unit4Qty " + | |||||
| // ": target.uom.unit3 != '' ? target.uom.unit3Qty " + | // ": target.uom.unit3 != '' ? target.uom.unit3Qty " + | ||||
| // ": target.uom.unit2 != '' ? target.uom.unit2Qty " + | // ": target.uom.unit2 != '' ? target.uom.unit2Qty " + | ||||
| // ": target.uom.unit1Qty)}") | // ": target.uom.unit1Qty)}") | ||||