Files
orion/app/modules/loyalty/docs/data-model.md
Samir Boulahtit f141cc4e6a docs: migrate module documentation to single source of truth
Move 39 documentation files from top-level docs/ into each module's
docs/ folder, accessible via symlinks from docs/modules/. Create
data-model.md files for 10 modules with full schema documentation.
Replace originals with redirect stubs. Remove empty guide stubs.

Modules migrated: tenancy, billing, loyalty, marketplace, orders,
messaging, cms, catalog, inventory, hosting, prospecting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 23:38:37 +01:00

10 KiB

Loyalty Data Model

Entity relationships and database schema for the loyalty module.

Entity Relationship Diagram

┌──────────────────────┐
│     Merchant         │ (from tenancy module)
│  (one program per    │
│   merchant)          │
└──────────┬───────────┘
           │ 1
           │
     ┌─────┴─────┐
     │            │
     ▼ 1          ▼ 1
┌──────────┐  ┌──────────────────────┐
│ Loyalty  │  │ MerchantLoyalty      │
│ Program  │  │ Settings             │
│          │  │                      │
│ type     │  │ staff_pin_policy     │
│ stamps   │  │ allow_self_enrollment│
│ points   │  │ allow_void           │
│ branding │  │ allow_cross_location │
│ anti-    │  │ require_order_ref    │
│ fraud    │  │ log_ip_addresses     │
└──┬───┬───┘  └──────────────────────┘
   │   │
   │   │ 1..*
   │   ▼
   │  ┌──────────────┐
   │  │  StaffPin     │
   │  │               │
   │  │  name         │
   │  │  pin_hash     │ (bcrypt)
   │  │  store_id     │
   │  │  failed_      │
   │  │  attempts     │
   │  │  locked_until │
   │  └──────────────┘
   │
   │ 1..*
   ▼
┌──────────────────┐       ┌──────────────────┐
│  LoyaltyCard     │       │  Customer        │ (from customers module)
│                  │ *───1 │                  │
│  card_number     │       └──────────────────┘
│  qr_code_data    │
│  stamp_count     │       ┌──────────────────┐
│  points_balance  │       │  Store           │ (from tenancy module)
│  google_object_id│ *───1 │  (enrolled_at)   │
│  apple_serial    │       └──────────────────┘
│  is_active       │
└──────┬───────────┘
       │
       │ 1..*
       ▼
┌──────────────────────┐
│ LoyaltyTransaction   │ (immutable audit log)
│                      │
│  transaction_type    │
│  stamps_delta        │ (signed: +1 earn, -N redeem)
│  points_delta        │ (signed: +N earn, -N redeem)
│  stamps_balance_after│
│  points_balance_after│
│  purchase_amount     │
│  staff_pin_id        │──── FK to StaffPin
│  store_id            │──── FK to Store (location)
│  related_txn_id      │──── FK to self (for voids)
│  ip_address          │
│  user_agent          │
└──────────────────────┘

┌──────────────────────────┐
│ AppleDeviceRegistration  │
│                          │
│  card_id                 │──── FK to LoyaltyCard
│  device_library_id       │
│  push_token              │
│                          │
│  UNIQUE(device, card)    │
└──────────────────────────┘

Models

LoyaltyProgram

Merchant-wide loyalty program configuration. One program per merchant, shared across all stores.

Field Type Description
merchant_id FK (unique) One program per merchant
loyalty_type Enum STAMPS, POINTS, or HYBRID
stamps_target Integer Stamps needed for reward
stamps_reward_description String Reward description text
stamps_reward_value_cents Integer Reward monetary value
points_per_euro Integer Points earned per euro spent
points_rewards JSON Reward catalog (id, name, points_cost)
points_expiration_days Integer Days until points expire (nullable)
welcome_bonus_points Integer Points given on enrollment
minimum_redemption_points Integer Minimum points to redeem
minimum_purchase_cents Integer Minimum purchase for earning
cooldown_minutes Integer Minutes between stamps (anti-fraud)
max_daily_stamps Integer Max stamps per card per day
require_staff_pin Boolean Whether PIN is required
card_name String Display name on card
card_color String Primary brand color (hex)
card_secondary_color String Secondary brand color (hex)
logo_url String Logo image URL
hero_image_url String Hero/banner image URL
google_issuer_id String Google Wallet issuer ID
google_class_id String Google Wallet class ID
apple_pass_type_id String Apple Wallet pass type identifier
terms_text Text Terms and conditions
privacy_url String Privacy policy URL
is_active Boolean Whether program is live
activated_at DateTime When program was activated

