引言

在上一篇《OMS订单管理系统全景图》中,我们建立了对OMS的全局认知。本文将深入OMS的基础层,理解订单管理领域的核心概念和数据模型设计。

掌握这些概念,是设计一个高质量OMS系统的基础。


一、OMS核心概念

1.1 订单(Order)

定义:订单是买卖双方的一份合约,记录了商品、价格、数量、地址、时间等信息。

订单的三个维度

维度1:业务维度

从业务角度看,订单包含:

  • 订单头(Order Header):订单号、下单时间、客户信息、收货地址、总金额
  • 订单行(Order Line):商品SKU、数量、单价、小计

维度2:系统维度

从系统角度看,订单包含:

  • 原始订单(Source Order):来自渠道的原始订单
  • 内部订单(Internal Order):OMS内部统一格式的订单
  • 子订单(Sub Order):拆分后的订单

维度3:状态维度

从状态角度看,订单有生命周期:

  • 创建 → 待支付 → 已支付 → 待审核 → 待分配 → 待出库 → 已出库 → 配送中 → 已签收 → 已完成

1.2 子订单(Sub Order)

定义:原始订单经过拆分后生成的订单。

拆分场景

场景1:跨仓拆分

原始订单:
- 商品A(北京仓)x 1
- 商品B(上海仓)x 1

拆分为2个子订单:
- 子订单1:商品A x 1(北京仓)
- 子订单2:商品B x 1(上海仓)

场景2:跨品类拆分

原始订单:
- 图书(普通仓)x 1
- 生鲜(冷链仓)x 1

拆分为2个子订单:
- 子订单1:图书 x 1(普通仓)
- 子订单2:生鲜 x 1(冷链仓)

场景3:预售+现货拆分

原始订单:
- 预售商品(15天后发货)x 1
- 现货商品(立即发货)x 1

拆分为2个子订单:
- 子订单1:预售商品 x 1(15天后处理)
- 子订单2:现货商品 x 1(立即处理)

关键设计要点

  • 子订单有独立的订单号
  • 子订单共享父订单的客户信息
  • 子订单状态独立变化
  • 父订单状态由所有子订单状态聚合决定

1.3 订单行(Order Line / Order Item)

定义:订单中的每一个商品明细。

订单行结构

{
  "line_id": "LINE001",
  "order_id": "ORD20251122001",
  "sku": "MACBOOK-PRO-14",
  "product_name": "MacBook Pro 14寸",
  "quantity": 1,
  "unit_price": 14999.00,
  "discount": 0.00,
  "tax": 0.00,
  "subtotal": 14999.00,
  "warehouse": "SHA",
  "status": "PENDING_SHIP"
}

订单行的状态机

待处理 → 待出库 → 已出库 → 配送中 → 已签收 → 已完成
                    ↓
                  缺货 → 取消 / 补货

1.4 SKU(Stock Keeping Unit)

定义:库存保有单位,是库存管理的最小单位。

SKU与商品的关系

商品:iPhone 15
├── SKU1: iPhone 15 黑色 128GB
├── SKU2: iPhone 15 黑色 256GB
├── SKU3: iPhone 15 白色 128GB
└── SKU4: iPhone 15 白色 256GB

SKU编码设计

SKU: IPHONE-15-BLK-128GB
     └─┬──┘ └┬┘ └┬┘ └──┬──┘
       │     │   │     └─ 规格
       │     │   └─ 颜色
       │     └─ 型号
       └─ 品类

1.5 订单类型

类型1:按来源分类

  • B2C订单:消费者订单(淘宝、京东)
  • B2B订单:企业订单(批发、大客户)
  • O2O订单:线上下单、线下自提

类型2:按履约方式分类

  • FBM(Fulfilled by Merchant):商家自发货
  • FBA(Fulfilled by Amazon):亚马逊代发货
  • JIT(Just In Time):零库存订单,收到订单后再采购

类型3:按特殊属性分类

  • 预售订单:提前预定,延期发货
  • 赠品订单:促销活动赠品
  • 售后订单:退货、换货、补发

