How to Implement an Order Returns and Refunds Workflow in the Mall E-Commerce System

The mall e-commerce system manages order returns and refunds through a state-driven workflow with four distinct statuses (0=pending, 1=confirmed, 2=completed, 3=rejected) implemented across the mall-portal and mall-admin modules using OmsOrderReturnApply entities and the updateStatus() method.

The macrozheng/mall project provides a complete, production-ready implementation of an order returns and refunds workflow that cleanly separates customer-facing request creation from backend administrative processing. This Spring Boot-based platform tracks return applications through a strict lifecycle—from initial submission to final refund completion or rejection—using MyBatis persistence and RESTful API endpoints. The implementation spans two primary modules: mall-portal handles customer submissions, while mall-admin provides the operational interface for review and status management.

Customer Submission: Creating a Return Request

Customers initiate the returns and refunds workflow through the portal module by submitting detailed application data via a dedicated REST endpoint.

Portal Controller Endpoint

The entry point for customer requests is OmsPortalOrderReturnApplyController#create, which exposes the POST /returnApply/create endpoint. This controller receives an OmsOrderReturnApplyParam DTO and delegates persistence to the portal service layer.

// mall-portal/src/main/java/com/macro/mall/portal/controller/OmsPortalOrderReturnApplyController.java
@PostMapping("/create")
public CommonResult create(@RequestBody OmsOrderReturnApplyParam returnApply) {
    int count = returnApplyService.create(returnApply);
    return count > 0 ? CommonResult.success(count) : CommonResult.failed();
}

Service Persistence Logic

The OmsPortalOrderReturnApplyServiceImpl.create() method transforms the input DTO into the persistence model OmsOrderReturnApply, automatically setting the initial status = 0 (pending) and recording the submission timestamp before inserting the record via MyBatis.

// mall-portal/src/main/java/com/macro/mall/portal/service/impl/OmsPortalOrderReturnApplyServiceImpl.java
OmsOrderReturnApply realApply = new OmsOrderReturnApply();
BeanUtils.copyProperties(returnApply, realApply);
realApply.setCreateTime(new Date());
realApply.setStatus(0);
returnApplyMapper.insert(realApply);

The MyBatis mapper OmsOrderReturnApplyMapper persists this data to the oms_order_return_apply table, creating a workflow instance that awaits administrative review.

Admin Processing: Managing Return Status Transitions

Administrators manage the returns and refunds workflow through the mall-admin module, which provides listing capabilities and state transition endpoints governed by the OmsOrderReturnApplyServiceImpl.updateStatus() method.

Core Status Update Logic

The updateStatus() method in OmsOrderReturnApplyServiceImpl implements the state machine logic, handling three valid transitions from the initial pending state:

// mall-admin/src/main/java/com/macro/mall/service/impl/OmsOrderReturnApplyServiceImpl.java
public int updateStatus(Long id, OmsUpdateStatusParam statusParam) {
    Integer status = statusParam.getStatus();
    OmsOrderReturnApply returnApply = new OmsOrderReturnApply();

    if (status.equals(1)) {               // Confirm return
        returnApply.setId(id);
        returnApply.setStatus(1);
        returnApply.setReturnAmount(statusParam.getReturnAmount());
        returnApply.setCompanyAddressId(statusParam.getCompanyAddressId());
        returnApply.setHandleTime(new Date());
        returnApply.setHandleMan(statusParam.getHandleMan());
        returnApply.setHandleNote(statusParam.getHandleNote());
    } else if (status.equals(2)) {        // Complete return
        returnApply.setId(id);
        returnApply.setStatus(2);
        returnApply.setReceiveTime(new Date());
        returnApply.setReceiveMan(statusParam.getReceiveMan());
        returnApply.setReceiveNote(statusParam.getReceiveNote());
    } else if (status.equals(3)) {        // Reject return
        returnApply.setId(id);
        returnApply.setStatus(3);
        returnApply.setHandleTime(new Date());
        returnApply.setHandleMan(statusParam.getHandleMan());
        returnApply.setHandleNote(statusParam.getHandleNote());
    } else {
        return 0;
    }
    return returnApplyMapper.updateByPrimaryKeySelective(returnApply);
}

Status Definitions and Business Rules

Each status value triggers specific business logic and data capture requirements:

  • Status 1 (Confirmed): Admin approves the return, specifies the refund amount (returnAmount), assigns a return warehouse address (companyAddressId), and records handler identity and notes via handleTime and handleMan.
  • Status 2 (Completed): Admin confirms physical receipt of returned goods, records receiveTime and receiveMan, and triggers downstream financial and inventory systems to process the actual refund and stock release.
  • Status 3 (Rejected): Admin denies the request, providing rejection rationale in handleNote without recording any financial transaction data.

The admin controller exposes these transitions via POST /returnApply/update/status, consuming the OmsUpdateStatusParam DTO.

