# Fulfillment — integrity

## Fulfillment posting flow (canonical)

1. **Validate** order line, warehouse, pick qty, reservation **open qty** ≥ ship qty.
2. In **one database transaction** (when co-located):
   - Append **consume** on reservation ledger for the reservation id / line binding.
   - Apply **stock_out** via inventory engine on the same warehouse/item with **matching qty**.
3. Update **fulfillment** records (shipment line, pack line) with references to **reservation movement id** and **stock movement id**.
4. Commit; then **after-commit** events (notifications, carrier APIs) per architecture docs.

---

## Reservation consumption coordination

- **Consume** must not succeed if **stock_out** would fail (available / catalog gates).
- **Order** within the transaction: typically **consume (reserved ↓)** then **stock_out (on_hand ↓)** so `applySignedDelta` sees updated reserved when recomputing available—or use the engine’s **locked projection** path that applies both in one unit (see inventory `consume` implementation pattern).

---

## Prevent split-brain

| Forbidden state | Prevention |
|-----------------|-------------|
| Reservation consumed, **no** stock_out | Single transaction; or saga with **pending_fulfillment** until stock confirmed. |
| stock_out exists, reservation **still open** for same ship qty | Consume before or atomically with stock_out; reconciliation job flags mismatch **critical**. |

---

## Partial fulfillment behavior

- Multiple shipment lines per order line: each shipment uses **consume + stock_out** for **that shipment qty** with **unique idempotency** per ship unit (e.g. `ship:{shipmentLineId}`).
- **Remaining open reservation** after partial ship must match **ordered − shipped** unless explicitly released.

---

## Critical stance

**Deterministic fulfillment beats convenience** — if the transaction cannot complete both legs, **nothing** from that attempt should commit.
