仓网查询 → 创建订单 | 分支: test-20260601 | 2026-06-03
ECMS 系统 │ ├─ ① 调用 /goms/open-api/base/warehouse/query │ 传入: province, district, centerCode │ 获得: 按市/县分组的仓库列表 + 库位 + 优先级 │ ├─ ② ECMS 根据返回结果选择仓库和库位 │ 根据 priority 选择优先级最高的仓库 │ 选择具体的 location 库位编码 │ └─ ③ 调用 /goms/open-api/order/create 将选定的 location 填入订单行 GOMS 根据 location 反查仓库并创建订单
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 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(...) |
warehouseList ├ priority=1 ├ warehouseCode=W001 └ locationList ├ L001 ← 选中 └ L002
OpenOrderLineCreateParam ├ materialCode: SKU001 ├ qty: 10 └ location: "L001"
location "L001" → location_mapping 映射 → warehouse_location → 回填 warehouseCode + warehouseId
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
String locationCode = firstOrderParam.getOpenOrderLineCreateList().get(0).getLocation();
oms_base_location_mapping 做映射转换baseLocationMappingClient.getBySrc(locationCode) → location_target
oms_base_warehouse_location 获取仓库信息warehouseLocationClient.getInfoByCode(targetLocationCode) → warehouse_code, warehouse_id
orderParam.setWarehouseCode(...)
orderParam.setWarehouseId(...)
oms_base_location_mapping 用于库位编码的映射转换:
| 字段 | 说明 |
|---|---|
| location_source | ECMS 传入的原始库位编码 |
| location_target | GOMS 内部的标准库位编码 |
ECMS 和 GOMS 可能使用不同的库位编码体系,此表做桥接。
| 编码 | 状态 | 说明 |
|---|---|---|
| 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 | 部分签收 |
status = 02 (PENDING) warehouse_status = DRAFT shipping_status = DRAFT accounting_status = UN_BOOKKEEPING
status = 06 (COMPLETED) accounting_status = BOOKKEEPING_FINISH
status = 09 (EXCEPTION_WAIT) warehouse_status = EXCEPTION_TO_BE_PROCESSED
┌──────────────┐
│ 01 INVOICE │
└──────┬───────┘
▼
┌────────────────────────────────────────────┐
│ 02 PENDING ──→ 03 ASSIGNED ──→ 04 SHIPPING │
└───────┬───────────────────────────┬────────┘
│ │
│ 库存校验失败 ▼
▼ ┌───────────────┐
┌─────────────────┐ │ 10 SIGNED │
│ 09 EXCEPTION │ │ 11 REJECTED │
│ _WAIT │ │ 12 PART_SIGN │
└─────────────────┘ └───────┬───────┘
▼
┌───────────────┐
│ 06 COMPLETED │
└───────────────┘
07 CANCELLED — 任意阶段可取消
08 FAILURE — 拆包失败
| 状态 | 说明 |
|---|---|
| SUCCESS | 源数据校验通过,已保存 |
| ERROR | 校验失败,原始数据已归档 |
| MQ_SUCCESS | 订单创建完成,MQ 已发送 |
| 表名 | 用途 | 关键字段 |
|---|---|---|
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 |
| 表名 | 用途 | 关键字段 |
|---|---|---|
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 |
| 表名 | 用途 | 关键字段 |
|---|---|---|
oms_shipping_order | 运单主表 | shipping_code, order_code, status |
oms_shipping_order_line | 运单行 | shipping_code, order_code, material_code |
| 表名 | 用途 | 关键字段 |
|---|---|---|
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 |
| 表名 | 用途 | 关键字段 |
|---|---|---|
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 |
ECMS_EVENT_ID,填充到每条订单参数 → 全链路追踪标识
OpenOrderCreateParam → OrderCreateParam,映射 OrderSourceCodeMappingEnum
receiverMobile、receiverAddress — DES 加密传输
centerCode → BaseCenterClient → countryCodelocation → mapping → warehouse_location → 回填 warehouseCode + warehouseId
OL + yyyyMMddHHmmss + 5位序号| 要点 | 说明 |
|---|---|
| 两级模块架构 | 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 | 物流业务层,运单管理 |
当 sourceDataValidate = true 时,系统不创建实际订单,仅执行数据校验、库存预占用并发送 MQ 消息。实际的订单创建在 MQ 消费端以 sourceDataValidate = false 模式异步完成。
ECMS 调用 API(sourceDataValidate=true)
│
▼
┌──────────────────────────────────────┐
│ goms-access-openapi 层 │
│ 1. JSR303 参数校验 │
│ 2. 订单数据转换 │
│ 3. 敏感信息解密(手机/地址) │
└──────────────┬───────────────────────┘
│ 调用履约服务
▼
┌──────────────────────────────────────┐
│ goms-agg-fulfillment 层 │
│ 1. 补齐仓库与库位映射信息 │
│ 2. 标准化处理入参字段 │
│ 3. 校验是否重复建单 │
│ 4. 库存预占用校验 │
│ └─ 失败:标记异常待处理,继续 │
│ 5. 发送 MQ(源数据同步) │
│ 6. 落库接单池(成功记录) │
└──────────────┬───────────────────────┘
│ 返回成功
▼
┌─────────────────────────┐
│ oms_inbound_ecms_order │
│ status = SUCCESS (1) │
│ dataValidateStatus = 1 │
└────────────┬────────────┘
│
│ (异步消费 MQ)
▼
┌──────────────────────────────────────┐
│ MQ 消费端(sourceDataValidate=false)│
│ 1. 创建销售出库订单 │
│ 2. 创建仓储作业单 │
│ 3. 创建运输作业单 │
│ 4. 创建用户基础信息 │
│ 5. 更新库存关联字段 │
│ 6. 同步 ECMS 发货状态 │
│ 7. 更新接单池状态为 MQ_SUCCESS │
└──────────────────────────────────────┘
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 补齐仓库信息 | 通过 baseLocationMappingClient 查询库位映射,若未命中则通过 warehouseLocationClient 获取仓库编码和 ID |
| 2 | 校验重复建单 | 调用 bizOmsOrderClient.existByOrderSn() 校验订单号是否已存在,若重复则保存错误记录并抛出异常 |
| 3 | 库存预占用校验 | 检查仓库 stockSwitch 开关,若开启则调用 materialStockClient.batchUpdateStock() 预扣库存失败处理:标记订单状态为 EXCEPTION_WAIT,仓储状态为 EXCEPTION_TO_BE_PROCESSED,发送异常事件和第三方通知,但不中断流程 |
| 4 | 组装接单池对象 |
rawData = 完整请求 JSONouterNo = 外部订单号(DN 号)requestId = eventIdbusinessDes = 订单业务类型 + 履约模式
|
| 属性 | 值 |
|---|---|
| Topic | goms_inbound_order_source |
| Tag | tag_inbound_order_source |
| 消息体 | List<OpenApiOrderCreateParam>(JSON 序列化) |
| 消息 Key | "DN:" + 排序后的外部订单号逗号分隔 |
| 发送方式 | InboundSourceDataValidateSender.sendInboundSourceDataSyncGoms() |
| 发送类 | InboundSourceDataValidateSenderImpl(goms-agg-fulfillment 模块) |
调用 saveSuccessInboundEcmsOrderInfo(inboundOrderCreateParam),写入表 oms_inbound_ecms_order:
| 字段 | 值 | 说明 |
|---|---|---|
| raw_data | 原始请求 JSON | 完整保存 ECMS 推送的原始数据 |
| outer_no | 外部订单号(DN 号) | 用于后续更新匹配 |
| request_id | eventId | 请求追踪 ID |
| receive_time | 当前时间 | 接单时间 |
| status | 1(SUCCESS) | MQ 发送成功 |
| data_validate_status | 1(SUCCESS) | 数据校验通过 |
| business_des | 业务描述 | 订单业务类型 + 履约模式 |
| error_msg | null | 无错误 |
| return_msg | null | 无返回消息 |
⚠️ 当前代码存在明显缺陷:
| 问题 | 详情 |
|---|---|
| 无 try-catch | MQ 发送调用 inboundSourceDataValidateSender.sendInboundSourceDataSyncGoms() 没有被 try-catch 包裹,位于 handleSourceDataValidateMode() 方法的第 273 行 |
| 无错误落库 | MQ 发送失败时,后续的 saveSuccessInboundEcmsOrderInfo() 不会被执行,接单池无任何记录 |
| 无重试机制 | 代码中没有任何重试逻辑,失败即终止 |
| 异常向上抛出 | 异常会沿调用链向上传播到 createOrder() 的外层 catch 块,最终抛出 BizException(ORDER_CREAT_ERROR),但数据库中无迹可查 |
💡 建议改进:在 MQ 发送外层加 try-catch,失败时调用 saveErrorInboundEcmsOrderInfo(inboundOrderCreateParam, errorMsg, returnMsg) 记录失败数据,并考虑加入重试机制。
MQ 消息被 InboundSourceDataValidateConsumer 消费后(匹配 tag tag_inbound_order_source),以 sourceDataValidate=false 模式调用 omsOrderService.createOrder(),执行实际订单创建:
| 步骤 | 操作 | 涉及表 | 异常处理 |
|---|---|---|---|
| 1 | 创建销售出库订单bizOmsOrderClient.create() |
oms_order_outbound(主表)oms_order_line_outbound(行明细)
|
Feign 调用失败抛出异常 |
| 2 | 查询完整订单信息bizOmsOrderClient.selectByOrderCodeList() |
— | — |
| 3 | 初始化日志上下文 | — | — |
| 4a | 创建仓储作业单bizWarehouseOrderClient.create() |
oms_warehouse_order_outboundoms_warehouse_order_line_outbound
|
try-catch 捕获异常 发送异常事件 发送第三方通知(仓储系统异常) |
| 4b | 创建运输作业单bizShippingOrderClient.create() |
oms_shipping_order_outboundoms_shipping_order_line_outbound
|
try-catch 捕获异常 发送异常事件 发送第三方通知(运输系统异常) |
| 4c | 创建用户基础信息baseUserInfoClient.createBatch() |
oms_base_user_info
|
try-catch 捕获异常 发送异常事件 |
| 5 | 更新库存关联字段materialStockChangeRecordsClient.updateByExternalOrderCodes() |
oms_material_stock_change_records
|
try-catch 捕获异常 发送库存异常事件 |
| 6 | 同步 ECMS 发货状态fulfillmentShippingTrackingEventSender.sendOrderCodeList() |
— | 历史订单跳过 |
| 7 | 更新接单池状态omsInboundEcmsOrderClient.updateByOuterNo() |
oms_inbound_ecms_orderstatus → 2(MQ_SUCCESS) |
— |
⚡ 消费失败处理:若 MQ 消费端抛出异常,InboundSourceDataValidateConsumer 会调用 omsInboundEcmsOrderClient.updateByOuterNo() 将接单池状态更新为 MQ_FAILED。
| 表名 | 类型 | 说明 | 创建关系 |
|---|---|---|---|
oms_order_outbound | 主表 | 销售出库订单主表 | 1 个 DN → 1 条记录 |
oms_order_line_outbound | 明细表 | 销售订单行明细 | 订单行项目对应 |
oms_warehouse_order_outbound | 仓储主表 | 仓储作业单主表 | 订单:仓单 = 1:1(需 isWarehouse=YES) |
oms_warehouse_order_line_outbound | 仓储明细表 | 仓储作业单行明细 | 物料级别 |
oms_shipping_order_outbound | 运输主表 | 运输作业单主表 | 订单:运单 = 1:N(按 SN 拆分,可能合并包裹) |
oms_shipping_order_line_outbound | 运输明细表 | 运输作业单行明细 | 物料级别 |
oms_base_user_info | 用户信息表 | 收件人敏感信息 | 客户编码 + 姓名 + 手机 + 地址 |
oms_material_stock | 库存表 | 物料库存(预占用) | 校验阶段预扣,建单后更新关联订单号 |
oms_material_stock_change_records | 库存变更记录表 | 库存变更流水 | 建单后更新 externalOrderCode → orderCode |
oms_inbound_ecms_order | 接单池 | ECMS 接单池(更新状态) | status 更新为 2(MQ_SUCCESS) |
oms_inbound_ecms_order.status 状态值: 0 (ERROR) 数据校验未通过 / 校验阶段异常 1 (SUCCESS) MQ 发送成功(校验阶段写入) 2 (MQ_SUCCESS) MQ 消费成功(订单创建完成后更新) 3 (MQ_FAILED) MQ 消费失败(消费端异常时更新) oms_inbound_ecms_order.data_validate_status 状态值: 0 (ERROR) 校验失败 1 (SUCCESS) 校验成功
| 类名 | 模块 | 说明 |
|---|---|---|
OmsOrderServiceStubImpl | goms-access-openapi | OpenAPI 层入口:接收 ECMS 请求,参数校验,数据转换 |
FulfillmentOrderServiceStubImpl | goms-agg-fulfillment | 核心实现:sourceDataValidate 分支判断 + 订单创建 |
InboundSourceDataValidateSenderImpl | goms-agg-fulfillment | MQ 发送实现 |
InboundSourceDataValidateConsumer | goms-access-openapi | MQ 消费端:根据 tag 路由到不同服务 |
OmsInboundEcmsOrderClient | goms-biz-inbound | 接单池 CRUD 客户端 |
BizOmsOrderClient | goms-biz-order | 销售出库订单 CRUD |
BizWarehouseOrderClient | goms-biz-warehouse | 仓储作业单 CRUD |
BizShippingOrderClient | goms-biz-shipping | 运输作业单 CRUD |
BaseUserInfoClient | goms-platform-base | 用户信息 CRUD |
MaterialStockClient | goms-biz-warehouse | 库存预占用和更新 |
📄 GOMS ECMS 全流程文档 | 分支: test-20260601 | 更新时间: 2026-06-03