Merit · E-Commerce Solution · Product explainer

Order state, explained

Every order in the E-Commerce Solution moves through one service. This page shows what it owns, the states an order can be in, how items and sellers move it, and every feature with the rules to test it by.

Owner: Brian Arfi Faridhi, Product Director · Audience: engineers and product people working on the E-Commerce Solution

01What it owns

It is an order state service, not a full order management system.

Writes an order or its statusE-commerce Corecreates the order from the confirmed basketPaymenteach payment leg moves the orderSeller Portalorder updates arrive by webhookGift card fulfilmentcompleted, partial or failed, by webhookOMSthe order state machine: status, items, history,refunds, expiry. The only service that moves anorderCalled by OMS, or listening to itFulfillment Servicefulfil this lineSettlementruns once the order is finalCommunication Hubtells the member, in the client brandAny subscribernine order events, by webhook

Core hands over the confirmed basket, and from that moment only OMS moves the state. It does not reserve stock, pick a carrier, process a payment or hold product data. Those belong to Core, the Fulfillment Service, Payment and PIM. The service map shows every seam.

02The states

Read off the code, because that is what runs.

DRAFTAWAITING_PAYMENTPAYMENT_COMPLETEDPROCESSINGCONFIRMEDSHIPPEDFULFILLEDThe main path of an orderPARTIALLY_FULFILLEDREFUNDEDEXPIREDFAILEDCANCELLEDTerminal: CANCELLED, REFUNDED, EXPIRED. FAILED and PARTIALLY_FULFILLED can go back to PROCESSING, for gift cards only, when an item is reprocessed.Payment status runs beside it: UNPAID, PARTIALLY_PAID, FULLY_PAID, PARTIALLY_REFUNDED, FULLY_REFUNDED.

Twelve order states, as the code defines them. Any other move is rejected with INVALID_ORDER_STATUS_TRANSITION. The table below lists every allowed move.

FromAllowed next states
DRAFTAWAITING_PAYMENT, CANCELLED, EXPIRED
AWAITING_PAYMENTPAYMENT_COMPLETED, FAILED, CANCELLED, EXPIRED
PAYMENT_COMPLETEDPROCESSING, CANCELLED, REFUNDED
PROCESSINGCONFIRMED, PARTIALLY_FULFILLED, FULFILLED, FAILED, CANCELLED
CONFIRMEDSHIPPED, PARTIALLY_FULFILLED, CANCELLED
SHIPPEDFULFILLED
PARTIALLY_FULFILLEDFULFILLED, REFUNDED, PROCESSING (gift cards only)
FULFILLEDREFUNDED
FAILEDDRAFT, PROCESSING (gift cards only)
CANCELLED, REFUNDED, EXPIREDnone, terminal

03How an order moves

Items move first, and the order follows them.

From items to the order

When the items areThe order becomes
Any item PROCESSINGPROCESSING
Every item CONFIRMED, SHIPPED, FULFILLED, REFUNDED, FAILED or CANCELLEDthe same status
Settled items that disagree, such as FULFILLED and FAILED togetherPARTIALLY_FULFILLED
Items still pending or in progress in a mixno change yet, wait for more updates

From the Seller Portal to OMS

Seller Portal statusOMS item status
IN_PROCESSPROCESSING
CONFIRMEDCONFIRMED
READY_TO_SHIPCONFIRMED, with carrier sub-status READY_TO_SHIP
SHIPPEDSHIPPED
DELIVEREDFULFILLED
CANCELEDCANCELLED
SHIPPED_TO_MERIT, RETURN statesCONFIRMED, with the matching carrier sub-status

04Cancel and refund

Cancelling and refunding are two separate things.

Who cancelsmember, seller, Merit OpsOMSthe order stateMerchandise servicethe seller sidePaymentthe refundMember, or Merit Opscancel, with a reasontrigger recorded as CUSTOMER, SYSTEM or ADMINrefund requesta person approves it in Phase 1Seller, before shipment onlycancel, reason from a dropdownCANCELED by webhookautomatic refund requestcancel and refund are two calls to two services

Two ways in, one refund path. For Al Fursan, client staff cannot cancel: cancelling is a Merit Ops action, and the client keeps the order report.

05Where the spec and the code differ

The PRDs were written before the build. Each row needs one answer: update the PRD, or change the code.

