Orders
An order's life after checkout, its status flow, and where the three third parties move it along.
How this page was verified
Read on 2026-09-15 from the backend orders module (service, cron, resolvers), the storefront /user/my-order, and the admin /admin/orders (view only).
The model and statuses
Tables: orders, order_items, order_addresses. Status values (utils/order-status.const.ts):
| Status | Meaning |
|---|---|
pending_payment | created, waiting for the customer to pay |
processing | paid (DOKU success), being prepared |
shipped | handed to the courier / picked by the WMS |
completed | delivered |
canceled | cancelled (by the customer, or expired unpaid) |
What moves an order between statuses
The order is created pending_payment by createOrder() (see Cart and checkout). After that, the three third parties drive it — each through its inbound webhook:
- DOKU —
webhook-payments.service.ts: ontransaction.status === 'SUCCESS'the order goes toprocessing. - WMS —
webhook-wms.service.ts: an inbound WMS sales-order event moves the order toshipped(deliveryprocessing). - Biteship —
webhook-deliveries.service.ts: maps Biteship tracking to deliveryshipped/delivered; on delivered the order goes tocompleted.
See Third parties for how the callbacks arrive.
The expiry cron
OrdersCronService.handleOrderPaymentExpiry (src/orders/services/orders-cron.service.ts) runs every minute. It finds pending_payment orders past paymentExpiredAt, re-checks the DOKU status, and cancels the expired ones — cancelling the WMS order and the Biteship draft too. This is the only cron in the backend.
Resolvers
- CMS (
orders.resolver):orders,order,orderTransactionMetrics. - Storefront (
storefront-orders.resolver):frontMemberOrders(search, status),frontMemberOrder(orderId),frontCancelMemberOrder(orderId). - REST (
orderscontroller):GET excelexport, test-email endpoints, and a fix endpointfix/update-order-wms-status/:orderId.
Storefront
/user/my-order (src/app/user/my-order/page.tsx) — order history with ?status= tabs (e.g. pending_payment). UI in src/modules/my-order/components/ (item, detail, status tabs, status badge, search). "Pay again" re-opens DOKU from the order detail. Cancel calls frontCancelMemberOrder.
Admin
/admin/orders is view only — list page.tsx and [slug] detail. src/lib/orders/index.ts has only orders and order queries, no mutations, so status changes are not wired in the admin; the webhooks drive them.
Gotchas
- The admin cannot change an order's status. Status flows from the webhooks, not from a button.
- Order number prefix is
EXSPORT_ORDER_NO_PREFIX; notification emails are gated byEXSPORT_ORDER_SHOULD_SEND_NOTIF_EMAIL.