17 · Gift cards · loyalty · membership

Stored-value gift cards, points/rewards loyalty, and “membership” as loyalty tiers + customer CRM — not a third separate product. All of it ties into POS tenders and (for loyalty earn) finalize + customer on the cart.

Plan: gift_cards · loyalty POS tender giftcard + loyalty built Parallel route trees — prefer admin/programs + POS

How the three words relate

flowchart TB
  CRM[Customers CRM]
  GC[Gift cards
stored value liability] LOY[Loyalty program
points + rules] TIER[Tiers / membership levels
Bronze · Silver · Gold…] POS[POS cart] INV[Core Invoicing] CRM --> LOY LOY --> TIER GC -->|tender/giftcard| POS LOY -->|tender/loyalty redeem| POS POS -->|finalize + customerId| LOY POS --> INV CRM -.->|optional on card| GC
WordWhat it is in GPE
Gift cards Prepaid balance instruments (issue, reload, redeem, void). Liability reporting.
Loyalty Points program: earn rules, redeem as tender, accounts per customer.
Membership Not a separate app. UI language for loyalty tiers + being a known customer (CRM). Tier thresholds/perks live under Programs → Loyalty → Tiers.

Membership (how to think about it)

There is no standalone /membership product module “Members” are customers with a LoyaltyAccount (and optionally a tier name). Tiers are configured in admin as membership levels (points or spend thresholds, benefits JSON). Seat/visit theater “member knows their seat” is CRM + loyalty + future visit object — see DocHub 15 identity.
  • Customer — who they are (/customers, cart attach)
  • LoyaltyAccount — points, lifetimePoints, tierName, status, optional customerId/email/phone
  • Tier — program config (name, min spend/points, benefits)

Gift cards

Concepts

ConceptMeaning
Program settingsEnabled, reloadable, min/max issue/reload, expiry days, partial redeem, refunds-to-card
CardCode/number, balanceCents, status active/inactive/expired/redeemed/voided, optional customerId, batchId
BatchBulk issue of cards (admin batches UI)
TransactionsIssue / redeem / reload / adjust audit trail
LiabilityOutstanding balances report (/api/admin/programs/liability/giftcards or liability router)

Admin UI

Under /admin/programs/* with FeatureGate gift_cards (also wraps loyalty nav in the same programs shell).

  • /admin/programs/gift-cards — program overview
  • /admin/programs/gift-cards/issue — issue / batch create
  • /admin/programs/gift-cards/batches
  • /admin/programs/gift-cards/settings
  • Reports: sales gift cards

POS

  • Modern POS (and Standard): tender tab gift card → POST /api/pos/carts/:id/tender/giftcard
  • Looks up code, checks active/expiry, reduces balance, adds payment method giftcard
  • Then finalize like any other tender → Core Invoicing
  • Mobile POS — no gift card tender UI yet (parity gap; see DocHub 14)

Loyalty

Program configuration (admin)

UI pathConfig area
/admin/programs/loyalty · settingsProgram on/off, core settings
…/loyalty/rulesAccrual basis, include tax/tip, caps
…/loyalty/earningPoints per dollar / earning rules
…/loyalty/redemptionHow points convert to cents, min/step
…/loyalty/tiersMembership tiers — thresholds & perks

Admin API of record for UI: /api/admin/programs/loyalty and section routes /loyalty/tiers, /loyalty/earning, /loyalty/rules, /loyalty/redemption, /loyalty/settings (stored on LoyaltyProgram + metadata JSON).

Accounts & events

  • LoyaltyAccount — points balance, lifetime, tierName, link to customerId
  • LoyaltyEvent / POS-written events — earn/redeem history
  • loyaltyPoints.service.jscalculatePointsEarned, processTransactionLoyalty on finalize

POS integration (money path)

flowchart TD
  A[Attach customer on cart] --> B{Tender?}
  B -->|Gift code| C[tender/giftcard
debit gift_cards balance] B -->|Loyalty points| D[tender/loyalty
debit LoyaltyAccount points] B -->|Cash/card/crypto| E[other tenders] C --> F[payments[] on cart] D --> F E --> F F --> G[finalize] G --> H[Core Invoicing] G --> I[processTransactionLoyalty earn
if customerId + program]
StepAPIRequires
Redeem gift cardPOST …/tender/giftcard { code, amountCents? }Active card, balance
Redeem pointsPOST …/tender/loyalty { points, … }Customer + active loyalty account
Earn pointsInside finalize after invoicecustomerId on cart; program enabled
Identity link Loyalty earn/redeem are weak without a customer on the cart. Gift cards can work anonymously by code; optional customerId on issue for CRM.

Admin Programs hub

/admin/programs — FeatureGate currently keyed on gift_cards for the shell (loyalty pages live under the same layout).

Plan moduleIn planFeatures
gift_cardsPremium / Enterprise (category premium)
loyaltyPremium / Enterprise

Note: BASIC plan in config may not list them; verify live tenant plan flags before demos.

API map (what’s mounted)

MountRoleNotes
/api/admin/programs Admin gift + loyalty config, batches, check-balance, liability helpers Primary admin UI · gated gift_cards on mount
/api/giftcards Create, list, redeem, reload by code Session + tenant inside router · feature gift_cards
/api/giftcard issue / redeem / balance / adjust / void Alternate giftCard.routes · session
/api/loyalty grant, redeem, balance/:customerId Feature loyalty · grant path has TODO on full account update in one route
/api/pos/…/tender/giftcard|loyalty Checkout tenders Canonical for sales
giftCardManagement.routes · loyaltyManagement.routes Richer management APIs Present as files; not clearly dual-mounted as primary — prefer admin.programs + POS
/api/admin/liability Liability reads Outstanding gift/loyalty exposure

Debt, gaps, audit notes

ItemDetail
Parallel implementations Multiple gift/loyalty route + service + model pairs (Sequelize-era + SQL multi-tenant). Prefer one path when changing code.
Full E2E re-verify AUDIT deferred gift/loyalty deep re-trace (S9-5) — treat as “likely works via POS; re-verify before big promo.”
Mobile POS parity No gift/loyalty tender UI on MobilePOS
Grant API TODO POST /api/loyalty/grant comments that account balance update may only audit in that path — POS redeem/earn uses posQueries accounts
Programs FeatureGate Shell gated on gift_cards; loyalty-only tenants theoretically awkward
Membership product No paid “subscription membership” engine separate from loyalty tiers — if you need dues/subscriptions, that’s additional scope

File anchors

ConcernPath
Admin programs APIbackend/routes/admin.programs.routes.js
Gift cards APIgiftcards.routes.js · giftCard.routes.js · services giftCard*
Loyalty APIloyalty.routes.js · loyaltyPoints.service.js · loyaltyManagement*
ModelsgiftCard* · giftcardBatch · loyaltyProgram · loyaltyAccount · loyaltyEvent
POS tenders + earnpos.routes.js tender/giftcard, tender/loyalty, finalize processTransactionLoyalty
Admin UIfrontend/src/pages/admin/sections/programs/*
POS UIModernPOS gift/loyalty tabs · StandardPOS
OAO17-gift-cards.html · 18-loyalty.html

Related DocHub