# Commercial Integrity Bundle v40

v40 closes five accumulated commercial correctness debts in one bundle.

## 1. Pricing temporal integrity

Old behavior:
one active price row per price-list / variant / unit, regardless of time period.

New behavior:
multiple active rows are allowed when their effective periods do not overlap.

Database authority:
PostgreSQL GiST exclusion constraint using `btree_gist` and a half-open `[from,to)`
`tstzrange`.

Null effective boundaries are treated as infinite.

Application validation performs an overlap-aware precheck; the exclusion constraint is
the concurrency backstop.

## 2. Two-pass basket promotion evaluation

Old behavior:
each line saw only the running subtotal up to its position.

New behavior:
- pass 1 resolves prices and calculates full gross basket subtotal
- pass 2 evaluates every promotion against that same final subtotal

Therefore minimum-basket eligibility is invariant to cart-line ordering.

## 3. Promotion usage consumption

`promotions.usage_counters` remains the fast eligibility projection.

New durable `promotions.usage_consumptions` records exactly one use per:
checkout command + campaign.

Checkout:
- deduplicates a campaign applied to several lines
- atomically checks total/customer limits
- increments global/customer projections
- records durable consumption
- rolls everything back if checkout fails

This closes the previous gap where limits were evaluated but never consumed.

## 4. Checkout idempotency fingerprint

New checkout commands persist SHA-256 fingerprint of:
tenant + cart + expected version.

Same idempotency key with:
- another cart → conflict
- another expected version → conflict

Pre-v40 commands remain backward-compatible: they are bound to their original cart even
though they do not have a stored fingerprint.

## 5. Null-safe sale number sequence uniqueness

Original PostgreSQL UNIQUE allowed multiple rows when `branch_id IS NULL`.

v40 adds a null-safe unique expression index:
tenant + COALESCE(branch_id,0) + business_date.

The existing advisory-lock numbering strategy remains intact; the index becomes the DB
concurrency/integrity backstop.

## Future commercial work

Not included in v40:
- basket-level fixed-discount allocation semantics
- BOGO free-item materialization
- promotion stacking policy beyond current exclusive/priority behavior
- branch/company timezone business-date normalization
