# retail.loyalty-points One purchase through a points scheme: the member spends some points against the bill, pays the rest, and earns points on what they paid, at their tier's rate. ## Order of operations 1. **Redeem.** `redeemPoints` must be a multiple of `redeemBlock` (schemes such as "150 points = £1.50" redeem in blocks) and no more than the balance. The discount is `redeemPoints / redeemBlock x blockValue`, and it may not exceed the spend. 2. **Pay.** `amountPayable = spend - discount`. 3. **Earn on what was paid.** Points are not earned on the part of the bill paid with points, which is how most UK schemes work and stops points earning points. - base = `amountPayable x earnPoints / earnPer`, rounded with `earnRounding` (`down` gives "1 point per whole pound"). - earned = `base x multiplierBasisPoints / 10000`, rounded the same way. 4. **Balance.** `balance - redeemedPoints + earnedPoints`. Rounding twice is deliberate. A "double points for Gold" scheme doubles the points you would have earned, so £9.99 at 1 point per whole pound is 9 points, doubled to 18. Rounding once (9.99 x 2 = 19.98, so 19) gives the customer a point the scheme's own terms do not. ## Tiers The tier is the one with the highest `threshold` at or below `qualifyingSpend` (the first listed wins a tie). With no tier reached, `tier` is null and the multiplier is 1x. What counts as qualifying spend (this year, the last 12 months, including this purchase or not) is the scheme's rule, so the caller passes it in. ## Errors Redeeming more points than the balance, a number that is not a whole number of blocks, or more value than the spend is an error, not a silent cap: a till that quietly redeems fewer points than the customer asked for is a complaint. All amounts must be in one currency. Refunds are not handled here; reverse the original transaction's points instead.