订单拆分与合并策略——复杂场景的处理逻辑
引言:为什么需要拆单和合单 拆单场景: 一个订单的商品分布在不同仓库,需要从多个仓库发货 部分商品有货,部分商品需要预售 订单重量超过物流限制,需要拆成多个包裹 合单场景: 同一客户短时间内下了多个订单,可以合并发货节省运费 促销活动中的凑单场景 这些逻辑看似简单,但实现起来非常复杂,涉及库存、物流、财务等多个方面。 一、订单模型设计 1.1 三层订单模型 ┌─────────────────────────────────────────────────────┐ │ 原始订单 │ │ (Source Order) │ │ 客户下单时的原始订单 │ └─────────────────────┬───────────────────────────────┘ │ 拆分/合并 ▼ ┌─────────────────────────────────────────────────────┐ │ 履约订单 │ │ (Fulfillment Order) │ │ 实际执行发货的订单单元 │ └─────────────────────┬───────────────────────────────┘ │ 下发 ▼ ┌─────────────────────────────────────────────────────┐ │ 出库单 │ │ (Outbound Order) │ │ WMS执行的出库指令 │ └─────────────────────────────────────────────────────┘ 1.2 数据模型 /** * 原始订单 */ @Data public class SourceOrder { private String sourceOrderId; // 原始订单号 private String channelOrderId; // 渠道订单号 private String channel; // 渠道 private String buyerId; // 买家ID private Address shippingAddress; // 收货地址 private List<SourceOrderItem> items; // 订单明细 private Money totalAmount; // 订单总额 private OrderStatus status; // 状态 } /** * 履约订单 */ @Data public class FulfillmentOrder { private String fulfillmentOrderId; // 履约订单号 private String sourceOrderId; // 关联原始订单号 private String warehouseId; // 发货仓库 private String carrierId; // 承运商 private Address shippingAddress; // 收货地址 private List<FulfillmentOrderItem> items; // 履约明细 private Money shippingFee; // 运费 private FulfillmentStatus status; // 状态 } /** * 订单关系表 */ @Data public class OrderRelation { private String sourceOrderId; // 原始订单号 private String fulfillmentOrderId; // 履约订单号 private String relationType; // 关系类型:SPLIT/MERGE } 1.3 数据库设计 -- 原始订单表 CREATE TABLE t_source_order ( id BIGINT PRIMARY KEY AUTO_INCREMENT, source_order_id VARCHAR(32) NOT NULL, channel_order_id VARCHAR(64), channel VARCHAR(32), buyer_id VARCHAR(64), total_amount DECIMAL(12,2), currency VARCHAR(8), status VARCHAR(32), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_source_order_id (source_order_id) ); -- 履约订单表 CREATE TABLE t_fulfillment_order ( id BIGINT PRIMARY KEY AUTO_INCREMENT, fulfillment_order_id VARCHAR(32) NOT NULL, source_order_id VARCHAR(32) NOT NULL, warehouse_id VARCHAR(32), carrier_id VARCHAR(32), shipping_fee DECIMAL(12,2), status VARCHAR(32), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_fulfillment_order_id (fulfillment_order_id), KEY idx_source_order_id (source_order_id) ); -- 订单关系表 CREATE TABLE t_order_relation ( id BIGINT PRIMARY KEY AUTO_INCREMENT, source_order_id VARCHAR(32) NOT NULL, fulfillment_order_id VARCHAR(32) NOT NULL, relation_type VARCHAR(16) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_source_order_id (source_order_id), KEY idx_fulfillment_order_id (fulfillment_order_id) ); 二、拆单策略 2.1 拆单场景分类 场景 触发条件 处理方式 多仓拆单 商品分布在不同仓库 按仓库拆分 预售拆单 部分商品无货 有货先发,无货等待 超重拆单 包裹超过物流限重 按重量拆分 赠品拆单 赠品从不同仓库发 赠品单独发货 组合商品拆单 组合商品需要拆开 拆成单品发货 2.2 多仓拆单 场景:订单包含SKU-A和SKU-B,SKU-A在深圳仓,SKU-B在义乌仓 ...