TopicThe PRD saysThe code does
Order statesSeven: DRAFT, PENDING, CONFIRMED, FULFILLED, CANCELLED, FAILED, REFUNDEDTwelve. PENDING is split into AWAITING_PAYMENT and PAYMENT_COMPLETED, and PROCESSING, SHIPPED, PARTIALLY_FULFILLED and EXPIRED are added
Unpaid ordersCancelled after 30 minutes, reason SYSTEM_PAYMENT_TIMEOUTExpired after 15 minutes, to EXPIRED, not CANCELLED
SLA breachA CONFIRMED order past its SLA is escalated to a LiveOps queueNot found in the code
Partial fulfilmentNo order-level state for itPARTIALLY_FULFILLED exists at order level
Refund statesREQUESTED, VALIDATED, REJECTED, ESCALATED, SUBMITTED, COMPLETED, FAILEDPENDING, APPROVED, PROCESSING, COMPLETED, REJECTED, CANCELLED
Refund amountFull amount only in Phase 1Any amount from 0.01 is accepted
Bulk gift card ordersOne parent order, batched into calls of fiveThe five-item limit exists. The parent order does not
Event namesorder.created, order.confirmed and so onORDER_CREATED and eight more, including ORDER_PARTIALLY_FULFILLED and ORDER_EXPIRED

06Feature map

Every feature and the services it crosses. A story is split per service by engineering, not by product.

07Features

Who each one serves, what it does, the rules to test it by, and its spec. OPEN marks a question not yet decided.

F01

Create an order

MemberClient

As a member, I pay once and get exactly one order, even if my app retries.

Core creates the order from the confirmed basket. The order carries its items, the customer, the tenant and the payment legs.

  • Every create carries an idempotency key. A retry returns the same order.
  • Status changes run under a row lock, so two updates never cross.
  • Each item carries a product domain: merchandise, gift card, booking, add-on or subscription.
E-commerce CoreOMSPayment
Spec: PRD OMS Core Infrastructure. Code: POST /orders
F02

Status from payment

Member

As a member paying with points and card, my order confirms only when both legs are paid.

Each payment leg is tracked on its own. The order status follows the legs.

  • All legs pending: DRAFT. Some authorised: AWAITING_PAYMENT. All captured: PAYMENT_COMPLETED.
  • All legs failed, cancelled or refunded moves the order to the same state.
  • Payment status is tracked beside the order status, from UNPAID to FULLY_REFUNDED.
OMSPayment
Spec: PRD Order State Machine. Code: the order state machine
F03

Unpaid orders expire

Member

As a member who abandons checkout, my reserved basket does not stay open forever.

A job finds DRAFT and AWAITING_PAYMENT orders past their expiry time and moves them to EXPIRED.

  • The default time to live is 15 minutes.
  • The payment legs expire with the order.
  • EXPIRED is terminal.
OMSPayment
Spec: PRD Order State Machine. Code: the order expiry job
F04

Fulfilment and status roll-up

MemberMerit Ops

As a member with a phone and a gift card in one order, I see each item move on its own.

OMS asks the Fulfillment Service to fulfil each line, and each item carries its own status. The order status is derived from its items, per the roll-up table in section 03.

  • Item statuses: PENDING, PROCESSING, CONFIRMED, SHIPPED, PARTIALLY_FULFILLED, FULFILLED, FAILED, CANCELLED, REFUNDED.
  • OMS never talks to a carrier. The Fulfillment Service does.
OMSFulfillment Service
F05

Seller Portal orders

Seller

As a seller, what I do in the portal shows up as the order status everywhere else.

Merchandise orders enter OMS through an internal path, with no customer id and no payment legs. Seller actions come back as webhooks and map to OMS statuses, per the table in section 03.

  • Idempotency key per seller order: sp, tenant id, merchandise order id.
  • OMS is the source of truth for the status the Seller Portal shows.
Seller PortalOMS
Spec: Code: the merchandise orders service and status map
F06

Gift card fulfilment and reprocess

MemberMerit Ops

As Merit Ops, when one gift card in an order fails, I retry that one without touching the rest.

Gift cards are issued through the legacy gift card engine. A failed or partly fulfilled item can be reprocessed.

  • One call carries up to five gift cards. Larger lines go through the bulk path.
  • Only items in PARTIALLY_FULFILLED or FAILED can be reprocessed.
  • Transient failures retry with backoff. A supplier reject or out of stock does not retry.
OMSFulfillment Service
Spec: PRD OMS Refund Flow, retry policy. Code: POST /orders/:id/reprocess
F07

Cancellation

MemberSellerMerit Ops

As a seller who cannot fulfil, I cancel before shipping and the member is refunded.

