Adds CalculateEarning (docs/prd-point-coin.md F1, Q1, Q10, PC-202), a pure
function returning, per currency, the amount an order earns and the
settings that produced it, plus the basis:
basis = subtotal − discount − paid with EnakPoint (never negative)
amount = 0 below min_order_amount, else
floor(basis / earn_per_amount) × earn_value, capped by max_per_order
Tax and anything added on top of the subtotal are not part of the basis,
and the part paid with EnakPoint earns nothing. Money is handled in whole
cents: in float64 some baskets divide to 4956.999… and a naive floor would
lose a point, which a test reproduces. Metadata() gives the snapshot the
EARN row will freeze.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>