Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 19: POS Client Application

The Point of Sale Terminal

The POS Client is the primary interface for retail associates. It must be fast, reliable, and work offline when network connectivity is lost. This chapter provides complete specifications for building a production-grade POS terminal.


Technology Stack

ComponentTechnologyRationale
Framework.NET MAUI or Blazor HybridCross-platform, native performance
Local DatabaseSQLiteEmbedded, zero-config, reliable
State ManagementFluxor or custom MVVMPredictable state changes
Hardware APIPlatform Invoke (P/Invoke)Direct hardware access
Sync EngineCustom HTTP + SignalRReal-time + batch sync

Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                        POS CLIENT APPLICATION                        │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
│  │   Views     │  │  ViewModels │  │  Services   │  │  Hardware   │ │
│  │  (XAML/     │◄─┤  (State +   │◄─┤  (Business  │◄─┤  Drivers    │ │
│  │   Blazor)   │  │   Commands) │  │   Logic)    │  │             │ │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘ │
│         │                │                │                │        │
│         └────────────────┴────────────────┴────────────────┘        │
│                                   │                                  │
│                          ┌────────▼────────┐                        │
│                          │  Local SQLite   │                        │
│                          │    Database     │                        │
│                          └────────┬────────┘                        │
│                                   │                                  │
│                          ┌────────▼────────┐                        │
│                          │   Sync Engine   │                        │
│                          │  (Online/Queue) │                        │
│                          └────────┬────────┘                        │
└──────────────────────────────────┬──────────────────────────────────┘
                                   │
                          ┌────────▼────────┐
                          │  Central API    │
                          │  (When Online)  │
                          └─────────────────┘

Screen Specifications

Screen 1: Login Screen

Purpose: Authenticate retail associates with fast PIN entry.

Route: /login

╔════════════════════════════════════════════════════════════════════╗
║                                                                    ║
║                    ┌──────────────────────────┐                    ║
║                    │                          │                    ║
║                    │       STORE LOGO         │                    ║
║                    │       [128x128]          │                    ║
║                    │                          │                    ║
║                    └──────────────────────────┘                    ║
║                                                                    ║
║                         NEXUS CLOTHING                             ║
║                      Greenbrier Mall (GM)                          ║
║                                                                    ║
║                    ┌──────────────────────────┐                    ║
║                    │                          │                    ║
║                    │  Enter Employee PIN      │                    ║
║                    │                          │                    ║
║                    │     ● ● ● ○ ○ ○          │                    ║
║                    │                          │                    ║
║                    └──────────────────────────┘                    ║
║                                                                    ║
║                    ┌─────┬─────┬─────┐                             ║
║                    │  1  │  2  │  3  │                             ║
║                    ├─────┼─────┼─────┤                             ║
║                    │  4  │  5  │  6  │                             ║
║                    ├─────┼─────┼─────┤                             ║
║                    │  7  │  8  │  9  │                             ║
║                    ├─────┼─────┼─────┤                             ║
║                    │ CLR │  0  │ ENT │                             ║
║                    └─────┴─────┴─────┘                             ║
║                                                                    ║
║                    [Manager Override]                               ║
║                                                                    ║
║  ─────────────────────────────────────────────────────────────     ║
║  Status: ● Online  |  Last Sync: 2 min ago  |  v1.2.0              ║
╚════════════════════════════════════════════════════════════════════╝

Components:

ComponentSpecification
Logo128x128px, tenant-specific
Store Name24px, Bold, Primary color
Location14px, Secondary text
PIN Display6 circles, filled = entered
Numpad80x80px buttons, touch-friendly
Clear (CLR)Resets PIN entry
Enter (ENT)Submits PIN for validation
Manager OverrideOpens manager auth dialog
Status BarConnection, sync, version

Behavior:

  • PIN validated locally first (hash comparison)
  • Failed attempts: 3 max before lockout
  • Lockout duration: 5 minutes (configurable)
  • Auto-login timeout: 30 seconds of inactivity returns to login

Screen 2: Main Sale Screen

Purpose: Primary transaction interface for ringing up sales.

Route: /sale

╔════════════════════════════════════════════════════════════════════╗
║ NEXUS CLOTHING - GM         Sarah M.          12/29/2024  2:45 PM  ║
╠════════════════════════════════════════════════════════════════════╣
║                                                                    ║
║  ┌─────────────────────────────────────────────────────────────┐  ║
║  │ [Scan Item or Enter SKU...]                        [SEARCH] │  ║
║  └─────────────────────────────────────────────────────────────┘  ║
║                                                                    ║
║  ┌──────────────────────────────────┐  ┌───────────────────────┐  ║
║  │ CART                         (3) │  │ TOTALS                │  ║
║  ├──────────────────────────────────┤  ├───────────────────────┤  ║
║  │                                  │  │                       │  ║
║  │ 1. Galaxy V-Neck Tee        $29  │  │ Subtotal:    $104.00  │  ║
║  │    Size: M | Color: Navy         │  │                       │  ║
║  │    Qty: 2         [-] [+]   $58  │  │ Discount:     -$10.00 │  ║
║  │                           [DEL]  │  │                       │  ║
║  │ ─────────────────────────────────│  │ Tax (6%):      $5.64  │  ║
║  │ 2. Slim Fit Chinos          $46  │  │                       │  ║
║  │    Size: 32 | Color: Khaki       │  │ ─────────────────────  │  ║
║  │    Qty: 1         [-] [+]   $46  │  │                       │  ║
║  │                           [DEL]  │  │ TOTAL:        $99.64  │  ║
║  │ ─────────────────────────────────│  │                       │  ║
║  │                                  │  │                       │  ║
║  │                                  │  └───────────────────────┘  ║
║  │                                  │                             ║
║  │                                  │  ┌───────────────────────┐  ║
║  │                                  │  │ [DISCOUNT]  [HOLD]    │  ║
║  │                                  │  │                       │  ║
║  │                                  │  │ [CUSTOMER]  [VOID]    │  ║
║  │                                  │  │                       │  ║
║  └──────────────────────────────────┘  │ ┌───────────────────┐ │  ║
║                                        │ │                   │ │  ║
║  ┌──────────────────────────────────┐  │ │      PAY          │ │  ║
║  │ Customer: John Smith             │  │ │     $99.64        │ │  ║
║  │ Loyalty: Gold (2,450 pts)        │  │ │                   │ │  ║
║  │ [Remove Customer]                │  │ └───────────────────┘ │  ║
║  └──────────────────────────────────┘  └───────────────────────┘  ║
║                                                                    ║
╠════════════════════════════════════════════════════════════════════╣
║ [F1 Help] [F2 Lookup] [F3 Returns] [F4 Reports]  ● Online  Rcpt#42 ║
╚════════════════════════════════════════════════════════════════════╝

Layout Regions:

RegionWidthContent
Header100%Store, associate, date/time
Search Bar100%SKU/barcode entry with search
Cart Panel60%Line items with quantity controls
Totals Panel40%Running totals, discounts, tax
Action Buttons40%Discount, Hold, Customer, Void
Pay Button40%Large, prominent payment trigger
Customer Info60%Attached customer details
Footer100%Function keys, status, receipt #

Cart Item Layout:

┌─────────────────────────────────────────────────────────────┐
│ 1. Galaxy V-Neck Tee                                   $29  │
│    Size: M | Color: Navy                                    │
│    Qty: 2                  [-] [+]                     $58  │
│                                                      [DEL]  │
└─────────────────────────────────────────────────────────────┘

Keyboard Shortcuts:

KeyAction
F1Help overlay
F2Product lookup
F3Returns mode
F4Quick reports
F5Price check
F8Suspend sale
F9Recall sale
F12Manager functions
EnterAdd scanned item
EscCancel current action

Screen 3: Customer Lookup

Purpose: Find or create customer records for loyalty tracking.

Route: /customer-lookup (Modal overlay)

