refactor: replace Odoo printer service with direct window-based HTML rendering for closing receipts
This commit is contained in:
parent
9710d798b4
commit
527b0f63bf
@ -21,23 +21,11 @@
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.pos-closing-receipt-print {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.pos-closing-receipt-print .pos-receipt {
|
||||
padding-left: 20px !important;
|
||||
padding-right: 20px !important;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
.render-container .pos-closing-receipt-print .pos-receipt {
|
||||
font-size: 28px !important;
|
||||
width: 320px !important;
|
||||
max-width: 320px !important;
|
||||
padding: 12px !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -165,16 +165,134 @@ patch(ClosePosPopup.prototype, {
|
||||
this.pos.env.services.ui.block();
|
||||
}
|
||||
try {
|
||||
const printResult = await this.printer.print(ClosingReceipt, receiptData, {
|
||||
webPrintFallback: true,
|
||||
});
|
||||
console.log("[pos_closing_receipt] Print operation resolved with result:", printResult);
|
||||
let cashRow = "";
|
||||
if (receiptData.cashPayment) {
|
||||
cashRow = `
|
||||
<tr>
|
||||
<td style="padding:3px 0;">${receiptData.cashPayment.name}</td>
|
||||
<td style="text-align:right;padding:3px 0;">${receiptData.cashPayment.formattedAmount}</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
// Explicit safety delay to let printer buffers flush (especially for Bluetooth/JSPM)
|
||||
const delayMs = 1500;
|
||||
console.log(`[pos_closing_receipt] Applying safety buffer delay of ${delayMs}ms...`);
|
||||
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
||||
console.log("[pos_closing_receipt] Safety buffer complete.");
|
||||
const nonCashRows = (receiptData.nonCashPayments || []).map(
|
||||
(pm) => `
|
||||
<tr>
|
||||
<td style="padding:3px 0;">${pm.name}</td>
|
||||
<td style="text-align:right;padding:3px 0;">${pm.formattedAmount}</td>
|
||||
</tr>`
|
||||
);
|
||||
|
||||
const html = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Closing Summary</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 28px;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
.receipt {
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
margin: 0 auto;
|
||||
padding: 12px;
|
||||
}
|
||||
.center { text-align: center; }
|
||||
.header-title {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.header-sub {
|
||||
margin-top: 4px;
|
||||
font-size: 24px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
.dashed { border-top: 1px dashed #000; margin: 8px 0; }
|
||||
.solid { border-top: 1px solid #000; margin: 8px 0; }
|
||||
table { width: 100%; border-collapse: collapse; margin-bottom: 8px; }
|
||||
td { padding: 5px 0; }
|
||||
.right { text-align: right; }
|
||||
.bold { font-weight: bold; }
|
||||
.total-row td { font-weight: bold; font-size: 32px; padding: 6px 0; }
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 12px;
|
||||
font-size: 24px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.feed { margin-top: 28px; }
|
||||
@media print {
|
||||
@page { size: 80mm auto; margin: 3mm; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="receipt">
|
||||
<div class="center" style="margin-bottom:10px;">
|
||||
<div class="header-title">${receiptData.sessionName}</div>
|
||||
<div class="header-sub">SESSION CLOSING SUMMARY</div>
|
||||
</div>
|
||||
<div class="dashed"></div>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="bold">Cashier</td>
|
||||
<td class="right">${receiptData.cashierName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bold">Date/Time</td>
|
||||
<td class="right" style="font-size:24px;">${receiptData.closingTime}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="dashed"></div>
|
||||
<table>
|
||||
${cashRow}
|
||||
${nonCashRows.join("")}
|
||||
</table>
|
||||
<div class="solid"></div>
|
||||
<table>
|
||||
<tr class="total-row">
|
||||
<td>TOTAL</td>
|
||||
<td class="right">${receiptData.grandTotal}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="dashed"></div>
|
||||
<div class="footer">*** Session Closed ***</div>
|
||||
<div class="feed"> </div>
|
||||
</div>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.print();
|
||||
setTimeout(function() { window.close(); }, 1000);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const printWindow = window.open("", "_blank", "width=400,height=600");
|
||||
if (!printWindow) {
|
||||
const notification = this.pos?.env?.services?.notification;
|
||||
if (notification) {
|
||||
notification.add(
|
||||
_t("Pop-up blocked. Please allow pop-ups for this site and try again to print closing receipt."),
|
||||
{ type: "warning" }
|
||||
);
|
||||
} else {
|
||||
alert("Pop-up blocked. Please allow pop-ups for this site and try again to print closing receipt.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
printWindow.document.open();
|
||||
printWindow.document.write(html);
|
||||
printWindow.document.close();
|
||||
|
||||
// Safety delay to allow window to open and print dialog to spawn before proceeding
|
||||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||
} catch (err) {
|
||||
console.error("[pos_closing_receipt] CRITICAL: Failed to print closing receipt:", err);
|
||||
} finally {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user