二、订单状态机设计

2.1 订单状态机的核心原则

原则1:单向流转

  • 订单状态应该单向流转,避免循环(如:已发货 → 待发货)
  • 异常状态通过独立的状态表示(如:缺货、取消)

原则2:状态粒度适中

  • 状态过细:增加系统复杂度
  • 状态过粗:缺少监控点

原则3:状态与动作分离

  • 状态:订单当前所处的阶段(名词)
  • 动作:触发状态变化的事件(动词)

2.2 标准订单状态机

                    +----------------+
                    |   CREATED      |  订单创建
                    +----------------+
                            ↓ 提交订单
                    +----------------+
                    | PENDING_PAYMENT|  待支付
                    +----------------+
                      ↓              ↓
                支付成功        支付超时/取消
                      ↓              ↓
            +----------------+   +----------------+
            |     PAID       |   |   CANCELLED    |  已取消
            +----------------+   +----------------+
                      ↓
            +----------------+
            |   APPROVED     |  审核通过
            +----------------+
                      ↓
            +----------------+
            | PENDING_ALLOCATE| 待分配仓库
            +----------------+
                      ↓
            +----------------+
            | PENDING_SHIP   |  待出库
            +----------------+
                      ↓
            +----------------+
            |    SHIPPED     |  已出库
            +----------------+
                      ↓
            +----------------+
            |  IN_TRANSIT    |  配送中
            +----------------+
                      ↓
            +----------------+
            |   DELIVERED    |  已签收
            +----------------+
                      ↓
            +----------------+
            |   COMPLETED    |  已完成
            +----------------+

2.3 状态转换规则表

当前状态触发动作下一状态系统动作
CREATED提交订单PENDING_PAYMENT生成支付链接
PENDING_PAYMENT支付成功PAID库存预占、发送订单处理消息
PENDING_PAYMENT支付超时CANCELLED释放库存(如有)
PAID审核通过APPROVED进入订单处理流程
PAID审核不通过CANCELLED退款、释放库存
APPROVED仓库分配成功PENDING_ALLOCATE记录分配仓库
PENDING_ALLOCATE订单下发WMS成功PENDING_SHIP生成出库指令
PENDING_SHIPWMS反馈已发货SHIPPED生成运单号、通知客户
SHIPPED物流揽收IN_TRANSIT开始物流追踪
IN_TRANSIT客户签收DELIVERED扣减实际库存、同步ERP结算
DELIVERED确认收货(或自动)COMPLETED订单归档、支持售后(7-15天)
任意状态用户申请取消CANCELLED根据当前状态,执行相应回滚(释放库存、退款、取消出库)

2.4 状态机代码实现

方式1:枚举+Switch(简单场景)

public enum OrderStatus {
    CREATED,
    PENDING_PAYMENT,
    PAID,
    APPROVED,
    PENDING_ALLOCATE,
    PENDING_SHIP,
    SHIPPED,
    IN_TRANSIT,
    DELIVERED,
    COMPLETED,
    CANCELLED
}

public class OrderService {
    public void changeStatus(Order order, OrderStatus targetStatus) {
        OrderStatus currentStatus = order.getStatus();

        switch (currentStatus) {
            case CREATED:
                if (targetStatus == OrderStatus.PENDING_PAYMENT) {
                    // 允许转换
                    order.setStatus(targetStatus);
                } else {
                    throw new IllegalStateException("Invalid state transition");
                }
                break;
            case PENDING_PAYMENT:
                if (targetStatus == OrderStatus.PAID || targetStatus == OrderStatus.CANCELLED) {
                    order.setStatus(targetStatus);
                } else {
                    throw new IllegalStateException("Invalid state transition");
                }
                break;
            // ... 其他状态
        }
    }
}

方式2:状态模式(复杂场景)

public interface OrderState {
    void pay(OrderContext context);
    void approve(OrderContext context);
    void ship(OrderContext context);
    void cancel(OrderContext context);
}