╔════════════════════════════════════════════════════════════════════╗
║ CUSTOMER LOOKUP                                              [X]   ║
╠════════════════════════════════════════════════════════════════════╣
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ [Search by name, phone, email, or loyalty #...]              │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ RESULTS (3 found)                                            │ ║
║  ├──────────────────────────────────────────────────────────────┤ ║
║  │                                                              │ ║
║  │  ○ John Smith                                                │ ║
║  │    Phone: (555) 123-4567                                     │ ║
║  │    Email: john.smith@email.com                               │ ║
║  │    Loyalty: Gold (2,450 pts)  |  Last Visit: 12/15/2024     │ ║
║  │                                                              │ ║
║  │  ───────────────────────────────────────────────────────────  │ ║
║  │                                                              │ ║
║  │  ○ Johnny Smith Jr.                                          │ ║
║  │    Phone: (555) 234-5678                                     │ ║
║  │    Email: johnny.jr@email.com                                │ ║
║  │    Loyalty: Silver (890 pts)  |  Last Visit: 11/20/2024     │ ║
║  │                                                              │ ║
║  │  ───────────────────────────────────────────────────────────  │ ║
║  │                                                              │ ║
║  │  ○ Jonathan Smithson                                         │ ║
║  │    Phone: (555) 345-6789                                     │ ║
║  │    Email: j.smithson@work.com                                │ ║
║  │    Loyalty: None  |  Last Visit: 10/05/2024                 │ ║
║  │                                                              │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌────────────────────────────────────────────────────────────────╢
║  │                                                                ║
║  │  [NEW CUSTOMER]                      [SELECT]   [CANCEL]       ║
║  │                                                                ║
║  └────────────────────────────────────────────────────────────────╢
╚════════════════════════════════════════════════════════════════════╝

New Customer Form:

╔════════════════════════════════════════════════════════════════════╗
║ NEW CUSTOMER                                                 [X]   ║
╠════════════════════════════════════════════════════════════════════╣
║                                                                    ║
║  First Name *         Last Name *                                  ║
║  ┌──────────────────┐ ┌──────────────────────────────────────────┐ ║
║  │ John             │ │ Smith                                    │ ║
║  └──────────────────┘ └──────────────────────────────────────────┘ ║
║                                                                    ║
║  Phone *                        Email                              ║
║  ┌──────────────────────────┐   ┌────────────────────────────────┐ ║
║  │ (555) 123-4567           │   │ john.smith@email.com           │ ║
║  └──────────────────────────┘   └────────────────────────────────┘ ║
║                                                                    ║
║  Address Line 1                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ 123 Main Street                                              │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  City                    State        ZIP                          ║
║  ┌────────────────────┐  ┌─────────┐  ┌───────────────────────────┐║
║  │ Virginia Beach     │  │ VA    ▼ │  │ 23451                     │║
║  └────────────────────┘  └─────────┘  └───────────────────────────┘║
║                                                                    ║
║  [ ] Enroll in Loyalty Program                                     ║
║  [ ] Subscribe to email marketing                                  ║
║                                                                    ║
║  ┌────────────────────────────────────────────────────────────────╢
║  │                                                                ║
║  │                                        [SAVE]   [CANCEL]       ║
║  │                                                                ║
║  └────────────────────────────────────────────────────────────────╢
╚════════════════════════════════════════════════════════════════════╝

Screen 4: Returns Processing

Purpose: Process merchandise returns and exchanges.

Route: /returns

╔════════════════════════════════════════════════════════════════════╗
║ RETURNS PROCESSING                                    [Exit Return]║
╠════════════════════════════════════════════════════════════════════╣
║                                                                    ║
║  STEP 1: FIND ORIGINAL TRANSACTION                                 ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ Receipt #: [________________]  OR  [Lookup by Customer]      │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ ORIGINAL TRANSACTION #12345                  12/20/2024      │ ║
║  ├──────────────────────────────────────────────────────────────┤ ║
║  │ Customer: John Smith                                         │ ║
║  │ Payment: Visa ****4242                                       │ ║
║  ├──────────────────────────────────────────────────────────────┤ ║
║  │                                                              │ ║
║  │  [x] 1. Galaxy V-Neck Tee (M, Navy)             $29.00       │ ║
║  │      Reason: [Wrong Size           ▼]                        │ ║
║  │      Condition: [Good - Resellable ▼]                        │ ║
║  │                                                              │ ║
║  │  [ ] 2. Slim Fit Chinos (32, Khaki)             $46.00       │ ║
║  │                                                              │ ║
║  │  [ ] 3. Leather Belt (M)                        $35.00       │ ║
║  │                                                              │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌────────────────────────┐  ┌───────────────────────────────────┐║
║  │ RETURN SUMMARY         │  │ REFUND TO                         │║
║  ├────────────────────────┤  ├───────────────────────────────────┤║
║  │ Items: 1               │  │ ○ Original Payment (Visa ****42)  │║
║  │ Subtotal: $29.00       │  │ ○ Store Credit                    │║
║  │ Tax Refund: $1.74      │  │ ○ Cash                            │║
║  │ ──────────────────     │  │ ○ Exchange (Add to New Sale)      │║
║  │ TOTAL: $30.74          │  │                                   │║
║  └────────────────────────┘  └───────────────────────────────────┘║
║                                                                    ║
║  Manager Approval Required: [ ] Over $100  [ ] No Receipt         ║
║                                                                    ║
║  ┌────────────────────────────────────────────────────────────────╢
║  │                                                                ║
║  │  [SCAN RETURN ITEMS]              [PROCESS RETURN]  [CANCEL]   ║
║  │                                                                ║
║  └────────────────────────────────────────────────────────────────╢
╚════════════════════════════════════════════════════════════════════╝

Return Reasons (Configurable):

  • Wrong Size
  • Wrong Color
  • Defective
  • Changed Mind
  • Gift Return
  • Price Adjustment
  • Other

Return Conditions:

  • Good - Resellable
  • Damaged - Cannot Resell
  • Missing Tags - Markdown

Screen 5: Inventory Lookup

Purpose: Check stock levels across all locations.

Route: /inventory (Modal overlay)

╔════════════════════════════════════════════════════════════════════╗
║ INVENTORY LOOKUP                                             [X]   ║
╠════════════════════════════════════════════════════════════════════╣
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ [Search by SKU, name, or scan barcode...]            [SEARCH]│ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │                                                              │ ║
║  │  Galaxy V-Neck Tee                                   $29.00  │ ║
║  │  SKU: NXJ1078-NAV-M                                          │ ║
║  │  ────────────────────────────────────────────────────────────│ ║
║  │                                                              │ ║
║  │  VARIANTS:                                                   │ ║
║  │  ┌────────────┬─────┬─────┬─────┬─────┬─────┬───────┐       │ ║
║  │  │ Size/Color │  HQ │  GM │  HM │  LM │  NM │ TOTAL │       │ ║
║  │  ├────────────┼─────┼─────┼─────┼─────┼─────┼───────┤       │ ║
║  │  │ S / Navy   │  12 │   3 │   2 │   4 │   1 │    22 │       │ ║
║  │  │ M / Navy   │  15 │   5*│   3 │   2 │   0 │    25 │       │ ║
║  │  │ L / Navy   │   8 │   4 │   1 │   3 │   2 │    18 │       │ ║
║  │  │ XL / Navy  │   4 │   2 │   0 │   1 │   1 │     8 │       │ ║
║  │  │ S / Black  │  10 │   2 │   3 │   2 │   2 │    19 │       │ ║
║  │  │ M / Black  │  18 │   6 │   4 │   5 │   3 │    36 │       │ ║
║  │  └────────────┴─────┴─────┴─────┴─────┴─────┴───────┘       │ ║
║  │                                                              │ ║
║  │  * Current Location (GM)                                     │ ║
║  │                                                              │ ║
║  │  Last Updated: 12/29/2024 2:30 PM                           │ ║
║  │                                                              │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌────────────────────────────────────────────────────────────────╢
║  │                                                                ║
║  │  [REQUEST TRANSFER]    [PRICE CHECK]           [CLOSE]         ║
║  │                                                                ║
║  └────────────────────────────────────────────────────────────────╢
╚════════════════════════════════════════════════════════════════════╝

Screen 6: End of Day

Purpose: Close register, balance cash, generate reports.

Route: /end-of-day

╔════════════════════════════════════════════════════════════════════╗
║ END OF DAY - Close Register                              [Cancel]  ║
╠════════════════════════════════════════════════════════════════════╣
║                                                                    ║
║  Register: REGISTER-01 (GM)              Date: 12/29/2024          ║
║  Cashier: Sarah Miller                   Shift: 9:00 AM - 5:30 PM  ║
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ SALES SUMMARY                                                │ ║
║  ├──────────────────────────────────────────────────────────────┤ ║
║  │                                                              │ ║
║  │  Total Transactions:            47                           │ ║
║  │  Gross Sales:               $3,245.67                        │ ║
║  │  Returns:                     -$125.00                       │ ║
║  │  Discounts:                   -$89.50                        │ ║
║  │  ──────────────────────────────────────                      │ ║
║  │  Net Sales:                 $3,031.17                        │ ║
║  │  Tax Collected:               $181.87                        │ ║
║  │                                                              │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ CASH COUNT                                                   │ ║
║  ├──────────────────────────────────────────────────────────────┤ ║
║  │                                                              │ ║
║  │  Starting Cash:      $200.00                                 │ ║
║  │  Cash Sales:         $845.50                                 │ ║
║  │  Cash Returns:       -$45.00                                 │ ║
║  │  ──────────────────────────────────────                      │ ║
║  │  Expected Cash:    $1,000.50                                 │ ║
║  │                                                              │ ║
║  │  Counted Cash:     [_______________]  <-- Enter amount       │ ║
║  │                                                              │ ║
║  │  Variance:         $___.__ (Calculates automatically)        │ ║
║  │                                                              │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌──────────────────────────────────────────────────────────────┐ ║
║  │ PAYMENT BREAKDOWN                                            │ ║
║  ├──────────────────────────────────────────────────────────────┤ ║
║  │  Cash:                  $845.50   (28 trans)                 │ ║
║  │  Credit Card:         $1,856.32   (15 trans)                 │ ║
║  │  Debit Card:            $254.35   (3 trans)                  │ ║
║  │  Store Credit:           $75.00   (1 trans)                  │ ║
║  └──────────────────────────────────────────────────────────────┘ ║
║                                                                    ║
║  ┌────────────────────────────────────────────────────────────────╢
║  │                                                                ║
║  │  [PRINT REPORT]  [RECOUNT]           [CLOSE REGISTER]          ║
║  │                                                                ║
║  └────────────────────────────────────────────────────────────────╢
╚════════════════════════════════════════════════════════════════════╝

Payment Screen

Purpose: Process various payment methods.

╔════════════════════════════════════════════════════════════════════╗
║ PAYMENT                                                      [X]   ║
╠════════════════════════════════════════════════════════════════════╣
║                                                                    ║
║                    AMOUNT DUE: $99.64                              ║
║                                                                    ║
║  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐    ║
║  │                 │  │                 │  │                 │    ║
║  │   [CREDIT]      │  │   [DEBIT]       │  │   [CASH]        │    ║
║  │      CARD       │  │     CARD        │  │                 │    ║
║  │                 │  │                 │  │                 │    ║
║  └─────────────────┘  └─────────────────┘  └─────────────────┘    ║
║                                                                    ║
║  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐    ║
║  │                 │  │                 │  │                 │    ║
║  │   [GIFT]        │  │   [STORE]       │  │   [SPLIT]       │    ║
║  │    CARD         │  │   CREDIT        │  │   PAYMENT       │    ║
║  │                 │  │                 │  │                 │    ║
║  └─────────────────┘  └─────────────────┘  └─────────────────┘    ║
║                                                                    ║
║  ═══════════════════════════════════════════════════════════════  ║
║                                                                    ║
║  CASH QUICK AMOUNTS:                                               ║
║                                                                    ║
║  ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐     ║
║  │  $20  │ │  $50  │ │ $100  │ │ $120  │ │ EXACT │ │ OTHER │     ║
║  └───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └───────┘     ║
║                                                                    ║
║                    Amount Tendered: $________                      ║
║                    Change Due:      $________                      ║
║                                                                    ║
║  ┌────────────────────────────────────────────────────────────────╢
║  │                                                                ║
║  │                                        [PROCESS]   [CANCEL]    ║
║  │                                                                ║
║  └────────────────────────────────────────────────────────────────╢
╚════════════════════════════════════════════════════════════════════╝

State Management

Application State Model

public class PosState
{
    // Authentication
    public AuthState Auth { get; set; }

    // Current Transaction
    public TransactionState Transaction { get; set; }

    // Cart Items
    public List<CartItem> Cart { get; set; }

    // Customer
    public CustomerState Customer { get; set; }

    // Register
    public RegisterState Register { get; set; }

    // Sync Status
    public SyncState Sync { get; set; }

    // UI State
    public UiState Ui { get; set; }
}

public class TransactionState
{
    public string TransactionId { get; set; }
    public TransactionType Type { get; set; }  // Sale, Return, Exchange
    public TransactionStatus Status { get; set; }
    public decimal Subtotal { get; set; }
    public decimal DiscountTotal { get; set; }
    public decimal TaxTotal { get; set; }
    public decimal GrandTotal { get; set; }
    public List<PaymentEntry> Payments { get; set; }
    public decimal BalanceDue { get; set; }
}

State Actions

ActionDescription
AddToCartAdd item with quantity
UpdateQuantityChange line item quantity
RemoveFromCartDelete line item
ApplyDiscountAdd transaction/line discount
AttachCustomerLink customer to sale
ProcessPaymentRecord payment entry
VoidTransactionCancel entire transaction
SuspendSalePark sale for later
RecallSaleResume suspended sale

Sync Service Design

Sync Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                        SYNC ENGINE                                   │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐            │
│  │   OUTBOUND  │     │   INBOUND   │     │   CONFLICT  │            │
│  │    QUEUE    │────▶│   HANDLER   │────▶│   RESOLVER  │            │
│  │ (SQLite)    │     │  (API Sync) │     │             │            │
│  └─────────────┘     └─────────────┘     └─────────────┘            │
│         │                   │                   │                    │
│         ▼                   ▼                   ▼                    │
│  ┌─────────────────────────────────────────────────────┐            │
│  │              LOCAL SQLITE DATABASE                   │            │
│  │  - Transactions (pending sync)                       │            │
│  │  - Products (cached catalog)                         │            │
│  │  - Customers (cached records)                        │            │
│  │  - Inventory (last known levels)                     │            │
│  │  - Sync metadata (timestamps, versions)              │            │
│  └─────────────────────────────────────────────────────┘            │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Sync Priorities

PriorityData TypeFrequencyDirection
1 (Critical)TransactionsImmediateOutbound
2 (High)Inventory Changes5 minBoth
3 (Medium)Customers15 minBoth
4 (Low)Products1 hourInbound
5 (Batch)ReportsDailyOutbound

Offline Queue Schema

CREATE TABLE sync_queue (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    entity_type TEXT NOT NULL,       -- 'transaction', 'customer', etc.
    entity_id TEXT NOT NULL,
    action TEXT NOT NULL,            -- 'create', 'update', 'delete'
    payload TEXT NOT NULL,           -- JSON serialized data
    priority INTEGER DEFAULT 5,
    retry_count INTEGER DEFAULT 0,
    created_at TEXT NOT NULL,
    last_attempt TEXT,
    status TEXT DEFAULT 'pending'    -- 'pending', 'syncing', 'failed', 'synced'
);

CREATE INDEX idx_sync_queue_status ON sync_queue(status, priority);

Hardware Integration

Receipt Printer

public interface IReceiptPrinter
{
    Task<bool> PrintReceiptAsync(Receipt receipt);
    Task<bool> OpenCashDrawerAsync();
    Task<bool> CutPaperAsync();
    Task<PrinterStatus> GetStatusAsync();
}

public class EpsonTM88Printer : IReceiptPrinter
{
    private readonly string _portName;

    public async Task<bool> PrintReceiptAsync(Receipt receipt)
    {
        var commands = new List<byte>();

        // Initialize printer
        commands.AddRange(new byte[] { 0x1B, 0x40 });  // ESC @

        // Center align
        commands.AddRange(new byte[] { 0x1B, 0x61, 0x01 });  // ESC a 1

        // Store header (double width/height)
        commands.AddRange(new byte[] { 0x1D, 0x21, 0x11 });  // GS ! 0x11
        commands.AddRange(Encoding.ASCII.GetBytes(receipt.StoreName + "\n"));

        // Reset text size
        commands.AddRange(new byte[] { 0x1D, 0x21, 0x00 });

        // ... additional formatting

        // Cut paper
        commands.AddRange(new byte[] { 0x1D, 0x56, 0x00 });  // GS V 0

        return await SendToPortAsync(commands.ToArray());
    }
}

Barcode Scanner

public interface IBarcodeScanner
{
    event EventHandler<BarcodeScannedEventArgs> BarcodeScanned;
    Task StartListeningAsync();
    Task StopListeningAsync();
}

public class HoneywellScanner : IBarcodeScanner
{
    public event EventHandler<BarcodeScannedEventArgs> BarcodeScanned;

    private SerialPort _port;

    public async Task StartListeningAsync()
    {
        _port = new SerialPort("COM3", 9600);
        _port.DataReceived += OnDataReceived;
        _port.Open();
    }

    private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        var barcode = _port.ReadLine().Trim();
        BarcodeScanned?.Invoke(this, new BarcodeScannedEventArgs(barcode));
    }
}

