订单拆分与合并策略——复杂场景的处理逻辑

引言:为什么需要拆单和合单 拆单场景: 一个订单的商品分布在不同仓库,需要从多个仓库发货 部分商品有货,部分商品需要预售 订单重量超过物流限制,需要拆成多个包裹 合单场景: 同一客户短时间内下了多个订单,可以合并发货节省运费 促销活动中的凑单场景 这些逻辑看似简单,但实现起来非常复杂,涉及库存、物流、财务等多个方面。 一、订单模型设计 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在义乌仓 ...

2026-01-29 · maneng

订单拆分与合并策略:复杂场景下的智能决策

引言 在电商场景中,一个看似简单的订单可能面临复杂的履约挑战:商品分布在不同仓库、部分商品是预售、有些需要跨境发货。这时,订单拆分与合并就成为OMS系统的核心能力。 订单拆分与合并不仅仅是技术问题,更是业务策略问题。拆得太细,物流成本高、用户体验差;合得太粗,库存利用率低、发货时效慢。如何在成本、时效、体验之间找到最优解?本文将从第一性原理出发,系统性地探讨这个问题。 为什么需要订单拆分? 业务驱动因素 订单拆分的本质是将一个逻辑订单按照履约能力拆分成多个物理订单。驱动因素包括: 1. 库存分布不一致 用户订单: - 商品A × 2(华东仓有货) - 商品B × 1(华南仓有货) - 商品C × 1(华北仓有货) 拆分策略:按仓库拆分成3个子订单 2. 商品属性差异 用户订单: - 普通商品(现货) - 预售商品(7天后发货) - 大件商品(需要专门配送) 拆分策略:按发货时效和物流方式拆分 3. 跨境与国内混合 用户订单: - 国内商品(保税仓) - 跨境商品(海外直邮) 拆分策略:按清关类型拆分 拆分的核心目标 最大化履约效率:让每个子订单都能快速发货 优化物流成本:减少不必要的拆分 保障用户体验:透明化拆分信息,合理预期 提高库存周转:优先消化滞销库存 订单拆分的典型场景 场景1:跨仓拆分 业务场景: 用户购买了3件商品,分别在上海仓、北京仓、广州仓有库存。 拆分策略: class CrossWarehouseSplitStrategy: """跨仓拆分策略""" def split(self, order, inventory_map): """ 按仓库拆分订单 Args: order: 原始订单 inventory_map: {sku_id: [warehouse_id, stock]} Returns: List[SubOrder]: 子订单列表 """ # 按仓库分组商品 warehouse_groups = defaultdict(list) for item in order.items: warehouse_id = self._find_best_warehouse( item.sku_id, item.quantity, inventory_map, order.delivery_address ) warehouse_groups[warehouse_id].append(item) # 生成子订单 sub_orders = [] for warehouse_id, items in warehouse_groups.items(): sub_order = self._create_sub_order( parent_order=order, warehouse_id=warehouse_id, items=items ) sub_orders.append(sub_order) return sub_orders def _find_best_warehouse(self, sku_id, quantity, inventory_map, delivery_address): """选择最优仓库""" available_warehouses = [ (wh_id, stock) for wh_id, stock in inventory_map.get(sku_id, []) if stock >= quantity ] if not available_warehouses: raise InsufficientStockException(sku_id) # 按距离排序,选择最近的仓库 return self._sort_by_distance( available_warehouses, delivery_address )[0][0] 关键决策点: ...

2025-11-22 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...