Skip to content

PRD: Sale order & cart

ModuleOrders (CORE-07)PRD IDPRD-ORD-001
StatusShippedOwnerOrders squad
Date2025-12-31Versionv1.0
Packages@nx/saleURDORD

TL;DR

Lets a merchant build a sale as a draft cart, add and edit its line items, then drive it through checkout into a payable order that reaches a paid/completed terminal state. This is the first end-to-end "cart → order → payment" spine of the Orders module - every order now has a controlled lifecycle, locked prices at checkout, and a place to hold payment and shipping detail.

1. Context & Problem

The order package starts as skeleton controllers (cart, cart-item, order, order-item, payment-info, shipping-info) with no working lifecycle: there is no way to build an order as a cart, mutate its lines, and move it through checkout to payment. Without that spine, nothing downstream - payment capture, kitchen tickets, POS sessions, loyalty - has an order to attach to.

This increment establishes the foundational sale-order lifecycle: a single entity that plays both the cart (while in DRAFT) and the committed order role, with line-item mutation in draft, a checkout path that validates and locks prices, and the order service that drives state transitions. It founds the Orders URD ORD feature that everything else in the module builds on.

2. Goals & Non-Goals

Goals

  • Build an order as a draft cart and add/update/remove line items while in DRAFT.
  • A controlled lifecycle from creation, through checkout into processing, to a paid/completed terminal state, with revert and cancellation paths.
  • Checkout that validates the cart (non-empty, prices ≥ 0, quantity ≥ 1) and locks prices.
  • Hold payment and shipping detail against the order (payment-info, shipping-info).
  • Provide working order request/response contracts and a checkout endpoint.

Non-Goals

  • Refund / return flow - a URD non-goal (Planned).
  • Stock mutation - owned by Inventory.
  • Payment-provider integration - owned by Payment.
  • Combo fan-out, split/merge, customer link, and multi-currency - later refinements (URD-ORD-005, URD-ORD-012..016).
  • Check splitting, kitchen tickets, stations, POS sessions, reservations, loyalty points - later F&B features (CHK/KIT/STA/POS/RSV/PNT).

3. Success Metrics

MetricTarget / signal
Lifecycle coverage100% of sales flow through the order lifecycle (no order created outside DRAFT → checkout)
Checkout integrityZero orders reach PROCESSING with an empty cart, negative price, or zero quantity
Price stabilityPrices locked at checkout do not drift before payment
Cycle timeMedian time DRAFT → COMPLETED per merchant trends down

4. Personas & Use Cases

PersonaGoal in this feature
CashierBuild a cart, edit lines, check out, and take an order to payment
Manager / OwnerTrust that every sale follows a controlled, auditable order lifecycle

Core scenarios: create a draft cart → add/update/remove line items while in DRAFT → checkout (validate + lock prices) into PROCESSING → reach PARTIAL on partial payment or COMPLETED on full payment → cancel a non-terminal order or revert PROCESSING back to DRAFT.

5. User Stories

  • As a cashier, I want to create a draft order and add line items to it, so I can build up a sale as a cart.
  • As a cashier, I want to update or remove items while the order is in DRAFT, so I can correct the cart before committing.
  • As a cashier, I want to check out a draft order, so the cart is validated, prices are locked, and the order is ready for payment.
  • As a cashier, I want to revert a checked-out order back to DRAFT, so I can fix the cart after starting checkout.
  • As a cashier, I want to record payment and shipping detail against the order, so the order carries the information a payment needs.
  • As a cashier, I want to cancel a non-terminal order, so mistaken orders don't proceed to payment.
  • As a manager, I want an order to reach PARTIAL on partial payment and COMPLETED on full payment, so the lifecycle reflects what was paid.

6. Functional Requirements

