feat: enhance basic receipt layout with double-height printing and conditional header skipping

This commit is contained in:
Suherdy Yacob 2026-06-01 15:09:38 +07:00
parent e667ef3bac
commit d1df33bdb2

View File

@ -209,13 +209,13 @@ export class EscPosGenerator {
cmds.push(...this.initialize());
// ── Header ────────────────────────────────────────────────────────
if (receiptData.headerData) {
// On basic receipt (table checker): skip company header, print only minimal info
if (!receiptData.isBasicReceipt && receiptData.headerData) {
const h = receiptData.headerData;
if (h.companyName) {
cmds.push(...this.addLine(h.companyName, { align: 'center', bold: true, width: 2, height: 2 }));
}
if (h.address) {
// Long addresses should wrap — print as-is (printer wraps automatically)
cmds.push(...this.addLine(h.address, { align: 'center' }));
}
if (h.phone) {
@ -230,12 +230,20 @@ export class EscPosGenerator {
// ── Order info ────────────────────────────────────────────────────
if (receiptData.orderData) {
const o = receiptData.orderData;
if (o.orderName) cmds.push(...this.addLine(`Order: ${o.orderName}`));
if (o.date) cmds.push(...this.addLine(`Date: ${o.date}`));
if (o.cashier) cmds.push(...this.addLine(`Cashier: ${o.cashier}`));
// Table name — printed after cashier, matching pos_restaurant ReceiptHeader
if (o.tableName) cmds.push(...this.addLine(o.tableName, { bold: true, align: 'center' }));
if (o.customer) cmds.push(...this.addLine(`Customer: ${o.customer}`));
if (receiptData.isBasicReceipt) {
// Basic receipt (table checker): all info at double height for readability
if (o.orderName) cmds.push(...this.addLine(`Order: ${o.orderName}`, { height: 2, bold: true }));
if (o.date) cmds.push(...this.addLine(o.date, { height: 2 }));
if (o.cashier) cmds.push(...this.addLine(`By: ${o.cashier}`, { height: 2 }));
if (o.tableName) cmds.push(...this.addLine(o.tableName, { bold: true, height: 2, align: 'center' }));
if (o.customer) cmds.push(...this.addLine(`Cust: ${o.customer}`, { height: 2 }));
} else {
if (o.orderName) cmds.push(...this.addLine(`Order: ${o.orderName}`));
if (o.date) cmds.push(...this.addLine(`Date: ${o.date}`));
if (o.cashier) cmds.push(...this.addLine(`Cashier: ${o.cashier}`));
if (o.tableName) cmds.push(...this.addLine(o.tableName, { bold: true, align: 'center' }));
if (o.customer) cmds.push(...this.addLine(`Customer: ${o.customer}`));
}
cmds.push(...this.addLine(this.divider()));
}
@ -248,15 +256,16 @@ export class EscPosGenerator {
if (receiptData.isBasicReceipt) {
// ── Basic receipt / table checker ──────────────────────────
// Show only qty + product name (no price/total), matching
// Odoo's basic_receipt behaviour (vals.price = false).
// Format: "2 Mie Ayam Geprek"
const qtyLabel = qtyStr.padEnd(3);
const nameMaxLen = W - qtyLabel.length;
// Show only qty + product name (no price/total), at double-width
// double-height for maximum readability on 58mm paper.
// At width=2, each char is 2x wide, so effective cols = W/2 = 16
const halfW = Math.floor(W / 2);
const qtyLabel = qtyStr.padEnd(2) + ' ';
const nameMaxLen = halfW - qtyLabel.length;
const displayName = name.length > nameMaxLen
? name.substring(0, nameMaxLen - 1) + '.'
: name;
cmds.push(...this.addLine(qtyLabel + displayName, { bold: true, height: 2 }));
cmds.push(...this.addLine(qtyLabel + displayName, { bold: true, width: 2, height: 2 }));
} else {
// ── Full receipt ───────────────────────────────────────────
// Line 1: product name
@ -279,14 +288,24 @@ export class EscPosGenerator {
const subQty = sub.quantity || 0;
const subQtyStr = subQty % 1 === 0 ? subQty.toFixed(0) : subQty.toFixed(2);
// Format: " - 1x Mie Goreng"
const prefix = ` - ${subQtyStr}x `;
const maxSubLen = W - prefix.length;
const displayName = subName.length > maxSubLen
? subName.substring(0, maxSubLen - 1) + '.'
: subName;
cmds.push(...this.addLine(prefix + displayName, { bold: true }));
if (receiptData.isBasicReceipt) {
// Double-height sub-lines on basic receipt
const halfW = Math.floor(W / 2);
const prefix = ` ${subQtyStr}x `;
const maxSubLen = halfW - prefix.length;
const displaySub = subName.length > maxSubLen
? subName.substring(0, maxSubLen - 1) + '.'
: subName;
cmds.push(...this.addLine(prefix + displaySub, { height: 2 }));
} else {
// Format: " - 1x Mie Goreng"
const prefix = ` - ${subQtyStr}x `;
const maxSubLen = W - prefix.length;
const displaySub = subName.length > maxSubLen
? subName.substring(0, maxSubLen - 1) + '.'
: subName;
cmds.push(...this.addLine(prefix + displaySub, { bold: true }));
}
});
}
@ -323,7 +342,11 @@ export class EscPosGenerator {
wrappedLines.forEach((l, i) => {
const prefix = i === 0 ? '* ' : ' ';
cmds.push(...this.addLine(prefix + l, { bold: true }));
if (receiptData.isBasicReceipt) {
cmds.push(...this.addLine(prefix + l, { bold: true, height: 2 }));
} else {
cmds.push(...this.addLine(prefix + l, { bold: true }));
}
});
}
});