🔗 GOMS ECMS 全流程文档
仓网查询 → 创建订单 | 分支: test-20260601 | 2026-06-03
1整体业务流程(ECMS 视角)
ECMS 系统
│
├─ ① 调用 /goms/open-api/base/warehouse/query
│ 传入: province, district, centerCode
│ 获得: 按市/县分组的仓库列表 + 库位 + 优先级
│
├─ ② ECMS 根据返回结果选择仓库和库位
│ 根据 priority 选择优先级最高的仓库
│ 选择具体的 location 库位编码
│
└─ ③ 调用 /goms/open-api/order/create
将选定的 location 填入订单行
GOMS 根据 location 反查仓库并创建订单
2仓网查询接口
请求参数
| 字段 | 类型 | 必填 | 说明 |
| regionCode | String | 否 | 国家编码(默认 VN) |
| tenantCode | String | 否 | 租户编码(默认 HAIER) |
| areaCode | String | 否 | 区域简码 |
| province | String | 是 | 府/州简码 |
| district | String | 是 | 市/县简码 |
| centerCode | String | 是 | 贸易公司编码 |
| type | String | 否 | 类型 |
返回结构
BaseWarehouseEcmsDataVO
├── areaName / areaCode // 区域
├── provinceName / provinceCode // 府/州
├── districtName / districtCode // 市/县
├── coverProvinceName // 覆盖范围
└── warehouseList[]
├── priority // 优先级
├── warehouseCode // 仓库编码
├── warehouseName // 仓库名称
└── locationList[]
├── location // ← 这个值填入订单行!
└── locationName
查询涉及的表
| 表名 | 用途 | 查询条件 |
oms_base_warehouse_route | 仓网线路表 | country_code + tenant_code + province_name + center_code |
oms_base_warehouse | 仓库主数据 | country_code + tenant_code + area_code + district_code + warehouse_code IN(...) |
oms_base_warehouse_location | 库位数据 | warehouse_code IN(...) |
3仓网查询与订单创建的关联
⚠️ 关键连接点:库位(location)
订单创建接口不会直接调用仓网查询,调用方(ECMS)必须先查询仓网,再将 location 填入订单行。
仓网查询返回
warehouseList
├ priority=1
├ warehouseCode=W001
└ locationList
├ L001 ← 选中
└ L002
→
订单行入参
OpenOrderLineCreateParam
├ materialCode: SKU001
├ qty: 10
└ location: "L001"
→
GOMS 内部
location "L001"
→ location_mapping 映射
→ warehouse_location
→ 回填 warehouseCode
+ warehouseId
4创建订单完整调用链
POST /goms/open-api/order/create
│
├─ [1] OrderController.createOrder()
│ └─ 提取 eventId,填充到参数
│
├─ [2] OmsOrderServiceImpl.createOrder()
│ └─ 日志记录 + 转发
│
├─ [3] OmsOrderServiceStubImpl.createOrder()
│ ├─ JSR303 参数校验
│ ├─ OpenOrderCreateParam → OrderCreateParam 转换
│ ├─ 设置履约模式 (PICKUP / NON_INTEGRATED)
│ ├─ 解密敏感信息 (手机号、地址 - DES)
│ ├─ 处理订单行 (仓库编码继承、赠品标记)
│ └─ 调用 FulfillmentOrderClient.createOrder() [Feign RPC]
│
├─ [4] FulfillmentOrderServiceStubImpl.createOrder()
│ ├─ ★ completeWarehouseInfo() ← 仓库补全
│ │ ├─ 从第一条订单行取 location
│ │ ├─ 查 oms_base_location_mapping 做映射
│ │ ├─ 查 oms_base_warehouse_location 取仓库
│ │ └─ 回填 warehouseCode + warehouseId
│ ├─ standardizeOrderParams() 参数标准化
│ │
│ ├─ [分支A: sourceDataValidate=true 校验模式]
│ │ ├─ checkIfOrderExist() 去重校验
│ │ ├─ updateMaterialStock() 库存预校验
│ │ ├─ 发送 MQ 消息
│ │ └─ 保存入池记录 (SUCCESS/ERROR)
│ │
│ └─ [分支B: sourceDataValidate=false 创建模式]
│ ├─ ★ 创建订单 (Redis 分布式锁)
│ │ ├─ 生成订单号: OL + 时间戳 + 5位序号
│ │ ├─ INSERT oms_order_outbound
│ │ ├─ INSERT oms_order_line_outbound
│ │ └─ INSERT oms_order_outbound_shipping_provider
│ ├─ 查询已创建订单
│ ├─ ★ createDownstreamAssets()
│ │ ├─ tryCreateWarehouseOrder() → 仓储单
│ │ ├─ tryCreateShippingOrder() → 运单
│ │ └─ tryCreateUserInfo() → 用户敏感信息
│ ├─ 更新库存关联记录
│ ├─ MQ 同步物流状态到 ECMS
│ └─ 入池状态更新为 MQ_SUCCESS
5仓库 & 库位选择逻辑(重点)
5.1 仓库补全流程 completeWarehouseInfo()
Step 1:从第一条订单行取 location
String locationCode = firstOrderParam.getOpenOrderLineCreateList().get(0).getLocation();
Step 2:查 oms_base_location_mapping 做映射转换
baseLocationMappingClient.getBySrc(locationCode) → location_target
Step 3:查 oms_base_warehouse_location 获取仓库信息
warehouseLocationClient.getInfoByCode(targetLocationCode) → warehouse_code, warehouse_id
Step 4:回填到所有订单参数
orderParam.setWarehouseCode(...)
orderParam.setWarehouseId(...)
💡 规则:
• 如果订单行已有 warehouseCode → 保留不覆盖
• 如果 warehouseCode 为空 → 通过 location 反查回填
• 如果 location 映射不存在 → 直接用原始 location 编码查
5.2 库位映射表作用
oms_base_location_mapping 用于库位编码的映射转换:
| 字段 | 说明 |
| location_source | ECMS 传入的原始库位编码 |
| location_target | GOMS 内部的标准库位编码 |
ECMS 和 GOMS 可能使用不同的库位编码体系,此表做桥接。
6订单状态流转(重点)
6.1 OrderStatusEnum 订单状态枚举
| 编码 | 状态 | 说明 |
| 01 | INVOICE | 发票待导入 |
| 02 | PENDING | 待分配 新订单初始 |
| 03 | ASSIGNED | 已分配 |
| 04 | SHIPPING | 发货中 |
| 05 | RETURN | 收货中 |
| 06 | COMPLETED | 已完成 |
| 07 | CANCELLED | 已取消 |
| 08 | FAILURE | 拆包失败 |
| 09 | EXCEPTION_WAIT | 异常待处理 |
| 10 | SIGNED | 签收 |
| 11 | REJECTED | 拒签 |
| 12 | PARTIALLY_SIGNED | 部分签收 |
6.2 创建时的初始状态
✅ 正常订单
status = 02 (PENDING)
warehouse_status = DRAFT
shipping_status = DRAFT
accounting_status = UN_BOOKKEEPING
📜 历史订单 (oldOrder=1)
status = 06 (COMPLETED)
accounting_status = BOOKKEEPING_FINISH
❌ 库存校验失败
status = 09 (EXCEPTION_WAIT)
warehouse_status = EXCEPTION_TO_BE_PROCESSED
6.3 状态流转图
┌──────────────┐
│ 01 INVOICE │
└──────┬───────┘
▼
┌────────────────────────────────────────────┐
│ 02 PENDING ──→ 03 ASSIGNED ──→ 04 SHIPPING │
└───────┬───────────────────────────┬────────┘
│ │
│ 库存校验失败 ▼
▼ ┌───────────────┐
┌─────────────────┐ │ 10 SIGNED │
│ 09 EXCEPTION │ │ 11 REJECTED │
│ _WAIT │ │ 12 PART_SIGN │
└─────────────────┘ └───────┬───────┘
▼
┌───────────────┐
│ 06 COMPLETED │
└───────────────┘
07 CANCELLED — 任意阶段可取消
08 FAILURE — 拆包失败
6.4 入池状态(Inbound Pool)
| 状态 | 说明 |
| SUCCESS | 源数据校验通过,已保存 |
| ERROR | 校验失败,原始数据已归档 |
| MQ_SUCCESS | 订单创建完成,MQ 已发送 |
7使用的数据库表(重点)
7.1 核心订单表
| 表名 | 用途 | 关键字段 |
oms_order_outbound | 正向订单主表 | order_code, external_order_code, status, warehouse_code, warehouse_id, location, center_code |
oms_order_line_outbound | 订单行明细 | order_id, order_code, material_code, qty, location, warehouse_code |
oms_order_outbound_shipping_provider | 订单承运商 | order_id, order_code, shipping_provider_code |
7.2 仓储相关表
| 表名 | 用途 | 关键字段 |
oms_warehouse_order | 仓储操作单 | warehouse_order_code, order_code, status, warehouse_code |
oms_warehouse_order_line | 仓储单行 | warehouse_order_code, material_code, qty |
oms_base_warehouse | 仓库主数据 | warehouse_code, warehouse_name, stock_switch |
oms_base_warehouse_route | 仓网线路 | warehouse_code, country_code, center_code, priority |
oms_base_warehouse_location | 库位主数据 | location_code, warehouse_code, warehouse_id |
oms_base_location_mapping | 库位映射 | location_source, location_target |
7.3 物流相关表
| 表名 | 用途 | 关键字段 |
oms_shipping_order | 运单主表 | shipping_code, order_code, status |
oms_shipping_order_line | 运单行 | shipping_code, order_code, material_code |
7.4 库存相关表
| 表名 | 用途 | 关键字段 |
oms_material_stock | 库存主表 | warehouse_code, material_code, stock_qty, locked_qty |
oms_material_stock_change_records | 库存变更日志 | external_order_code, order_code, operation_type |
oms_base_material | 物料主数据 | material_code, material_name |
7.5 辅助表
| 表名 | 用途 | 关键字段 |
oms_inbound_ecms_order | 入池数据归档 | outer_no, raw_data, status, data_validate_status |
oms_base_user_info | 用户敏感信息 | order_code, receiver_name, receiver_mobile, receiver_address |
oms_base_center | 贸易公司 | center_code, country_code |
8创建订单详细业务逻辑(按阶段)
阶段一:openapi 层预处理
1. 提取 eventId
从 HTTP Header 读取 ECMS_EVENT_ID,填充到每条订单参数 → 全链路追踪标识
2. JSR303 参数校验
校验 externalOrderCode、orderSource、paymentType 等必填字段
失败 → 入池(ERROR)
3. 参数转换
OpenOrderCreateParam → OrderCreateParam,映射 OrderSourceCodeMappingEnum
4. 设置履约模式
PICKUP(自提)/ NON_INTEGRATED(非集成)
5. 解密敏感信息
receiverMobile、receiverAddress — DES 加密传输
6. 订单行处理
• 行级 warehouseCode 继承订单头
• 销售单位标准化("SET" → "PC")
• 赠品标记继承(套装商品)
• 初始化数量字段为 0(actualDeliveryQty, returnQty, actualReceiveQty)
7. 国家编码查询
centerCode → BaseCenterClient → countryCode
特殊处理:TikTok VN 订单,districtName 与 cityName 相同时清空
阶段二:fulfillment 层核心逻辑
8. ★ 仓库补全 completeWarehouseInfo()
location → mapping → warehouse_location → 回填 warehouseCode + warehouseId
9. 参数标准化
district 值为 "0" 时清空
10. 分支A:校验模式 (sourceDataValidate=true)
├─ 去重校验(externalOrderCode + orderType + tenant + region)
├─ 库存预校验(stock_switch 开启时查 oms_material_stock)
│ └─ 失败 → status=09, warehouse_status=EXCEPTION
├─ 发送 MQ 消息
└─ 入池状态 = SUCCESS
11. 分支B:创建模式 (sourceDataValidate=false)
├─ Redis 分布式锁(key: externalOrderCode2)
├─ 生成订单号:OL + yyyyMMddHHmmss + 5位序号
├─ INSERT oms_order_outbound(主订单)
├─ INSERT oms_order_line_outbound(订单行)
├─ INSERT oms_order_outbound_shipping_provider(承运商)
├─ 释放锁
├─ 查询已创建订单
├─ 创建下游资产:
│ ├─ 仓储单 (isWarehouse=1)
│ ├─ 运单 (isWarehouse=1 或 isPickup=1)
│ │ ├─ 自提模式:每个行项每个数量单位一个运单
│ │ └─ 普通模式:按 externalOrderCode2 分组 + 合包策略
│ └─ 用户敏感信息
├─ 更新库存关联记录
├─ MQ 同步物流状态到 ECMS
├─ 入池状态更新为 MQ_SUCCESS
└─ 自动分配承运商(可选,按 centerCode 配置)
9关键设计要点
🏗️ 架构设计
| 要点 | 说明 |
| 两级模块架构 | openapi 层负责对外接口、参数校验、格式转换;base/fulfillment 层负责核心业务逻辑和数据库操作。两层通过 Feign RPC 通信。 |
| 两种执行模式 | 校验模式 (sourceDataValidate=true):仅校验 + 保存原始数据 + 发 MQ 创建模式 (sourceDataValidate=false):实际创建订单 |
| 幂等保障 | Redis 分布式锁防止重复创建;复合键唯一性检查(externalOrderCode + orderType + tenant + region) |
| 错误处理 | 校验失败 → 入池(ERROR) 保存原始数据 创建失败 → 发送异常事件 + 通知第三方 下游资产创建失败不回滚主订单(最终一致性) |
| 读写分离 | 查询操作使用从库 @UseDataSource(SLAVE) |
| 逻辑删除 | 所有核心表使用 deleted 字段(isLogicDelete=true) |
| 国家编码补全 | 未传 regionCode 默认 VN,再通过 centerCode 查询真实国家编码并覆盖 |
| 线路优先 | 仓网查询先查线路表确定覆盖关系,优先级来自线路表而非仓库表 |
| 订单号生成 | Redis 原子自增5位序号,Key 1秒过期。格式:OL2026060314302500001 |
| 敏感数据 | 手机号、地址 DES 加密传输,用户信息单独存储到 oms_base_user_info |
📊 涉及的模块总览
| 模块 | 职责 |
goms-access-openapi | 对外开放接口层,承接 ECMS 请求 |
goms-agg-fulfillment | 订单履约聚合层,仓库补全 + 订单创建 + 下游资产 |
goms-biz-order | 订单业务层,订单入库 + 订单号生成 |
goms-platform-base | 基础平台层,仓库/库位/物料等主数据 |
goms-biz-warehouse | 仓储业务层,仓储操作单 |
goms-biz-shipping | 物流业务层,运单管理 |
📄 GOMS ECMS 全流程文档 | 分支: test-20260601 | 生成时间: 2026-06-03