Amounts and orders Required
Freeze what the customer agreed to on the order
When the order is created, copy the unit price, quantity, discount, tax rate, tax amount and currency onto each line. Never recompute them from the catalogue.
How to do it
Prices, tax rates and coupons change. An order, its invoice and its refunds must show what the customer agreed to. Keep the price ID on the line for reports. Store the tax calculation ID from your tax service too. Refunds and credit notes work only from the stored lines.
Example
CREATE TABLE order_lines (
order_id text NOT NULL REFERENCES orders(id),
line_no int NOT NULL,
price_id text NOT NULL,
description text NOT NULL,
quantity int NOT NULL CHECK (quantity > 0),
unit_amount_minor bigint NOT NULL,
discount_minor bigint NOT NULL DEFAULT 0,
tax_rate_bp int NOT NULL,
tax_minor bigint NOT NULL,
currency char(3) NOT NULL,
PRIMARY KEY (order_id, line_no)
);
How to check
On staging, change a price and a tax rate, then open an older order and refund it. The order, the invoice and the refund all show the old amounts.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers payments playbook: https://agentwranglers.se/playbook/payments/amounts-and-orders/order-snapshot.