Chore/LOY-511): Add documentation for rewards & redeem flow * chore(LOY-511): Add documentation for the rewards system * chore(LOY-511): move doc * chore(LOY-511): remove old doc * Removed AI documentation * Remove ToC Approved-by: Matilda Landström
114 lines
3.6 KiB
Markdown
114 lines
3.6 KiB
Markdown
# Rewards System
|
|
|
|
This doc provides a comprehensive guide to the rewards system for developers maintaining the codebase.
|
|
|
|
## Overview
|
|
|
|
The rewards system manages loyalty benefits for Scandic Hotels members. It combines data from two sources:
|
|
|
|
1. **Scandic Profile API** - Provides reward availability, states, and coupon codes
|
|
2. **Contentstack CMS** - Provides reward content (labels, descriptions, redeem instructions)
|
|
|
|
Rewards are tied to **membership levels** (L1-L7, called "Friends") and come in different **types** (Tier, Surprise, Campaign, Member-voucher).
|
|
|
|
````
|
|
|
|
### Data Merging Process
|
|
|
|
Rewards are matched between API and CMS using the `reward_id` field:
|
|
|
|
```typescript
|
|
// From query.ts - merging API and CMS data
|
|
const rewards: BaseReward[] = cmsRewards.map((cmsReward) => {
|
|
const apiReward = redeemableRewards.find(
|
|
({ rewardId }) => rewardId === cmsReward.reward_id
|
|
)!
|
|
return {
|
|
...apiReward, // API data: status, coupon codes, redeem location
|
|
...cmsReward, // CMS data: label, description, redeem_description
|
|
}
|
|
})
|
|
````
|
|
|
|
## Reward Types
|
|
|
|
### 1. Tier Rewards (`rewardType: "Tier"`)
|
|
|
|
Permanent benefits tied to membership level. These are always available once a member reaches the required tier.
|
|
|
|
**Characteristics:**
|
|
|
|
- Linked to `rewardTierLevel` (e.g., "L1", "L2")
|
|
- No coupon codes required for most
|
|
- Examples: 10% food discount, early check-in, late checkout
|
|
|
|
**Redeem behavior:**
|
|
|
|
- `On-site`: Show membership number at hotel
|
|
- `Non-redeemable`: Display-only benefits (e.g., earn rate bonuses)
|
|
|
|
### 2. Surprise Rewards (`rewardType: "Surprise"`)
|
|
|
|
Special rewards that appear as wrapped gifts and need to be "unwrapped" before use.
|
|
|
|
**Characteristics:**
|
|
|
|
- Part of `coupons` array in API response
|
|
- Have `unwrapped: boolean` flag on each coupon
|
|
- Must call `unwrap` mutation before becoming redeemable
|
|
- After unwrapping, appear in regular rewards list
|
|
|
|
**Flow:**
|
|
|
|
1. User sees surprise modal with wrapped gift
|
|
2. User clicks to reveal/unwrap
|
|
3. Frontend calls `rewards.unwrap` mutation
|
|
4. Surprise moves to current rewards
|
|
|
|
### 3. Campaign Rewards (`rewardType: "Campaign"`)
|
|
|
|
Promotional rewards with promo codes for online use.
|
|
|
|
**Characteristics:**
|
|
|
|
- Part of `coupons` array
|
|
- Have `couponCode` for redemption
|
|
- Typically redeemed online
|
|
- May have expiration dates
|
|
|
|
**Redeem behavior:**
|
|
|
|
- Display promo code with copy-to-clipboard functionality
|
|
|
|
### 4. Member Voucher (`rewardType: "Member-voucher"`)
|
|
|
|
Voucher-based rewards similar to campaigns.
|
|
|
|
**Characteristics:**
|
|
|
|
- Part of `coupons` array
|
|
- Have coupon codes
|
|
- Similar flow to Campaign rewards
|
|
|
|
---
|
|
|
|
## Coupon States & Redemption
|
|
|
|
### Coupon States
|
|
|
|
| State | Description | Redeemable |
|
|
| ---------- | ---------------------------------------------- | ---------- |
|
|
| `claimed` | Coupon has been claimed by user | Yes |
|
|
| `viewed` | Coupon has been viewed (schema only, not used) | Yes |
|
|
| `redeemed` | Coupon has been used | No |
|
|
|
|
**Note:** Only `redeemed` state is actively filtered out in business logic. Both `claimed` and `viewed` are treated as redeemable.
|
|
|
|
### Redeem Locations
|
|
|
|
| Location | Description | UI Behavior |
|
|
| ---------------- | --------------------------------- | ----------------------------- |
|
|
| `On-site` | Redeem at hotel (show to staff) | Shows membership number badge |
|
|
| `Online` | Redeem digitally with promo code | Shows copy-to-clipboard |
|
|
| `Non-redeemable` | Display-only (automatic benefits) | No redeem button, info only |
|