⚡ LQPOS Documentation Hub v0.1 Release
Core Specification • Spec 02

02 POS Terminal & Cashier Interface

Focus-free barcode interception, numpad ergonomics, ESC/POS hardware, and AAMVA PDF417 ID verification.

02 — POS Terminal & Cashier Interface Specification

1. Ergonomics & Keyboard-First Design Philosophy

Liquor retail checkout requires intense velocity. During Friday 4:30 PM to 7:00 PM rush hours, every fraction of a second spent clicking a mouse or waiting for a dialog to render costs real throughput and frustrates customers.

Key Ergonomic Directives

  1. Focus-Free Barcode Interception:
    • In naive web POS apps, if a cashier accidentally clicks away from the search input, scanned barcodes are lost or trigger random browser shortcuts.
    • LQPOS implements a Global Keystroke Interceptor:
      • Hardware barcode scanners simulate high-speed keyboard input (bursts of 10–14 characters within 15–30ms terminated by Enter or \r\n).
      • The POS application tracks keystroke arrival velocity. When a high-speed character burst is detected, it is immediately routed to the item ingestion engine, regardless of which screen element currently has DOM focus.
  2. 100% Numpad & Hotkey Operability:
    • A cashier can ring up a 10-item transaction, apply a bag fee, verify age, and tender cash without touching a mouse or lifting hands from the keyboard.
  3. Primary Keyboard Shortcuts:
    • F1 — Fast Customer Lookup (Phone / Loyalty)
    • F2 — Park / Suspend Transaction (Switch cart)
    • F3 — Recall Suspended Transaction
    • F4 — Age Verification (Manual Override Modal)
    • F8 — Line Item Discount / Coupon
    • F9 — Void Selected Line Item
    • F10 — Cash Drawer No-Sale Open (Manager PIN required)
    • Enter (on empty cart bar) — Proceed to Tender Screen
    • * on Numpad — Quantity Multiplier (e.g. 6 * [Scan] = 6 of scanned item)
    • Esc — Cancel current action / Back out of modal

2. Hardware Abstraction Layer (HAL)

The POS Terminal communicates with peripheral hardware via a dedicated background driver agent (running inside Tauri/Electron or a lightweight local daemon):

┌────────────────────────────────────────────────────────────────────────┐
│                        POS REGISTER FRONTEND                           │
│                     (React / Zustand State Store)                      │
└───────────────────────────────────▲────────────────────────────────────┘
                                    │ WebSockets / IPC
┌───────────────────────────────────▼────────────────────────────────────┐
│                  HARDWARE ABSTRACTION LAYER (HAL)                      │
├────────────────────────────────────────────────────────────────────────┤
│ • Scanner Adapter: USB HID Wedge + Serial COM                          │
│ • Printer Driver: Raw ESC/POS byte streaming (USB, TCP 9100, Serial)   │
│ • Cash Drawer: Standard RJ-11 kick solenoid via printer pin 2 or pin 5 │
│ • Pole Display: 2x20 VFD Serial or Dual-Head HDMI HTML5 Canvas         │
│ • Scale Driver: Weight stability detection (RS232 / USB)               │
│ • EMV Terminal: TCP/IP JSON protocol to PAX / Dejavoo / Stripe         │
└────────────────────────────────────────────────────────────────────────┘

Supported Hardware Protocols

  1. Thermal Receipt Printers (ESC/POS):
    • Epson TM-T88VI / TM-T20III, Star Micronics TSP143, Bixolon SRP-350.
    • Prints text, graphics, QR codes, and cut commands directly via raw ESC/POS byte buffers (avoiding slow browser print dialogs).
  2. Cash Drawers:
    • Standard APG / M-S Cash Drawer with RJ-11 / RJ-12 interface plugged into receipt printer DK port.
    • Drawer kick trigger: ESC p 0 25 250 (Pin 2 kick) or ESC p 1 25 250 (Pin 5 kick).
    • Supports drawer open/closed status sensor via printer pulse feedback.
  3. Barcode Scanners (1D & 2D):
    • Honeywell Voyager / Xenon 1900, Zebra DS2208 / DS8178.
    • Configured to output standard prefixes/suffixes for reliable parsing of UPC-A, EAN-13, ITF-14, Code 128, and PDF417.
  4. Customer Facing Display (CFD):
    • Dual HDMI Screen: Secondary monitor running an independent lightweight HTML5 client displaying current cart line items, pricing, store announcements, and payment prompts.
    • Serial VFD Pole Display: Fallback support for standard 2-line x 20-character vacuum fluorescent displays (ESC/POS display commands).

3. High-Velocity Cashier UI Layout

┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ LQPOS Lane 1 | Cashier: Sarah J. | Shift: #124 | Status: ● Online LAN                                   │
├─────────────────────────────────────────────────────────────────────┬────────────────────────────────────┤
│ CART ITEMS (4 Items)                                                │ QUICK-KEY TOUCH GRID               │
├─────────────────────────────────────────────────────────────────────┼──────────────┬──────────────┬──────┤
│ 1. Tito's Handmade Vodka 1.75L                    $33.99            │ 5LB ICE BAG  │ 10LB ICE BAG │ BAG  │
│    UPC: 088004000305 | Dep: $0.00                                   │   $2.49      │    $3.99     │$0.10 │
│                                                                     ├──────────────┼──────────────┼──────┤
│ 2. Coors Light 12oz Cans 24-Pack Case             $23.99            │ FIREBALL     │ JAGER        │ RED  │
│    UPC: 071990300174 | Dep: $0.00                                   │ 50ML SHOT    │ 50ML SHOT    │ BULL │
│                                                                     │   $1.25      │    $1.50     │$2.99 │
│ 3. Odell IPA 12oz Cans 6-Pack                     $11.99            ├──────────────┼──────────────┼──────┤
│    UPC: 754527000201 | Mix-6 Eligible                               │ LEMONS /     │ BOTTLE GIFT  │ KEG  │
│                                                                     │ LIMES        │ BAG          │ TAP  │
│ 4. Single Craft Can (Pick-6 Bundle Item)           $2.50            │   $0.75      │    $2.99     │$50.00│
├─────────────────────────────────────────────────────────────────────┼──────────────┴──────────────┴──────┤
│ [F4] AGE VERIFIED: 28 YRS (Exp: 2028-04-12) [✓ VALID DL]            │ TOTALS SUMMARY                     │
├─────────────────────────────────────────────────────────────────────┼────────────────────────────────────┤
│ ITEM SCAN / SEARCH:                                                 │ Subtotal:                   $72.47 │
│ [ 071990300174                                           ] [Enter]  │ Mix & Match Discount:       -$1.50 │
│                                                                     │ Sales Tax (Liquor 7.5%):     $5.32 │
│ [F1: Customer] [F2: Hold Cart] [F8: Discount] [F9: Void] [F10: Drop]│ Grand Total:                $76.29 │
├─────────────────────────────────────────────────────────────────────┴────────────────────────────────────┤
│ [ CASH ($76.29) ]   [ CREDIT / DEBIT (PAX EMV) ]   [ SPLIT TENDER ]   [ EXACT CASH ($80.00) ]           │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘

4. 21+ Age Verification & Driver's License Decoding Engine

Liquor retail requires absolute compliance with state liquor laws. Selling to minors results in severe fines, suspension, or license revocation.

Workflow: 2D Barcode (AAMVA PDF417) Scan

  1. Trigger: Cashier scans the customer's driver's license using the 2D barcode scanner at any point during the sale.
  2. Parser Specification:
    • The system intercepts the raw string conforming to the AAMVA DL/ID Standard (American Association of Motor Vehicle Administrators).
    • Mandatory elements extracted:
      • DBB — Date of Birth (YYYYMMDD or MMDDYYYY)
      • DBA — Expiration Date (YYYYMMDD or MMDDYYYY)
      • DAA — Customer Full Name (Optional display for card matching)
      • DAQ — Document ID / License Number
  3. Validation Logic:
    function verifyAge(dlRawString: string): AgeCheckResult {
      const parsed = parseAAMVAPDF417(dlRawString);
      const birthDate = parsed.dateOfBirth;
      const expiryDate = parsed.expirationDate;
      const today = new Date();
    
      // 1. Check ID Expiration
      if (expiryDate < today) {
        return { valid: false, reason: 'ID_EXPIRED', age: null };
      }
    
      // 2. Calculate Exact Age
      let age = today.getFullYear() - birthDate.getFullYear();
      const monthDiff = today.getMonth() - birthDate.getMonth();
      if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
        age--;
      }
    
      // 3. Threshold Check
      if (age >= 21) {
        return { 
          valid: true, 
          age: age, 
          auditHash: sha256(parsed.licenseNumber + birthDate.toISOString() + getStoreSalt()) 
        };
      } else {
        return { valid: false, reason: 'UNDERAGE', age: age };
      }
    }
    
  4. Visual Cashier Feedback:
    • PASSED (21+): Full-width GREEN banner across screen: "VERIFIED: 28 YEARS OLD (BIRTHDATE: 1998-05-14) — ID VALID".
    • FAILED (Underage): Full-screen flashing RED modal with audible alert tone: "UNDERAGE SALE BLOCKED: CUSTOMER IS 19 YEARS OLD". Checkout locked until modal dismissed.
    • EXPIRED: Full-width AMBER banner: "REJECTED: DRIVER'S LICENSE EXPIRED ON 2026-03-01".
  5. Privacy & Audit Logging:
    • To prevent liability under data privacy laws, full PII (customer address, full name, driver's license number) is not stored permanently in the sales database.
    • The system stores a one-way cryptographic SHA-256 hash (audit_hash) of the license number + transaction ID + timestamp as proof that a valid ID was physically scanned.

5. Cart Lifecycle, Split Tenders & Edge Cases

1. Multi-Cart Suspend / Hold & Recall

  • If a customer reaches the counter, starts ringing up items, and says, "Wait, I forgot vermouth in aisle 2," the cashier presses F2 (Hold).
  • Current cart is saved to the active shift's local cache with a reference index (Cart #2 - 3 Items - $34.50).
  • The register clears instantly for the next customer in line.
  • Pressing F3 (Recall) brings up a quick drawer to restore suspended carts in 1 click.

2. Split Tender Execution

  • Common in liquor retail: customer wants to pay $40 in cash and the remaining balance on a credit card, or two patrons splitting a large party order.
  • The cashier enters $40.00 and presses [CASH].
  • System records payment row: method: cash, amount: $40.00, remaining_due: $36.29.
  • System auto-prompts remaining balance $36.29 directly to the EMV terminal.
  • Once terminal returns approved status, transaction is finalized and receipt prints automatically.

3. Container & Keg Deposit Flow

  • Keg Shell & Tap Deposits:
    • Selling a 1/2 Barrel of Craft Beer ($160.00) automatically appends two non-taxable deposit line items:
      • Keg Shell Deposit: $30.00
      • Keg Tap Rental Deposit: $50.00
    • Receipt prints a dedicated Keg Return Ticket with unique barcode.
  • Returns & Empties:
    • Customer brings back empty keg shell.
    • Cashier clicks [Quick Key: Keg Return] or scans ticket barcode.
    • Cart displays -$30.00 Keg Return Refund.
    • Cashier tenders payout directly from drawer.