Context
Tracked for 0.7 off the pre-merge audit of #4. This is the real pardakht / ersal ask.
Motivation
VAT (9% in IR), discounts, and quantity math are the bread-and-butter operations in any checkout / invoice path. Today Amount only supports add / subtract between two Amount instances — anything involving a scalar (unit price × quantity, price × 0.09 for VAT, price × 0.85 for 15% off) forces callers to pop back to ->rials, do the math as a raw int/float, and reconstruct via fromRials. That's exactly the escape-hatch the VO is meant to prevent.
Proposed API
public function times(int \$qty): Amount; // unit-price × quantity
public function percentOf(int|float \$pct): Amount; // VAT (9), discount (15), etc.
Both return new Amount instances; both guard against negative results via the existing ctor invariant.
Open question — rounding mode
percentOf(9) on 1,234,567 rials = 111,111.03 rials. What integer rounds out?
- Banker's rounding (PHP
PHP_ROUND_HALF_EVEN): finance-industry default, bias-free over large samples.
- Half-up (
PHP_ROUND_HALF_UP): what most humans expect; what Iranian accounting software appears to use (unverified — needs confirmation).
Prefer not to decide this one on a napkin. Let pardakht integrate with a sandbox PSP, compare totals against what the PSP emits, and pick the mode that matches. Expose as an optional 2nd arg with a default, don't lock it into the signature permanently.
Why 0.7, not 0.6.1
Same reason as #: additive, wants real call-site data before method names + rounding defaults are set in stone.
Context
Tracked for 0.7 off the pre-merge audit of #4. This is the real
pardakht/ersalask.Motivation
VAT (9% in IR), discounts, and quantity math are the bread-and-butter operations in any checkout / invoice path. Today
Amountonly supportsadd/subtractbetween twoAmountinstances — anything involving a scalar (unit price × quantity, price × 0.09 for VAT, price × 0.85 for 15% off) forces callers to pop back to->rials, do the math as a raw int/float, and reconstruct viafromRials. That's exactly the escape-hatch the VO is meant to prevent.Proposed API
Both return new
Amountinstances; both guard against negative results via the existing ctor invariant.Open question — rounding mode
percentOf(9)on1,234,567 rials=111,111.03 rials. What integer rounds out?PHP_ROUND_HALF_EVEN): finance-industry default, bias-free over large samples.PHP_ROUND_HALF_UP): what most humans expect; what Iranian accounting software appears to use (unverified — needs confirmation).Prefer not to decide this one on a napkin. Let
pardakhtintegrate with a sandbox PSP, compare totals against what the PSP emits, and pick the mode that matches. Expose as an optional 2nd arg with a default, don't lock it into the signature permanently.Why 0.7, not 0.6.1
Same reason as #: additive, wants real call-site data before method names + rounding defaults are set in stone.