Cash Drawer

public interface ICashDrawer
{
    Task<bool> OpenAsync();
    Task<bool> IsOpenAsync();
}

public class ApgCashDrawer : ICashDrawer
{
    private readonly IReceiptPrinter _printer;

    public async Task<bool> OpenAsync()
    {
        // Most cash drawers open via printer kick command
        return await _printer.OpenCashDrawerAsync();
    }
}

Local Database Schema

-- Products (cached from central)
CREATE TABLE products (
    id TEXT PRIMARY KEY,
    sku TEXT NOT NULL UNIQUE,
    barcode TEXT,
    name TEXT NOT NULL,
    description TEXT,
    price REAL NOT NULL,
    cost REAL,
    category_id TEXT,
    tax_rate REAL DEFAULT 0,
    is_active INTEGER DEFAULT 1,
    last_synced TEXT NOT NULL
);

-- Inventory (cached levels)
CREATE TABLE inventory (
    product_id TEXT NOT NULL,
    location_code TEXT NOT NULL,
    quantity INTEGER NOT NULL,
    last_synced TEXT NOT NULL,
    PRIMARY KEY (product_id, location_code)
);

-- Customers (cached)
CREATE TABLE customers (
    id TEXT PRIMARY KEY,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL,
    phone TEXT,
    email TEXT,
    loyalty_tier TEXT,
    loyalty_points INTEGER DEFAULT 0,
    last_synced TEXT NOT NULL
);