LoyaltyCard

Customer loyalty card linking a customer to a merchant's program. One card per customer per merchant.

Field Type Description
merchant_id FK Links to program's merchant
customer_id FK Card owner
program_id FK Associated program
enrolled_at_store_id FK Store where customer enrolled
card_number String (unique) Formatted XXXX-XXXX-XXXX
qr_code_data String (unique) URL-safe token for QR codes
stamp_count Integer Current stamp count
total_stamps_earned Integer Lifetime stamps earned
stamps_redeemed Integer Total redemptions
points_balance Integer Current points balance
total_points_earned Integer Lifetime points earned
points_redeemed Integer Total points redeemed
total_points_voided Integer Total points voided
google_object_id String Google Wallet object ID
google_object_jwt Text Google Wallet JWT
apple_serial_number String Apple Wallet serial number
apple_auth_token String Apple Wallet auth token
last_stamp_at DateTime Last stamp timestamp
last_points_at DateTime Last points timestamp
last_redemption_at DateTime Last redemption timestamp
last_activity_at DateTime Last activity of any kind
is_active Boolean Whether card is active

LoyaltyTransaction

Immutable audit log of all loyalty operations. Every stamp, point, redemption, and void is recorded.

Field Type Description
merchant_id FK Merchant program owner
card_id FK Affected card
store_id FK Store where transaction occurred
staff_pin_id FK (nullable) Staff who verified
related_transaction_id FK (nullable) For void/return linking
transaction_type Enum See transaction types below
stamps_delta Integer Signed stamp change
points_delta Integer Signed points change
stamps_balance_after Integer Stamp count after transaction
points_balance_after Integer Points balance after transaction
purchase_amount_cents Integer Purchase amount for points earning
order_reference String External order reference
reward_id String Redeemed reward identifier
reward_description String Redeemed reward description
ip_address String Client IP (audit)
user_agent String Client user agent (audit)
notes Text Staff/admin notes
transaction_at DateTime When transaction occurred

Transaction Types:

Type Category Description
STAMP_EARNED Stamps Customer earned a stamp
STAMP_REDEEMED Stamps Stamps exchanged for reward
STAMP_VOIDED Stamps Stamp reversed (return)
STAMP_ADJUSTMENT Stamps Manual adjustment
POINTS_EARNED Points Points from purchase
POINTS_REDEEMED Points Points exchanged for reward
POINTS_VOIDED Points Points reversed (return)
POINTS_ADJUSTMENT Points Manual adjustment
POINTS_EXPIRED Points Points expired due to inactivity
CARD_CREATED Lifecycle Card enrollment
CARD_DEACTIVATED Lifecycle Card deactivated
WELCOME_BONUS Bonus Welcome bonus points on enrollment

StaffPin

Staff authentication PINs for fraud prevention. Scoped to a store within a merchant's program.

Field Type Description
merchant_id FK Merchant
program_id FK Associated program
store_id FK Store this PIN is for
name String Staff member name
staff_id String External staff identifier
pin_hash String Bcrypt-hashed PIN
failed_attempts Integer Consecutive failed attempts
locked_until DateTime Lockout expiry (nullable)
last_used_at DateTime Last successful use
is_active Boolean Whether PIN is active

MerchantLoyaltySettings

Admin-controlled settings for a merchant's loyalty program. Separate from program config to allow admin overrides.

Field Type Description
merchant_id FK (unique) One settings record per merchant
staff_pin_policy Enum REQUIRED, OPTIONAL, or DISABLED
staff_pin_lockout_attempts Integer Failed attempts before lockout
staff_pin_lockout_minutes Integer Lockout duration
allow_self_enrollment Boolean Whether customers can self-enroll
allow_void_transactions Boolean Whether voids are allowed
allow_cross_location_redemption Boolean Cross-store redemption
require_order_reference Boolean Require order ref for points
log_ip_addresses Boolean Log IPs in transactions

AppleDeviceRegistration

Tracks Apple devices registered for wallet push notifications when card balances change.

Field Type Description
card_id FK Associated loyalty card
device_library_identifier String Apple device identifier
push_token String APNs push token

Unique constraint on (device_library_identifier, card_id).