Skip to content
OrderAgentOrderAgent

The order lifecycle

Every status an order can hold, what moves it, what locks it, and when stock is reserved or restored.

Every order holds exactly one status. This page lists them all, what moves an order between them, and — the part that matters most — when stock moves.

The statuses

StatusMeaningStock
DRAFTBuilt from a message, not yet confirmed by the customer.Not reserved
PAYMENT_PENDINGConfirmed. Stock reserved, prices frozen, deadline running.Reserved
PAYMENT_REVIEWA receipt arrived and was rejected. Locked until a new one arrives.Reserved
PAIDYou approved the payment. Invoice issued.Reserved (sold)
PACKINGBeing picked and packed.Sold
OUT_FOR_DELIVERYOn the van.Sold
DELIVEREDComplete.Sold
CANCELLEDCancelled by the customer or by you.Restored
EXPIREDThe payment deadline passed unpaid.Restored

CONFIRMED exists on old records. It is not used by the live flow — a confirm moves an order straight from DRAFT to PAYMENT_PENDING.

The normal path

DRAFT → PAYMENT_PENDING → PAID → PACKING → OUT_FOR_DELIVERY → DELIVERED

What moves an order

TransitionTriggered by
DRAFTPAYMENT_PENDINGThe customer tapping Confirm
PAYMENT_PENDINGPAIDYou, and only you
PAYMENT_PENDINGPAYMENT_REVIEWYou rejecting a receipt
PAYMENT_REVIEWPAYMENT_PENDINGThe customer sending a fresh receipt
PAYMENT_PENDINGEXPIREDThe deadline passing, unpaid
Any pre-fulfilment status → CANCELLEDThe customer, or you
PAIDPACKINGOUT_FOR_DELIVERYDELIVEREDYou, from WhatsApp or the dashboard

Which statuses are open to change

A draft is the only status you can add to. While an order is a draft, any further order-shaped message from that customer joins it, and adding a product already on the order merges into that line.

Once it moves to awaiting payment it is locked. A new order-shaped message gets told payment is outstanding, rather than either appending to a reserved order or opening a second one silently. A request to change a quantity or remove a line raises an alert for you instead of acting.

This boundary was deliberately tightened. It used to sit much later, and the result was orders changing shape after the customer had already been told what to pay.

Expiry

An unpaid order expires at its deadline — normally 24 hours after confirm. Expiry restores the stock and marks the order EXPIRED, which is deliberately distinct from CANCELLED: one is a deadline, the other is a decision, and you will want to tell them apart when you look back at a month.

Expiry is safe to run twice. It re-checks the status and the deadline before touching anything, so a payment landing at the same moment can never cause a double restore.

Extending a deadline

EXTEND FB-1204 pushes the deadline out, from WhatsApp or from the order screen. Use it when a customer says the transfer is coming — it is cheaper than letting the order expire and rebuilding it.

Extending is only available on statuses where a deadline is meaningful. The button is disabled elsewhere for the same reason the command refuses: they read the same list.

Reading an order's history

Every order screen shows its full payment history, including rejected receipts. That history is the audit trail. A rejected receipt disappearing would remove exactly the record you would want if a customer disputed something.