Order placement → assignment
Customer browses → checkout → backend assigns to nearest distributor
✅
Add to cart
CartContext on RN
CartSheet on web
CartSheet on web
CLIENT
✅
Checkout
Slot · Address · Coupon · Pay mode
CLIENT
✅
POST /api/orders
orderController.createOrder
API
✅
Order created
status: PENDING
orderType: B2C
orderType: B2C
DB
⚠️
Route to distributor
order.distributor = nearest depot
ASSIGN
⚠️
Notify distributor
push / socket event
polling only today
polling only today
NOTIFY
POLLING
Current step
—
Click ▶ Play or Step ▸ to walk the flow.
Code reference
Files in play
The data lifecycle is anchored in three files:
Active stage (animating)
Completed step
Pending step
✅ implemented · ⚠️ partial · ❌ missing
Wallet — top-up, spend, settle, refund
Embedded ledger in
User.distributorProfile.walletTransactions[]✅
Open wallet
Distributor sees balance + ledger
SCREEN
✅
Top-up via Razorpay
recordCreditPayment()
razorpay_payment_id stored
razorpay_payment_id stored
PAYMENT
✅
walletBalance += amount
+ txn type: TOPUP
LEDGER
✅
B2B order placed
createB2BOrder()
SPEND
✅
Deduct wallet first
walletBalance -= n
creditUsed += spillover
creditUsed += spillover
LEDGER
❌
Credit on B2C DELIVERED
No earnings settled today
GAP
MISSING
⚠️
Refund on cancel
Razorpay refund API
+ REFUND txn
+ REFUND txn
REVERSAL
Live ledger preview
Razorpay top-up · rzp_pmnt_8X4..
TOPUP
+₹10,000
bal ₹10,000
B2B order #ORDER37 · 120 × Milk 500ml
ORDER
−₹6,840
bal ₹3,160
B2C delivery commission (proposed)
SETTLE
+₹38
bal ₹3,198
Cancellation refund · #ORDER41
REFUND
+₹420
bal ₹3,618
Current step
—
Click ▶ Play to animate top-up → spend → settle → refund.
Schema reference
Where this lives
The ledger is embedded on the distributor's user document:
COD cash reconciliation
Distributor collects cash on delivery → marks collected → settled to platform on payout day
✅
Order created · COD
paymentMethod: COD
paymentMode: CASH
paymentMode: CASH
DB
✅
Out for delivery
Distributor en route
or rider en route
or rider en route
STATUS
⚠️
Collect cash at door
Customer pays in person
PHYSICAL
❌
Mark "Cash received"
PATCH /payment-collected
order.paymentCollected = true
order.paymentCollected = true
NEW
PROPOSED
✅
Mark delivered
status: DELIVERED
timeline.deliveredAt
timeline.deliveredAt
STATUS
Post-delivery
❌
Auto-invoice
Invoice.create on DELIVERED
NEW
❌
Cash held in wallet
walletBalance -= cashHeld
(distributor owes platform)
(distributor owes platform)
NEW
❌
Daily settlement
Cron: cashHeld → 0
Settlement record
Settlement record
CRON
❌
Admin reconciles
/dashboard/settlements
UI
Current step
—
Watch the cash journey — from customer's pocket → distributor's wallet → platform settlement.
What's missing today
Add to Order schema
The COD reconciliation hinges on three new fields plus a settlement job:
Delivery completion — self vs rider
Order PENDING → CONFIRMED → PREPARING → OUT_FOR_DELIVERY → DELIVERED with OTP, notifications & payout
✅
PENDING
Order lands on distributor screen
STATUS
✅
CONFIRMED
"Accept order" tapped
STATUS
✅
PREPARING
"Start packing"
STATUS
⚠️
Pick delivery
"Me (self)" or roster rider
not enforced today
not enforced today
CHOICE
❌
OTP generated
6-digit · sent to customer
order.deliveryOtp
order.deliveryOtp
NEW
PROPOSED
✅
OUT_FOR_DELIVERY
"Mark ready for pickup"
STATUS
Self-delivery branch
❌
Live location ping
Every 30s while en route
NEW
❌
Verify customer OTP
Customer reads code
POST /verify-delivery-otp
POST /verify-delivery-otp
NEW
❌
Cash collected? (COD)
paymentCollected = true
NEW
⚠️
DELIVERED
timeline.deliveredAt set
currently nothing else fires
currently nothing else fires
STATUS
SUCCESS
❌
Invoice + wallet + notify
Auto-invoice
+₹commission to wallet
customer push
+₹commission to wallet
customer push
NEW
Rider branch
✅
Rider sees order
DeliveryList screen
STATUS
⚠️
Rider location
Geolocation service
not yet pushed to backend
not yet pushed to backend
PARTIAL
✅
Rider OTP
DeliveryOtp screen exists
SCREEN
⚠️
DELIVERED (rider)
Status update only
STATUS
Failure paths
❌
Customer not reachable
DELIVERY_FAILED status
+ attempt log
+ attempt log
NEW
❌
Reschedule
Pick new slot · max 3 tries
NEW
❌
RETURNED
Refund + notify
STATUS
Current step
—
Hit Play to watch a full happy-path delivery, then see where the rider branch and failure path diverge.
Implementation map
17 stages, ~6 ✅, ~3 ⚠️, ~8 ❌
Today the status pipeline works end-to-end but nothing fires around it. The 8 ❌ stages need:
Active stage
Done
Pending
Branches play sequentially: main → self → rider → failure