public class PendingPaymentState implements OrderState {
    @Override
    public void pay(OrderContext context) {
        // 支付成功,转换到PAID状态
        context.setState(new PaidState());
        // 执行库存预占等业务逻辑
        context.reserveInventory();
    }

    @Override
    public void cancel(OrderContext context) {
        // 取消订单,转换到CANCELLED状态
        context.setState(new CancelledState());
    }

    @Override
    public void approve(OrderContext context) {
        throw new IllegalStateException("Cannot approve before payment");
    }

    @Override
    public void ship(OrderContext context) {
        throw new IllegalStateException("Cannot ship before payment");
    }
}

public class OrderContext {
    private OrderState state;
    private Order order;

    public void pay() {
        state.pay(this);
    }

    public void setState(OrderState state) {
        this.state = state;
        this.order.setStatus(state.getStatus());
    }
}

三、数据模型设计

3.1 核心表结构

表1:订单主表(t_order)

CREATE TABLE t_order (
    -- 主键
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id VARCHAR(64) NOT NULL UNIQUE COMMENT '订单号',

    -- 渠道信息
    channel VARCHAR(32) NOT NULL COMMENT '渠道:taobao/jd/shopify',
    channel_order_id VARCHAR(64) COMMENT '渠道订单号',
    shop_id VARCHAR(32) COMMENT '店铺ID',

    -- 客户信息
    buyer_id VARCHAR(64) COMMENT '买家ID',
    buyer_name VARCHAR(128) COMMENT '买家姓名',
    buyer_phone VARCHAR(32) COMMENT '买家手机',
    buyer_email VARCHAR(128) COMMENT '买家邮箱',

    -- 收货地址
    receiver_name VARCHAR(128) COMMENT '收货人',
    receiver_phone VARCHAR(32) COMMENT '收货电话',
    receiver_province VARCHAR(64) COMMENT '省份',
    receiver_city VARCHAR(64) COMMENT '城市',
    receiver_district VARCHAR(64) COMMENT '区县',
    receiver_address VARCHAR(512) COMMENT '详细地址',
    receiver_postcode VARCHAR(16) COMMENT '邮编',

    -- 金额信息
    total_amount DECIMAL(12,2) NOT NULL COMMENT '订单总金额',
    discount_amount DECIMAL(12,2) DEFAULT 0.00 COMMENT '优惠金额',
    shipping_fee DECIMAL(12,2) DEFAULT 0.00 COMMENT '运费',
    tax_amount DECIMAL(12,2) DEFAULT 0.00 COMMENT '税费',
    paid_amount DECIMAL(12,2) COMMENT '实付金额',

    -- 订单状态
    status VARCHAR(32) NOT NULL COMMENT '订单状态',
    sub_status VARCHAR(32) COMMENT '子状态',

    -- 业务信息
    order_type VARCHAR(32) COMMENT '订单类型:normal/presale/gift',
    payment_method VARCHAR(32) COMMENT '支付方式',
    payment_time DATETIME COMMENT '支付时间',

    -- 履约信息
    warehouse_code VARCHAR(32) COMMENT '分配仓库',
    carrier_code VARCHAR(32) COMMENT '物流公司',
    tracking_number VARCHAR(64) COMMENT '运单号',
    shipped_time DATETIME COMMENT '发货时间',
    delivered_time DATETIME COMMENT '签收时间',

    -- 备注
    buyer_message VARCHAR(512) COMMENT '买家留言',
    seller_memo VARCHAR(512) COMMENT '卖家备注',

    -- 父子订单关系
    parent_order_id VARCHAR(64) COMMENT '父订单号(拆分场景)',
    is_split TINYINT DEFAULT 0 COMMENT '是否已拆分:0否1是',

    -- 时间戳
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    -- 索引
    INDEX idx_channel_order_id (channel, channel_order_id),
    INDEX idx_buyer_id (buyer_id),
    INDEX idx_status (status),
    INDEX idx_created_at (created_at),
    INDEX idx_parent_order_id (parent_order_id)
) COMMENT='订单主表';

表2:订单明细表(t_order_item)