An order or item is cancelled with a reason and a trigger: customer, system or admin.

  • A seller cancels only before shipment, with a reason from a dropdown.
  • A seller cancel happens in the merchandise service. The refund is a separate call.
  • For Al Fursan, client staff cannot cancel. Merit Ops can.
OMSSeller PortalStorefront Admin PortalPayment
Spec: PRD OMS Refund Flow, seller cancellation
F08

Refunds

Merit OpsMember

As customer care, I refund an order or one item, and the record shows who asked and why.

A refund belongs to an order or to one item. A failed fulfilment that runs out of retries opens a refund request by itself. A person still approves it.

  • Refundable only from CONFIRMED or FULFILLED in the spec.
  • Refund window per country. Saudi Arabia: 14 days from delivery.
  • Card refunds must stay inside the payment provider window of 30 days.
  • Partial refund amounts, and refunds on mixed points and card payments.OPEN
OMSPayment
F09

Cooling-off delay

Merit Ops

As the fraud team, a risky gift card order waits a few hours before it is fulfilled.

Admin rules hold an order before fulfilment. They match on product type, minimum price, category or collection. When several match, the longest wait wins.

  • The item stays Placed. No new status, and the member sees no difference.
  • Reprocess is blocked inside the window. Cancel and refund are allowed.
  • The rules are set in the Storefront Admin Portal, and OMS applies them.
OMSStorefront Admin Portal
Spec: Al Fursan migration PRD, cooling period
F10

Status history

Merit OpsFinance

As Merit Ops, I can see every status an order went through, when, and who moved it.

Every change writes a row to the order status history.

  • Append only. A row is never edited.
  • Each row records what triggered it: platform, system or admin.
OMS
F11

Order events

Engineering

As a downstream service, I subscribe to the order events I need instead of polling.

OMS sends nine events to registered webhook endpoints.

  • ORDER_CREATED, ORDER_CONFIRMED, ORDER_PROCESSING, ORDER_PARTIALLY_FULFILLED, ORDER_FULFILLED, ORDER_CANCELLED, ORDER_REFUNDED, ORDER_FAILED, ORDER_EXPIRED.
  • Notifications and settlement react to these events. OMS does not call them directly.
OMSSettlementCommunication Hub
F12

Seller order reference

Seller

As a seller packing boxes, I read a short reference, not a long system id.

A short reference sits next to the system order id and is printed on the pick and pack label.

  • Format SELLER_PREFIX-YYMMDD-NNNN, for example AF-260819-0042.
  • The counter runs per seller per day and resets at Riyadh midnight.
  • Never usable to look an order up: not in a URL, not in an API.
Seller PortalOMS
Spec: Seller Portal operations requirements
F13

Bulk gift card orders

Client

As a client ordering 3,000 gift cards, I place one order and track one status.

Large gift card orders are split into calls of five behind one order the client sees.

  • Bulk orders over five items: 24 hour SLA. Five or fewer: instant.
  • The parent order that holds the batches is not built yet, and partial failure handling is not decided.OPEN
OMSFulfillment Service
F14

Settlement trigger

Finance

As Finance, money moves only when an order is final.

Settlement is its own service. It runs once fulfilment completes or breakage happens, turns the hold into a charge, and records the revenue line.

  • OMS tracks the order. Settlement tracks the money.
  • Delivery and its money consequences are never built as one thing.
OMSSettlement
Spec: the service map, section 07
F15

Cashback release

Member

As an Al Fursan member, my Miles cashback lands after delivery, not at payment.

Earned cashback is released by order state, anchored on delivery.

  • Delivery must happen first. An open return, refund, cancellation or care case freezes release.
  • A refund for non-delivery cancels the order and the earn together.
  • Phase 1 cancels and returns the whole order. Per item comes later.
OMSPayment
Spec: Al Fursan earn model decisions

08Glossary

The order words, used the same way every time.

Open the glossary, 10 terms
OMS
Order state management. Records the order and moves its state. Nothing else writes the status.
Order status
One of the twelve states in section 02.
Item status
The fulfilment status of one line. The order status is derived from them.
Payment leg
One part of the payment, such as the points part or the card part.
Idempotency key
A key sent with a request so a retry never creates a second order.
Reprocess
Retrying a failed or partly fulfilled gift card item.
Cooling-off delay
A hold before fulfilment, set by fraud rules. Invisible to the member.
Expiry
An unpaid order past its time to live. It moves to EXPIRED.
Settlement
The service that turns a hold into a charge once the order is final.
Breakage
Gift card value never revealed or used. It becomes revenue after the rule period.