102 lines
3.6 KiB
Markdown
102 lines
3.6 KiB
Markdown
# Phase Handover — Loyalty 7.2 Point Engine
|
|
|
|
## Metadata
|
|
|
|
| Field | Value |
|
|
| --- | --- |
|
|
| Phase ID | loyalty-7.2 |
|
|
| Title | Point Engine (immutable ledger) |
|
|
| Status | Complete |
|
|
| Service(s) | loyalty (`loyalty-service`, port 8004) |
|
|
| Version | 0.7.2.0 |
|
|
| Date | 2026-07-26 |
|
|
| ADR(s) | ADR-001, ADR-003, ADR-006, ADR-011 |
|
|
|
|
## Reusable Components
|
|
|
|
| Component | Location | Reuse notes |
|
|
| --- | --- | --- |
|
|
| PointLedgerEntry | `app/models/ledger.py` | Append-only pattern for wallet/gift (7.6/7.7) |
|
|
| PointLedgerRepository | `app/repositories/ledger.py` | Balance sum + filtered list |
|
|
| PointEngineService | `app/services/point_engine.py` | Earn/redeem/adjust/expire orchestration |
|
|
| Ledger validators | `app/validators/ledger.py` | Signed amounts + open-account checks |
|
|
|
|
## Public APIs
|
|
|
|
| Method | Path | Auth / Permission | Notes |
|
|
| --- | --- | --- | --- |
|
|
| GET | `/api/v1/point-accounts/{id}/balance` | `loyalty.points.view` | Computed balance |
|
|
| GET | `/api/v1/point-accounts/{id}/ledger` | `loyalty.points.view` | Paginated entries |
|
|
| POST | `/api/v1/point-accounts/{id}/earn` | `loyalty.points.earn` | Idempotent optional |
|
|
| POST | `/api/v1/point-accounts/{id}/redeem` | `loyalty.points.redeem` | Rejects insufficient |
|
|
| POST | `/api/v1/point-accounts/{id}/adjust` | `loyalty.points.adjust` | Signed delta |
|
|
| POST | `/api/v1/point-accounts/{id}/expire-points` | `loyalty.points.expire` | Debit expire |
|
|
|
|
## Events
|
|
|
|
| Event type | Domain / Integration | Payload summary | Version |
|
|
| --- | --- | --- | --- |
|
|
| `loyalty.points.earned` | Domain | account, amount, balance_after | 1 |
|
|
| `loyalty.points.redeemed` | Domain | account, amount, balance_after | 1 |
|
|
| `loyalty.points.adjusted` | Domain | account, amount, balance_after | 1 |
|
|
| `loyalty.points.expired` | Domain | account, amount, balance_after | 1 |
|
|
|
|
## Extension Points
|
|
|
|
| Extension point | How to extend | Forbidden uses |
|
|
| --- | --- | --- |
|
|
| Ledger entry types | Add enum + validators + tests | Mutate existing rows |
|
|
| Balance source | Always SUM(ledger) | Add mutable balance column |
|
|
| Reward redemption | Call PointEngine from 7.3 | Bypass ledger for rewards |
|
|
|
|
## Known Limitations
|
|
|
|
- No scheduled expire worker
|
|
- No per-lot FIFO expiration
|
|
- Member transfer does not move ledger rows
|
|
|
|
## Migration Notes
|
|
|
|
| Item | Detail |
|
|
| --- | --- |
|
|
| Alembic revision(s) | `0003_phase_72_points` |
|
|
| Upgrade steps | `alembic upgrade head` in loyalty service |
|
|
| Downgrade support | Yes (drops table) |
|
|
| Data backfill | None |
|
|
| Breaking changes | None (additive) |
|
|
|
|
## Dependencies
|
|
|
|
| Dependency | Type | Required for |
|
|
| --- | --- | --- |
|
|
| loyalty-7.1 | Phase | Membership + point accounts |
|
|
| shared-lib | Library | Events, security, exceptions |
|
|
|
|
## Next Phase Entry
|
|
|
|
1. This handover + [loyalty-phase-7-2.md](../loyalty-phase-7-2.md)
|
|
2. Service snapshot + manifests
|
|
3. Build Rewards Engine on top of PointEngine redeem — do not mutate balances directly
|
|
4. Suggested next: `loyalty-7.3` Rewards Engine
|
|
|
|
| Field | Value |
|
|
| --- | --- |
|
|
| Recommended next phase | loyalty-7.3 |
|
|
| Blockers for next phase | None |
|
|
| Entry checklist | Read 7.2 handover; keep ledger immutable; reuse PointEngineService |
|
|
|
|
## Completion Sign-Off
|
|
|
|
- [x] Quality gates passed
|
|
- [x] Tests green (61)
|
|
- [x] Documentation updated
|
|
- [x] Progress / next-steps / registries updated
|
|
- [x] Service Snapshot regenerated
|
|
- [x] No TODO for claimed deliverables
|
|
|
|
## Related Documents
|
|
|
|
- [loyalty-phase-7-2.md](../loyalty-phase-7-2.md)
|
|
- [loyalty-phase-7-1.md](../loyalty-phase-7-1.md)
|
|
- [ADR-011](../architecture/adr/ADR-011.md)
|