CREATE TABLE t_order_item (
    -- 主键
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    item_id VARCHAR(64) NOT NULL UNIQUE COMMENT '订单行ID',
    order_id VARCHAR(64) NOT NULL COMMENT '订单号',

    -- 商品信息
    sku VARCHAR(64) NOT NULL COMMENT 'SKU编码',
    product_id VARCHAR(64) COMMENT '商品ID',
    product_name VARCHAR(256) COMMENT '商品名称',
    product_image VARCHAR(512) COMMENT '商品图片',

    -- 规格信息
    spec_desc VARCHAR(256) COMMENT '规格描述:颜色/尺寸',
    barcode VARCHAR(64) COMMENT '商品条码',

    -- 数量与价格
    quantity INT NOT NULL COMMENT '购买数量',
    unit_price DECIMAL(12,2) NOT NULL COMMENT '单价',
    discount_amount DECIMAL(12,2) DEFAULT 0.00 COMMENT '优惠金额',
    tax_amount DECIMAL(12,2) DEFAULT 0.00 COMMENT '税费',
    subtotal DECIMAL(12,2) NOT NULL COMMENT '小计',

    -- 履约信息
    warehouse_code VARCHAR(32) COMMENT '分配仓库',
    location_code VARCHAR(64) COMMENT '库位编码',

    -- 状态
    status VARCHAR(32) NOT NULL COMMENT '订单行状态',

    -- 时间戳
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    -- 索引
    INDEX idx_order_id (order_id),
    INDEX idx_sku (sku),
    INDEX idx_status (status)
) COMMENT='订单明细表';

表3:订单状态流转记录表(t_order_status_history)

CREATE TABLE t_order_status_history (
    -- 主键
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id VARCHAR(64) NOT NULL COMMENT '订单号',

    -- 状态变更
    from_status VARCHAR(32) COMMENT '变更前状态',
    to_status VARCHAR(32) NOT NULL COMMENT '变更后状态',

    -- 变更原因
    reason VARCHAR(512) COMMENT '变更原因',
    operator VARCHAR(64) COMMENT '操作人',
    operator_type VARCHAR(32) COMMENT '操作类型:system/user',

    -- 时间戳
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    -- 索引
    INDEX idx_order_id (order_id),
    INDEX idx_created_at (created_at)
) COMMENT='订单状态流转记录表';

3.2 扩展表设计

表4:订单扩展信息表(t_order_extra)

用于存储不常用但又需要保留的信息,避免主表字段过多。

CREATE TABLE t_order_extra (
    -- 主键
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id VARCHAR(64) NOT NULL UNIQUE COMMENT '订单号',

    -- JSON格式存储扩展信息
    extra_data JSON COMMENT '扩展信息',

    -- 常用扩展字段(也可以放在JSON中)
    coupon_code VARCHAR(64) COMMENT '优惠券编码',
    promotion_id VARCHAR(64) COMMENT '促销活动ID',
    member_level VARCHAR(32) COMMENT '会员等级',
    points_used INT DEFAULT 0 COMMENT '使用积分',

    -- 时间戳
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) COMMENT='订单扩展信息表';

表5:订单日志表(t_order_log)

记录订单的所有操作日志,用于问题排查和审计。

CREATE TABLE t_order_log (
    -- 主键
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id VARCHAR(64) NOT NULL COMMENT '订单号',

    -- 日志信息
    log_type VARCHAR(32) NOT NULL COMMENT '日志类型:API调用/状态变更/异常',
    log_level VARCHAR(16) COMMENT '日志级别:INFO/WARN/ERROR',
    message TEXT COMMENT '日志内容',

    -- 操作信息
    operator VARCHAR(64) COMMENT '操作人',
    ip_address VARCHAR(64) COMMENT 'IP地址',

    -- 时间戳
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    -- 索引
    INDEX idx_order_id (order_id),
    INDEX idx_log_type (log_type),
    INDEX idx_created_at (created_at)
) COMMENT='订单日志表';

四、订单编号规则设计

4.1 订单号设计原则

