forked from alaguraj/odoo-testing-addons
enabled multi-printer configuration for billing and kitchen printers
This commit is contained in:
parent
8fc4ae447a
commit
e7c67653e4
@ -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",
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
@ -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"/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user