Skip to main content

Order Lifecycle

Related docs: Checkout Flow · Payment Architecture · Delivery Tracking · Delivery Signing


1. Order Status State Machine


2. Order Statuses

StatusDescriptionActor
PENDINGOrder created; payment not yet confirmedSystem (on order creation)
CONFIRMEDPayment received and verified via webhookSystem (webhook handler)
PROCESSINGVendor has accepted and is preparing the orderVendor / Admin
SHIPPEDOrder packed and ready for pickupVendor / Admin
OUT_FOR_DELIVERYOrder handed to agent; GPS tracking activeDelivery Agent
DELIVEREDPIN-based confirmation + digital signature completedDelivery Agent / Customer
CANCELLEDOrder cancelled; no payment or pre-dispatchCustomer / Admin
REFUNDEDRefund issued to customerAdmin

3. Payment Status

StatusDescription
PENDINGPayment initiated; awaiting confirmation
PAIDConfirmed via webhook (InboundPayment.status = CAPTURED)
FAILEDGateway reported failure or timeout
REFUNDEDRefund completed

Payment status is stored on Order.paymentStatus and updated exclusively by webhook handlers (never by the frontend directly).


4. Settlement Status (per OrderItem)

StateDescription
HELDFunds in provider wallet; payout blocked
RELEASABLEDelivery confirmed; payout authorised
PAID_OUTPayout instruction sent to PawaPay/Flutterwave

5. Status Transition Actors

TransitionActorAPI / Trigger
Created → PENDINGCustomerPOST /api/v1/orders
PENDING → CONFIRMEDSystemWebhook (deposit.completed / charge.completed)
CONFIRMED → PROCESSINGVendor / AdminAdmin dashboard action
PROCESSING → SHIPPEDVendor / AdminMark as shipped
SHIPPED → OUT_FOR_DELIVERYDelivery AgentAgent confirms pickup
OUT_FOR_DELIVERY → DELIVEREDDelivery AgentPIN verification + digital signature (POST /api/v1/delivery/agent/confirm)
Any → CANCELLEDCustomer / AdminPATCH /api/v1/orders/:id/cancel
HELD → RELEASABLESystemAutomatic on delivery confirmation
RELEASABLE → PAID_OUTSystemSettlementLedger.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

ScenarioSteps
Customer cancels before paymentOrder status → CANCELLED; no payment to refund
Customer cancels after payment, before dispatchAdmin initiates refund via PawaPayAdapter.processRefund() or FlutterwaveAdapter.processRefund()
Defective item returned after deliveryAdmin 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 termPakashop term
ShippingDelivery
Shipping addressDelivery address
Shipping & handlingDelivery fee
ShippedOut for delivery
Free shippingFree 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 OrderItem records are affected; the rest of the order continues normally (partial cancellation support is on the roadmap).
  • Each shop's OrderItem has its own settlementStatus and can be released independently.

10. ZRA Smart Invoice Integration

Upon order confirmation (CONFIRMED):

  1. If ZRA invoicing is enabled (feature flag) and the vendor has a valid TPIN:
    • pakashop-invoicing service (port 3013) generates a Smart Invoice payload
    • Payload transmitted to ZRA VSDC API
    • Transmission logged in ZraInvoice table
  2. If mock mode is enabled: simulate transmission, log mock receipt
  3. Failed transmissions auto-retry (3 attempts, exponential backoff)
  4. Admin can view transmission status in dashboard

For internal use only. Do not distribute outside Pakashop engineering.