原则1:全局唯一

  • 订单号在整个系统中必须唯一
  • 避免使用数据库自增ID作为订单号(安全风险)

原则2:可读性

  • 订单号包含业务含义,便于识别
  • 例如:包含日期、渠道、序列号

原则3:可排序

  • 订单号可按时间排序
  • 便于查询和分析

原则4:防篡改

  • 避免连续的订单号(如123456、123457),防止恶意猜测

4.2 订单号生成方案

方案1:时间戳 + 随机数

订单号格式:ORD + YYYYMMDDHHMMSS + 6位随机数
示例:ORD20251122103045123456

优点:
- 简单易实现
- 可排序
- 全局唯一(概率极高)

缺点:
- 无业务语义
- 高并发下可能重复(需要唯一性校验)

Java实现

public class OrderIdGenerator {
    private static final String PREFIX = "ORD";
    private static final SecureRandom random = new SecureRandom();

    public static String generate() {
        // 时间戳部分:YYYYMMDDHHmmss
        String timestamp = LocalDateTime.now()
            .format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

        // 随机数部分:6位
        int randomNum = random.nextInt(900000) + 100000; // 100000-999999

        return PREFIX + timestamp + randomNum;
    }
}

方案2:雪花算法(Snowflake)

订单号格式:64位Long型数字
结构:1位符号 + 41位时间戳 + 10位机器ID + 12位序列号

优点:
- 全局唯一
- 趋势递增
- 高性能(本地生成,无需数据库)

缺点:
- 纯数字,不易读
- 需要转换为字符串展示

Java实现

public class SnowflakeOrderIdGenerator {
    // 起始时间戳(2025-01-01 00:00:00)
    private static final long START_TIMESTAMP = 1735660800000L;

    // 机器ID位数
    private static final long WORKER_ID_BITS = 10L;
    // 序列号位数
    private static final long SEQUENCE_BITS = 12L;

