Order state machine
Enforced by VALID_ORDER_TRANSITIONS in two files that were identical on 2026-10-01:
order/services/order-state-machine.ts— used byorder-command.service.tsandorder.service.tsorder-status/domain/order-state-machine.ts— used byorder-status.service.ts
The comment lists a shorter set of transitions. It omits ON_HOLD, and it omits several DISPUTED, PARTIALLY_RETURNED, and RETURNED edges that the map includes. The map is what isValidOrderTransition runs.
isValidOrderTransition returns true when from is null or undefined. That allows any initial status when there is no current status. Business intent of that shortcut is unknown.
Allowed transitions
| From | To |
|---|---|
PENDING | CONFIRMED, ON_HOLD, CANCELLED, DISPUTED |
ON_HOLD | PENDING, CONFIRMED, CANCELLED |
CONFIRMED | ON_HOLD, PARTIALLY_FULFILLED, FULFILLED, CANCELLED, DISPUTED |
PARTIALLY_FULFILLED | FULFILLED, CANCELLED, DISPUTED |
FULFILLED | DELIVERED, RETURN_REQUESTED, DISPUTED |
DELIVERED | RETURN_REQUESTED, CLOSED, DISPUTED |
CANCELLED | REFUNDED |
RETURN_REQUESTED | RETURN_RECEIVED, CANCELLED, DISPUTED |
RETURN_RECEIVED | PARTIALLY_RETURNED, RETURNED, REFUNDED, PARTIALLY_REFUNDED, DISPUTED |
PARTIALLY_RETURNED | RETURNED, RETURN_REQUESTED, PARTIALLY_REFUNDED, REFUNDED, CLOSED, DISPUTED |
RETURNED | REFUNDED, PARTIALLY_REFUNDED, CLOSED, DISPUTED |
REFUNDED | CLOSED |
PARTIALLY_REFUNDED | CLOSED, RETURN_REQUESTED, DISPUTED |
DISPUTED | REFUNDED, CLOSED, PENDING |
CLOSED | none |
The diagram omits a few edges that the table includes (PARTIALLY_RETURNED to refund and return-requested, RETURNED to PARTIALLY_REFUNDED, PARTIALLY_REFUNDED to RETURN_REQUESTED and DISPUTED) so it stays readable. The table is complete.
Cancellation
CANCELLED is reachable from PENDING, ON_HOLD, CONFIRMED, PARTIALLY_FULFILLED, and RETURN_REQUESTED. Downstream stock release is whatever order.status.changed listeners do. Whether cancellation of a partially fulfilled order restocks picked units is unknown.
Which transitions the admin UI exposes
Unknown. The map is the server rule. It does not say which buttons operators can click.