Basic Architecture of Sport Web
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# ADR-0011: Money as integer minor units
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-08-11
|
||||
|
||||
## Context
|
||||
|
||||
`0.1 + 0.2 !== 0.3`. Floating-point money produces discrepancies that are invisible in
|
||||
testing and unfixable once they are in an order history.
|
||||
|
||||
## Decision
|
||||
|
||||
All monetary values are integers in the currency's minor unit, in the database
|
||||
(`priceAmount Int`), across the API (`{ amount, currency }`), and in TypeScript (`Money`).
|
||||
VND has a minor-unit scale of 0, so `250000` means ₫250.000. Conversion to a display string
|
||||
happens in exactly one function, `formatMoney`, using `Intl.NumberFormat`.
|
||||
|
||||
## Consequences
|
||||
|
||||
Arithmetic is exact. No conversion happens between layers because every layer holds
|
||||
the same integer. Multi-currency is already representable without a schema change.
|
||||
|
||||
Developers must remember that `price.amount` is not a display value; the single formatter and
|
||||
the absence of any other division by 100 are what keep that from going wrong.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
`Decimal`/`numeric` columns — correct in the database but arrive in JavaScript as
|
||||
strings or a Decimal object that must be handled at every boundary. Floats — never.
|
||||
Reference in New Issue
Block a user