feat: implement order and line notes for basic receipts in ESC/POS generator and update receipt data mapping
This commit is contained in:
parent
e80bce30fa
commit
5524546dab
@ -207,6 +207,7 @@ export class EscPosGenerator {
|
||||
|
||||
// ── Initialize ────────────────────────────────────────────────────
|
||||
cmds.push(...this.initialize());
|
||||
cmds.push(...this.setAlignment('left'));
|
||||
|
||||
// ── Header ────────────────────────────────────────────────────────
|
||||
// On basic receipt (table checker): skip company header, print only minimal info
|
||||
@ -353,6 +354,25 @@ export class EscPosGenerator {
|
||||
cmds.push(...this.addLine(this.divider()));
|
||||
}
|
||||
|
||||
// ── Order Notes (Basic Receipt) ───────────────────────────────────
|
||||
if (receiptData.isBasicReceipt && receiptData.orderData) {
|
||||
const o = receiptData.orderData;
|
||||
if (o.internalNote) {
|
||||
const noteLines = String(o.internalNote).split('\n');
|
||||
cmds.push(...this.addLine('Order Note:', { height: 2, bold: true }));
|
||||
noteLines.forEach(l => {
|
||||
cmds.push(...this.addLine(` ${l}`, { height: 2, bold: true }));
|
||||
});
|
||||
}
|
||||
if (o.customerNote) {
|
||||
const noteLines = String(o.customerNote).split('\n');
|
||||
cmds.push(...this.addLine('Cust Note:', { height: 2, bold: true }));
|
||||
noteLines.forEach(l => {
|
||||
cmds.push(...this.addLine(` ${l}`, { height: 2, bold: true }));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ── Totals ────────────────────────────────────────────────────────
|
||||
// Hidden on basic receipt — matches t-if="!props.basic_receipt" in order_receipt.xml
|
||||
if (!receiptData.isBasicReceipt && receiptData.totals) {
|
||||
|
||||
@ -248,11 +248,14 @@ patch(PosPrinterService.prototype, {
|
||||
if (isMobile) {
|
||||
console.log('[BluetoothPrint] Mobile or WebView environment detected. Falling back to native printWeb on main window.');
|
||||
try {
|
||||
this.printWeb(el);
|
||||
console.log('[BluetoothPrint] Invoking await this.printWeb(el)...');
|
||||
await this.printWeb(el);
|
||||
console.log('[BluetoothPrint] printWeb has finished executing.');
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('[BluetoothPrint] printWeb failed, calling window.print directly:', e);
|
||||
window.print(el);
|
||||
console.log('[BluetoothPrint] direct window.print has returned.');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -260,6 +263,7 @@ patch(PosPrinterService.prototype, {
|
||||
return new Promise((resolve) => {
|
||||
// Create a hidden iframe for printing
|
||||
const printFrame = document.createElement('iframe');
|
||||
printFrame.className = 'pos-print-iframe';
|
||||
printFrame.style.position = 'fixed';
|
||||
printFrame.style.right = '0';
|
||||
printFrame.style.bottom = '0';
|
||||
@ -655,6 +659,7 @@ patch(PosPrinterService.prototype, {
|
||||
_buildReceiptDataFromOrder(order) {
|
||||
console.log('[BluetoothPrint] _buildReceiptDataFromOrder called for:', order?.pos_reference);
|
||||
|
||||
const isBasic = !!this._currentPrintBasic;
|
||||
const pos = this.env?.services?.pos;
|
||||
const company = order.company || pos?.company || {};
|
||||
const config = order.config || pos?.config || {};
|
||||
@ -716,6 +721,8 @@ patch(PosPrinterService.prototype, {
|
||||
cashier: formatFirstLastName((typeof order.getCashierName === 'function' ? order.getCashierName() : '') || ''),
|
||||
customer: order.partner_id?.name || null,
|
||||
tableName,
|
||||
internalNote: isBasic ? (pos?.getStrNotes ? pos.getStrNotes(order.internal_note || '[]') : (typeof order.internal_note === 'string' ? order.internal_note : '')) : '',
|
||||
customerNote: isBasic ? (order.general_customer_note || '') : '',
|
||||
};
|
||||
|
||||
// ── Order lines ────────────────────────────────────────────────────────
|
||||
@ -723,7 +730,6 @@ patch(PosPrinterService.prototype, {
|
||||
? order.getOrderlines()
|
||||
: (order.lines || []);
|
||||
|
||||
const isBasic = !!this._currentPrintBasic;
|
||||
const lines = orderlines
|
||||
.filter(line => {
|
||||
if (line.combo_parent_id) return false; // skip combo sub-lines
|
||||
@ -747,8 +753,22 @@ patch(PosPrinterService.prototype, {
|
||||
? line.displayPriceUnit
|
||||
: (qty !== 0 ? lineTotal / qty : line.price_unit || 0);
|
||||
|
||||
// Customer-facing note (always shown, even on basic receipt)
|
||||
const note = line.customer_note || '';
|
||||
// Construct combined line note if basic receipt, else empty string
|
||||
let note = '';
|
||||
if (isBasic) {
|
||||
const noteParts = [];
|
||||
const customerNote = line.customer_note || line.customerNote || '';
|
||||
if (customerNote) {
|
||||
noteParts.push(customerNote);
|
||||
}
|
||||
if (line.note) {
|
||||
const internalNote = pos?.getStrNotes ? pos.getStrNotes(line.note) : (typeof line.note === 'string' ? line.note : '');
|
||||
if (internalNote) {
|
||||
noteParts.push(internalNote);
|
||||
}
|
||||
}
|
||||
note = noteParts.join(' | ');
|
||||
}
|
||||
|
||||
// Find combo sub-lines linked to this line
|
||||
const comboSubLines = orderlines
|
||||
|
||||
@ -31,14 +31,17 @@ describe('ESC/POS Conversion Properties', () => {
|
||||
orderName: fc.string({ minLength: 1, maxLength: 50 }),
|
||||
date: fc.date().map(d => d.toISOString()),
|
||||
cashier: fc.string({ minLength: 1, maxLength: 50 }),
|
||||
customer: fc.option(fc.string({ minLength: 1, maxLength: 100 }))
|
||||
customer: fc.option(fc.string({ minLength: 1, maxLength: 100 })),
|
||||
internalNote: fc.option(fc.string({ maxLength: 100 })),
|
||||
customerNote: fc.option(fc.string({ maxLength: 100 }))
|
||||
}),
|
||||
lines: fc.array(
|
||||
fc.record({
|
||||
productName: fc.string({ minLength: 1, maxLength: 100 }),
|
||||
quantity: fc.float({ min: Math.fround(0.01), max: Math.fround(1000), noNaN: true }),
|
||||
price: fc.float({ min: Math.fround(0.01), max: Math.fround(100000), noNaN: true }),
|
||||
total: fc.float({ min: Math.fround(0.01), max: Math.fround(100000), noNaN: true })
|
||||
total: fc.float({ min: Math.fround(0.01), max: Math.fround(100000), noNaN: true }),
|
||||
note: fc.option(fc.string({ maxLength: 100 }))
|
||||
}),
|
||||
{ minLength: 1, maxLength: 50 }
|
||||
),
|
||||
@ -56,7 +59,8 @@ describe('ESC/POS Conversion Properties', () => {
|
||||
footerData: fc.record({
|
||||
message: fc.string({ maxLength: 200 }),
|
||||
barcode: fc.option(fc.string({ minLength: 1, maxLength: 50 }))
|
||||
})
|
||||
}),
|
||||
isBasicReceipt: fc.boolean()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user