Skip to content

PRD: Pricing simulation & order pricing preview

ModulePricingPRD IDPRD-SIM-001
StatusReady to devFEATSIM · BANA-1434
EpicPlaneBANA-1550
Date2026-06-15Versionv1.0
Packages@nx/pricing · @nx/saleURDSIM
SurfaceBackend
OwnerPhát Nguyễn

What pricing simulation & order pricing preview are

Once the cashier has built the basket, the sale flow prices the whole basket in one call, up to 100 lines, and no order is persisted and no stock is touched. What comes back is a pricing snapshot: one snapshot for the order, plus one snapshot for each line. Each snapshot carries every decision applied to that line - which price, which taxes, which discounts, which fees - and each decision is copied at compute time, so renaming or deactivating a rule later leaves an old receipt reading exactly as it did on the day of sale.

The snapshot also records who bears what: how much the buyer pays, how much the seller absorbs, and which portions belong to the government, the platform, or a supplier. Readers take the figure straight from it instead of re-adding it. Before checkout, the customer is shown the price through a read-only action: the order is re-priced and the snapshot is returned, and the order's status does not change. At checkout the order is priced by that same engine, and the snapshot is persisted alongside the order for later audit, tax declaration, and dispute resolution.

Why a simulation surface is needed

The fare and tax engine decides the winning fare per variant and computes compound taxes. It answers "what is this one variant's price right now". But the sale flow needs to price a whole basket at once, show that price to a customer before any order is committed, and later keep an auditable record of exactly how each line was priced.

Without a simulation surface the sale flow would have to call the fare and tax primitives line by line, re-assemble order totals itself, and re-implement the inclusive/exclusive tax rules. Worse, there would be no immutable, self-contained record of the pricing decision to attach to the order for tax declaration, ledger, and dispute resolution. A merchant also cannot show a trustworthy "this is what you will pay" figure if pricing is only computed at the moment of commit.

This increment closes that gap with a stateless pricing engine that returns a pricing snapshot, plus the read-only preview the sale flow consumes - with no order persistence, no status change, and no stock side effects.

One example, start to finish

StepWhat happensResult
A cashier builds a basket of three linesThe sale flow calls the order-pricing previewThe order is re-priced read-only, returning a pricing snapshot - each line with price, taxes, per-party ledger - plus the order total, with nothing persisted
The customer sees the price before payingCheckout happensThe order is re-priced by that same engine and the snapshot is persisted alongside it
A line's variant has no active fare setThe line is pricedThe real upstream rejection reason is surfaced, rather than a generic failure

The easiest thing to get wrong

A preview persists nothing, even when it returns exactly what checkout would

The order-pricing preview and the pricing simulation are pure reads. They always price FROM SCRATCH and return a fresh snapshot - never reading back a previously persisted snapshot, and never writing anything to the order. Only checkout actually persists a snapshot alongside the order.

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.