diff --git a/addons/dine360_qz_printer/static/src/js/qz_wrapper.js b/addons/dine360_qz_printer/static/src/js/qz_wrapper.js index 30cda58..1bdb1d1 100644 --- a/addons/dine360_qz_printer/static/src/js/qz_wrapper.js +++ b/addons/dine360_qz_printer/static/src/js/qz_wrapper.js @@ -21,6 +21,10 @@ function getBillingPrinterName(config) { return config?.qz_billing_printer_name || config?.qz_printer_name || ""; } +function paperWidthMm(config) { + return String(config?.qz_paper_width || DEFAULT_COLUMNS) === "48" ? 80 : 58; +} + function cleanText(value) { return String(value ?? "") .normalize("NFKD") @@ -132,6 +136,65 @@ function bytesToBase64(bytes) { return btoa(binary); } +function absoluteUrl(value) { + if (!value || value.startsWith("data:") || value.startsWith("blob:")) { + return value; + } + return new URL(value, window.location.origin).href; +} + +function collectPrintableStyles() { + return Array.from(document.querySelectorAll("link[rel='stylesheet'], style")) + .map((node) => { + if (node.tagName === "LINK") { + return ``; + } + return node.outerHTML; + }) + .join("\n"); +} + +function buildHtmlReceipt(receiptElement, pos) { + const config = pos?.config || {}; + const widthMm = paperWidthMm(config); + const clone = receiptElement.cloneNode(true); + for (const node of clone.querySelectorAll("[src]")) { + node.setAttribute("src", absoluteUrl(node.getAttribute("src"))); + } + for (const node of clone.querySelectorAll("[href]")) { + node.setAttribute("href", absoluteUrl(node.getAttribute("href"))); + } + + return ` + + + + + ${collectPrintableStyles()} + + +${clone.outerHTML} +`; +} + class EscPosBuilder { constructor(columns) { this.columns = columns; @@ -448,6 +511,31 @@ patch(ReceiptScreen.prototype, { await qz.websocket.connect({ retries: 2, delay: 1 }); } + const receiptElement = this.el?.querySelector?.(".pos-receipt"); + if (receiptElement) { + const widthMm = paperWidthMm(this.pos.config); + const config = qz.configs.create(printerName, { + copies: 1, + margins: 0, + units: "mm", + size: { width: widthMm }, + rasterize: true, + scaleContent: true, + spool: { size: 1 }, + }); + await qz.print(config, [{ + type: "pixel", + format: "html", + flavor: "plain", + data: buildHtmlReceipt(receiptElement, this.pos), + }]); + + if (this.currentOrder) { + this.currentOrder._printed = true; + } + return true; + } + const config = qz.configs.create(printerName, { encoding: "CP437", copies: 1,