#RequirementURD ref
FR-1Create a draft order (cart) with line itemsURD-ORD-001
FR-2Add, update, and remove items only while in DRAFTURD-ORD-002
FR-3Adding the same product merges quantity onto the existing lineURD-ORD-003
FR-4Setting an item quantity to zero removes the lineURD-ORD-004
FR-5Checkout: DRAFT → PROCESSING (validate items, lock prices)URD-ORD-006
FR-6Checkout validation: non-empty cart, prices ≥ 0, quantity ≥ 1URD-ORD-007
FR-7Revert: PROCESSING → DRAFTURD-ORD-008
FR-8Cancel from DRAFT, PROCESSING, or PARTIAL (with optional reason)URD-ORD-009
FR-9Partial payment → PARTIAL statusURD-ORD-010
FR-10Full payment → COMPLETED statusURD-ORD-011
FR-11Hold payment-info and shipping-info against the orderURD-ORD-001

Full requirement text and acceptance criteria live in the Orders URD. This PRD references them rather than restating them.

7. Non-Functional Requirements

AreaRequirement
Data integrityItems are mutable only in DRAFT; checkout locks prices so totals can't drift before payment
Lifecycle integrityTransitions are constrained to the defined state graph; no skipping from DRAFT straight to a paid state
Tenancy & authzAll operations scoped per merchant and require authentication
ConsistencyCart mutation and checkout are transactional; partial failures don't leave a half-built order
i18nUser-facing labels/statuses are bilingual ({ en, vi })

8. UX & Flows

Key screens (in apps/client): the cart/order builder, line-item editing, the checkout action, and a cancel/revert control. Full screen inventory lives in the Orders module flows.

9. Data & Domain

EntityRole
SaleOrderThe order document - plays both cart (DRAFT) and committed-order roles; carries status and totals
OrderItemA line item - product reference, quantity, locked price
PaymentInfoPayment detail held against the order
ShippingInfoShipping detail held against the order

Conceptual only - full schema and invariants in the sale domain model.

10. Dependencies & Assumptions

Depends on

  • Product (Products) - order items reference product variants.
  • Payment (@nx/payment) - payment events drive PARTIAL / COMPLETED / CANCELLED transitions.

Assumptions

  • A merchant context is present on every request (merchant-scoped, authenticated).
  • Products exist to add as line items before checkout.

11. Risks & Open Questions

Risk / questionMitigation / status
Cart mutation after checkout could corrupt locked totalsItems mutable only in DRAFT; revert to DRAFT is the supported path to edit
Lifecycle state values evolve as the package maturesURD states (DRAFT → PROCESSING → PARTIAL → COMPLETED / CANCELLED) are the source of truth; later features align to them
No refund/return path in this incrementOut of scope; owned by a Planned refund feature
Combo / split / multi-currency not yet supportedDeferred to later increments (URD-ORD-005, URD-ORD-012..016)

12. Release Plan & Launch Criteria

AspectPlan
PhaseP1 (foundation) - see URD feature catalog
RolloutAll merchants; no feature flag
MigrationNew entities; schema migrations for the order tables
Launch criteriaCreate cart → edit lines → checkout → payment verified end-to-end; checkout validation rejects empty cart / bad price / bad quantity; prices locked at checkout
MonitoringOrder volume per merchant, checkout rejection rate, lifecycle transition errors

13. FAQ

Can items be changed after checkout? No - items are editable only in DRAFT. Use the PROCESSING → DRAFT revert to make changes, or cancel.

What does checkout actually do? It validates the cart (non-empty, prices ≥ 0, quantity ≥ 1), locks prices, and moves the order DRAFT → PROCESSING so it is ready for payment.

What's the difference between PARTIAL and COMPLETED? PARTIAL means the order is underpaid; COMPLETED means it is fully paid.

Does this increment handle combos, bill splitting, or multi-currency? No - those are later features/refinements. This increment founds the core single-order lifecycle.

Where does stock get reserved or consumed? Not here - stock mutation is owned by Inventory. This feature only drives the order lifecycle.

References

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.