Design Rationale — Pricing

Non-obvious design choices for the pricing module — the WHY behind each decision.

Pricing (locked 2026-06-09)

Carved out of inventory into its own schema

Decision: Pricing rules live in pricing schema, not inventory. Inventory holds the base price on item_variant; all rule-based pricing is pricing.

Why: Pricing rules have distinct consumers (POS checkout, order quoting, promotions engine) and distinct lifecycle (rules change frequently; item records change rarely). Bundling into inventory schema would bloat a core schema with a high-churn concern.

Rejected: Price columns only on item_variant — can't express customer-specific prices, quantity breaks, scheduled promotions, or account-level pricing without a rule table.


One price_rule table absorbs all pricing kinds

Decision: price_rule handles level-based, customer-specific, quantity-break, and date-scheduled pricing via scope_type + price_type + min_qty + valid_from/valid_until — not a separate table per pricing kind.

Why: Discriminator-over-sprawl (see Cross-Cutting Patterns) — all pricing kinds are "a rule that sets a price under certain conditions." A single table with well-chosen columns handles all variants cleanly.

Rejected: Separate sale_price_rule, contract_price_rule, tier_price_rule tables — proliferates tables, duplicates resolution logic, and creates ambiguity when multiple rule types apply to the same item.


Precedence resolution is PricingService logic, not a DB constraint

Decision: Which rule wins when multiple rules apply (customer-specific > group > default, etc.) is PricingService policy, not a database constraint.

Why: Precedence is a business rule that may evolve (e.g. "group beats customer-specific for loyalty members"). Encoding precedence in schema constraints would freeze it.

Guard: Do not add DB constraints trying to enforce pricing precedence. The resolution algorithm belongs in PricingService.resolvePrice(). Schema changes are expensive; rule changes should be code changes.


Last modified: Jun 17, 2026, 8:37 PM PT
On this page
Esc