From 95a01c8958add05e42496d60d9080d4bf41a959d Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Sat, 18 Jul 2026 16:22:26 +0000 Subject: [PATCH] Improve ticket legibility: larger fonts, spacing, indentation and thermal emphasized mode --- pos/services/thermal_printer.py | 16 ++++++++++++++++ pos/static/js/pos.js | 28 ++++++++++++++-------------- pos/static/pwa/sw.js | 2 +- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/pos/services/thermal_printer.py b/pos/services/thermal_printer.py index e51354d..505dbce 100644 --- a/pos/services/thermal_printer.py +++ b/pos/services/thermal_printer.py @@ -16,9 +16,13 @@ ALIGN_CENTER = ESC + b'a' + b'\x01' ALIGN_RIGHT = ESC + b'a' + b'\x02' BOLD_ON = ESC + b'E' + b'\x01' BOLD_OFF = ESC + b'E' + b'\x00' +EMPH_ON = ESC + b'G' + b'\x01' # Double-strike / emphasized +EMPH_OFF = ESC + b'G' + b'\x00' DOUBLE_HEIGHT = ESC + b'!' + b'\x10' NORMAL_SIZE = ESC + b'!' + b'\x00' LARGE_SIZE = ESC + b'!' + b'\x30' # Double width + double height +LINE_SPACING_140 = ESC + b'3' + b'\x28' # ~1.4x line spacing +LINE_SPACING_DEFAULT = ESC + b'2' def generate_ticket(sale_data, business_info, width=80): @@ -34,6 +38,8 @@ def generate_ticket(sale_data, business_info, width=80): chars = 32 if width == 58 else 48 # characters per line buf = bytearray() buf += INIT + buf += EMPH_ON + buf += LINE_SPACING_140 # Header: business name (centered, bold, large) buf += ALIGN_CENTER @@ -100,6 +106,8 @@ def generate_ticket(sale_data, business_info, width=80): buf += 'Gracias por su compra!\n'.encode('cp437', errors='replace') buf += 'Nexus Autoparts POS\n'.encode('cp437', errors='replace') buf += b'\n\n\n' + buf += LINE_SPACING_DEFAULT + buf += EMPH_OFF buf += FEED + b'\x05' # Feed 5 lines before cutting buf += CUT # Full cut @@ -120,6 +128,8 @@ def generate_quotation_ticket(quote_data, business_info, width=80): chars = 32 if width == 58 else 48 buf = bytearray() buf += INIT + buf += EMPH_ON + buf += LINE_SPACING_140 # Header buf += ALIGN_CENTER @@ -188,6 +198,8 @@ def generate_quotation_ticket(quote_data, business_info, width=80): buf += 'Precios sujetos a disponibilidad\n'.encode('cp437', errors='replace') buf += 'Nexus Autoparts POS\n'.encode('cp437', errors='replace') buf += b'\n\n\n' + buf += LINE_SPACING_DEFAULT + buf += EMPH_OFF buf += FEED + b'\x05' buf += CUT @@ -226,6 +238,8 @@ def generate_service_order_ticket(so_data, business_info, width=80): chars = 32 if width == 58 else 48 buf = bytearray() buf += INIT + buf += EMPH_ON + buf += LINE_SPACING_140 # Header buf += ALIGN_CENTER @@ -340,6 +354,8 @@ def generate_service_order_ticket(so_data, business_info, width=80): buf += "No es comprobante fiscal\n".encode("cp437", errors="replace") buf += "Nexus Autoparts POS\n".encode("cp437", errors="replace") buf += b"\n\n\n" + buf += LINE_SPACING_DEFAULT + buf += EMPH_OFF buf += FEED + b'\x05' buf += CUT diff --git a/pos/static/js/pos.js b/pos/static/js/pos.js index 5adfb24..b76c024 100644 --- a/pos/static/js/pos.js +++ b/pos/static/js/pos.js @@ -1666,9 +1666,9 @@ const POS = (() => { const paperWidth = parseInt(rc('paper_width', '80'), 10) || 80; const is58 = paperWidth === 58; const printWidth = is58 ? 48 : 72; - const fontSize = is58 ? '7.5pt' : '9pt'; - const smallFont = is58 ? '6.5pt' : '8pt'; - const nameMax = is58 ? '18mm' : '34mm'; + const fontSize = is58 ? '9.5pt' : '11pt'; + const smallFont = is58 ? '8pt' : '9.5pt'; + const nameMax = is58 ? '17mm' : '32mm'; let iframe = document.getElementById('ticketPrintFrame'); if (!iframe) { @@ -1691,22 +1691,22 @@ const POS = (() => { ${src.innerHTML} diff --git a/pos/static/pwa/sw.js b/pos/static/pwa/sw.js index 6f979b4..2653212 100644 --- a/pos/static/pwa/sw.js +++ b/pos/static/pwa/sw.js @@ -6,7 +6,7 @@ // The fetch handler normalizes static asset URLs (strips ?v= query strings) // so templates can use cache-busting query params freely. -const VERSION = 47; +const VERSION = 48; const CACHE_NAME = 'nexus-pos-v' + VERSION; const APP_SHELL = [