# Architect — F-021 Orders module ## Feature F-021 records purchase truth with item snapshots and an explicit state machine. Catalog changes must never alter historical order values. ## Design ### Module boundaries Create `project/src/modules/orders/` with domain/application/infrastructure/api/tests. Orders owns order persistence only. It does not own catalog, pricing or inventory truth. ### Data model Add migration `016_orders.js`: - `orders_orders`: id, user_id, idempotency_key unique nullable, state, totals snapshots, timestamps. - `orders_items`: id, order_id, product_id, variant_id, sku, ean nullable, name, unit_price_cents, discount_cents, tax_cents, quantity. - Check `state IN (...)`. - `idempotency_key` allows checkout idempotency later. ### State machine States: PENDING, AWAITING_PAYMENT, PAID, PROCESSING, SHIPPED, DELIVERED, CANCELLED, REFUNDED, PARTIALLY_REFUNDED. Allowed transitions: - PENDING -> AWAITING_PAYMENT or CANCELLED - AWAITING_PAYMENT -> PAID or CANCELLED - PAID -> PROCESSING, SHIPPED, REFUNDED, CANCELLED - PROCESSING -> SHIPPED, CANCELLED, REFUNDED - SHIPPED -> DELIVERED, PARTIALLY_REFUNDED - DELIVERED -> PARTIALLY_REFUNDED - REFUNDED and PARTIALLY_REFUNDED are terminal. Any other transition throws `OrderStateTransitionError`. ### Use cases - `createOrder(input)`: snapshots items, starts at PENDING or AWAITING_PAYMENT, emits `OrderCreated`. - `transition(orderId, nextState)`: enforces state machine; emits `OrderPaid`/`OrderCancelled` events when relevant. - `getOrder(orderId)`: ownership scoped to user. ### API - Authenticated `POST /orders` creates an order from a snapshot payload; ownership-scoped reads. ### Domain events - `OrderCreated`, `OrderPaid`, `OrderCancelled` emitted synchronously via an event publisher interface (no-op implementation for v1; integration points in checkout F-022 and notifications F-024). ## Acceptance trace - Snapshot survives catalog edits: order items keep name/sku/ean/price/tax/discount from creation. - Illegal transitions are rejected, e.g. SHIPPED -> PENDING. - All legal transitions are covered by unit tests. - `OrderCreated` is published on creation.