Order Lifecycle - mukular/food-delivery-feastfast--architecture GitHub Wiki
Order Lifecycle Documentation
This document explains the complete lifecycle of an order in the Food Delivery Platform — from cart checkout to final delivery or cancellation.
Note: The system uses three independent but coordinated lifecycles:
Order.statusrepresents the overall order state (created → confirmed → completed / cancelled)ShopOrder.statusrepresents restaurant-specific preparation and deliveryDeliveryAssignment.statusrepresents delivery partner assignment and fulfillmentEach lifecycle progresses independently but triggers transitions in the others based on deterministic rules.
It covers:
- State transitions
- Role responsibilities
- Payment handling
- Failure scenarios
- Real-world edge cases
1. High-Level Overview
An Order represents a customer checkout that may involve one or multiple restaurants.
Each restaurant inside an order is handled as a ShopOrder with its own lifecycle.
Customer Order
├── ShopOrder (Restaurant A)
├── ShopOrder (Restaurant B)
└── ...
2. Order Creation Phase
Trigger
Customer clicks Place Order.
Backend Flow
- Validate cart items & availability
- Validate delivery location (geo radius)
- Calculate:
- Item subtotal
- Delivery fee (distance-based)
- Tax
- Apply coupon (if any)
- Create Order with status created
- Create embedded shopOrders
Initial State
Order.status = "created"
Order.paymentStatus = "pending"
ShopOrder.status = "pending"
3. Payment Phase
Supported Payment Methods
- Wallet
- Cash on Delivery (COD)
- Online (Razorpay)
3.1 Wallet Payment
Flow
- Wallet balance checked
- Amount deducted immediately
- Order marked as paid
paymentStatus = "paid"
Coupon usage is incremented immediately here.
3.2 Cash on Delivery (COD)
Flow
- No upfront payment
- Order marked as unpaid
- Payment happens at delivery
Coupon usage is incremented immediately (business decision).
3.3 Online Payment (Razorpay)
Flow
- Razorpay order created
- Customer completes payment
- Razorpay webhook fires payment.captured
- Backend verifies:
- Signature
- Amount
- Idempotency
- Order marked as paid
paymentStatus = "paid"
Coupon usage is incremented at order creation to avoid overuse.
4. Shop Order Acceptance Phase
Trigger
Seller views incoming orders.
Seller Actions
- Accept order
State Change
order.status = "confirmed"
shopOrder.status = "preparing"
ShopOrder.acceptedAt = Date
Customer is notified via:
- Socket event
- Toast notification
5. Food Preparation Phase
Seller Updates
Seller updates order as food is prepared.
Status Transitions
pending → preparing → ready
ShopOrder.preparedAt = Date
6. Delivery Assignment Phase
Trigger
Shop marks order as ready.
Backend Flow
- Find nearest available delivery partner
- Create DeliveryAssignment
- Assign delivery partner
- Emit socket events
DeliveryAssignment.status = "assigned"
7. Pickup Phase
Delivery Partner Actions
- Reaches restaurant
- Picks up order
DeliveryAssignment.status = "picked_up"
ShopOrder.status = "out_for_delivery"
Live location tracking starts.
8. Delivery Phase
Delivery Partner Actions
- Reaches customer
- Hands over order
- Collects COD (if applicable)
Final State
DeliveryAssignment.status = "completed"
ShopOrder.status = "delivered"
ShopOrder.deliveredAt = Date
9. Order Completion
Once all shopOrders are delivered:
Order.status = "completed"
Order is now immutable (read-only).
10. Cancellation Scenarios
10.1 Customer Cancels (Early)
Allowed only if:
- Order not confirmed by seller
Order.status = "cancelled"
Refund rules:
- Wallet → instant
- Online → Razorpay refund
- COD → no action
11. Coupon Lifecycle Integration
Coupons affect the order lifecycle at creation time.
Key Rules
- Coupon validity checked at order creation
- Coupon usage count incremented immediately
- Prevents overuse under concurrency
- No reservation/locking complexity
This is a conscious business trade-off.
12. State Transition Diagram (Textual)
created
└── payment pending
├── paid
│ └── confirmed
│ └── preparing
│ └── ready
│ └── out_for_delivery
│ └── delivered
│ └── completed
└── cancelled
13. Why This Lifecycle Works Well
- Supports multi-restaurant orders
- Scales horizontally
- Clean separation of responsibilities
- Idempotent payment handling
- Real-time user feedback
- Simple yet production-ready