diff --git a/public/pos/history.html b/public/pos/history.html
index 6892d6c..10a6711 100644
--- a/public/pos/history.html
+++ b/public/pos/history.html
@@ -220,6 +220,9 @@ async function load(){
method: METHOD_LABELS[s.payment_method] || 'Cash',
dt: new Date(s.created),
}));
+ // Cache for reprint() — needs both the PosSale and its PosSaleItems
+ // to reconstruct the sessionStorage shape that receipt.html expects.
+ cachedRows = rows;
const grandTotal = rows.reduce((sum,r)=>sum+r.total,0);
document.getElementById('kpiCount').textContent = sales.length;
document.getElementById('kpiTotal').textContent = fmt(grandTotal);
@@ -244,8 +247,61 @@ async function load(){
}
}
+// Cached after each load() — lets reprint() look up the full PosSale +
+// PosSaleItems for a clicked row without re-fetching. The list is the
+// only source of truth for "what's on screen", so this stays in sync
+// whenever the user picks a different day.
+let cachedRows = [];
+
+// Reprint = hop to receipt.html with the sale stashed in
+// sessionStorage. The receipt page already handles loading from
+// sessionStorage and has the full Bluetooth / Network print logic
+// (including the epos-print.js network path added 2026-09-03), so we
+// just translate the API shape into the till-rendered shape and let
+// the existing code drive the printer.
window.reprint = function(orderId){
- alert('Reprint: slip ' + orderId + '. (Use the browser print dialog to re-print.)');
+ const row = cachedRows.find(r => r.s.id === orderId);
+ if(!row){
+ alert('Sale not loaded — try again after the list finishes loading.');
+ return;
+ }
+ const s = row.s;
+ const sessionSale = {
+ localId: s.client_ref || s.id,
+ createdAt: s.created,
+ payment: s.payment_method,
+ cashGiven: s.cash_given || 0,
+ change: s.change_given || 0,
+ gross: s.gross_total,
+ discount: {
+ kind: s.discount_kind || 'none',
+ input: s.discount_input || 0,
+ amount: s.discount_amount || 0,
+ },
+ sub: s.subtotal,
+ vat: s.vat,
+ total: s.total,
+ items: row.items.map(it => ({
+ sku: it.sku,
+ description: it.description,
+ unit: 'ea',
+ cost_price: it.unit_cost,
+ selling_price: it.unit_price,
+ edited: false,
+ qty: it.qty,
+ product_id: it.stock_item,
+ })),
+ // The API returns the customer as a relation id only (no name
+ // expansion in the sales list). Pass null so receipt.html's
+ // `if (s.customer)` guard skips the line — better than printing
+ // "Customer: undefined". If we need the name, the user can add
+ // a /api/v1/pos/sales/:id endpoint that expands it.
+ customer: null,
+ synced: true,
+ serverRef: s.id,
+ };
+ try{ sessionStorage.setItem('pos.lastSale', JSON.stringify(sessionSale)); }catch(_){}
+ setTimeout(() => { location.href = 'receipt.html'; }, 80);
};
paintDays(); load();