fix(loyalty): use Code 128 barcode for retail scanner compatibility
Switch wallet pass barcodes from QR to Code 128 format using the card_number (digits only), so standard retail barcode scanners can read loyalty cards. Apple Wallet keeps QR as fallback in barcodes array. Also fix stale Vendor.loyalty_program relationship (now company-based), add parent init calls in vendor JS components, and update module docs to reflect Phase 2 completion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ The Loyalty Module provides stamp-based and points-based loyalty programs for Wi
|
||||
|--------|-------------|
|
||||
| Module Code | `loyalty` |
|
||||
| Dependencies | `customers` |
|
||||
| Status | Phase 1 MVP Complete |
|
||||
| Status | Phase 2 Complete |
|
||||
|
||||
### Key Features
|
||||
|
||||
@@ -23,36 +23,37 @@ The Loyalty Module provides stamp-based and points-based loyalty programs for Wi
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ Vendor │───────│ LoyaltyProgram │
|
||||
│ Company │───────│ LoyaltyProgram │
|
||||
└─────────────────┘ 1:1 └─────────────────┘
|
||||
│
|
||||
┌───────────┼───────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ StaffPin │ │LoyaltyCard│ │ (config)│
|
||||
└──────────┘ └──────────┘ └──────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌──────────────┐
|
||||
└───▶│ Transaction │
|
||||
└──────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│AppleDeviceRegistration│
|
||||
└──────────────────────┘
|
||||
│ │
|
||||
▼ ┌────────┼──────────┐
|
||||
┌──────────────────┐ │ │ │
|
||||
│ CompanyLoyalty │ ▼ ▼ ▼
|
||||
│ Settings │┌──────────┐┌──────────┐┌────────┐
|
||||
└──────────────────┘│ StaffPin ││LoyaltyCard││(config)│
|
||||
└──────────┘└──────────┘└────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌──────────────┐
|
||||
└──▶│ Transaction │
|
||||
└──────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│AppleDeviceRegistration│
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
### Database Tables
|
||||
|
||||
| Table | Purpose |
|
||||
|-------|---------|
|
||||
| `loyalty_programs` | Vendor's program configuration (type, targets, branding) |
|
||||
| `loyalty_cards` | Customer cards with stamp/point balances |
|
||||
| `loyalty_programs` | Company's program configuration (type, targets, branding) |
|
||||
| `loyalty_cards` | Customer cards with stamp/point balances (company-scoped) |
|
||||
| `loyalty_transactions` | Immutable audit log of all operations |
|
||||
| `staff_pins` | Hashed PINs for fraud prevention |
|
||||
| `apple_device_registrations` | Apple Wallet push notification tokens |
|
||||
| `company_loyalty_settings` | Admin-controlled per-company settings |
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -112,6 +113,14 @@ LOYALTY_APPLE_SIGNER_KEY_PATH=/path/to/signer.key
|
||||
| `GET` | `/programs/{id}/stats` | Get program statistics |
|
||||
| `GET` | `/stats` | Platform-wide statistics |
|
||||
|
||||
### Storefront Endpoints (`/api/v1/storefront/loyalty/`)
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| `GET` | `/card` | Get customer's loyalty card and balance |
|
||||
| `GET` | `/transactions` | Get customer's transaction history |
|
||||
| `POST` | `/enroll` | Self-enrollment in loyalty program |
|
||||
|
||||
### Public Endpoints (`/api/v1/loyalty/`)
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
@@ -254,22 +263,54 @@ result = points_service.earn_points(
|
||||
| Task | Schedule | Description |
|
||||
|------|----------|-------------|
|
||||
| `loyalty.sync_wallet_passes` | Hourly | Sync cards that missed real-time updates |
|
||||
| `loyalty.expire_points` | Daily 02:00 | Expire old points (future enhancement) |
|
||||
| `loyalty.expire_points` | Daily 02:00 | Expire points for inactive cards (based on `points_expiration_days`) |
|
||||
|
||||
## UI Pages
|
||||
|
||||
### Admin Pages
|
||||
|
||||
| Page | Path | Description |
|
||||
|------|------|-------------|
|
||||
| Programs Dashboard | `/admin/loyalty/programs` | List all loyalty programs with stats |
|
||||
| Company Detail | `/admin/loyalty/companies/{id}` | Detailed view of a company's program |
|
||||
| Company Settings | `/admin/loyalty/companies/{id}/settings` | Admin-controlled company settings |
|
||||
| Analytics | `/admin/loyalty/analytics` | Platform-wide analytics |
|
||||
|
||||
### Vendor Pages
|
||||
|
||||
| Page | Path | Description |
|
||||
|------|------|-------------|
|
||||
| Terminal | `/vendor/loyalty/terminal` | Scan card, add stamps/points, redeem |
|
||||
| Cards List | `/vendor/loyalty/cards` | Browse customer cards |
|
||||
| Card Detail | `/vendor/loyalty/cards/{id}` | Individual card detail |
|
||||
| Enroll | `/vendor/loyalty/enroll` | Enroll new customer |
|
||||
| Settings | `/vendor/loyalty/settings` | Program settings |
|
||||
| Stats | `/vendor/loyalty/stats` | Vendor-level statistics |
|
||||
|
||||
### Storefront Pages
|
||||
|
||||
| Page | Path | Description |
|
||||
|------|------|-------------|
|
||||
| Dashboard | `/loyalty/dashboard` | Customer's card and balance |
|
||||
| History | `/loyalty/history` | Transaction history |
|
||||
| Enroll | `/loyalty/enroll` | Self-enrollment page |
|
||||
|
||||
## Localization
|
||||
|
||||
Available in 4 languages:
|
||||
Available in 5 languages:
|
||||
- English (`en.json`)
|
||||
- French (`fr.json`)
|
||||
- German (`de.json`)
|
||||
- Luxembourgish (`lu.json`)
|
||||
- Luxembourgish (`lu.json`, `lb.json`)
|
||||
|
||||
## Future Enhancements (Phase 2)
|
||||
## Future Enhancements (Phase 3+)
|
||||
|
||||
- Rewards catalog with configurable tiers
|
||||
- Customer tiers (Bronze/Silver/Gold)
|
||||
- Promotions engine (bonus points, discounts, free items)
|
||||
- Referral program
|
||||
- Gamification (spin wheel, scratch cards)
|
||||
- POS integration
|
||||
- Points expiration rules
|
||||
- Batch import of existing loyalty cards
|
||||
- Real-time WebSocket updates
|
||||
- Receipt printing
|
||||
|
||||
Reference in New Issue
Block a user