TorbatYar/docs/loyalty-phase-7-3.md
Mortezakoohjani 071c484530 Ship Loyalty phases 7.2-7.6 (points through wallet) with production deploy.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 21:27:22 +03:30

93 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 7.3 — Rewards Engine
| Field | Value |
| --- | --- |
| Identifier | `loyalty-7.3` |
| Status | Complete |
| Module | loyalty |
| Service | `loyalty-service` |
| Version | `0.7.3.0` |
| Database | `loyalty_db` |
| Depends On | Phase 7.2 |
| ADR(s) | ADR-001, ADR-003, ADR-006, ADR-011 |
| Manifest | [phase-manifest.yaml](ai-framework/phase-manifest.yaml) |
## Objective
Deliver the Rewards Engine: redemption lifecycle on catalog rewards with points debited exclusively through the immutable Point Engine — without campaign rules, referral, wallet, or gift cards.
## Scope
### In Scope
- Reward inventory fields: `stock_limit`, `redeemed_count`, `max_per_member`
- `RewardRedemption` lifecycle: pending → fulfilled | cancelled
- Redeem / fulfill / cancel APIs; list by reward and globally
- Points debit/refund via `PointEngineService` (`auto_commit=False` composition)
- Permissions, events, validators, migration `0004_phase_73_rewards`
- Tests + documentation + handover + service snapshot
### Out of Scope
- Campaign rule engine (7.4)
- Referral / wallet / gift cards / analytics / partner APIs (7.57.9)
## Redemption Rules
| Rule | Detail |
| --- | --- |
| Active reward only | Status must be `active` |
| Stock | `redeemed_count < stock_limit` when limit set |
| Per-member cap | Non-cancelled count ≤ `max_per_member` when set |
| Member | Must be `active` |
| Points | Debit via ledger; free (`points_cost=0`) skips ledger |
| Cancel | Only from `pending`; refunds points; decrements stock counter |
| Fulfill | Only from `pending` |
## APIs
| Method | Path | Permission |
| --- | --- | --- |
| POST | `/api/v1/rewards/{id}/redeem` | `loyalty.rewards.redeem` |
| GET | `/api/v1/rewards/{id}/redemptions` | `loyalty.redemptions.view` |
| GET | `/api/v1/redemptions` | `loyalty.redemptions.view` |
| GET | `/api/v1/redemptions/{id}` | `loyalty.redemptions.view` |
| POST | `/api/v1/redemptions/{id}/fulfill` | `loyalty.rewards.fulfill` |
| POST | `/api/v1/redemptions/{id}/cancel` | `loyalty.rewards.cancel` |
## Events
| Event | When |
| --- | --- |
| `loyalty.reward.redeemed` | Redeem (points deducted) |
| `loyalty.reward.fulfilled` | Fulfill |
| `loyalty.reward.redemption_cancelled` | Cancel + refund |
## Migration
| Item | Detail |
| --- | --- |
| Alembic | `0004_phase_73_rewards` (down_revision `0003_phase_72_points`) |
| Breaking | None — additive columns + table |
## Tests
Command: `cd backend/services/loyalty && pytest -q`**72 passed**
## Known Limitations
- No automatic redemption expiry worker
- No partner fulfillment webhooks (7.9)
- Campaign-driven rewards deferred to 7.4
## Next Phase
Phase 7.4 — Campaign Engine
## Related Documents
- [Handover](phase-handover/phase-7-3.md)
- [Phase 7.2](loyalty-phase-7-2.md)
- [Service Snapshot](service-snapshots/loyalty.yaml)
- [ADR-011](architecture/adr/ADR-011.md)