| @@ -35,7 +35,6 @@ open class ZebraPrinterUtil { | |||
| * @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. | |||
| */ | |||
| @JvmStatic | |||
| fun printPdfToZebra(pdfFile: File, printerIp: String, printerPort: Int, printQty: Int? = 1, printDirection: PrintDirection = PrintDirection.NORMAL) { | |||
| // Check if the file exists and is readable | |||
| @@ -47,22 +46,36 @@ open class ZebraPrinterUtil { | |||
| // 1. Load the PDF document | |||
| PDDocument.load(pdfFile).use { 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.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) { | |||
| @@ -695,7 +695,7 @@ open class DeliveryOrderService( | |||
| //Print Delivery Note | |||
| @Transactional | |||
| 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( | |||
| ExportDeliveryNoteRequest( | |||
| @@ -713,12 +713,12 @@ open class DeliveryOrderService( | |||
| try{ | |||
| 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 { | |||
| // tempPdfFile.delete() | |||
| //tempPdfFile.delete() | |||
| } | |||
| } | |||
| @@ -754,14 +754,15 @@ open class DeliveryOrderService( | |||
| "filename" to "${cartonLabelInfo[0].code}_carton_labels" | |||
| ) | |||
| } | |||
| //Print Carton Labels | |||
| @Transactional | |||
| 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( | |||
| ExportDNLabelsRequest( | |||
| @@ -778,10 +779,10 @@ open class DeliveryOrderService( | |||
| 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}") | |||
| @@ -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.ReleaseDoRequest | |||
| 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.validation.Valid | |||
| import net.sf.jasperreports.engine.JasperExportManager | |||
| @@ -195,8 +196,8 @@ class DeliveryOrderController( | |||
| out.write(JasperExportManager.exportReportToPdf(jasperPrint)) | |||
| } | |||
| @GetMapping("print-DN") | |||
| fun printDN(@RequestBody request: PrintDeliveryNoteRequest) { | |||
| @GetMapping("/print-DN") | |||
| fun printDN(@ModelAttribute request: PrintDeliveryNoteRequest) { | |||
| deliveryOrderService.printDeliveryNote(request) | |||
| } | |||
| @@ -213,7 +214,7 @@ class DeliveryOrderController( | |||
| } | |||
| @GetMapping("print-DNLabels") | |||
| fun printDN(@RequestBody request: PrintDNLabelsRequest) { | |||
| fun printDN(@ModelAttribute request: PrintDNLabelsRequest) { | |||
| deliveryOrderService.printDNLabels(request) | |||
| } | |||
| } | |||
| @@ -13,30 +13,32 @@ interface InventoryInfo{ | |||
| val itemName: String? | |||
| @get:Value("#{target.item.type}") | |||
| 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}") | |||
| 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}") | |||
| 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}") | |||
| 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)}") | |||
| val availableQty: BigDecimal? | |||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom.code}") | |||
| val uomCode: String? | |||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom?.udfudesc}") | |||
| val uomUdfudesc: String? | |||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom?.udfShortDesc}") | |||
| val uomShortDesc: String? | |||
| // @get:Value("#{target.qty * target.uom.gramPerSmallestUnit}") | |||
| // val germPerSmallestUnit: BigDecimal? | |||
| @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty)}") | |||
| val qtyPerSmallestUnit: BigDecimal? | |||
| @get:Value("#{target.item.itemUoms.^[baseUnit == true && deleted == false]?.uom?.udfudesc}") | |||
| 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.unit2 != '' ? target.uom.unit2Qty " + | |||
| // ": target.uom.unit1Qty)}") | |||