feat: truncate long cashier names to first and last name, apply bold formatting to receipt items, and reduce paper feed length

This commit is contained in:
Suherdy Yacob 2026-06-01 08:49:26 +07:00
parent 85ddc0ab44
commit fe1b692f4f
2 changed files with 26 additions and 8 deletions

View File

@ -255,12 +255,12 @@ export class EscPosGenerator {
const displayName = name.length > nameMaxLen
? name.substring(0, nameMaxLen - 1) + '.'
: name;
cmds.push(...this.addLine(qtyLabel + displayName));
cmds.push(...this.addLine(qtyLabel + displayName, { bold: true, height: 2 }));
} else {
// ── Full receipt ───────────────────────────────────────────
// Line 1: product name
const displayName = name.length > W ? name.substring(0, W - 1) + '.' : name;
cmds.push(...this.addLine(displayName));
cmds.push(...this.addLine(displayName, { bold: true, height: 2 }));
// Line 2: qty x unitPrice = total (right-aligned)
const priceStr = this.formatAmount(line.price || 0);
@ -268,14 +268,15 @@ export class EscPosGenerator {
const middle = `${qtyStr}x ${priceStr}`;
let itemLine = middle + totalStr.padStart(W - middle.length);
if (itemLine.length > W) itemLine = totalStr.padStart(W);
cmds.push(...this.addLine(itemLine));
cmds.push(...this.addLine(itemLine, { bold: true, height: 2 }));
}
// Note line (customer note / kitchen note) — shown on both modes
if (line.note) {
const noteText = `* ${line.note}`;
cmds.push(...this.addLine(
noteText.length > W ? noteText.substring(0, W - 1) + '.' : noteText
noteText.length > W ? noteText.substring(0, W - 1) + '.' : noteText,
{ bold: true }
));
}
});
@ -336,8 +337,8 @@ export class EscPosGenerator {
}
}
// Feed and cut
cmds.push(...this.feedAndCut(4));
// Feed and cut (reduced feed to 1 line to prevent footer white spaces on integrated Android/iMin printers)
cmds.push(...this.feedAndCut(1));
return new Uint8Array(cmds);
}

View File

@ -17,6 +17,22 @@ import { EscPosGraphics } from "./escpos_graphics";
* Ensures sale completion is never blocked by print errors.
*/
const formatFirstLastName = (name) => {
if (!name) return "";
let temp = name.trim();
let prefix = "";
const prefixMatch = temp.match(/^(served\s+by:?|order\s+taker:?|kasir:?)\s*/i);
if (prefixMatch) {
prefix = prefixMatch[0];
temp = temp.substring(prefix.length).trim();
}
const parts = temp.split(/\s+/);
if (parts.length <= 2) {
return name;
}
return prefix + parts[0] + " " + parts[parts.length - 1];
};
// Singleton instances for the POS session
let bluetoothManager = null;
let escposGenerator = null;
@ -680,7 +696,7 @@ patch(PosPrinterService.prototype, {
const orderData = {
orderName: order.pos_reference || order.name || '',
date: dateStr || new Date().toLocaleString(),
cashier: (typeof order.getCashierName === 'function' ? order.getCashierName() : '') || '',
cashier: formatFirstLastName((typeof order.getCashierName === 'function' ? order.getCashierName() : '') || ''),
customer: order.partner_id?.name || null,
tableName,
};
@ -823,7 +839,7 @@ patch(PosPrinterService.prototype, {
const orderData = {
orderName: getText('.pos-receipt-vat') || getText('.pos-receipt-order-name') || getText('.order-name') || getText('.pos-receipt-order-data') || '',
date: getText('#order-date') || getText('.pos-receipt-date') || new Date().toLocaleString(),
cashier: getText('.cashier') || getText('.pos-receipt-cashier') || '',
cashier: formatFirstLastName(getText('.cashier') || getText('.pos-receipt-cashier') || ''),
customer: getText('.pos-receipt-customer') || getText('.customer') || null
};
@ -1073,6 +1089,7 @@ patch(PosPrinterService.prototype, {
} else if (pos.user) {
cashierName = pos.user.name || '';
}
cashierName = formatFirstLastName(cashierName);
console.log('[BluetoothPrint] Cashier name:', cashierName);
// Get customer info - try multiple ways