37 lines
2.2 KiB
Markdown
37 lines
2.2 KiB
Markdown
# Architect — F-022 Checkout orchestrator with idempotency
|
|
|
|
## Feature
|
|
F-022 orchestrates the money path: cart -> validation -> pricing -> stock -> discounts -> shipping -> order -> reservation -> payment intent. It owns no business data and exposes a single endpoint with idempotency.
|
|
|
|
## Design
|
|
|
|
### Module boundaries
|
|
Create `project/src/modules/checkout/` with domain/application/api/tests. Checkout does not own persistence; it composes cart, pricing, promotions, inventory, shipping, orders and a payment provider interface stub.
|
|
|
|
### Endpoint
|
|
- `POST /checkout` requires authenticated user, payload `{ items, address, promoCode?, idempotencyKey }` (recalculated internally). Server fetches cart via `CartService`, recalculates through Pricing/Promotions/Inventory/Shipping, validates everything, creates `AWAITING_PAYMENT` order, reserves stock, creates payment intent.
|
|
|
|
### Idempotency
|
|
- `idempotency_key` is required on the request body.
|
|
- The orders table already has `idempotency_key UNIQUE`. When an order already exists for `(userId, idempotencyKey)` the orchestrator returns the existing order without re-reserving stock or re-creating payment intent.
|
|
- Double-submit returns the same order id with no duplicate stock reservation.
|
|
|
|
### Flow and failure handling
|
|
1. Load cart. Reject 409 if cart empty or any item unavailable after recalculation.
|
|
2. Apply promo discount server-side; reject 422 on invalid promo.
|
|
3. Calculate shipping with default address if missing; reject 422 outside zones.
|
|
4. Create `AWAITING_PAYMENT` order with snapshots.
|
|
5. Reserve inventory atomically. If any reservation fails: cancel the order (state machine), release any partial reservations, return HTTP 409 with reason.
|
|
6. Create payment intent (interface stub for v1) and link to order.
|
|
7. Return 200 with order summary, stock reserved, payment intent reference.
|
|
|
|
### Metrics
|
|
- `checkout_success_total` counter
|
|
- `checkout_failure_total` counter
|
|
|
|
## Acceptance trace
|
|
- Unavailable item -> 409, no order, no payment, no reservation.
|
|
- Idempotent key reuse -> same order, no duplicate reservation, no duplicate payment.
|
|
- Successful checkout -> order AWAITING_PAYMENT + stock reserved.
|
|
- Failure after reservation -> reservation released, order cancelled.
|