Post-Completion Side Effects: Inventory and Refunds

When the returns and refunds workflow reaches status 2 (completed), the system triggers associated side effects for inventory management and payment processing.

The returnAmount field stored during the confirmation phase (status 1) serves as the authorized refund value that external payment gateways should process upon completion. While the core mall repository does not include specific payment provider integrations, the data model supports this through the persisted OmsOrderReturnApply entity.

For inventory management, completing a return (status 2) conceptually reverses the stock lock placed during order creation. The system utilizes portalOrderDao.releaseSkuStockLock()—typically invoked in order cancellation paths—to restore SKU availability when returns are finalized, ensuring accurate inventory accounting across the warehouse management system.

Practical API Examples

The following cURL commands demonstrate the complete order returns and refunds workflow from customer submission through administrative completion.

Creating a Return Request (Customer)

curl -X POST https://api.example.com/returnApply/create \
  -H "Content-Type: application/json" \
  -d '{
        "orderId": 1024,
        "productId": 215,
        "orderSn": "202310150001",
        "memberUsername": "john.doe",
        "returnName": "John Doe",
        "returnPhone": "13800138000",
        "productPic": "http://img.example.com/215.jpg",
        "productName": "Wireless Mouse",
        "productBrand": "Logitech",
        "productAttr": "颜色:黑色;尺码:标准",
        "productCount": 1,
        "productPrice": 99.99,
        "productRealPrice": 79.99,
        "reason": "商品损坏",
        "description": "收到时包装已破损",
        "proofPics": "http://img.example.com/claim1.jpg,http://img.example.com/claim2.jpg"
      }'

This creates a record with status = 0 and returns {"code":200,"data":1,"message":"操作成功"}.

Listing Pending Returns (Admin)

curl -G https://admin.example.com/returnApply/list \
  -d status=0 \
  -d pageNum=1 \
  -d pageSize=10

Confirming the Return (Status 1)

curl -X POST https://admin.example.com/returnApply/update/status \
  -H "Content-Type: application/json" \
  -d '{
        "id": 5,
        "status": 1,
        "returnAmount": 79.99,
        "companyAddressId": 3,
        "handleMan": "admin1",
        "handleNote": "确认退货,准备退款"
      }'

Completing the Return (Status 2)

curl -X POST https://admin.example.com/returnApply/update/status \
  -H "Content-Type: application/json" \
  -d '{
        "id": 5,
        "status": 2,
        "receiveMan": "finance1",
        "receiveNote": "已退款,释放库存"
      }'

Key Source Files and Implementation Details

The returns and refunds workflow is implemented across the following specific source files in the macrozheng/mall repository:

Summary

  • The mall project implements a four-state returns and refunds workflow (0=pending, 1=confirmed, 2=completed, 3=rejected) managed across separate portal and admin modules.
  • Customers initiate requests via OmsPortalOrderReturnApplyController#create, which persists data with status = 0 through OmsPortalOrderReturnApplyServiceImpl.
  • Administrators transition requests through confirmed and completed states using OmsOrderReturnApplyServiceImpl.updateStatus(), which captures refund amounts, handler information, and receipt timestamps.
  • Status 2 (completed) serves as the trigger point for downstream financial refunds and inventory release operations, with the returnAmount field providing the authorized refund value.
  • All workflow data persists to the oms_order_return_apply table via MyBatis mappers, maintaining a complete audit trail through createTime, handleTime, and receiveTime fields.

Frequently Asked Questions

What are the valid status values in the mall return workflow?

The system defines four integer status values: 0 (待处理/pending) for new customer submissions, 1 (已确认/confirmed) for admin-approved returns awaiting physical receipt, 2 (已完成/completed) for finalized returns triggering refunds and stock release, and 3 (已拒绝/rejected) for denied applications. These values are set via the updateStatus() method in mall-admin/src/main/java/com/macro/mall/service/impl/OmsOrderReturnApplyServiceImpl.java.

How does the system handle inventory when a return is completed?

When an administrator sets status = 2 (completed), the workflow signals that physical goods have been received and verified. At this stage, the system should invoke inventory release mechanisms such as portalOrderDao.releaseSkuStockLock() to restore the returned SKU quantities to available stock, reversing the original order reservation.

Where is the actual payment refund processing implemented?

The mall repository captures the authorized refund amount in the returnAmount field of the OmsOrderReturnApply entity during the confirmation phase (status 1), but it does not include specific payment gateway integrations. The status 2 completion event serves as the integration hook where external financial systems should read this amount and process the actual monetary refund to the customer.

Can customers modify or cancel a return request after submission?

According to the source code analysis, the mall-portal module only provides the create endpoint (/returnApply/create) for initial submission. There is no customer-facing update or delete operation exposed in OmsPortalOrderReturnApplyController. Customers must rely on administrative rejection (status 3) if they need to cancel a request, or contact support to modify application details before an admin confirms the return.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →