Money Conventions
This page describes how KahunaCart stores and calculates monetary amounts. It applies to every price, adjustment and transaction in the store.
KahunaCart uses vendored brick/money for calculation and BIGINT minor units for storage. Nothing monetary is ever a float.
Storage
- Every monetary column is named
*_minorand holds the amount in the currency's minor unit.1999is $19.99, and500is¥500, because JPY has no minor unit and brick/money knows that. - Currency is stored once per order, in
kahunacart_orders.currencyas an ISO 4217 code. That order's items, adjustments and transactions are all in that currency. - Catalog prices are in the store currency from config.
- Adjustment
amount_minoris negative for discounts and positive for charges. - Transaction amounts are always positive. Direction comes from
type, eitherpurchaseorrefund.
Note
KahunaCart is single-currency. If multi-currency arrives, it will be a per-order currency chosen at cart creation, never mixed currencies within one order.
Calculation
- All arithmetic happens on
Brick\Money\Moneyvalues obtained throughGrav\Plugin\KahunaCart\Money\Money::minor()and stored back with::toMinor(). - Raw integer math on minor units is allowed only for straight sums. Anything involving rates, division or allocation goes through brick/money.
- Default rounding is
HALF_UP, applied explicitly at defined points, such as after a percentage or tax computation. It is never applied implicitly mid-chain. TheMoneyhelper's methods encode these points, so do not call brick with other rounding modes. - Order-level amounts distributed across line items use
Money::allocate(), which wraps brick'ssplit()and guarantees no cent is created or lost. Order discounts and order-level tax back-allocation both use it. - Tax-inclusive prices back-calculate the included tax with
Money::includedTax(). The result is stored as an adjustment withincluded = 1, so it appears on receipts without changing the total.
Why not hand-rolled integer arithmetic
Integer-cents arithmetic looks sufficient until you hit allocation (splitting $10.00 three ways), currency metadata (JPY has 0 decimals, BHD has 3) and compounding rate rounding. brick/money is MIT-licensed, actively maintained, PHP 8.2+, exact (it is built on brick/math), and widely deployed.
The one risk is a vendoring collision if another plugin ships a different brick/math version. The fix would be prefix-scoping the KahunaCart vendor namespace at build time.