# How the Order Workflow and State Machine Work in Mall (macrozheng/mall)

> Explore the order workflow and state machine in the macrozheng/mall e-commerce platform. Understand how the integer status field and service methods manage order transitions from pending payment to invalid.

- Repository: [macro/mall](https://github.com/macrozheng/mall)
- Tags: internals
- Published: 2026-02-28

---

**The Mall e-commerce platform implements a finite-state machine for orders using an integer `status` field in the `OmsOrder` entity, with six distinct states ranging from pending payment (0) to invalid (5), guarded by service methods in `OmsPortalOrderServiceImpl` and `OmsOrderServiceImpl` that enforce valid transitions.**

The `macrozheng/mall` repository provides a comprehensive Spring Boot e-commerce solution with sophisticated order lifecycle management. The **order workflow and state machine** architecture ensures data integrity by codifying business rules—such as preventing payment on cancelled orders—directly into the service layer transition guards.

## Order State Definitions in OmsOrder

At the core of the workflow is the `OmsOrder` model class located at [`mall-mbg/src/main/java/com/macro/mall/model/OmsOrder.java`](https://github.com/macrozheng/mall/blob/main/mall-mbg/src/main/java/com/macro/mall/model/OmsOrder.java). The Javadoc on line 52 defines the `status` field as an integer representing the order's lifecycle stage:

- **0**: **待付款** (Pending payment)
- **1**: **待发货** (Waiting for delivery / Paid)
- **2**: **已发货** (Shipped)
- **3**: **已完成** (Completed / Buyer confirmed receipt)
- **4**: **已关闭** (Closed / Cancelled)
- **5**: **无效订单** (Invalid / Reserved for future use)

The system treats this `status` column as the single source of truth, with all transitions mediated through specific service methods that validate preconditions before persisting changes.

## Order Creation and Initial State

New orders enter the system with **status 0** (pending payment). In [`mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderServiceImpl.java), the `generateOrder` method instantiates an `OmsOrder` object and explicitly sets the initial state at line 197:

```java
order.setStatus(0);

```

At this stage, the order is persisted to the database and a delayed message is queued for automatic timeout handling. No permanent inventory deduction occurs yet; stock remains locked pending payment confirmation.

## Payment Success Transition (0 → 1)

When a buyer completes payment, the `paySuccess` method at line 55 of [`OmsPortalOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsPortalOrderServiceImpl.java) executes the transition to **status 1** (waiting for delivery). This method enforces a critical guard condition: it verifies the current status is exactly `0` before proceeding.

```java
// Simplified logic from OmsPortalOrderServiceImpl.java
if (order.getStatus() != 0) {
    throw new BusinessException("Order is not in pending payment status");
}
order.setStatus(1);
order.setPaymentTime(new Date());

```

If the order has already been cancelled (status 4) or is in any other state, the payment is rejected to prevent charging customers for invalid orders.

## Backend Shipment Transition (1 → 2)

The transition to **status 2** (shipped) is initiated by administrators through the `delivery` method in [`mall-admin/src/main/java/com/macro/mall/service/impl/OmsOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/mall-admin/src/main/java/com/macro/mall/service/impl/OmsOrderServiceImpl.java). At line 52, the service creates an `OmsOrderOperateHistory` entry with `orderStatus = 2` to audit the shipment event.

While the current implementation primarily logs this via history records, the state change signals to the frontend that logistics information—such as tracking numbers—has been associated with the order. The buyer can now view shipment details and anticipate delivery.

## Buyer Confirmation Transition (2 → 3)

Once the buyer receives the goods, they invoke `confirmReceiveOrder` at line 66 of [`OmsPortalOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsPortalOrderServiceImpl.java) to transition the order to **status 3** (completed). This method applies two validation guards:

1. **Ownership verification**: The order must belong to the currently authenticated user.
2. **State verification**: The order must currently have **status 2** (shipped).

Upon successful validation, the method updates `status` to `3`, sets the confirmation flag, and records the receipt timestamp, effectively closing the transaction lifecycle from the buyer's perspective.

## Order Cancellation and Closure (→ 4)

Orders transition to **status 4** (closed) through three distinct pathways, all implemented in the service layer:

### Automated Timeout Cancellation

The `OrderTimeOutCancelTask` scheduled component runs every ten minutes to identify unpaid orders exceeding their expiration window. It delegates to `cancelTimeOutOrder` at line 94 of [`OmsPortalOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsPortalOrderServiceImpl.java), which executes:

```java
// Batch update from status 0 to 4 for expired orders
portalOrderDao.updateOrderStatus(orderIds, 4);

```

This batch operation releases locked inventory and reverts any applied coupon usage automatically.

### Manual Cancellation

Administrators may manually cancel pending orders via the `cancelOrder` method at line 25 of [`OmsPortalOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsPortalOrderServiceImpl.java). This method specifically targets orders with `status = 0`, updating them to `4` while triggering resource reclamation.

### Administrative Closure

For disputes or post-payment issues, the `close` method at line 63 of [`OmsOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsOrderServiceImpl.java) creates a new `OmsOrder` record—or updates existing records—to **status 4**, providing a formal audit trail for forced terminations outside the standard workflow.

## Invalid State Reservation (5)

**Status 5** (invalid order) is defined in the `OmsOrder` entity but remains unused in the current codebase. It is reserved for future data-migration scenarios or soft-delete implementations where orders must be retained for audit purposes while being excluded from active business metrics.

## State Transition Guards and Enforcement

The state machine enforces business rules through explicit guard clauses in service methods:

- **Transition 0 → 1**: `paySuccess` validates `status == 0`
- **Transition 2 → 3**: `confirmReceiveOrder` validates `status == 2`
- **Transition to 4**: Cancellation methods validate the order is cancellable (typically status 0)

These guards prevent illegal transitions—such as attempting to ship a cancelled order or paying a completed order—at the application layer before any database update occurs.

## Practical Implementation Examples

The following snippets demonstrate typical service invocations for managing the order lifecycle:

```java
// Create order (status becomes 0)
Map<String, Object> result = portalOrderService.generateOrder(orderParam);

// Process payment (status 0 → 1)
int updated = portalOrderService.paySuccess(orderId, 1); // 1 = Alipay

// Admin marks as shipped (status 1 → 2)
List<OmsOrderDeliveryParam> deliveries = Collections.singletonList(
    new OmsOrderDeliveryParam(orderId, "SF Express", "SF123456789", 1));
int shipped = orderService.delivery(deliveries);

// Buyer confirms receipt (status 2 → 3)
portalOrderService.confirmReceiveOrder(orderId);

// Cancel unpaid order (status 0 → 4)
orderService.cancelOrder(orderId);

```

## Summary

- The **order workflow and state machine** in `macrozheng/mall` uses six integer states (0-5) defined in [`OmsOrder.java`](https://github.com/macrozheng/mall/blob/main/OmsOrder.java) to model the complete e-commerce lifecycle from pending payment through completion or cancellation.
- State transitions are guarded by methods in `OmsPortalOrderServiceImpl` (frontend) and `OmsOrderServiceImpl` (backend) that validate preconditions before updating the `status` field, ensuring illegal transitions are rejected.
- Automated timeout handling via `OrderTimeOutCancelTask` ensures unpaid orders automatically close after expiration, releasing inventory resources and reverting coupon usage without manual intervention.
- The architecture separates concerns between customer-facing actions (payment, confirmation) and administrative controls (shipping, forced closure) while maintaining data integrity through rigorous status validation at the service layer.

## Frequently Asked Questions

### What are the integer status values for orders in the Mall project?

The `OmsOrder.status` field uses six integer codes defined at line 52 of [`mall-mbg/src/main/java/com/macro/mall/model/OmsOrder.java`](https://github.com/macrozheng/mall/blob/main/mall-mbg/src/main/java/com/macro/mall/model/OmsOrder.java): **0** (pending payment), **1** (waiting for delivery), **2** (shipped), **3** (completed), **4** (closed/cancelled), and **5** (invalid/reserved).

### How does Mall prevent invalid order state transitions?

Service methods enforce **guard conditions** that check the current `status` before allowing updates. For example, `paySuccess` in [`OmsPortalOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsPortalOrderServiceImpl.java) throws an exception if the order status is not `0`, and `confirmReceiveOrder` requires status `2`. This prevents operations like paying for cancelled orders or confirming receipt of unshipped items.

### What triggers automatic order cancellation in the Mall workflow?

The `OrderTimeOutCancelTask` scheduled task runs every ten minutes to detect unpaid orders past their expiration time. It calls `cancelTimeOutOrder` in [`OmsPortalOrderServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsPortalOrderServiceImpl.java) (line 94), which batch-updates eligible orders from status `0` to `4` and releases locked stock and coupons automatically.

### Can an order move from "shipped" (status 2) back to "waiting for delivery" (status 1)?

No, the state machine does not support backward transitions. Once `confirmReceiveOrder` or administrative closure methods update the status, the change is unidirectional. Business reversals—such as returns—are handled through separate return-apply workflows in [`OmsPortalOrderReturnApplyServiceImpl.java`](https://github.com/macrozheng/mall/blob/main/OmsPortalOrderReturnApplyServiceImpl.java) rather than by reverting the main order state.