Skip to content

Customers

The Customers page (/point-of-sale/customers) provides customer lookup and management at the lane, including loyalty points, membership status, and quick customer creation.

Customers List

┌──────────────────────────────────────────────────────────┐
│ Add customer | Search | Sync catalog │
├──────────────────────────────────────────────────────────┤
│ Status tabs: All | Active | Blocked | Pending │
├──────────────────────────────────────────────────────────┤
│ Customers table │
│ - Avatar | Name | Email | Phone | Location │
│ - Orders | Membership | Loyalty points | Revenue │
│ - Status badge │
└──────────────────────────────────────────────────────────┘

Opens customer creation modal:

  1. Click “Add customer” (blue button with user-add icon)
  2. Fill form:
    • Name (required)
    • Email (optional, must be unique if provided)
    • Phone (optional)
    • Address fields
    • Retail login (optional — enables customer portal access)
  3. Submit → Customer created, appears in list
  • Searches: Name, email, phone
  • Debounced 350ms
  • Clears on focus loss if empty
  • Matches partial strings (case-insensitive)

Force refresh customer data from server:

  • Click sync icon → fetches latest customer list
  • Background sync runs automatically when online
TabShows
AllAll customers regardless of status
Activestatus = "active" — can place orders
Blockedstatus = "blocked" — cannot place orders (debt, fraud, etc.)
Pendingstatus = "pending" — awaiting approval or verification

Click tab to filter, selection persists in URL param ?tab=<status>.

ColumnContentNotes
CustomerAvatar + name + emailAvatar uses fallback generator if no image
PhoneContact phoneShows ”—” if empty
LocationAddress/citySimplified display
OrdersOrder countLifetime total
MembershipMembership tier name”—” if none
LoyaltyPoints balanceFormatted as whole number
RevenueTotal spentOnly visible if allowViewCustomerRevenue = true in store config
StatusStatus badgeColored pill (green=active, red=blocked, yellow=pending)

Revenue column appears only when store configuration enables allowViewCustomerRevenue:

  • Enabled: Shows total customer spending (formatted currency)
  • Disabled: Column hidden entirely

Controlled by storeConfigurationPosFlagsFromSnapshot(configuration).allowViewCustomerRevenue.

Opens customer detail modal showing:

  • Full contact info
  • Order history summary
  • Loyalty points + membership details
  • Revenue (if enabled)
  • Recent orders (last 5)

Modal is read-only in POS workspace. To edit customer, must use Dashboard → Customers.

Profile:

  • Name, email, phone
  • Address (full)
  • Date created
  • Customer ID (for support)

Loyalty & Membership:

  • Current points balance
  • Points earned / redeemed
  • Active membership tier
  • Membership expiry (if applicable)

Order stats:

  • Total orders
  • Total spent (if revenue visible)
  • Average order value
  • Last order date

Recent orders (expandable):

  • Last 5 orders with date, total, status
  • Click order → closes modal, opens order detail
  • Close — Dismiss modal
  • View full history — Navigate to Dashboard → Customers → Detail (if user has permission)

Required:

  • Name: Full customer name
  • Store: Pre-filled with selected store (locked for employees)

Optional:

  • Email: Must be unique across system
  • Phone: Mobile or landline
  • Address: Street, city, district, country
  • Notes: Internal notes (not visible to customer)
  • Retail login: Checkbox to enable customer portal access (requires email)

When enabled (enableOptionalRetailLogin = true):

  • Creates customer account on retail portal
  • Customer can view orders, loyalty points
  • Sends email invite with temporary password
  1. Validates form (Zod schema)
  2. API call: POST /vendor/customers with store_id
  3. Success → Toast message, modal closes, table refreshes
  4. Error → Shows validation errors inline
  • Default page size: 10 rows
  • Options: 10, 20, 50, 100
  • Jump to page: Type page number, press Enter
  • Total: Shows “X customers” at bottom

Pagination resets to page 1 when:

  • Search query changes
  • Status tab changes
  • Page size changes
  • Shows cached customer data immediately (if available)
  • Fetches fresh data in background
  • Merges fresh data when ready

Customers cached in:

  • Browser: IndexedDB (POS_LOCAL_CATALOG_CACHE_KEYS.customers)
  • Desktop: SQLite local database

Cache key: customers-<storeId>

When offline, amber banner appears:

  • “Viewing cached customer data (offline)”
  • Data may be stale if not recently synced

From sale workspace, select customer before checkout:

  1. Click “Select customer” in top toolbar
  2. Customer search modal opens (same component as this page)
  3. Search and select customer
  4. Customer linked to current cart
  5. On checkout, order associates with customer

Benefits of linking:

  • Loyalty points: Auto-applied, earn/redeem
  • Membership discounts: Applied if customer has active membership
  • Order history: Order appears in customer’s history
  • Debt tracking: If customer has credit terms
FlagEffect
allowViewCustomerRevenueShows/hides Revenue column in table
enableRetailLoginShows retail login checkbox in creation modal

Flags read from vendor_store_configuration via storeConfigurationPosFlagsFromSnapshot().

Missing permissions: Requires customer write Solution: Contact owner to grant permission

Cache stale: Click sync button to refresh Wrong store: Customer belongs to different store

Not an issue: Column hidden intentionally if store owner disabled allowViewCustomerRevenue