enabled multi-printer configuration for billing and kitchen printers

This commit is contained in:
Alaguraj0361 2026-05-07 16:58:11 +05:30
parent 8fc4ae447a
commit e7c67653e4
4 changed files with 103 additions and 8 deletions

View File

@ -4,7 +4,8 @@ class PosConfig(models.Model):
_inherit = 'pos.config'
use_qz_printer = fields.Boolean("Use QZ Tray Printer", help="Print directly using QZ Tray locally")
qz_printer_name = fields.Char("QZ Printer Name", help="Name of the printer mapped in QZ Tray")
qz_billing_printer_name = fields.Char("Billing Printer Name", help="Name of the billing printer mapped in QZ Tray")
qz_kitchen_printer_name = fields.Char("Kitchen Printer Name", help="Name of the kitchen printer mapped in QZ Tray")
qz_paper_width = fields.Selection(
[('42', '58mm / 42 columns'), ('48', '80mm / 48 columns')],
string="QZ Receipt Width",

View File

@ -5,7 +5,8 @@ class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
use_qz_printer = fields.Boolean(related='pos_config_id.use_qz_printer', readonly=False)
qz_printer_name = fields.Char(related='pos_config_id.qz_printer_name', readonly=False)
qz_billing_printer_name = fields.Char(related='pos_config_id.qz_billing_printer_name', readonly=False)
qz_kitchen_printer_name = fields.Char(related='pos_config_id.qz_kitchen_printer_name', readonly=False)
qz_paper_width = fields.Selection(related='pos_config_id.qz_paper_width', readonly=False)
qz_print_logo = fields.Boolean(related='pos_config_id.qz_print_logo', readonly=False)
qz_enable_cutter = fields.Boolean(related='pos_config_id.qz_enable_cutter', readonly=False)

View File

@ -3,6 +3,7 @@
import { patch } from "@web/core/utils/patch";
import { ReceiptScreen } from "@point_of_sale/app/screens/receipt_screen/receipt_screen";
import { ErrorPopup } from "@point_of_sale/app/errors/popups/error_popup";
import { PosStore } from "@point_of_sale/app/store/pos_store";
const ESC = 0x1b;
const GS = 0x1d;
@ -355,7 +356,7 @@ async function buildEscPosReceipt(order, pos) {
patch(ReceiptScreen.prototype, {
async printReceipt() {
if (this.pos.config.use_qz_printer && this.pos.config.qz_printer_name) {
if (this.pos.config.use_qz_printer && this.pos.config.qz_billing_printer_name) {
try {
if (!window.qz) {
console.error("QZ Tray library not loaded.");
@ -366,7 +367,7 @@ patch(ReceiptScreen.prototype, {
await qz.websocket.connect({ retries: 2, delay: 1 });
}
const config = qz.configs.create(this.pos.config.qz_printer_name, {
const config = qz.configs.create(this.pos.config.qz_billing_printer_name, {
encoding: "CP437",
copies: 1,
spool: { size: 1 },
@ -395,3 +396,87 @@ patch(ReceiptScreen.prototype, {
return super.printReceipt(...arguments);
},
});
async function buildEscPosKitchenTicket(order, pos, changes) {
const config = pos?.config || {};
const columns = columnsFromConfig(config);
const builder = new EscPosBuilder(columns);
builder.init();
builder.align("center");
builder.bold(true);
builder.size("doubleHeight");
builder.line("KITCHEN ORDER");
builder.size("normal");
builder.line("");
builder.align("left");
if (order.name) builder.line(`Order: ${order.name}`);
if (order.table?.name) builder.line(`Table: ${order.table.name}`);
if (order.customer_count) builder.line(`Guests: ${order.customer_count}`);
builder.line(`Time: ${new Date().toLocaleTimeString()}`);
builder.separator("=");
for (const category of Object.values(changes.categories || {})) {
if (category.name) {
builder.bold(true);
builder.line(category.name.toUpperCase());
builder.bold(false);
}
for (const line of category.orderlines || []) {
const qty = line.quantity;
const qtyText = Number.isInteger(qty) ? String(qty) : qty.toFixed(2).replace(/\.?0+$/, "");
addWrappedLine(builder, `${qtyText} x ${line.name}`);
if (line.note) {
addWrappedLine(builder, `Note: ${line.note}`, "", 2);
}
}
builder.line("");
}
builder.feed(END_FEED_LINES);
if (config.qz_enable_cutter !== false) {
builder.cut(config.qz_cut_mode || "partial");
}
builder.feed(1);
return bytesToBase64(builder.bytes);
}
patch(PosStore.prototype, {
async sendOrderToPrinter(order) {
if (this.config.use_qz_printer && this.config.qz_kitchen_printer_name) {
const changes = order.computeChanges();
if (Object.keys(changes.categories).length > 0) {
try {
if (!window.qz) {
console.error("QZ Tray library not loaded.");
return false;
}
if (!qz.websocket.isActive()) {
await qz.websocket.connect({ retries: 2, delay: 1 });
}
const config = qz.configs.create(this.config.qz_kitchen_printer_name, {
encoding: "CP437",
copies: 1,
spool: { size: 1 },
});
const payload = await buildEscPosKitchenTicket(order, this, changes);
await qz.print(config, [{
type: "raw",
format: "command",
flavor: "base64",
data: payload,
}]);
order.saved_quantity = order.get_orderlines().reduce((acc, line) => acc + line.get_quantity(), 0);
return true;
} catch (err) {
console.error("QZ Tray Kitchen Print Error:", err);
// Fallback or show error
}
}
return true;
}
return super.sendOrderToPrinter(...arguments);
},
});

View File

@ -11,8 +11,12 @@
<field name="use_qz_printer"/>
<div class="content-group" invisible="not use_qz_printer">
<div class="row mt16">
<label string="Printer Name" for="qz_printer_name" class="col-lg-3 o_light_label"/>
<field name="qz_printer_name"/>
<label string="Billing Printer" for="qz_billing_printer_name" class="col-lg-3 o_light_label"/>
<field name="qz_billing_printer_name"/>
</div>
<div class="row mt16">
<label string="Kitchen Printer" for="qz_kitchen_printer_name" class="col-lg-3 o_light_label"/>
<field name="qz_kitchen_printer_name"/>
</div>
<div class="row mt16">
<label string="Receipt Width" for="qz_paper_width" class="col-lg-3 o_light_label"/>
@ -46,8 +50,12 @@
<field name="use_qz_printer"/>
<div class="content-group" invisible="not use_qz_printer">
<div class="row mt16">
<label string="Printer Name" for="qz_printer_name" class="col-lg-3 o_light_label"/>
<field name="qz_printer_name"/>
<label string="Billing Printer" for="qz_billing_printer_name" class="col-lg-3 o_light_label"/>
<field name="qz_billing_printer_name"/>
</div>
<div class="row mt16">
<label string="Kitchen Printer" for="qz_kitchen_printer_name" class="col-lg-3 o_light_label"/>
<field name="qz_kitchen_printer_name"/>
</div>
<div class="row mt16">
<label string="Receipt Width" for="qz_paper_width" class="col-lg-3 o_light_label"/>