    // 最大机器ID
    private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
    // 最大序列号
    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);

    // 时间戳左移位数
    private static final long TIMESTAMP_SHIFT = WORKER_ID_BITS + SEQUENCE_BITS;
    // 机器ID左移位数
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;

    private final long workerId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeOrderIdGenerator(long workerId) {
        if (workerId > MAX_WORKER_ID || workerId < 0) {
            throw new IllegalArgumentException("Worker ID out of range");
        }
        this.workerId = workerId;
    }

    public synchronized long generateId() {
        long timestamp = System.currentTimeMillis();

        // 时钟回拨检测
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards");
        }

        // 同一毫秒内,序列号递增
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            // 序列号溢出,等待下一毫秒
            if (sequence == 0) {
                timestamp = waitNextMillis(timestamp);
            }
        } else {
            // 新的毫秒,序列号重置为0
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        // 拼接ID
        return ((timestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT)
            | (workerId << WORKER_ID_SHIFT)
            | sequence;
    }

    private long waitNextMillis(long currentTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= currentTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    // 转换为字符串订单号
    public String generateOrderId() {
        return "ORD" + generateId();
    }
}

方案3:业务前缀 + 时间 + 序列号(推荐)

订单号格式:业务前缀 + 日期 + 序列号
示例:ORD20251122000001

优点:
- 有业务语义
- 可读性强
- 可排序

缺点:
- 需要维护序列号(Redis或数据库)

Redis实现

public class OrderIdGenerator {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String PREFIX = "ORD";

    public String generate() {
        // 日期部分:YYYYMMDD
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

        // Redis Key:ORDER:ID:20251122
        String redisKey = "ORDER:ID:" + date;

        // 自增序列号
        Long sequence = redisTemplate.opsForValue().increment(redisKey);

        // 设置过期时间:7天后过期
        if (sequence == 1) {
            redisTemplate.expire(redisKey, 7, TimeUnit.DAYS);
        }

        // 拼接订单号:ORD20251122000001
        return String.format("%s%s%06d", PREFIX, date, sequence);
    }
}

4.3 订单号校验

public class OrderIdValidator {
    // 订单号格式:ORD + 8位日期 + 6位序列号
    private static final Pattern PATTERN = Pattern.compile("^ORD\\d{8}\\d{6}$");

    public static boolean validate(String orderId) {
        if (orderId == null || orderId.isEmpty()) {
            return false;
        }

        // 格式校验
        if (!PATTERN.matcher(orderId).matches()) {
            return false;
        }

        // 日期校验
        String dateStr = orderId.substring(3, 11); // 提取日期部分
        try {
            LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

五、订单类型分类

5.1 按业务场景分类

订单类型英文简称说明特殊处理
普通订单NORMAL常规销售订单
预售订单PRESALE提前预定,延期发货延迟下发WMS,需记录预计发货时间
赠品订单GIFT促销活动赠品金额为0,不参与财务结算
换货订单EXCHANGE售后换货订单关联原订单,退货后自动发货
补发订单RESEND物流丢失或破损后补发关联原订单,不收费
退货订单RETURN退货订单(逆向订单)逆向物流,退款处理
拼团订单GROUP_BUY拼多多等拼团订单成团后才处理,需等待拼团成功
秒杀订单FLASH_SALE秒杀活动订单高并发,需特殊库存预占机制
虚拟商品订单VIRTUAL充值卡、会员卡等虚拟商品无需物流,自动发货(发码)
跨境订单CROSS_BORDER跨境电商订单需报关、清关,履约周期长
企业采购订单B2B企业批量采购订单支持账期结算,需开具发票
O2O订单O2O线上下单、线下自提无需物流,到店核销
定制订单CUSTOMIZED定制化商品订单需生产周期,延期发货
分期付款订单INSTALLMENT分期付款订单需对接金融机构,支持分期扣款

5.2 订单类型枚举

public enum OrderType {
    NORMAL("NORMAL", "普通订单"),
    PRESALE("PRESALE", "预售订单"),
    GIFT("GIFT", "赠品订单"),
    EXCHANGE("EXCHANGE", "换货订单"),
    RESEND("RESEND", "补发订单"),
    RETURN("RETURN", "退货订单"),
    GROUP_BUY("GROUP_BUY", "拼团订单"),
    FLASH_SALE("FLASH_SALE", "秒杀订单"),
    VIRTUAL("VIRTUAL", "虚拟商品订单"),
    CROSS_BORDER("CROSS_BORDER", "跨境订单"),
    B2B("B2B", "企业采购订单"),
    O2O("O2O", "O2O订单"),
    CUSTOMIZED("CUSTOMIZED", "定制订单"),
    INSTALLMENT("INSTALLMENT", "分期付款订单");

    private final String code;
    private final String description;

    OrderType(String code, String description) {
        this.code = code;
        this.description = description;
    }

    // Getter方法...
}

六、总结

6.1 核心要点回顾

  1. 订单的三个维度:业务维度(订单头+订单行)、系统维度(原始订单+子订单)、状态维度(生命周期)
  2. 订单状态机:单向流转、状态粒度适中、状态与动作分离
  3. 数据模型设计:订单主表、订单明细表、状态流转表、扩展表、日志表
  4. 订单号设计:全局唯一、可读性、可排序、防篡改
  5. 订单类型分类:14种典型订单类型,每种类型有特殊处理逻辑

6.2 设计建议

  1. 状态机不要过度设计:根据业务实际需要设计状态,避免过细或过粗
  2. 数据表分离关注点:主表存核心信息,扩展表存可选信息,日志表存操作记录
  3. 订单号方案选择
    • 小型系统:时间戳+随机数
    • 中型系统:业务前缀+日期+Redis序列号(推荐)
    • 大型系统:雪花算法+业务前缀
  4. 预留扩展字段:订单表预留JSON字段,存储不常用的扩展信息

6.3 下一步学习

本文详细讲解了OMS的核心概念和数据模型。在下一篇文章中,我们将探讨多渠道订单接入与标准化,了解如何对接淘宝、京东、Shopify等平台的订单API。


关键词:OMS数据模型、订单状态机、订单编号、订单类型、数据库设计、领域建模、订单管理