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.status represents the overall order state (created → confirmed → completed / cancelled)
  • ShopOrder.status represents restaurant-specific preparation and delivery
  • DeliveryAssignment.status represents delivery partner assignment and fulfillment

Each 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