Order Lifecycle
Related docs:
Checkout Flow·Payment Architecture·Delivery Tracking·Delivery Signing
1. Order Status State Machine
2. Order Statuses
| Status | Description | Actor |
|---|---|---|
PENDING | Order created; payment not yet confirmed | System (on order creation) |
CONFIRMED | Payment received and verified via webhook | System (webhook handler) |
PROCESSING | Vendor has accepted and is preparing the order | Vendor / Admin |
SHIPPED | Order packed and ready for pickup | Vendor / Admin |
OUT_FOR_DELIVERY | Order handed to agent; GPS tracking active | Delivery Agent |
DELIVERED | PIN-based confirmation + digital signature completed | Delivery Agent / Customer |
CANCELLED | Order cancelled; no payment or pre-dispatch | Customer / Admin |
REFUNDED | Refund issued to customer | Admin |
3. Payment Status
| Status | Description |
|---|---|
PENDING | Payment initiated; awaiting confirmation |
PAID | Confirmed via webhook (InboundPayment.status = CAPTURED) |
FAILED | Gateway reported failure or timeout |
REFUNDED | Refund completed |
Payment status is stored on Order.paymentStatus and updated exclusively by webhook handlers (never by the frontend directly).
4. Settlement Status (per OrderItem)
| State | Description |
|---|---|
HELD | Funds in provider wallet; payout blocked |
RELEASABLE | Delivery confirmed; payout authorised |
PAID_OUT | Payout instruction sent to PawaPay/Flutterwave |
5. Status Transition Actors
| Transition | Actor | API / Trigger |
|---|---|---|
| Created → PENDING | Customer | POST /api/v1/orders |
| PENDING → CONFIRMED | System | Webhook (deposit.completed / charge.completed) |
| CONFIRMED → PROCESSING | Vendor / Admin | Admin dashboard action |
| PROCESSING → SHIPPED | Vendor / Admin | Mark as shipped |
| SHIPPED → OUT_FOR_DELIVERY | Delivery Agent | Agent confirms pickup |
| OUT_FOR_DELIVERY → DELIVERED | Delivery Agent | PIN verification + digital signature (POST /api/v1/delivery/agent/confirm) |
| Any → CANCELLED | Customer / Admin | PATCH /api/v1/orders/:id/cancel |
| HELD → RELEASABLE | System | Automatic on delivery confirmation |
| RELEASABLE → PAID_OUT | System | SettlementLedger.disburseVendorPayouts() (batch job) |
6. Settlement Calculation
Per OrderItem, on payment confirmation:
vendorAmount = item.price × item.quantity × (1 − PLATFORM_COMMISSION_PCT)
platformFee = item.price × item.quantity × PLATFORM_COMMISSION_PCT
Default PLATFORM_COMMISSION_PCT = 0.05 (5%).
VAT (16%) is included in displayed prices and broken out for compliance. It does not affect the vendor/platform split calculation — the split is applied to the total including VAT.
Wholesale tier pricing: If the order quantity qualifies for a wholesale tier, the price used in settlement is the tier price, not the standard price.
7. Refund Scenarios
| Scenario | Steps |
|---|---|
| Customer cancels before payment | Order status → CANCELLED; no payment to refund |
| Customer cancels after payment, before dispatch | Admin initiates refund via PawaPayAdapter.processRefund() or FlutterwaveAdapter.processRefund() |
| Defective item returned after delivery | Admin verifies return → refund initiated; Order.status → REFUNDED |
| Partial refund (one item of multi-item order) | Not yet automated; admin processes manually via gateway dashboard |
8. Delivery Terminology
Pakashop is a Zambia-only platform. All references to movement of goods use delivery language:
| Replaced term | Pakashop term |
|---|---|
| Shipping | Delivery |
| Shipping address | Delivery address |
| Shipping & handling | Delivery fee |
| Shipped | Out for delivery |
| Free shipping | Free delivery |
The order status SHIPPED (stored in the DB for backward compatibility) is displayed to users as "Ready for Pickup" and transitions to "Out for Delivery" when the agent picks up the order.
9. Multi-Vendor Order Splitting
A single order may contain items from multiple vendors (shops). The order is stored as one Order record with multiple OrderItem records, each linked to a different Shop.
- Settlement is calculated and disbursed per shop (vendor).
- The vendor dashboard shows only their items within a given order.
- If one vendor cancels their items, only their
OrderItemrecords are affected; the rest of the order continues normally (partial cancellation support is on the roadmap). - Each shop's
OrderItemhas its ownsettlementStatusand can be released independently.
10. ZRA Smart Invoice Integration
Upon order confirmation (CONFIRMED):
- If ZRA invoicing is enabled (feature flag) and the vendor has a valid TPIN:
pakashop-invoicingservice (port 3013) generates a Smart Invoice payload- Payload transmitted to ZRA VSDC API
- Transmission logged in
ZraInvoicetable
- If mock mode is enabled: simulate transmission, log mock receipt
- Failed transmissions auto-retry (3 attempts, exponential backoff)
- Admin can view transmission status in dashboard
For internal use only. Do not distribute outside Pakashop engineering.