Orders and fulfilment

Cart to order to shipment to return on revenexx, the stock those movements consume, the audit feed and the number ranges — four apps, one flow.

Four apps carry this flow, and each owns one stage:

AppBase pathOwns
carts/v1/cartsThe buying workspace, until it becomes an order
orderlists/v1/orderlistsSaved, reusable position collections
orders/v1/ordersThe order, its shipments, cancellations, returns and audit trail
inventories/v1/inventoriesLocations, stock levels, the movements ledger, reservations

The one design rule to internalise

Each route does exactly one thing, and the orchestration is yours. Placing an order does not reserve stock, take payment or talk to an ERP. Shipping does not print a label. Cancelling refunds nothing and returns nothing to stock. Completing a return books the goods on the order and hands you a restock array to pass on.

That is deliberate: an order lifecycle differs per merchant, and an app that fused the steps would be un-composable. What ties the steps together is the event trail — every action writes an order_events row, which is also the domain event a workflow reacts to, so what a workflow saw and what an operator reads cannot diverge.

The happy path

text
POST /v1/carts                       open a cart
POST /v1/carts/{id}/items            add lines
POST /v1/carts/{id}/order            close the cart, hand off  ─┐
POST /v1/orders/place                the order comes into being ┘
POST /v1/orders/{id}/acknowledge     the fulfilling system took it
POST /v1/inventories/reserve         hold the stock
POST /v1/orders/{id}/ship            book goods out
POST /v1/inventories/commit          consume the reservation
POST /v1/orders/{id}/payment-status  record what the money did
POST /v1/orders/{id}/complete        close it (or let shipping close it)

And when goods come back:

text
POST /v1/orders/{id}/return                       register the case
POST /v1/orders/{id}/returns/{rid}/receive        the parcel is here
POST /v1/orders/{id}/returns/{rid}/complete       accept it — books quantity_returned
POST /v1/inventories/restock                      put the sellable goods back
There is no /v1/returns. A return is a sub-resource of an order and has no top-level path. See Returns.

Five status dimensions, and they are orthogonal

DimensionValuesWritten by
statuspending, placed, in_fulfillment, completed, cancelledThe action routes
fulfillment_statusunfulfilled, partial, fulfilledDerived from position arithmetic
payment_statusopen, pending, authorized, paid, partially_paid, refunded, failedFed in by whatever took the money
on_hold + hold_reasonbooleanhold / unhold, and deliberately outside the lifecycle
Return statusregistered, received, completed, rejectedThe four return routes

In this group