Managing Order Transitions
Managing Order Transitions
Huge congrats for making it this far. 🎉 You’ve built a full “mini e-commerce backend” flow: carts → items → checkout → orders → retrieval. What’s left now is the part that makes orders feel “alive”: state transitions.
In this final lesson, you’ll implement the two most important “actions” on an order in this codebase:
- Pay an order:
POST /api/orders/:id/pay - Cancel an order:
POST /api/orders/:id/cancel
You’ll see the same layering pattern you’ve used throughout the course:
- Routes validate input and enforce HTTP method rules.
- Services enforce business rules like “only pending orders can be paid.”
- Repositories persist state changes with a safe
UPDATE ... RETURNING ....
What “Order Transitions” Mean Here
Orders have a status field with a small set of allowed values:
pending(created at checkout)paidshippedcancelled
This project intentionally uses action routes (/pay, /cancel) instead of a generic “update status” endpoint. That’s because transitions are not “free-form edits”—they’re business actions with rules:
- Paying is only valid from
pending. - Canceling is blocked if the order is already
shippedor alreadycancelled.
Those rules belong in the service layer, so every caller follows the same policy.
Repository: Persisting a Status Change With setOrderStatus
