Problem statement
Design the object model and core APIs for a loyalty programme that accrues points on purchases and lets members redeem them, for a single retailer's rewards service.
Operating context. Each member has a points account. A completed order earns points via the active earn rules for the member's tier and the order's contents. Points are granted as dated lots with a validity horizon and expire when it passes. Members redeem points for a reward (a cart credit or a catalogue item), spending the oldest un-expired lot first. Tiers (e.g. silver, gold) move up or down from a member's rolling qualifying activity. Accrual and redemption for one member may occur concurrently, and the whole service is a single in-process component.
Out of scope. The payment step, placing the order itself, tax, notification/email delivery, and the admin UI for authoring earn rules and tiers (assume they exist in memory).
What to produce. The class hierarchy (Member, PointsAccount/ledger with point lots, EarnRule, Tier, RewardOption, LoyaltyService facade), the public API each exposes, and the state transitions for tiers and for lot expiry. Be explicit about: how a new earn rule is added without editing the accrual engine, how expiry is reflected in a balance query without a manual sweep, and how concurrent accrual and redemption keep the balance correct.
Must do 5
Functional requirements
- Accrue points for a completed order by running the active earn rules for the member's tier and the order's contents.
- Redeem points for a reward, deducting from the oldest un-expired lot first.
- Expire points once their lot passes its validity horizon, without the caller running a manual sweep.
- Recompute a member's tier from their rolling qualifying activity and apply the resulting up/downgrade.
- Report a member's redeemable balance, pending (not-yet-cleared) balance, and next expiry date.