-- Transactions (local first, then synced)
CREATE TABLE transactions (
    id TEXT PRIMARY KEY,
    transaction_number INTEGER NOT NULL,
    type TEXT NOT NULL,
    status TEXT NOT NULL,
    customer_id TEXT,
    associate_id TEXT NOT NULL,
    register_id TEXT NOT NULL,
    subtotal REAL NOT NULL,
    discount_total REAL DEFAULT 0,
    tax_total REAL NOT NULL,
    grand_total REAL NOT NULL,
    created_at TEXT NOT NULL,
    completed_at TEXT,
    synced_at TEXT,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

-- Transaction Line Items
CREATE TABLE transaction_items (
    id TEXT PRIMARY KEY,
    transaction_id TEXT NOT NULL,
    product_id TEXT NOT NULL,
    sku TEXT NOT NULL,
    name TEXT NOT NULL,
    quantity INTEGER NOT NULL,
    unit_price REAL NOT NULL,
    discount REAL DEFAULT 0,
    tax_amount REAL NOT NULL,
    line_total REAL NOT NULL,
    FOREIGN KEY (transaction_id) REFERENCES transactions(id)
);

-- Payments
CREATE TABLE payments (
    id TEXT PRIMARY KEY,
    transaction_id TEXT NOT NULL,
    method TEXT NOT NULL,
    amount REAL NOT NULL,
    reference TEXT,
    created_at TEXT NOT NULL,
    FOREIGN KEY (transaction_id) REFERENCES transactions(id)
);

Performance Requirements

MetricTargetMeasurement
App Launch< 3 secondsCold start to login screen
Item Scan< 100msBarcode to cart display
Product Search< 200msKeystroke to results
Payment Process< 2 secondsButton tap to receipt
Offline SwitchInstantSeamless transition
Sync Latency< 5 secondsTransaction to central

Security Considerations

ConcernMitigation
PIN StorageHashed with bcrypt, salted
Local DBSQLCipher encryption
API TokensSecure storage (Keychain/DPAPI)
PCI ComplianceNo card data stored locally
Session TimeoutAuto-logout after inactivity
Audit TrailAll actions logged with timestamp

Role-Based Interface (Learned from Lightspeed)

Competitive Insight: Lightspeed separates Cashier and Manager views to reduce cognitive load. Cashiers see only what they need; managers have full access.

Cashier Mode vs Manager Mode

┌─────────────────────────────────────────────────────────────────────────┐
│                        ROLE-BASED UI SPLIT                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  CASHIER MODE                         MANAGER MODE                       │
│  ┌─────────────────────────┐          ┌─────────────────────────┐       │
│  │ • Sales Screen          │          │ • Full Dashboard        │       │
│  │ • Customer Lookup       │          │ • All Cashier Features  │       │
│  │ • Basic Returns         │          │ • Inventory Adjustments │       │
│  │ • Receipt Reprint       │          │ • Employee Management   │       │
│  │ • Price Check           │          │ • Reports & Analytics   │       │
│  │                         │          │ • System Settings       │       │
│  │ [Simplified Navigation] │          │ • Void/Override Powers  │       │
│  │ [Large Touch Targets]   │          │ • Cash Drawer Access    │       │
│  └─────────────────────────┘          │ • End of Day Close      │       │
│                                       └─────────────────────────┘       │
│                                                                          │
│  [Switch to Manager Mode] ─────────────────────────> [PIN Required]     │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Mode Switch Behavior

public class RoleModeService
{
    private UserRole _currentRole = UserRole.Cashier;

    public async Task<bool> SwitchToManagerMode(string managerPin)
    {
        var isValid = await _authService.ValidateManagerPin(managerPin);
        if (isValid)
        {
            _currentRole = UserRole.Manager;
            _auditLog.Log("MODE_SWITCH", "Switched to Manager mode");
            return true;
        }
        return false;
    }

    public void SwitchToCashierMode()
    {
        _currentRole = UserRole.Cashier;
        _auditLog.Log("MODE_SWITCH", "Switched to Cashier mode");
    }

    public bool CanAccess(string feature) => _rolePermissions[_currentRole].Contains(feature);
}

Actions Requiring Manager Override

ActionCashier Can DoManager PIN Required
Ring sale-
Apply discount > 20%
Void transaction
Return without receipt
Open cash drawer (no sale)
Price override
View reports
End of day close

View Preferences (Learned from Lightspeed)

Competitive Insight: Lightspeed offers Grid/List toggle and Dark Mode. Users have different preferences - some like images, some prefer text density.

Product Display Options

┌─────────────────────────────────────────────────────────────────────────┐
│ Products    [Grid ▣] [List ≡]    [🌙 Dark Mode]                         │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  GRID VIEW (Default)                  LIST VIEW                          │
│  ┌───────┐ ┌───────┐ ┌───────┐       ┌─────────────────────────────────┐│
│  │ [IMG] │ │ [IMG] │ │ [IMG] │       │ 👕 Galaxy Tee - Navy - $29  [+] ││
│  │ Tee   │ │ Pants │ │ Jacket│       │ 👖 Slim Chinos - Khaki - $46[+] ││
│  │ $29   │ │ $46   │ │ $89   │       │ 🧥 Bomber Jacket - $89      [+] ││
│  │  [+]  │ │  [+]  │ │  [+]  │       │ 👔 Oxford Shirt - $55       [+] ││
│  └───────┘ └───────┘ └───────┘       └─────────────────────────────────┘│
│                                                                          │
│  Best for: Visual products           Best for: High SKU count            │
│  Use when: Fashion, gifts            Use when: Hardware, parts           │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Dark Mode Support

┌─────────────────────────────────────────────────────────────────────────┐
│                          THEME MODES                                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  LIGHT MODE (Default)                 DARK MODE                          │
│  ┌─────────────────────────┐          ┌─────────────────────────┐       │
│  │ Background: #FFFFFF     │          │ Background: #1a1a2e     │       │
│  │ Text: #1f2937           │          │ Text: #f3f4f6           │       │
│  │ Primary: #4f46e5        │          │ Primary: #818cf8        │       │
│  │ Cards: #f9fafb          │          │ Cards: #16213e          │       │
│  │ Borders: #e5e7eb        │          │ Borders: #374151        │       │
│  └─────────────────────────┘          └─────────────────────────┘       │
│                                                                          │
│  Benefits:                            Benefits:                          │
│  • Standard retail look               • Reduces eye strain (long shifts) │
│  • Better in bright stores            • Better for low-light stores      │
│  • Matches receipts                   • Saves battery (OLED screens)     │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

User Preferences Storage

public class UserPreferences
{
    public string EmployeeId { get; set; }
    public ViewMode ProductViewMode { get; set; } = ViewMode.Grid;
    public ThemeMode Theme { get; set; } = ThemeMode.Light;
    public int GridColumnsCount { get; set; } = 4;
    public bool ShowProductImages { get; set; } = true;
    public bool ShowQuickAccessBar { get; set; } = true;
    public List<string> FavoriteProducts { get; set; } = new();
    public string DefaultCategory { get; set; }
}

public enum ViewMode { Grid, List }
public enum ThemeMode { Light, Dark, System }

Quick Access Layout Editor (Learned from Lightspeed)

Competitive Insight: Lightspeed lets managers arrange product buttons visually. Frequently sold items get prime positions.

Layout Editor Screen

╔════════════════════════════════════════════════════════════════════╗
║ QUICK ACCESS LAYOUT EDITOR                        [Save] [Cancel]   ║
╠════════════════════════════════════════════════════════════════════╣
║                                                                     ║
║  QUICK ACCESS BAR (Drag to arrange)                                ║
║  ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐     ║
║  │ Galaxy  │ Slim    │ Bomber  │ Gift    │ Bag     │ [Empty] │     ║
║  │ Tee     │ Chinos  │ Jacket  │ Card    │ Small   │  [+]    │     ║
║  │ $29     │ $46     │ $89     │ $25+    │ $3      │         │     ║
║  └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘     ║
║                                                                     ║
║  AVAILABLE PRODUCTS (Drag to Quick Access bar above)               ║
║  ┌──────────────────────────────────────────────────────────────┐  ║
║  │ Search: [_______________]  Category: [All        ▼]          │  ║
║  ├──────────────────────────────────────────────────────────────┤  ║
║  │                                                               │  ║
║  │  ⬚ Oxford Shirt     ⬚ Crew Neck       ⬚ Cargo Pants          │  ║
║  │  ⬚ Polo Classic     ⬚ Denim Jacket    ⬚ Belt Leather         │  ║
║  │  ⬚ Hoodie Basic     ⬚ V-Neck Tee      ⬚ Socks 3-Pack         │  ║
║  │                                                               │  ║
║  └──────────────────────────────────────────────────────────────┘  ║
║                                                                     ║
║  Layout applies to: ○ This register only  ● All registers at GM    ║
║                                                                     ║
╚════════════════════════════════════════════════════════════════════╝

Quick Access Data Model

public class QuickAccessLayout
{
    public string Id { get; set; }
    public string TenantId { get; set; }
    public string LocationId { get; set; }       // null = all locations
    public string RegisterId { get; set; }       // null = all registers
    public List<QuickAccessSlot> Slots { get; set; } = new();
    public DateTime UpdatedAt { get; set; }
    public string UpdatedBy { get; set; }
}

public class QuickAccessSlot
{
    public int Position { get; set; }           // 0-11 (2 rows of 6)
    public string ItemId { get; set; }
    public string CustomLabel { get; set; }     // Override display name
    public string CustomColor { get; set; }     // Button color (#hex)
}

Quick Access Display

┌─────────────────────────────────────────────────────────────────────────┐
│ QUICK ACCESS                                                     [Edit] │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌────────┐ │
│  │ #6366f1 │ │ #10b981 │ │ #f59e0b │ │ #ef4444 │ │ #8b5cf6 │ │ #ec4899│ │
│  │ Galaxy  │ │ Slim    │ │ Bomber  │ │ Gift    │ │ Bag     │ │ Hoodie │ │
│  │ Tee     │ │ Chinos  │ │ Jacket  │ │ Card    │ │ Small   │ │        │ │
│  │ $29     │ │ $46     │ │ $89     │ │ $25+    │ │ $3      │ │ $55    │ │
│  └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └────────┘ │
│                                                                          │
│  One-tap access to best sellers. Manager can customize via [Edit].      │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Summary

The POS Client Application is designed for:

  1. Speed: Sub-second response times for all common operations
  2. Reliability: Full offline capability with automatic sync
  3. Usability: Touch-friendly, keyboard shortcuts, minimal training
  4. Security: PIN auth, encrypted storage, audit logging
  5. Integration: Hardware support for printers, scanners, drawers
  6. Role-Based UI: Simplified Cashier mode, full Manager mode (Lightspeed insight)
  7. Personalization: Grid/List toggle, Dark mode, Quick Access layout (Lightspeed insight)

Competitive Feature Matrix

FeatureOur POSRetail ProLightspeed
Offline Mode✅ Full✅ Full❌ None
Role-Based UI✅ Yes✅ Yes✅ Yes
Dark Mode✅ Yes❌ No✅ Yes
Grid/List Toggle✅ Yes❌ No✅ Yes
Quick Access Editor✅ Yes✅ Yes✅ Yes
Keyboard Shortcuts✅ F1-F12✅ Full⚠️ Limited
PIN Login✅ Yes✅ Yes✅ Yes
Manager Override✅ Yes✅ Yes✅ Yes

Implementation complete. Ready for engineer review.