Scales & Money
Fixed-point scaling, GST, rounding, surcharge, and point-rate conventions used across the retail POS.
All money, quantity, and percent values are stored as scaled integers — never
floats. The same constants are defined on both sides
(retail_pos_server/src/libs/constants.ts and
retail_pos_app/src/renderer/src/libs/constants.ts).
Scaling constants
| Constant | Value | Meaning |
|---|---|---|
MONEY_SCALE | 100 | Money is stored in cents. 1000 = $10.00 |
QTY_SCALE | 1000 | Quantity ×1000. 3500 = 3.5 units |
PCT_SCALE | 1000 | Percent ×1000. 1000 = 1% |
MONEY_DP | 2 | Money display decimal places |
QTY_DP | 3 | Quantity display decimal places |
PCT_DP | 3 | Percent display decimal places |
GST (tax)
GST applies only to taxable items (Item.taxable, default false — most
items are non-taxable). For a taxable row the price already includes GST,
extracted as round(total / 11) (Australian 10%); non-taxable rows have zero
tax. Tax is never added on top.
unit_price_effective = unit_price_adjusted ?? unit_price_discounted ?? unit_price_original
row.total = round(unit_price_effective × qty / QTY_SCALE)
row.tax_amount = taxable ? round(row.total / 11) : 0
row.net = row.total - row.tax_amountSource: retail_pos_server/src/v1/sale/sale.create.service.ts.
Cash rounding (5¢)
When every payment on an invoice is cash, the subtotal is snapped to the
nearest 5 cents; the difference is stored as rounding. Mixed/non-cash invoices
have rounding = 0.
rounding = cashOnly ? (round(subtotal / 5) × 5) - subtotal : 0Source: retail_pos_server/src/v1/sale/sale.refund.service.ts,
sale.repay.service.ts.
Credit surcharge
A configurable surcharge applies to CREDIT tenders. GIFTCARD is treated as
"CREDIT without surcharge".
StoreSetting.credit_surcharge_rate— permille (default15= 1.5%).- Surcharge GST follows the same
1/11rule:surchargeTax ≈ round(creditSurchargeAmount / 11)(±1¢ drift tolerated).
Loyalty point rates
StoreSetting (defaults shown):
| Field | Default | Meaning |
|---|---|---|
cash_point_rate | 10 | Percent of the cash-paid base earned as points (10 = 1%) |
other_point_rate | 10 | Percent of the non-cash base earned as points (10 = 1%) |
user_daily_voucher_default | 2000 | Default staff daily voucher amount (cents = $20.00) |
Time limits
| Constant | Value | Where |
|---|---|---|
REPAY_TIME_LIMIT_MS | 10 * 60 * 1000 (10 min) | retail_pos_server/src/v1/sale/sale.repay.service.ts |
Invoice invariants
For a SaleInvoice (see schema.prisma):
Σ rows.total == linesTotal
Σ rows.tax_amount == lineTax
Σ payments.amount == total
total == linesTotal + rounding + creditSurchargeAmount