204 KiB
OMS 业务系统 — 表结构与接口设计
1 导读
1.1 这份文档解决什么问题?
- 订单:创建、预报、支付、状态机、费用与版本对齐、模板/批量任务等。
- 渠道:销售产品、服务渠道、计价与发布、计重、分区、自动触发、标签等。
- 操作:入库、出库、面单打印等仓储作业。
- 充值:充值申请、审核及入账(客户账户与余额权威以权限/客户域实现为准)。
- 系统主数据:国家、字典、仓库地址、通知等
/system/*能力。
1.2 文档定位
OMS 为 业务系统;认证、RBAC、内部用户、客户主数据等由 docs/rbac系统设计-050901.md 独立设计与迭代。业务侧以 CustomerId(主客户) 表达订单/充值等归属;与令牌主体(principalType / principalId 及子账号场景下的主客户标识)的对齐见 1.4。本篇不展开客户域、用户域表与接口。
1.3 业务模块一览
| 模块 | 章 | 说明 |
|---|---|---|
| 订单 | 4 | 全生命周期、查价、模板与批量任务 |
| 渠道 | 5 | 销售产品、服务渠道、计价、计重、分区、标签等 |
| 操作 | 6 | 入库、出库、打印 |
| 充值 | 7 | 充值申请、审核、入账 |
| 系统主数据 | 8 | 国家、字典、仓库、通知(/system/*) |
1.4 与客户 / 用户数据的边界
客户主数据、子账号、内部用户、认证与 RBAC 均在 docs/rbac系统设计-050901.md;本篇不写上述领域的需求变更与表结构。
OMS 业务表中的 CustomerId 等外键表示业务归属,口径上等于主客户 t_customer.Id。子账号 登录时,令牌与 get-current-user 等响应中的 主客户标识(如 main_customer_id / mainCustomerId)见 docs/rbac系统设计-050901.md;OMS 侧订单/充值等 CustomerId 须与该主客户对齐,不得把子账号业务 Id 误当主客户 Id。存在性、状态、余额、子账号归主等仍以 权限/客户域服务 与联调约定为准,不得仅凭请求体 Id 绕过鉴权。
不在本篇设计的内容:统一认证、RBAC、内部用户、客户主数据与子账号等 —— 见 docs/rbac系统设计-050901.md。
2 业务设计思路与主流程
2.1 职责边界:OMS 与 RBAC / 客户域
| 侧 | 职责 |
|---|---|
| OMS(本文) | 订单全生命周期、渠道配置与算价支撑、仓内作业、充值业务流水、/system/* 业务主数据(国家、字典、仓库地址、通知等)。 |
| RBAC / 客户域(另文) | 登录与令牌、内部用户、客户主数据与子账号、权限码、账户余额的权威读写、与客户/员工相关的字典语义。 |
| 协作约定 | OMS 用 CustomerId 表达归属;客户是否存在、是否可用、子账号归主、余额是否够付 等一律以 客户域 / RBAC 服务 为准,禁止仅凭请求体 Id 当作已鉴权事实。 |
2.2 主流程 A:配置发布 → 运行时算价(渠道支撑订单)
设计意图:高并发查价/下单不走「每次打 DB 拉全量规则」;以 版本化快照 + Redis + 计费实例内存 为主路径,DB 发布表为审计与降级。
- 运营维护销售产品、卖价/买价、分区(KpiArea)、计重、排货、服务渠道等。
- 发布 产生 不可变版本;结构化快照写入 Redis,计费服务加载 本地内存。
- 查价与正式下单共用:按绑定时刻(如
bindTime)选取应对生效的 rules/price 版本 → 规则匹配(分区、计重、黑名单等)→ 出费用明细;查价响应宜带rulesVersion/priceVersion便于与订单对齐。
2.3 主流程 B:订单(客户侧业务链)
设计意图:先锁「计费契约版本」、再按履约阶段分批落费;历史订单不因后台新发版被静默改价。
- 查价(可选)→ 创建 / 预报 → 校验 → 草稿与包裹 → 预报阶段将
ChargingTime = forecast(或未配置视为 forecast)的费用项写入t_order_fee。 - 契约固化:预报等关键节点写入
SalesProductRulesVersion、SalesProductPriceVersion(及渠道侧应付相关版本,若有);非显式「改单重算」流程 不得 因后台新发布而改写已存版本号。 - 状态机(概念顺序;枚举见
## 10 附录→### 10.3):如 草稿 → 已预报 → 已收货 → 待支付 → 待发货 → 运输中 → 派送成功/失败;另有拦截、问题件、删除等分支。 - 支付:OMS 侧订单状态与支付动作对接;扣减余额 / 支付渠道 的权威在 客户域(及支付集成约定)。
- 分阶段计费:卖价/买价主表
ChargingTime决定该项费用 何时 计入t_order_fee:forecast(预报) / inbound(入库) / outbound(出库)。每一阶段只计算本阶段命中的项;且算价时仍读取 该订单已绑定版本 的快照,不改用当前全局「最新发布」。 - 批量下单:Excel/模板 或 JSON 批量接口 → 异步任务;单次最多受理 2000 条;单票仍遵守版本选择与
ChargingTime规则。
2.4 主流程 C:操作(仓库)
- 入库扫描:实重、尺寸等落库;可触发
inbound阶段计费(配置为入库计费的项)。 - 出库扫描:可触发
outbound阶段计费。 - 标签打印:按单号与模板输出,记录打印结果。
2.5 主流程 D:充值
- 客户提交 →
t_recharge_record待审核。 - 审核通过/驳回;通过时增加余额 由 客户域 执行;OMS 保留流水与审核状态,不是余额账本权威。
2.6 主流程 E:系统主数据
国家、字典、仓库地址、通知供全业务引用;与客户/内部员工相关的 DictType 定义以 docs/rbac系统设计-050901.md 为准。
2.7 设计不变量(推断与实现时须一致)
| 不变量 | 说明 |
|---|---|
| 版本锁定 | 订单一旦写入规则/卖价版本字段,后续后台发版 不自动 推翻该票货的计费契约。 |
| 版本与落费时机解耦 | 版本在预报等节点锁定;何时写入 t_order_fee 由 ChargingTime 分阶段执行。 |
| 后阶段仍用旧版快照 | 入库/出库触发的算价,加载的是 该订单已绑定 version 的快照,不是「当前最新 version」。 |
| 客户与余额 | 校验客户、余额、子账号关系 → 客户域;OMS 持 CustomerId 与业务流程。 |
| 审计字段 | 写操作落 Create*/Update*;操作者来自 登录会话,见 ## 3 公共规范 → ### 3.2。 |
2.8 本文档章节索引(从流程跳转到细节)
| 上述块 | 正文位置 |
|---|---|
| 文档定位、模块一览、权限边界 | ## 1 导读 → ### 1.3~### 1.5 |
| 订单、查价、费用、版本策略 | ## 4 订单模块(尤其 ### 4.3 下单计费与版本策略) |
| 产品/渠道/发布/分区/计重/标签 | ## 5 渠道模块 |
| 入库/出库/打印 | ## 6 操作模块 |
| 充值 | ## 7 充值管理 |
| 国家/字典/仓库/通知 | ## 8 系统主数据 |
| 需求迭代与历史差异 | ## 9 需求迭代与变更记录 |
| 枚举与路径速查 | ## 10 附录 |
3 公共规范
3.1 表结构设计公共规范
3.1.1 表的字段命名规范
| 规范 | 说明 | 示例 |
|---|---|---|
| 驼峰命名 | 字段名开头大写+单词驼峰 | ServiceProviderId |
| 单数名词 | 表名用单数,表示实体 | order 而非 orders |
| 业务前缀 | 表名按业务模块加前缀 | t_order、t_channel |
3.1.2 必备字段(所有表)
| 字段名 | 字段类型 | 说明 |
|---|---|---|
| Id | BIGINT | 主键,自增,步长 1 |
| IsDeleted | TINYINT | 软删除:0-否,1-是,默认 0 |
| CreateUserId | INT | 创建人 |
| CreateTime | DATETIME | 创建时间 |
| UpdateUserId | INT | 更新人 |
| UpdateTime | DATETIME | 更新时间 |
3.1.3 字段命名规范
| 规范 | 说明 | 示例 |
|---|---|---|
| 布尔字段 | 用 IsXxx 或 HasXxx |
IsDeleted、IsActive |
| 外键字段 | 关联表名Id 或 XxxId |
CustomerId、WarehouseId |
| 时间字段 | XxxTime 或 XxxAt |
CreateTime、PayTime |
| 禁用保留字 | 不用 desc、range、match 等 | 用 Description 替代 Desc |
3.1.4 数据类型规范
| 类型 | 说明 |
|---|---|
| 主键 | BIGINT,单表自增 |
| 金额/重量 | DECIMAL,禁止 float/double |
| 字符串 | varchar 长度 ≤ 5000,超出用 TEXT |
| 枚举 | 小数据量用 TINYINT,可读性要求高用 VARCHAR |
| 状态标志 | TINYINT |
3.2 接口设计公共规范
| 规范 | 说明 |
|---|---|
| 操作审计必填 | 任何新增、编辑、删除操作,必须记录操作者与操作时间 |
| 新增接口 | 创建成功后需落库 CreateUserId、CreateTime |
| 编辑接口 | 更新成功后需落库 UpdateUserId、UpdateTime |
| 删除接口 | 逻辑删除时需落库 UpdateUserId、UpdateTime,并更新 IsDeleted=1 |
审计字段中的操作者信息优先从当前登录会话获取,不允许由前端直接信任覆盖。
4 订单模块
4.1 核心需求说明
- 我的订单:支持订单全流程管理,包括分页查询、详情查看、支付、预报、拦截/取消拦截、删除、打印、导出;订单状态覆盖草稿→已预报→已收货→待支付→待发货→运输中→派送成功/失败等全生命周期。
- 我要查价:根据目的国、运输方式、重量尺寸、货物类型等条件查价,返回可选渠道及费用明细;与正式下单共用「选版本 + 内存匹配」计费逻辑,响应宜携带
rulesVersion/priceVersion便于与订单对齐。 - 我要下单:支持下载下单模板、上传 Excel 批量下单、查看任务进度与详情;模板分为标准模板与自定义模板。单次导入订单上限 2000 条(Excel 有效数据行或
/order/parcel/batch-create请求数组长度,超出拒绝)。
4.2 表结构设计
命名约定:表名按业务模块加 t_ 前缀;字段名驼峰命名(开头大写+单词驼峰)。
4.2.1 订单表 t_order
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| ServiceNo | VARCHAR | 64 | - | 是 | 运单号 |
| ClientNo | VARCHAR | 64 | - | 否 | 客户单号 |
| TrackNo | VARCHAR | 64 | - | 否 | 跟踪号 |
| ProductCode | VARCHAR | 128 | - | 否 | 产品code |
| ChannelCode | VARCHAR | 128 | - | 否 | 渠道code |
| ConsigneeCountry | VARCHAR | 8 | - | 否 | 国家二字码 |
| CargoAttribute | VARCHAR | 32 | - | 否 | 货物属性:general-普货,electronics-3c&带电,sensitive-敏感货 |
| OrderStatus | VARCHAR | 32 | - | 是 | 订单状态 |
| WarehouseId | BIGINT | - | 外键 | 否 | 仓库ID |
| CustomerId | BIGINT | - | 外键 | 否 | 客户ID |
| SenderId | BIGINT | - | 外键 | 否 | 发件人ID → t_order_sender |
| RecipientId | BIGINT | - | 外键 | 否 | 收件人ID → t_order_recipient |
| DeclarationId | BIGINT | - | 外键 | 否 | 申报信息ID → t_order_declaration |
| ExportCustomsMode | VARCHAR | 16 | - | 否 | 出口报关方式,见 ExportCustomsMode 枚举 |
| ReceiveTime | DATETIME | - | - | 否 | 收货时间 |
| ShipTime | DATETIME | - | - | 否 | 发货时间 |
| PayTime | DATETIME | - | - | 否 | 支付时间 |
| SignTime | DATETIME | - | - | 否 | 签收时间 |
| IsCod | TINYINT | - | - | 否 | 是否COD:0-否,1-是 |
| CodCurrency | VARCHAR | 16 | - | 否 | COD币种 |
| CodSum | DECIMAL | 18,4 | - | 否 | COD金额 |
| IsIntercept | TINYINT | - | - | 否 | 是否拦截:0-否,1-是 |
| IsRemote | TINYINT | - | - | 否 | 是否偏远:0-否,1-是 |
| PredeclareFailReason | VARCHAR | 512 | - | 否 | 预报失败原因:草稿已落库后环节失败时记录;黑名单命中、快照未命中等不落库场景不写此字段 |
| SalesProductRulesVersion | VARCHAR | 32 | - | 否 | 下单绑定的规则版本号(与发布记录 Version 一致,OperatorType=rules) |
| SalesProductPriceVersion | VARCHAR | 32 | - | 否 | 下单绑定的价格版本号(与发布记录 Version 一致,OperatorType=price) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
OrderStatus 枚举:draft, predeclared, received, pendingPayment, pendingShip, pendingOnline, shipping, deliverySuccess, deliveryFailed, problematic, deleted, claimed
CargoAttribute 枚举:general-普货,electronics-3c&带电,sensitive-敏感货
ExportCustomsMode 枚举(存库与下列 code 一致):9610Simple(9610简易申报),9610Summary(9610汇总申报),9610Separate(9610单独申报),9710,9810,0110
4.2.2 下单模板表 t_order_template
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| Name | VARCHAR | 64 | - | 是 | 模板名称 |
| Type | VARCHAR | 16 | - | 是 | standard/custom |
| TemplateKey | VARCHAR | 64 | - | 否 | 模板标识 |
| CustomerId | BIGINT | - | 外键 | 否 | 客户ID(自定义模板) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
4.2.3 下单任务表 t_order_task
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| TaskName | VARCHAR | 128 | - | 是 | 任务名称 |
| Quantity | INT | - | - | 否 | 数量 |
| Status | VARCHAR | 16 | - | 是 | 处理中/已完成/待处理 |
| TemplateId | BIGINT | - | 外键 | 否 | 模板ID |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
| CustomerId | BIGINT | - | 外键 | 否 | 客户ID |
4.2.4 订单发件人表 t_order_sender
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| OrderId | BIGINT | - | 外键 | 是 | 订单ID |
| SenderName | VARCHAR | 50 | - | 否 | 姓名 |
| Company | VARCHAR | 255 | - | 否 | 公司 |
| Country | INT | - | - | 否 | 国家 |
| Province | VARCHAR | 50 | - | 否 | 州省 |
| City | VARCHAR | 50 | - | 否 | 城市 |
| ZipCode | VARCHAR | 50 | - | 否 | 邮编 |
| StreetAddress1 | VARCHAR | 500 | - | 否 | 地址1 |
| StreetAddress2 | VARCHAR | 500 | - | 否 | 地址2 |
| StreetAddress3 | VARCHAR | 500 | - | 否 | 地址3 |
| HouseNumber | VARCHAR | 50 | - | 否 | 门牌号 |
| Phone | VARCHAR | 50 | - | 否 | 手机 |
| TelePhone | VARCHAR | 50 | - | 否 | 电话 |
| VARCHAR | 60 | - | 否 | 邮箱 | |
| IsDefault | TINYINT | - | - | 否 | 是否默认:0-否,1-是 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
4.2.5 订单收件人表 t_order_recipient
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| OrderId | BIGINT | - | 外键 | 是 | 订单ID |
| RecipientsName | VARCHAR | 30 | - | 否 | 收件人名称 |
| CompanyName | VARCHAR | 60 | - | 否 | 收件人公司名称 |
| Country | INT | - | - | 否 | 国家 |
| Phone | VARCHAR | 20 | - | 否 | 收件人手机 |
| TelePhone | VARCHAR | 20 | - | 否 | 收件人电话 |
| ZipCode | VARCHAR | 15 | - | 否 | 收件人邮编 |
| Province | VARCHAR | 25 | - | 否 | 收件人省/州 |
| City | VARCHAR | 25 | - | 否 | 收件人城市 |
| StreetNumber | VARCHAR | 20 | - | 否 | 收件人门牌号 |
| StreetAddress1 | VARCHAR | 255 | - | 否 | 收件人地址1 |
| StreetAddress2 | VARCHAR | 255 | - | 否 | 收件人地址2 |
| StreetAddress3 | VARCHAR | 255 | - | 否 | 收件人地址3 |
| VARCHAR | 60 | - | 否 | 收件人邮箱 | |
| TaxType | INT | - | - | 否 | 税号类型 |
| TaxNo | VARCHAR | 35 | - | 否 | 税号 |
| CertificateType | INT | - | - | 否 | 证件类型 |
| CertificateNo | VARCHAR | 30 | - | 否 | 证件号码 |
| Eori | VARCHAR | 255 | - | 否 | EORI |
| Vat | VARCHAR | 255 | - | 否 | Vat |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
4.2.6 订单申报信息表 t_order_declaration
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| OrderId | BIGINT | - | 外键 | 是 | 订单ID |
| CnName | VARCHAR | 500 | - | 否 | 品名--中 |
| EnName | VARCHAR | 500 | - | 否 | 品名--英 |
| Sku | VARCHAR | 255 | - | 否 | SKU |
| Unit | VARCHAR | 5 | - | 否 | 单位 |
| UnitPrice | DECIMAL | 10,2 | - | 否 | 单价 |
| UnitWeight | DECIMAL | 11,3 | - | 否 | 单重 |
| Quantity | INT | - | - | 否 | 数量 |
| Amount | DECIMAL | 11,2 | - | 否 | 总金额 |
| Weight | DECIMAL | 11,3 | - | 否 | 总重量 |
| HsCode | VARCHAR | 50 | - | 否 | HsCode |
| SkuImage | VARCHAR | 255 | - | 否 | 图片 |
| Category | VARCHAR | 20 | - | 否 | 类别 |
| Brand | VARCHAR | 50 | - | 否 | 品牌 |
| BrandType | VARCHAR | 50 | - | 否 | 品牌类型 |
| IsMagnetic | BIT | - | - | 否 | 是否带磁带电 |
| Distribution | VARCHAR | 255 | - | 否 | 配货信息 |
| Material | VARCHAR | 50 | - | 否 | 材质 |
| EnMaterial | VARCHAR | 64 | - | 否 | 英文材质 |
| Purpose | VARCHAR | 50 | - | 否 | 用途 |
| Attributes | VARCHAR | 50 | - | 否 | 属性 |
| OriginCountry | VARCHAR | 50 | - | 否 | 原产国 |
| SalesLink | VARCHAR | 255 | - | 否 | 销售链接 |
| Model | VARCHAR | 64 | - | 否 | 型号 |
| Specifications | VARCHAR | 50 | - | 否 | 规格 |
| Comment | VARCHAR | 500 | - | 否 | 备注 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
4.2.7 订单件重尺表 t_order_weight
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| OrderId | BIGINT | - | 外键 | 是 | 订单ID |
| Type | VARCHAR | 16 | - | 是 | 类型:forecast/receive/ship/downstream |
| Length | DECIMAL | 10,2 | - | 否 | 长(cm) |
| Width | DECIMAL | 10,2 | - | 否 | 宽(cm) |
| Height | DECIMAL | 10,2 | - | 否 | 高(cm) |
| ActualWeight | DECIMAL | 10,3 | - | 否 | 实重(kg) |
| VolumetricWeight | DECIMAL | 10,3 | - | 否 | 体积重(kg) |
| ChargeableWeight | DECIMAL | 10,3 | - | 否 | 计费重(kg) |
| Cubic | DECIMAL | 12,6 | - | 否 | 立方(m³) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
Type 枚举:forecast(预报)、receive(收货)、ship(发货)、downstream(下游)
履约更新:入库后须用收货测量 覆盖并重算 receive 行,并 默认将 receive 行当前件重尺与计重结果(Length/Width/Height/ActualWeight/Cubic/VolumetricWeight/ChargeableWeight)同步覆盖 ship 与 downstream(§6.3.1.1、§4.3.4)。出库后须 覆盖并重算 ship 行,并 默认将 ship 行上述字段同步覆盖 downstream(§6.3.2.1、§4.3.4)。forecast 一般保留下单预报口径;若渠道/下游回传与默认快照不一致,可再 单独覆盖 downstream。
4.2.8 订单费用表 t_order_fee(子表,关联 t_order)
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| OrderId | BIGINT | - | 外键 | 是 | 订单ID |
| Type | VARCHAR | 16 | - | 是 | 类型:receivable(应收)/payable(应付) |
| CostItem | VARCHAR | 64 | - | 是 | 费用项 |
| Amount | DECIMAL | 18,4 | - | 是 | 金额 |
| Currency | VARCHAR | 16 | - | 是 | 币种:RMB/USD/EUR |
| DownstreamProvider | VARCHAR | 128 | - | 否 | 下游服务商 |
| PriceNo | VARCHAR | 64 | - | 否 | 价格编号(建议写入订单绑定的 SalesProductPriceVersion 或渠道侧价格版本) |
| PriceEffectiveTime | DATETIME | - | - | 否 | 价格版本生效时间(对应该次计费所用快照的生效时刻) |
| ChargingStage | VARCHAR | 16 | - | 否 | 本行费用是在哪一阶段计入:forecast(预报)/inbound(入库)/outbound(出库),与卖价/买价项 ChargingTime 一致,便于对账 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
Type 枚举:receivable(应收)、payable(应付)
4.3 下单计费与版本策略(配置 → 运行时 → 下单)
本节约定销售产品维度的规则/卖价如何进入线上算价链路,以及与
t_order版本字段的对应关系;与渠道模块中「运营发布 → 生成版本」接口衔接。
4.3.1 总体流程
运营新建版本 → 录入/维护规则与卖价 → 发布并设为生效
↓
系统组装结构化 JSON(规则快照 + 价格快照,均绑定 salesProductId 与 version)
↓
写入 Redis(按产品/版本可寻址)→ 计费服务实例订阅或定时拉取 → 载入本地内存(热数据)
↓
用户下单 / 预估(高 QPS)
↓
内存匹配:按 bindTime 选定生效版本 → 规则(黑名单/偏远/计重/进位/价格分区等)→ 价格明细 → 输出费用
↓
订单落库:固化 SalesProductRulesVersion、SalesProductPriceVersion(必要时可另存发布记录 Id 便于追溯,非本表字段)
↓
后台上新发布、调价 → 仅刷新 Redis 与各实例内存中的「当前生效」视图
↓
新订单:bindTime 落在 new version 生效之后 → 绑定新版本算价
老订单:已写入的版本号不变 → 复核/对账/理赔仍以当时快照为准,不因后台最新发布而改历史费用
4.3.2 设计要点
| 要点 | 说明 |
|---|---|
| 版本不可变 | 订单创建/预报成功时写入 SalesProductRulesVersion、SalesProductPriceVersion,作为该票货的计费契约;非「改单重算」类流程不得静默改写。 |
| 生效与历史 | 同一 salesProductId 在同一时刻仅一条「对外生效」规则+价格组合;历史 version 保留在 Redis(多版本 key) 与 t_sales_product_publish_record,便于审计与回放。 |
| Redis | 建议按 salesProductId + version 存完整结构化快照 JSON;可选维护 current 指针 key 指向当前生效 version,便于实例 O(1) 发现最新配置。 |
| 本地内存 | 实例启动或收到变更通知后,将当前需服务的 JSON 反序列化并预热为内存对象(或编译为匹配结构),下单/预估路径禁止主链路同步穿透远程 DB。 |
| 下单与预估 | /order/parcel/create 与「我要查价」类预估接口共用同一套选版本与匹配逻辑;预估不落库,但响应中建议返回 rulesVersion / priceVersion 便于与正式单对齐展示。 |
| 降级 | Redis/内存未命中时,允许回退查询 t_sales_product_publish_record(按 bindTime 取当时生效的 rules/price 各一条,读 Content),命中后异步回写 Redis;并打点告警。 |
4.3.3 与运营侧发布的衔接
- 运营在 Admin 完成卖价、排货规则等配置后,通过 发布 生成新版本(参见渠道模块
/channel/sales-product/publish等);发布成功后由配置同步任务将结构化结果写入 Redis 并通知计费服务刷新内存。 - 「设为生效」与版本号
version、生效时间effectiveStartAt(或等价字段)应对齐,以便 bindTime 维度解析「当前应绑哪一版」。
4.3.4 版本确认时机 vs 费用计算时机(ChargingTime)
版本(契约):在下单/预报流程中(如
/order/parcel/create绑定快照时)即确定SalesProductRulesVersion、SalesProductPriceVersion(及渠道侧与应付相关的版本,若有)。后续只要未发生「改单重算」等显式流程,不得因后台发布新版本而改写订单已绑定版本。
金额(执行):应收、应付各费用项何时真正跑公式、写t_order_fee,由卖价主表/买价主表上的ChargingTime(收费时机) 决定,与版本确认时机解耦。
ChargingTime(建议值) |
典型触发节点 | 应收(Type=receivable) |
应付(Type=payable) |
|---|---|---|---|
forecast / 预报 |
下单预报成功(如 /order/parcel/create 走完全部校验) |
§4.3.4.1 应收重算:卖价项 chargingTime=forecast(或未配置视为 forecast)参与;重量取 t_order_weight.Type=forecast |
§4.3.4.2 应付重算:买价项按 chargingTime 筛选;重量/件重尺仅取 Type=downstream |
inbound / 入库 |
仓库收货确认:覆盖 t_order_weight 中 Type=receive 的件重尺后,按 §4.4.3.1 步骤 7、8 同口径对该行重算 VolumetricWeight、ChargeableWeight;默认将 receive 行计重结果同步覆盖 ship 与 downstream,再触发本阶段算价(详见 §6.3.1.1) |
§4.3.4.1:chargingTime=inbound 的卖价项;重量取 Type=receive |
§4.3.4.2:chargingTime=inbound 的买价项;仅 downstream |
outbound / 出库 |
仓库出库/发货扫描:覆盖 t_order_weight 中 Type=ship 的件重尺后,按 §4.4.3.1 步骤 7、8 同口径对该行重算计费重;默认将 ship 行计重结果同步覆盖 downstream,再触发本阶段算价(详见 §6.3.2.1) |
§4.3.4.1:chargingTime=outbound 的卖价项;重量取 Type=ship |
§4.3.4.2:chargingTime=outbound 的买价项;仅 downstream |
规则小结
- 先锁版本、再分阶段算钱:版本在预报阶段锁定;各阶段只计算「本阶段
ChargingTime命中的费用项」,避免一次性把所有费用项都算在预报里(除非配置均为预报)。 - 后阶段算价仍读旧版本快照:入库、出库触发算价时,仍从 Redis/内存(或降级 DB)加载该订单已绑定 version 对应的价格/规则内容,不使用当前全局「最新发布」。
- 计费重数据源与阶段口径:预报阶段仅对
Type=forecast行执行 §4.4.3.1 步骤 7、8,算价取该行ChargeableWeight。入库(§6.3.1.1)完成后须用收货实测 覆盖Type=receive的Length、Width、Height、ActualWeight(并更新Cubic),再 对该行按步骤 7、8 重算VolumetricWeight、ChargeableWeight;默认将receive行上述件重尺与计重字段 同步覆盖Type=ship与Type=downstream(与收货口径对齐,直至出库再分化ship)。ChargingTime=inbound的算价 以receive行计费重为准。出库(§6.3.2.1)完成后须 覆盖Type=ship:请求若带实测件重尺则写入;未带时可将当前receive行件重尺拷贝覆盖ship行(业务可约定固定复用收货测量),再 对该行按步骤 7、8 重算;默认将ship行计重结果 同步覆盖Type=downstream。ChargingTime=outbound的算价 以ship行计费重为准。forecast行保留预报口径,入库/出库重算 不强制回写forecast。若渠道/下游回传与默认downstream快照不一致,可再单独覆盖该行。
3a. 计重规则 / 进位 ID 选取:计算计费重时effectiveWeightRuleId、effectiveWeightRoundingId仅取本单绑定t_sales_product的WeightRuleId/WeightRoundingId(不在客户表配置)。明细来自t_weight_rule_info/t_weight_rounding_info,或与rules快照内嵌片段一致且与上述 ID 匹配(实现可二选一)。详见 §4.4.3.1 步骤 7、8。 - 缺省:若配置未填
ChargingTime,实现上按forecast处理,与历史「预报即全算」行为兼容。 - 快照字段对齐:发布写入价格快照的
priceItems[*].chargingTime应与主表ChargingTime一致;允许存中文(如「预报」「入库」「出库」)或与 DB 相同的英文编码,计费服务应在入口处归一化为forecast/inbound/outbound再参与阶段筛选。 - 链路复用:预报成功、入库完成、出库完成 各须调用 §4.3.4.1 更新/重算 应收;
downstream行被写入或更新后(含预报/入库/出库的默认同步、或渠道下游回传覆盖),须调用 §4.3.4.2 更新/重算 应付。运营批量纠偏见 §4.4.1.10。
4.3.4.1 应收费用重算(Type=receivable)
- 输入:订单 Id;订单已绑定
SalesProductPriceVersion对应卖价快照;本单t_order_weight四行当前值。 - 筛选卖价项:
priceItems中status=1,按各卖价项chargingTime(归一化后)参与对应阶段;批量重算时可对 全部已配置阶段 的应收项一次性重算,或仅重算与当前触发阶段相关的项(实现须文档化,同一订单内幂等)。 - 重量(及依赖件重尺的因子):严格按卖价项
ChargingStage/chargingTime映射t_order_weight行:forecast→Type=forecast;inbound→Type=receive;outbound→Type=ship。分区等其他因子仍按既有规则。 - 输出:计算金额后 写入或更新
t_order_fee(Type=receivable,ChargingStage与卖价项一致);建议OrderId+CostItem+ChargingStage(+ 可选 PriceNo) 幂等 upsert,避免重复行。 - 调用方:
/order/parcel/create预报成功、§6.3.1.1 入库、§6.3.2.1 出库 流程尾部;以及 §4.4.1.10 批量接口中scopes含receivable时。
4.3.4.2 应付费用重算(Type=payable)
- 输入:订单 Id;本单已确定服务渠道及绑定 买价 快照(版本与订单契约一致);本单
t_order_weight.Type=downstream当前行(仅此行参与件重尺/计费重类因子)。 - 筛选买价项:
chargingTime与当前触发阶段匹配(批量重算时可对全部应付项重算,实现须幂等)。 - 重量/体积/实重:一律取自
downstream行(如ChargeableWeight、Length、Width、Height、ActualWeight等,以买价因子配置为准),禁止使用forecast/receive/ship行替代。 - 输出:写入或更新
t_order_fee(Type=payable,ChargingStage与买价项一致)。 - 调用方:预报/入库/出库流程在
downstream行已更新 之后;渠道下游回传更新downstream后;以及 §4.4.1.10 中scopes含payable时。
4.4 核心接口设计
4.4.1 我的订单
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 分页查询订单列表 | POST | /order/list | 支持 status、keyword、createTimeStart/End 筛选 |
| 订单详情 | GET | /order/detail | 根据订单ID获取详情 |
| 支付 | POST | /order/pay | 订单支付 |
| 预报 | POST | /order/pre-declare | 订单预报 |
| 拦截 | POST | /order/intercept | 订单拦截 |
| 取消拦截 | POST | /order/cancel-intercept | 取消订单拦截 |
| 删除 | POST | /order/delete | 删除订单 |
| 打印 | POST | /order/print | 打印订单 |
| 导出 | POST | /order/export | 导出订单 |
| 批量重算费用 | POST | /order/fee/batch-recalculate | 入参订单 Id 列表 + scopes,分别触发 §4.3.4.1 应收 / §4.3.4.2 应付 |
4.4.1.1 分页查询订单列表(POST /order/list)
1 接口请求示例
请求 /order/list(POST,分页参数放 Body)
{
"page": 1, // 页码,从1开始
"pageSize": 20, // 每页条数
"status": "all|draft|predeclared|received|...", // 订单状态筛选
"keyword": "", // 关键词(运单号/客户单号/跟踪号)
"createTimeStart": "", // 创建时间起
"createTimeEnd": "" // 创建时间止
}
响应(用于 order/myOrders 列表及订单详情抽屉,字段与 parcel/create 对应,创建时传啥返回啥 + weightList)
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"clientNo": "CUST...",
"trackNo": "TRK...",
"serviceNo": "LP...",
"productCode": "US_AIR",
"channelCode": "CH001",
"cargoAttribute": "general",
"exportCustomsMode": "9610Simple",
"warehouseId": 1,
"warehouse": "深圳仓",
"customerId": 1,
"isCod": false,
"codCurrency": "",
"codSum": "",
"orderStatus": "待支付",
"status": "pendingPayment",
"receiveTime": "",
"shipTime": "",
"payTime": "",
"signTime": "",
"isIntercept": false,
"isRemote": false,
"createTime": "2024-01-01 12:00:00",
"createBy": "",
"updateTime": "",
"updateBy": "",
"sender": {
"senderName": "发件人",
"company": "示例公司",
"phone": "13800138000",
"telePhone": "",
"email": "sender@example.com",
"countryCode": 0,
"province": "广东省",
"city": "深圳市",
"zipCode": "518000",
"streetAddress1": "示例地址1",
"streetAddress2": "",
"streetAddress3": "",
"houseNumber": ""
},
"receiver": {
"recipientsName": "收件人1",
"companyName": "",
"phone": "13800138000",
"telePhone": "",
"email": "",
"countryCode": 0,
"province": "California",
"city": "Los Angeles",
"streetNumber": "",
"streetAddress1": "123 Main St",
"streetAddress2": "",
"streetAddress3": "",
"zipCode": "90001",
"taxType": 0,
"taxNo": "",
"certificateType": 0,
"certificateNo": "",
"eori": "",
"vat": ""
},
"items": [
{
"cnName": "示例商品",
"enName": "Sample Product",
"sku": "SKU001",
"unit": "件",
"unitPrice": 10,
"unitWeight": 0.5,
"quantity": 1,
"amount": 10,
"weight": 0.5,
"hsCode": "1234567890",
"skuImage": "",
"category": "普货",
"brand": "示例品牌",
"brandType": "自有",
"isMagnetic": false,
"distribution": "",
"material": "塑料",
"enMaterial": "Plastic",
"purpose": "日用",
"attributes": "",
"originCountry": "中国",
"salesLink": "",
"model": "",
"specifications": "",
"comment": ""
}
],
"weightList": [
{
"type": "forecast",
"length": "20",
"width": "15",
"height": "10",
"actualWeight": "2.50",
"volumetricWeight": "2.00",
"chargeableWeight": "2.50",
"cubic": "0.003"
}
]
}
],
"total": 100
}
}
2 接口业务逻辑
核心流程
状态与失败处理
校验与异常
4.4.1.2 订单详情(GET /order/detail)
1 接口请求示例
请求 /order/detail(GET,Query 参数)
?id=1
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"clientNo": "CUST...",
"trackNo": "TRK...",
"serviceNo": "LP...",
"productCode": "US_AIR",
"channelCode": "CH001",
"cargoAttribute": "general",
"exportCustomsMode": "9610Simple",
"warehouseId": 1,
"warehouse": "深圳仓",
"customerId": 1,
"sender": {},
"receiver": {},
"items": [],
"weightList": []
}
}
2 接口业务逻辑
核心流程
校验与异常
4.4.1.3 支付(POST /order/pay)
1 接口请求示例
请求 /order/pay(POST)
{
"id": 1,
"requestId": ""
}
requestId 幂等,可选。
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.1.4 预报(POST /order/pre-declare)
1 接口请求示例
请求 /order/pre-declare(POST)
{
"id": 1,
"requestId": ""
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.1.5 拦截(POST /order/intercept)
1 接口请求示例
请求 /order/intercept(POST)
{
"id": 1,
"requestId": ""
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.1.6 取消拦截(POST /order/cancel-intercept)
1 接口请求示例
请求 /order/cancel-intercept(POST)
{
"id": 1,
"requestId": ""
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.1.7 删除(POST /order/delete)
1 接口请求示例
请求 /order/delete(POST)
{
"id": 1,
"requestId": ""
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.1.8 打印(POST /order/print)
1 接口请求示例
请求 /order/print(POST)
{
"id": 1,
"requestId": ""
}
响应
{
"code": 0,
"msg": "success",
"data": {
"printUrl": ""
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.1.9 导出(POST /order/export)
1 接口请求示例
请求 /order/export(POST)
{
"status": "all|draft|...",
"keyword": "",
"createTimeStart": "",
"createTimeEnd": ""
}
响应
{
"code": 0,
"msg": "success",
"data": {
"downloadUrl": "",
"expireAt": ""
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.1.10 批量重算费用(POST /order/fee/batch-recalculate)
用于「我的订单」运营/对账场景:按订单 Id 列表 批量 重算并回写 t_order_fee,算法拆分为 应收 与 应付 两段(§4.3.4.1、§4.3.4.2),与预报、入库、出库、下游链路 共用同一套计算单元。
1 接口请求示例
请求 /order/fee/batch-recalculate(POST)
{
"orderIds": [1001, 1002, 1003],
"scopes": ["receivable", "payable"]
}
参数说明:
orderIds必填,非空数组,元素为t_order.Id。scopes必填,取值为receivable、payable的子集(可只传其一或两者都传)。receivable:对列表内订单执行 §4.3.4.1。payable:对列表内订单执行 §4.3.4.2(依赖downstream行已存在且有效)。
响应
{
"code": 0,
"msg": "success",
"data": {
"total": 3,
"successCount": 2,
"failCount": 1,
"failures": [{ "orderId": 1003, "reason": "缺少 t_order_weight.Type=downstream" }]
}
}
2 接口业务逻辑
核心流程
- 校验:
orderIds去重、长度上限(如 ≤500,可配置)、订单存在且IsDeleted=0;权限(如仅管理员/财务/指定角色)。 - 当
scopes含receivable(重算应收)- 逐单加载:绑定
SalesProductPriceVersion卖价快照、t_order_weight、t_order_fee既有应收行(若策略为全量重算可先逻辑清理再写)。 - 按 §4.3.4.1:卖价项按
chargingTime取forecast/receive/ship对应ChargeableWeight(及分区等),重算金额并 upsertType=receivable。
- 逐单加载:绑定
- 当
scopes含payable(重算应付)- 逐单校验
t_order_weight存在Type=downstream且可用于买价匹配;加载绑定 买价 快照。 - 按 §4.3.4.2:仅
downstream行参与重量/件重尺因子,重算并 upsertType=payable。
- 逐单校验
- 事务:建议 按订单 单事务提交,避免一批中一单失败影响其他单;
failures逐单记录原因。 - 与履约链路的关系:预报成功、入库完成、出库完成 应在各自流程内调用 §4.3.4.1;
downstream更新后(含三段流程同步写入、或下游回传)调用 §4.3.4.2。本接口为 显式批量补算,不改变订单已绑定版本契约。
校验与异常
orderIds为空、scopes为空或不合法、订单无绑定卖价/买价版本、缺downstream(在请求payable时)等返回业务错误;部分失败时仍返回200+data.failures(或与全局错误码策略一致)。
4.4.2 我要查价
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 查价 | POST | /order/price-check | 根据目的国、重量尺寸等查价 |
4.4.2.1 查价(POST /order/price-check)
1 接口请求示例
请求 /order/price-check(POST)
{
"destinationCountry": "US", // 目的国二字码
"shippingMethod": "", // 运输方式
"cargoWeight": "2", // 货物重量(kg)
"length": "20", // 长(cm)
"width": "15", // 宽(cm)
"height": "10", // 高(cm)
"cargoType": "普货", // 货物类型
"destinationProvince": "", // 目的省州
"postalCode": "" // 邮编
}
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"shippingMethod": "美国空运专线(普货)",
"warehouse": "一代深圳仓",
"deliveryTime": "3-7",
"volumetricWeight": "2",
"chargeableWeight": "2",
"costFormula": "(62*2) +5+7",
"freight": "62",
"otherFees": "5",
"totalCost": "136",
"maxDeliveryDays": 7,
"totalCostNum": 136
}
]
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.3 我要下单
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 模板列表 | GET | /order/template/list | 获取下单模板列表 |
| 下载模板 | GET | /order/template/download | 下载 Excel 模板 |
| 上传下单 | POST | /order/upload | multipart/form-data,file + templateId |
| 任务进度列表 | GET | /order/task/list | 批量下单任务列表 |
| 任务详情 | GET | /order/task/detail | 任务详情 |
| 创建小包 | POST | /order/parcel/create | 创建小包订单 |
| 批量创建小包 | POST | /order/parcel/batch-create | 批量创建小包订单 |
4.4.3.1 创建小包(POST /order/parcel/create)
1 接口请求示例
请求 /order/parcel/create(POST)
字段与 t_order、t_order_sender、t_order_recipient、t_order_declaration、t_order_weight 表对应,采用 camelCase。
{
"clientNo": "string", // 客户单号 t_order.ClientNo//必填
"trackNo": "string", // 跟踪号 t_order.TrackNo
"serviceNo": "string", // 运单号 t_order.ServiceNo
"productCode": "string", // 产品代码 t_order.ProductCode//必填
"channelCode": "string", // 渠道代码 t_order.ChannelCode
"cargoAttribute": "string", // 货物属性 t_order.CargoAttribute:general-普货,electronics-3c&带电,sensitive-敏感货//必填
"exportCustomsMode": "string", // 出口报关方式 t_order.ExportCustomsMode:9610Simple/9610Summary/9610Separate/9710/9810/0110,含义见 4.2.1 ExportCustomsMode 枚举//可选
"warehouseId": 0, // 仓库ID t_order.WarehouseId//必填
"length": 3, // 长(cm) t_order_weight.Length
"width": 3, // 宽(cm) t_order_weight.Width
"height": 3, // 高(cm) t_order_weight.Height
"actualWeight": 3, // 实重(kg) t_order_weight.ActualWeight//必填
"isCod": false, // 是否COD
"codSum": "string", // COD金额
"codCurrency": "string", // COD币种
"declaredCurrency": "string", // 申报币种//必填
"declaredSum": "string", // 申报总金额
"quantity": "string", // 包裹数量//必填
"receiver": { // 收件人 t_order_recipient
"recipientsName": "string", // 收件人名称//必填
"companyName": "string", // 收件人公司名称
"phone": "string", // 收件人手机//必填
"telePhone": "string", // 收件人电话
"email": "string", // 收件人邮箱
"countryCode": 0, // 国家//必填
"province": "string", // 收件人省/州
"city": "string", // 收件人城市
"streetNumber": "string", // 收件人门牌号
"streetAddress1": "string", // 收件人地址1//必填
"streetAddress2": "string", // 收件人地址2
"streetAddress3": "string", // 收件人地址3
"zipCode": "string", // 收件人邮编//必填
"taxType": 0, // 税号类型
"taxNo": "string", // 税号
"certificateType": 0, // 证件类型
"certificateNo": "string", // 证件号码
"eori": "string", // EORI
"vat": "string" // Vat
},
"sender": { // 发件人 t_order_sender
"senderName": "string", // 发件人姓名
"company": "string", // 发件人公司
"phone": "string", // 发件人手机
"telePhone": "string", // 发件人电话
"email": "string", // 发件人邮箱
"countryCode": 0, // 国家
"province": "string", // 州省
"city": "string", // 城市
"zipCode": "string", // 邮编
"streetAddress1": "string", // 地址1
"streetAddress2": "string", // 地址2
"streetAddress3": "string", // 地址3
"houseNumber": "string" // 门牌号
},
"items": [ // 申报明细 t_order_declaration
{
"cnName": "string", // 品名-中
"enName": "string", // 品名-英//必填
"sku": "string", // SKU
"unit": "string", // 单位
"unitPrice": 0, // 单价//必填
"unitWeight": 0, // 单重//必填
"quantity": 0, // 数量//必填
"amount": 0, // 总金额
"weight": 0, // 总重量
"imHsCode": "string", // 进口HsCode
"exHsCode": "string", // 出口HsCode
"skuImage": "string", // 图片
"category": "string", // 类别
"brand": "string", // 品牌
"brandType": "string", // 品牌类型
"isMagnetic": false, // 是否带磁带电
"distribution": "string", // 配货信息
"material": "string", // 材质
"enMaterial": "string", // 英文材质
"purpose": "string", // 用途
"attributes": "string", // 属性
"originCountry": "string", // 原产国
"salesLink": "string", // 销售链接
"model": "string", // 型号
"specifications": "string", // 规格
"comment": "string" // 备注
}
]
}
响应
{
"code": 0,
"msg": "success",
"data": {
"clientNo": "",
"serviceNo": "",
"trackNo": "",
"labelUrl": ""
}
}
幂等时可选传 requestId。
2 接口业务逻辑
核心流程
- 本接口用于创建小包订单预报数据,执行顺序固定为:参数校验 -> 查询销售产品与规则/价格快照绑定 -> 黑名单校验(命中则中止,不落库) -> 创建订单草稿 -> 偏远校验 -> 计费重计算 -> 仅「预报」时机费用计算与落库 -> 更新订单状态 -> 返回结果。(入库/出库时机费用见 §4.3.4,由仓储收货、出库流程触发。)
- 参数校验失败,或销售产品/快照绑定失败、黑名单校验命中时,均不创建任何订单数据,直接返回业务错误。
- 进入草稿创建后,先将订单主数据、发件人、收件人、申报明细、预报件重尺数据落库,订单状态固定写入
draft。 - 后续偏远、计费重、费用等流程全部基于已创建的草稿订单继续处理;如任一业务环节失败,订单状态不扩展新枚举,统一保留
draft,并在t_order.PredeclareFailReason记录失败原因。
详细业务逻辑
-
参数解析与基础数据校验
- 校验请求体必填字段:
productCode、warehouseId、customerId、length、width、height、actualWeight、receiver.recipientsName、receiver.countryCode、receiver.zipCode、sender.senderName、items。 - 校验数值合法性:
length/width/height/actualWeight必须大于 0。 - 校验枚举合法性:
cargoAttribute仅允许general、electronics、sensitive。 - 校验枚举合法性:
exportCustomsMode可选;若传入则须为 §4.2.1 ExportCustomsMode 枚举 code(9610Simple、9610Summary、9610Separate、9710、9810、0110),否则返回参数错误。 - 客户校验:按
customerId确认客户存在且业务状态可用(客户主数据与状态字段以 RBAC/客户域服务 为准;实现上可为远程调用或只读副本查询);不可用则返回错误。 - 查询
t_warehouse_address,条件:Id = warehouseId and IsDeleted = 0,返回字段:Id、WarehouseName;仓库不存在时返回错误。 - 查询
t_country,仅校验收件人国家,条件:Id = receiver.countryCode and IsDeleted = 0,返回字段:Id、CountryCode、ChineseName、EnglishName;国家不存在时返回错误。
- 校验请求体必填字段:
-
查询销售产品配置(用于定位发布记录)
- 查询
t_sales_product,条件:ProductCode = productCode and IsDeleted = 0 and IsActive = 1 - 返回字段:
Id、ProductCode、ProductName - 如不存在,不创建订单,直接返回失败(错误信息需明确「销售产品不存在或未启用」)。
- 查询
-
绑定销售产品计费快照(强关联:以创建订单当刻绑定的价格与规则为准;运行时优先 Redis + 本地内存)
- 绑定时点:以本次请求处理时间作为
bindTime(草稿落库后,t_order.CreateTime应与该时点一致或可由该时点推导)。 - 主路径(推荐):按
salesProductId = t_sales_product.Id与bindTime,从 Redis / 计费服务本地内存 解析「当前应对外生效」的 规则快照 与 价格快照(结构化 JSON,与运营发布组装的版本一致),得到:rulesSnapshot:含version、effectiveStartAt(或等价字段)、contentpriceSnapshot:含version、effectiveStartAt、content
- 降级路径:当 Redis/内存未命中或版本指针异常时,从
t_sales_product_publish_record读取:- 规则:条件
SalesProductId = t_sales_product.Id and OperatorType = 'rules' and Status = '生效' and PublishTime <= bindTime,按PublishTime desc取 1 条,Content即规则快照正文(与下文rulesSnapshot.content同构)。 - 价格:条件
OperatorType = 'price',其余同上,Content即价格快照正文。 - 命中后应异步回写 Redis,并打点监控。
- 规则:条件
- 绑定失败处理(尚未落库订单):
- 若未找到 rulesSnapshot:不创建订单,直接返回失败(错误信息需明确「未命中规则快照版本(内存/Redis/DB)」)。
- 若未找到 priceSnapshot:不创建订单,直接返回失败(错误信息需明确「未命中价格快照版本(内存/Redis/DB)」)。
- 版本字段落库:在下一步「创建订单草稿」插入
t_order时写入(强关联字段,新单新价、老单不改):SalesProductRulesVersion = rulesSnapshot.version(与发布记录Version一致)SalesProductPriceVersion = priceSnapshot.version
- 性能要求:
- 下单/预估主链路应在进程内内存完成快照读取与匹配;降级读 DB 仅作兜底,应限流并尽快恢复 Redis。
- 绑定时点:以本次请求处理时间作为
-
黑名单校验(拦截型,来自已绑定的 rules 快照
content)- 读取
rulesSnapshot.content.areas.blacklist.rules(国家/省市/邮编区间规则集合)。 - 匹配规则:
- 国家必须匹配参数校验阶段已解析的收件国家编码(与后续写入
t_order.ConsigneeCountry的值一致,来源于t_country.CountryCode) - 若规则配置了省/市,则请求体收件人
receiver的省/市也必须匹配 - 邮编落在任一
postcodeRanges.left ~ postcodeRanges.right区间内即视为命中
- 国家必须匹配参数校验阶段已解析的收件国家编码(与后续写入
- 命中处理:不创建订单,直接返回失败(错误信息需明确「收件地址命中黑名单区域」),不进入草稿落库及后续流程。
- 读取
-
创建订单草稿
- 插入
t_order:- 写入字段:
ServiceNo、ClientNo、TrackNo、ProductCode、ChannelCode、ConsigneeCountry、CargoAttribute、ExportCustomsMode、OrderStatus、WarehouseId、CustomerId、IsCod、CodCurrency、CodSum、IsIntercept、IsRemote、PredeclareFailReason、SalesProductRulesVersion、SalesProductPriceVersion、审计字段。 - 处理规则:
OrderStatus固定写draftConsigneeCountry取收件国家对应的t_country.CountryCodeIsIntercept初始写0IsRemote初始写0PredeclareFailReason初始写空SalesProductRulesVersion、SalesProductPriceVersion取步骤 3 已解析的快照版本ExportCustomsMode取请求体exportCustomsMode(须为 §4.2.1 枚举 code),未传则NULL
- 写入字段:
- 插入
t_order_sender:- 条件:使用新生成的
OrderId - 写入字段:
OrderId、SenderName、Company、Country、Province、City、ZipCode、StreetAddress1、StreetAddress2、StreetAddress3、HouseNumber、Phone、TelePhone、Email
- 条件:使用新生成的
- 插入
t_order_recipient:- 写入字段:
OrderId、RecipientsName、CompanyName、Country、Phone、TelePhone、ZipCode、Province、City、StreetNumber、StreetAddress1、StreetAddress2、StreetAddress3、Email、TaxType、TaxNo、CertificateType、CertificateNo、Eori、Vat
- 写入字段:
- 插入
t_order_declaration:- 对
items数组逐条入库 - 写入字段:
OrderId、CnName、EnName、Sku、Unit、UnitPrice、UnitWeight、Quantity、Amount、Weight、HsCode、SkuImage、Category、Brand、BrandType、IsMagnetic、Distribution、Material、EnMaterial、Purpose、Attributes、OriginCountry、SalesLink、Model、Specifications、Comment
- 对
- 插入
t_order_weight:- 一次性写入 4 条记录,
Type依次为forecast、receive、ship、downstream(与 §4.2.7Type枚举一致) - 写入字段:
OrderId、Type、Length、Width、Height、ActualWeight、VolumetricWeight、ChargeableWeight、Cubic - 先构造
Type = forecast行的初始值:ActualWeight取请求值VolumetricWeight、ChargeableWeight可先写请求体值或0,后续步骤 7、8 按规则重算并覆盖Cubic = Length × Width × Height / 1000000
Type = receive/ship/downstream三行:Length、Width、Height、ActualWeight、VolumetricWeight、ChargeableWeight、Cubic均与forecast行相同(创建时从forecast拷贝;后续收货、发货、下游等环节再按各自Type更新差异化测量)
- 一次性写入 4 条记录,
- 插入
-
偏远区域校验(标记型,来自已绑定的 rules 快照)
- 读取
rulesSnapshot.content.areas.remote.rules(国家/省市/邮编区间规则集合)。 - 匹配规则与黑名单一致。
- 命中则更新
t_order.IsRemote = 1;未命中则更新t_order.IsRemote = 0 - 偏远校验不拦截订单,只影响后续费用匹配。
- 读取
-
计费重计算(有效规则 ID:仅销售产品)
- 输入:仅使用
t_order_weight中Type = forecast的件重尺:Length、Width、Height、ActualWeight(单位与库表约定一致,一般为 cm / kg)。 - 解析
effectiveWeightRuleId:取本单绑定t_sales_product.WeightRuleId;须非空且对应t_weight_rule.IsDeleted=0。否则更新PredeclareFailReason(如「未配置计重规则」),保持draft,失败返回。 - 加载明细集合
rules:t_weight_rule_info中RuleId = effectiveWeightRuleId and IsDeleted=0,按Id升序排序;或从rulesSnapshot.content.weightRule读取与effectiveWeightRuleId一致的clientRules(结构无client字段,与表 §5.2.16 对齐)。集合为空则同上失败。 - 算法(未进位计费重
rawW):gw = ActualWeight(实重,kg)。- 依次遍历
rules中每一行(已按Id升序):对该行解析volumetricFactor为正数,计算vw = (Length × Width × Height) / volumetricFactor(与产品历史口径一致:体积 cm³ ÷ 系数 → 体积重 kg;若实现使用 m³,须在服务内统一换算)。 - 将该行的
gw、vw代入condition(支持>、>=、<、<=、==等,运算对象可为gw、vw及常量;不支持跨行交叉引用)。 - 第一条使
condition为真的行:命中行;若无一命中,失败(PredeclareFailReason建议「计重规则条件均未命中」)。 - 命中行的
billableWeight取值仅为gw或vw(大小写不敏感):rawW = (billableWeight == 'gw') ? gw : vw。 - 写回
t_order_weight.VolumetricWeight:建议取命中行对应的vw(便于对账;若业务约定取「展示用」体积重可另行说明)。本接口(预报草稿)建议将同一vw同步写入forecast、receive、ship、downstream四行,与创建时四行初始拷贝策略一致。入库在receive行重算后,默认将VolumetricWeight(及同次流程写回的件重尺字段)同步至ship、downstream;出库在ship行重算后,默认同步至downstream;均不再与forecast强制一致。
- 输入:仅使用
-
计费重进位(有效进位 ID:仅销售产品)
- 解析
effectiveWeightRoundingId:取本单绑定t_sales_product.WeightRoundingId;须非空且t_weight_rounding.IsDeleted=0。无效则失败(PredeclareFailReason如「未配置计重进位」)。 - 加载区间集合
ranges:t_weight_rounding_info中RoundingId = effectiveWeightRoundingId and IsDeleted=0;或快照rulesSnapshot.content.weightRounding.ranges(仅含start/end/public,与 §5.2.18 对齐)。 - 匹配区间:在
ranges中找到满足start <= rawW <= end的区间(多区间重叠时按Id升序取第一条,或产品约定唯一覆盖);无匹配则失败。 - 算法(最终计费重):设命中区间
public = u(正数,进位值 kg)。推荐统一为按进位值向上取整:ChargeableWeight = ceil(rawW / u) × uceil为数学向上取整;实现须固定小数位数(如 3 位)避免浮点误差。
- 更新
t_order_weight.ChargeableWeight:预报阶段建议四行与上一步VolumetricWeight策略一致,同步为同一计费重。入库:在receive行进位完成后,默认将ChargeableWeight同步至ship、downstream。出库:在ship行进位完成后,默认同步至downstream(§4.3.4)。若public为空或非法,失败。
- 解析
-
价格分区匹配(来自已绑定的 rules 快照)
- 读取
rulesSnapshot.content.areas.price.rules,按收件国家/省市/邮编区间匹配得到zoneName(如“美国西部”)。 - 若未匹配到价格分区,更新
t_order.PredeclareFailReason = '价格分区未匹配(规则快照)',订单状态保持draft,返回失败。
- 读取
-
费用计算与费用落库(拆分为应收 / 应付,与 §4.3.4.1、§4.3.4.2 一致;本接口处于预报节点)
- 1)重算应收(§4.3.4.1):对
chargingTime为forecast(或未配置视为 forecast) 的卖价项执行算价;重量等件重尺因子取Type=forecast;分区取步骤 9 的zoneName;结果 upsertt_order_fee(Type=receivable,ChargingStage=forecast)。inbound/outbound卖价项本接口跳过,留仓储流程触发后再跑 §4.3.4.1。 - 2)重算应付(§4.3.4.2):在
downstream行已随步骤 5~8 写入(与forecast等一致或已有值)后,对chargingTime=forecast(或未配置) 的买价项(若本单已确定服务渠道且存在绑定买价快照)算价;重量/件重尺仅允许Type=downstream;结果 upsertt_order_fee(Type=payable,ChargingStage=forecast)。无渠道或无买价快照时可跳过应付。 - 写入字段(各行):
OrderId、Type、CostItem、Amount、Currency、PriceNo、PriceEffectiveTime、ChargingStage;PriceNo应收写SalesProductPriceVersion,应付写渠道买价版本(若有)。 - 强校验建议:若订单存在至少一条启用的卖价项,且所有启用项的
chargingTime均不是预报,则本步骤可产生 0 条应收;是否允许「预报成功但尚无应收行」由产品策略决定。 - 若应收应算项未匹配到卖价明细,更新
t_order.PredeclareFailReason = '产品卖价快照未配置或未匹配到有效价格',订单状态保持draft,返回失败。
- 固定报价示例规则(某产品,来自 price 快照的 continuePricing)
- 示例规则:
- 首重:1kg 以内,首重价 18 元
- 续重:超出 1kg 部分,每 0.5kg 为一个续重单位,续重单价 6 元 / 0.5kg
- 进位规则:不足 0.5kg 按 0.5kg 进位
- 适用前提:
- 该产品已匹配到对应价格分区与卖价配置
t_order_weight.ChargeableWeight已完成最终进位- price 快照明细为
calculationFormula = 续单价且包含continuePricing
- 计算口径:
- 当
ChargeableWeight <= 1时,总费用 = 18 - 当
ChargeableWeight > 1时:- 先收首重价 18
- 超出部分 =
ChargeableWeight - 1 - 超出部分按 0.5kg 向上取整到续重单位数
- 续重费用 = 续重单位数 * 6
- 总费用 = 18 + 续重费用
- 当
- 示例:
ChargeableWeight = 0.8kg,进位到1.0kg,总费用 = 18ChargeableWeight = 1.2kg,超出0.2kg,按 0.5kg 进 1 个续重单位,总费用 = 18 + 6 = 24ChargeableWeight = 1.6kg,超出0.6kg,按 0.5kg 进 2 个续重单位,总费用 = 18 + 12 = 30
- 该示例说明:计费重来源仅为
t_order_weight,不参与t_order_declaration的商品重量汇总逻辑。
- 成功完成预报
- 当偏远标记完成、计费重计算完成、本阶段(预报)应计费用写入完成后(黑名单已在草稿落库前完成校验):
- 更新
t_order.OrderStatus = 'predeclared' - 更新
t_order.PredeclareFailReason = '' - 更新
t_order.UpdateUserId、t_order.UpdateTime
- 更新
- 返回字段:
clientNo:取t_order.ClientNoserviceNo:取t_order.ServiceNotrackNo:取t_order.TrackNolabelUrl:若当前流程未生成面单则返回空字符串
状态与失败处理
- 参数校验失败:不创建订单,直接返回错误。
- 销售产品不存在或未启用、规则/价格快照未命中、黑名单命中:均不创建订单,直接返回错误(与参数校验一致,不落库,不写
PredeclareFailReason)。 - 草稿创建成功但后续业务失败:订单状态统一保留
draft。 - 偏远命中:仅更新
IsRemote = 1,不拦截流程。 - 计重规则、进位规则、价格分区、卖价配置缺失或未匹配:统一写入
PredeclareFailReason,订单状态保持draft。
校验与异常
- 对必填参数、枚举值、数值范围、客户/仓库/国家/销售产品存在性进行校验,异常场景返回统一错误码与错误信息。
- 草稿创建后的异常场景需要保留订单数据,并将失败原因写入
t_order.PredeclareFailReason,供订单列表和详情页展示。
4.4.3.2 批量创建小包(POST /order/parcel/batch-create)
与 §4.4.3.1 创建小包 使用同一套单票业务规则(参数校验 → 销售产品与快照绑定 → 黑名单 → 草稿 → 偏远/计费重/预报费用 → 状态更新)。数组元素字段与单票请求体一致,含可选字段 exportCustomsMode(出口报关方式),枚举与落库规则见 §4.2.1、§4.4.3.1。差异:本接口先将批次内订单全部受理入库(或入队),HTTP 仅同步返回批量任务标识与受理概况,不返回每票的 serviceNo / labelUrl 等最终结果;逐票处理在后台异步执行,处理进度与失败明细通过 §4.4.3.7 任务详情(GET /order/task/detail)查询。
1 接口请求示例
请求 /order/parcel/batch-create(POST)
批量请求体为数组,数组内每一项与
/order/parcel/create的单票请求结构完全一致。单次导入条数上限为 2000:array.length > 2000时整批拒绝,不入队、不创建任务。幂等时可选传与单票一致的requestId(若实现批次级幂等,则以该字段或服务端生成的批次维度键为准)。
[
{
"clientNo": "string", // 客户单号 t_order.ClientNo
"trackNo": "string", // 跟踪号 t_order.TrackNo
"serviceNo": "string", // 运单号 t_order.ServiceNo
"productCode": "string", // 产品代码 t_order.ProductCode
"channelCode": "string", // 渠道代码 t_order.ChannelCode
"cargoAttribute": "string", // 货物属性 t_order.CargoAttribute:general-普货,electronics-3c&带电,sensitive-敏感货
"exportCustomsMode": "string", // 出口报关方式 t_order.ExportCustomsMode:9610Simple/9610Summary/9610Separate/9710/9810/0110,含义见 §4.2.1 ExportCustomsMode 枚举//可选,与单票 create 一致
"warehouseId": 0, // 仓库ID t_order.WarehouseId
"customerId": 0, // 客户ID t_order.CustomerId
"length": 3, // 长(cm) t_order_weight.Length
"width": 3, // 宽(cm) t_order_weight.Width
"height": 3, // 高(cm) t_order_weight.Height
"actualWeight": 3, // 实重(kg) t_order_weight.ActualWeight
"volumetricWeight": 3, // 体积重(kg) t_order_weight.VolumetricWeight
"chargeableWeight": 3, // 计费重(kg) t_order_weight.ChargeableWeight
"cubic": 0, // 立方(m³) t_order_weight.Cubic
"isCod": false, // 是否COD
"codCurrency": "string", // COD币种
"codSum": "string", // COD金额
"declaredCurrency": "string", // 申报币种
"declaredSum": "string", // 申报金额
"quantity": "string", // 包裹数量
"receiver": { // 收件人 t_order_recipient
"recipientsName": "string", // 收件人名称
"companyName": "string", // 收件人公司名称
"phone": "string", // 收件人手机
"telePhone": "string", // 收件人电话
"email": "string", // 收件人邮箱
"countryCode": 0, // 国家
"province": "string", // 收件人省/州
"city": "string", // 收件人城市
"streetNumber": "string", // 收件人门牌号
"streetAddress1": "string", // 收件人地址1
"streetAddress2": "string", // 收件人地址2
"streetAddress3": "string", // 收件人地址3
"zipCode": "string", // 收件人邮编
"taxType": 0, // 税号类型
"taxNo": "string", // 税号
"certificateType": 0, // 证件类型
"certificateNo": "string", // 证件号码
"eori": "string", // EORI
"vat": "string" // Vat
},
"sender": { // 发件人 t_order_sender
"senderName": "string", // 发件人姓名
"company": "string", // 发件人公司
"phone": "string", // 发件人手机
"telePhone": "string", // 发件人电话
"email": "string", // 发件人邮箱
"countryCode": 0, // 国家
"province": "string", // 州省
"city": "string", // 城市
"zipCode": "string", // 邮编
"streetAddress1": "string", // 地址1
"streetAddress2": "string", // 地址2
"streetAddress3": "string", // 地址3
"houseNumber": "string" // 门牌号
},
"items": [ // 申报明细 t_order_declaration
{
"cnName": "string", // 品名-中
"enName": "string", // 品名-英
"sku": "string", // SKU
"unit": "string", // 单位
"unitPrice": 0, // 单价
"unitWeight": 0, // 单重
"quantity": 0, // 数量
"amount": 0, // 总金额
"weight": 0, // 总重量
"imHsCode": "string", // 进口HsCode
"exHsCode": "string", // 出口HsCode
"skuImage": "string", // 图片
"category": "string", // 类别
"brand": "string", // 品牌
"brandType": "string", // 品牌类型
"isMagnetic": false, // 是否带磁带电
"distribution": "string", // 配货信息
"material": "string", // 材质
"enMaterial": "string", // 英文材质
"purpose": "string", // 用途
"attributes": "string", // 属性
"originCountry": "string", // 原产国
"salesLink": "string", // 销售链接
"model": "string", // 型号
"specifications": "string", // 规格
"comment": "string" // 备注
}
]
}
]
响应
成功受理时仅返回任务维度信息;单票业务结果(成功预报、草稿失败原因等)不在本响应中体现。
{
"code": 0,
"msg": "success",
"data": {
"taskId": 1,
"taskName": "批量创建小包_20240509120000",
"totalCount": 100,
"acceptedCount": 98,
"rejectedItems": [
{
"index": 3,
"clientNo": "optional-echo",
"reason": "同步拒收原因说明(如 JSON 结构非法、缺少整段 receiver 等)"
}
]
}
}
totalCount:请求数组长度。acceptedCount:已写入待异步处理队列(或等价持久化)的条数,acceptedCount + rejectedItems.length = totalCount(实现上也可将同步拒收记为 0 条入队,由rejectedItems说明)。rejectedItems:仅在同步阶段即确定无法受理的明细(例如某元素非对象、缺少整块必填结构);不在此列表中的条目将按单票逻辑在异步阶段处理,失败时记入任务详情中的失败列表或对应订单PredeclareFailReason(与 §4.4.3.1 一致)。
2 接口业务逻辑
核心流程
-
同步(请求线程)
- 校验批次 envelope:数组非空、单次条数 ≤ 2000、调用方权限/客户维度与单票接口一致。
- 对数组逐条做轻量同步校验(仅保证可进入异步流水线所需的最小结构;策略可选:过严则在同步期填入
rejectedItems,其余入队)。 - 创建
t_order_task主记录(或等价批量任务实体):TaskName建议带业务前缀与时间戳,Quantity = acceptedCount,Status初始为待处理/处理中;关联CustomerId等与上下文一致。 - 将
acceptedCount条明细持久化到待处理存储(任务明细表、消息队列、或带TaskId的缓冲表,实现选型由研发确定),每条携带原始 JSON 与行号index,供消费者拉取。 - 立即返回
taskId等响应字段,不等待任一票走完 §4.4.3.1 全链路。
-
异步(工作线程 / 消费者)
- 按 FIFO 或任务内顺序逐条取出明细,完全复用 §4.4.3.1「详细业务逻辑」各步骤(含:销售产品/快照失败与黑名单不落库;草稿后失败写
draft+PredeclareFailReason;成功则predeclared等)。 - 更新任务聚合进度:
successCount/failCount、Status(处理中 → 已完成);失败条目写入任务详情中的failList(建议含index、clientNo、错误码/原因,便于与上传文件行号对齐)。 - 与单票一致:幂等、并发、快照读取性能要求仍适用。
- 按 FIFO 或任务内顺序逐条取出明细,完全复用 §4.4.3.1「详细业务逻辑」各步骤(含:销售产品/快照失败与黑名单不落库;草稿后失败写
校验与异常
- 整批拒绝:数组为空、超过 2000 条、未授权等 → HTTP 业务错误,不创建任务、不入队。
- 同步 per-row 拒收:仅将明确无法入队的行写入
rejectedItems,其余正常入队;不要求在同步期校验仓库/国家/黑名单等业务规则(与单票异步阶段统一)。 exportCustomsMode:若某元素携带该字段,异步执行 §4.4.3.1 时按单票规则校验(须为 §4.2.1 枚举 code);非法则该票失败并写PredeclareFailReason(或任务详情failList),与cargoAttribute等枚举错误处理一致。- 异步失败:与 §4.4.3.1「状态与失败处理」一致;用户通过 §4.4.3.7 看批次汇总,通过订单列表/详情看单票
OrderStatus与PredeclareFailReason。
4.4.3.3 模板列表(GET /order/template/list)
1 接口请求示例
请求 /order/template/list(GET,Query 参数)
?page=1&pageSize=20&type=standard|custom&keyword=
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"name": "标准模板",
"type": "standard",
"templateKey": "standard_v1",
"customerId": 0,
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 10
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.3.4 下载模板(GET /order/template/download)
1 接口请求示例
请求 /order/template/download(GET,Query 参数)
?templateId=1
响应
直接返回 Excel 文件流,Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
2 接口业务逻辑
核心流程
- 标准模板 Excel 表头建议包含列 「出口报关方式」(与
exportCustomsMode/t_order.ExportCustomsMode对应),单元格填写 §4.2.1 ExportCustomsMode 枚举 code;列缺失或空单元格按 未传 处理,落库NULL。 - 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
- 若模板中提供「出口报关方式」列,非空值须为合法枚举 code,否则该行在解析或异步处理阶段失败(错误信息需可定位行号)。
4.4.3.5 上传下单(POST /order/upload)
1 接口请求示例
请求 /order/upload(POST,multipart/form-data)
| 字段 | 类型 | 说明 |
|---|---|---|
| file | File | Excel 文件 |
| templateId | number | 模板ID |
导入条数限制:按模板解析得到的有效订单数据行(不含表头)最多 2000 行;超出则拒绝本次上传并返回错误,不创建任务。
响应
{
"code": 0,
"msg": "success",
"data": {
"taskId": 1
}
}
2 接口业务逻辑
核心流程
- Excel 解析为与 §4.4.3.2 批量创建 单条元素等价的结构后入队;其中 出口报关方式 列(若模板配置)映射为
exportCustomsMode,规则与 GET /order/template/download 标准模板说明、§4.2.1 枚举一致。 - 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
- 文件格式、模板匹配、有效订单行数 ≤ 2000 等约束不满足时拒绝受理。
- 出口报关方式:列存在且单元格非空时,值须为 §4.2.1 枚举 code,否则拒绝该行或标记失败(与批量 JSON 单条校验一致)。
4.4.3.6 任务进度列表(GET /order/task/list)
1 接口请求示例
请求 /order/task/list(GET,Query 参数)
?page=1&pageSize=20&status=&keyword=
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"taskName": "批量下单_20240101",
"quantity": 100,
"status": "处理中",
"templateId": 1,
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 10
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
4.4.3.7 任务详情(GET /order/task/detail)
1 接口请求示例
请求 /order/task/detail(GET,Query 参数)
?taskId=1
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"taskName": "批量下单_20240101",
"quantity": 100,
"successCount": 80,
"failCount": 20,
"status": "已完成",
"templateId": 1,
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00",
"failList": []
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
5 渠道模块
5.1 核心需求说明
- 销售产品:管理对外销售的产品(专线/快递/邮政),配置时效、黑名单区、偏远分区、价格分区、计重规则、计重进位等;支持价格配置。
- 产品配置:产品基础信息(编码、名称、分组、时效、面单、黑名单区、偏远分区、价格分区、计重规则、计重进位等)。
- 产品卖价:为每个产品配置多条价格项(运费、保险费、燃油附加费等);每条价格项通过弹窗配置:
- 基础信息:费用项、费用单位、币种、收费时机、收费条件、计费因素(因素+因素值,如货物类型、分区、重量、仓库、客户等)。
- 价格表:根据计费因素动态生成价格表,支持分区/货物类型/重量等组合、计算公式(总价/单价/续单价)、计算值、客户组。
- 排货规则:选择排货方案(成本最低/时效最快/综合最优),配置服务商列表(服务商名称、服务渠道、权重、指定客户)。
- 发布记录:价格与规则的发布历史,支持查看版本内容、回滚到指定版本。
- 服务渠道:管理下游服务渠道(支持渠道组+渠道层级),配置预报单号类型、时效、买价等。
- 渠道配置:渠道基础信息(渠道代码、名称、时效、预报配置、描述、预报前脚本等)。
- 渠道买价:为每个渠道配置多条买价项(运费、保险费、燃油附加费等);每条买价项通过弹窗配置:
- 基础信息:费用项、费用单位、币种、收费时机、收费条件、计费因素(因素+因素值)。
- 价格表:根据计费因素动态生成价格表,支持分区/货物类型/重量等组合、计算公式、计算值、客户组。
- 发布记录:买价与规则的发布历史,支持查看版本内容、回滚到指定版本。
- 黑名单区/偏远分区/价格分区:共用 KpiArea 表,仅通过
AreaType区分;支持分区及明细(国家/省/市/邮编区间)的增删改查。 - 计重规则/计重进位:配置计费重量规则与进位方式,明细结构与分区类似。
- 自动触发:配置下单/入库/出库时的自动拦截、警告、问题件等触发规则。
- 标签设计:保存 vg-print 导出的标签模板 JSON,支持尾程/客户/入库/出库/sku 等类型。
5.2 表结构设计
5.2.1 销售产品表 t_sales_product
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| ProductCode | VARCHAR | 64 | - | 是 | 产品编码 |
| ProductName | VARCHAR | 128 | - | 是 | 产品名称 |
| ProductGroup | VARCHAR | 32 | - | 否 | 分组(专线/快递/邮政) |
| MinTimeliness | INT | - | - | 否 | 最小时效(天) |
| MaxTimeliness | INT | - | - | 否 | 最大时效(天) |
| CustomerWaybill | VARCHAR | 32 | - | 否 | 系统面单/客户面单 |
| BlacklistAreaId | BIGINT | - | 外键 | 否 | 黑名单区ID |
| RemoteAreaId | BIGINT | - | 外键 | 否 | 偏远分区ID |
| PriceAreaId | BIGINT | - | 外键 | 否 | 价格分区ID(t_kpi_area,AreaType=price) |
| WeightRuleId | BIGINT | - | 外键 | 否 | 计重规则ID |
| WeightRoundingId | BIGINT | - | 外键 | 否 | 计重进位ID |
| ProductDescription | TEXT | - | - | 否 | 产品描述 |
| PreStorageScript | TEXT | - | - | 否 | 入库前脚本 |
| IsActive | TINYINT | - | - | 是 | 是否启用 |
| Scheme | VARCHAR | 32 | - | 是 | 排货方案:costLowest/timeFastest/overallBest |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.2 产品卖价表 t_sales_product_price(子表,关联 t_sales_product)
产品卖价主表,每个产品可配置多条价格项(运费、保险费、燃油附加费等)。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| SalesProductId | BIGINT | - | 外键 | 是 | 销售产品ID |
| SerialNumber | INT | - | - | 是 | 序号 |
| Status | TINYINT | - | - | 是 | 状态:0-禁用,1-启用 |
| PriceName | VARCHAR | 64 | - | 是 | 价格名称(如运费、保险费) |
| CostItem | VARCHAR | 64 | - | 是 | 费用项 |
| CostUnit | VARCHAR | 16 | - | 是 | 费用单位:kg/票/件 |
| Currency | VARCHAR | 16 | - | 是 | 币种:RMB/USD/EUR |
| ChargingTime | VARCHAR | 32 | - | 否 | 收费时机:决定本费用项在订单哪一履约阶段写入 t_order_fee(见 §4.3.4)。建议存编码:forecast(预报)、inbound(入库)、outbound(出库);展示可对应中文「预报/入库/出库」。缺省按 forecast。 |
| ChargingCondition | VARCHAR | 64 | - | 否 | 收费条件 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.3 产品卖价-计费因素表 t_sales_product_price_factor(子表,关联 t_sales_product_price)
弹窗「基础信息」中的计费因素配置,支持货物类型、分区、重量、仓库、客户等。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| PriceId | BIGINT | - | 外键 | 是 | 产品卖价ID |
| SerialNumber | INT | - | - | 是 | 序号(决定因素排序) |
| Factor | VARCHAR | 64 | - | 是 | 因素:货物类型/分区/重量/仓库/客户 |
| FactorValues | JSON | - | - | 否 | 因素值数组,如 ["普货","敏感货"] |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.4 产品卖价-价格表明细表 t_sales_product_price_detail(子表,关联 t_sales_product_price)
弹窗「价格表」中的价格明细,表头由计费因素动态生成,存储各组合的价格值。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| PriceId | BIGINT | - | 外键 | 是 | 产品卖价ID |
| FactorValuesJson | JSON | - | - | 否 | 非客户因素组合,如 {"分区":"欧洲","货物类型":"普货","重量":"0-0.5"} |
| CalculationFormula | VARCHAR | 32 | - | 是 | 计算公式:总价/单价/续单价 |
| CalculatedValue | DECIMAL | 18,4 | - | 否 | 计算值 |
| CustomerGroupValues | JSON | - | - | 否 | 客户组对应价格,如 {"客户组1":10,"客户组2":12} |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.5 排货规则-服务商表 t_sales_product_allocation_provider(子表,关联 t_sales_product_allocation_rule)
服务商列表:服务商名称、服务渠道、权重、指定客户。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| SalesProductId | BIGINT | - | 外键 | 是 | 销售产品ID |
| SerialNumber | INT | - | - | 是 | 序号 |
| ProviderName | VARCHAR | 128 | - | 是 | 服务商名称 |
| ServiceChannelId | BIGINT | - | 外键 | 否 | 服务渠道ID |
| Weight | INT | - | - | 是 | 权重(评分用) |
| CustomerIds | JSON | - | - | 否 | 指定客户ID数组,空表示全部 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
Scheme 枚举:costLowest(成本最低)、timeFastest(时效最快)、overallBest(综合最优)
5.2.6 发布记录表 t_sales_product_publish_record(子表,关联 t_sales_product)
价格与规则的发布历史,支持查看版本内容、回滚。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| SalesProductId | BIGINT | - | 外键 | 是 | 销售产品ID |
| Version | VARCHAR | 32 | - | 是 | 版本号,如 20231227112339 |
| OperatorType | VARCHAR | 16 | - | 是 | 操作类型:price(价格)/rules(规则) |
| Status | VARCHAR | 16 | - | 是 | 状态:生效/回滚/无效 |
| PublishUser | VARCHAR | 64 | - | 是 | 发布人 |
| PublishTime | DATETIME | - | - | 是 | 发布时间 |
| Description | VARCHAR | 512 | - | 否 | 版本备注 |
| Content | JSON | - | - | 否 | 发布内容(价格或规则配置的JSON快照) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.6.1 发布内容 Content(JSON快照)结构规范(用于限制校验与计费)
设计目标:
- 强绑定有效期:订单创建时按当时的生效版本(PublishTime)绑定发布记录;后续计算以绑定版本为准。
- 计算快:下单/计费/校验不再联查
t_kpi_area*、t_weight_rule*、t_weight_rounding*、t_sales_product_price*等多表;只读取一次发布记录Content(可缓存)。- 可回溯:任何时候都能根据订单绑定的发布记录ID拿到当时的规则/价格快照。
性能实现要求(强制):
- 发布后的规则/价格快照以
t_sales_product_publish_record为权威落库;同步任务将标准化后的Content写入 Redis(按salesProductId+OperatorType+Version或current指针),并通知计费服务刷新本地内存。- 在线下单/预估只读 Redis + 本地内存;仅在 Redis/内存异常时降级直读发布记录表(见订单模块
/order/parcel/create步骤 4),并应异步回填 Redis。
5.2.6.2 Redis 与发布同步(在线计费)
- Key 示例(可按团队规范调整前缀):
oms:pricing:sp:{salesProductId}:rules:{version}/...:price:{version}:存放与Content同构的 JSON(或已序列化的二进制)。oms:pricing:sp:{salesProductId}:rules:current/...:price:current:指向当前对外生效的version字符串,便于 O(1) 定位。
- 在线匹配数据来源:计费服务进程内已解析的
rulesSnapshot/priceSnapshot(来自 Redis 加载或启动预热)。
发布同步流程(必须):
- 业务侧完成一次规则或价格发布,写入
t_sales_product_publish_record(含Version、Status、PublishTime、Content)。 - 将
Content标准化后写入 Redis(对应OperatorType的 key);更新current指针指向新版本(与「生效」语义一致)。 - 通知各计费实例刷新内存;实例冷启动可从 Redis 全量加载,必要时可从发布表补齐缺失版本。
- 若 Redis 写入失败:应阻断或重试发布,直至线上可见一致快照,避免「库里有版本但线上算价仍用旧缓存」。
1) 通用字段(rules / price 共用)
schemaVersion:快照结构版本(从 1 开始)operatorType:rules或price(与发布记录OperatorType保持一致)salesProduct:发布时的产品基础信息快照(用于展示与校验,不参与联查)effective:startAt:生效时间(一般等于PublishTime)endAt:失效时间(可为空,表示至今有效;当有新版本发布时可由系统补齐旧版本endAt)
checksum:可选,用于校验内容是否被篡改(如 sha256)
2) rules 快照内容(限制 + 计重 + 进位)
Content 示例(OperatorType=rules):
{
"schemaVersion": 1,
"operatorType": "rules",
"salesProduct": {
"salesProductId": 1,
"productCode": "US_AIR",
"productName": "美国空运专线(普货)",
"cargoAttributes": ["general", "electronics", "sensitive"],
"scheme": "overallBest"
},
"effective": { "startAt": "2026-04-25 14:30:00", "endAt": null },
"areas": {
"blacklist": {
"areaName": "黑名单区1",
"rules": [
{
"countryCode": "US",
"province": null,
"city": null,
"postcodeRanges": [
{ "left": "90000", "right": "90010" },
{ "left": "91000", "right": "91099" }
]
}
]
},
"remote": {
"areaName": "偏远分区1",
"rules": [
{
"countryCode": "US",
"province": "California",
"city": null,
"postcodeRanges": [{ "left": "90001", "right": "90099" }]
}
]
},
"price": {
"areaName": "价格分区(美国)",
"rules": [
{
"zoneCode": "US_WEST",
"zoneName": "美国西部",
"countryCode": "US",
"province": null,
"city": null,
"postcodeRanges": [{ "left": "90000", "right": "96999" }]
}
]
}
},
"weightRule": {
"weightRuleId": 1,
"name": "标准计重规则",
"clientRules": [
{ "volumetricFactor": 6000, "condition": "gw>vw", "billableWeight": "gw" },
{ "volumetricFactor": 6000, "condition": "gw<=vw", "billableWeight": "vw" }
]
},
"weightRounding": {
"weightRoundingId": 1,
"name": "标准进位",
"ranges": [{ "start": 0, "end": 30, "public": "0.5" }]
},
"checksum": ""
}
说明:
areas.blacklist/remote/price将t_kpi_area_info的明细扁平化内嵌到快照里,避免下单时联查分区表。areas.price.rules[*].zoneCode/zoneName用于后续计价因子“分区”匹配(对应价格快照的factorValuesJson.分区)。weightRule.clientRules将t_weight_rule_info直接内嵌(无client列);运行时以 §4.4.3.1 步骤 7 解析的effectiveWeightRuleId为准,与快照中weightRuleId对齐或回表查询。weightRounding.ranges将t_weight_rounding_info内嵌(仅public进位值);运行时以步骤 8 的effectiveWeightRoundingId为准。
3) price 快照内容(卖价配置 + 价格表)
Content 示例(OperatorType=price):
{
"schemaVersion": 1,
"operatorType": "price",
"salesProduct": {
"salesProductId": 1,
"productCode": "US_AIR",
"productName": "美国空运专线(普货)"
},
"effective": { "startAt": "2026-04-25 14:30:00", "endAt": null },
"priceItems": [
{
"serialNumber": 1,
"status": 1,
"priceName": "运费",
"costItem": "freight",
"costUnit": "kg",
"currency": "RMB",
"chargingTime": "预报",
"chargingCondition": "",
"factors": [
{ "serialNumber": 1, "factor": "分区" },
{ "serialNumber": 2, "factor": "重量" }
],
"details": [
{
"factorValuesJson": { "分区": "美国西部", "重量": "0-9999" },
"calculationFormula": "续单价",
"calculatedValue": 0,
"customerGroupValues": null,
"continuePricing": {
"firstWeightKg": 1,
"firstPrice": 18,
"continueUnitKg": 0.5,
"continueUnitPrice": 6,
"roundingUnitKg": 0.5
}
}
]
}
],
"checksum": ""
}
说明:
- 为了支持“首重/续重/进位”的可落地配置,当
calculationFormula = 续单价时,使用continuePricing描述完整计费参数(不再依赖额外表字段)。 roundingUnitKg表示计价侧进位值(如 0.5kg)。若同时存在规则侧进位(rules快照里的weightRounding),计费重进位以规则侧为准,roundingUnitKg用于价格项自身的续重单位计算兜底(两者一般配置一致)。
5.2.7 服务渠道组表 t_service_channel_group
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| Name | VARCHAR | 128 | - | 是 | 渠道组名称 |
| AppId | BIGINT | - | - | 否 | 应用ID(页面新增/编辑服务商时保存) |
| ApiServiceProviderId | BIGINT | - | - | 否 | API服务商ID(页面新增/编辑服务商时保存) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.8 服务渠道表 t_service_channel
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| GroupId | BIGINT | - | 外键 | 否 | 渠道组ID(可选) |
| ChannelCode | VARCHAR | 64 | - | 是 | 渠道编码 |
| ChannelName | VARCHAR | 128 | - | 是 | 渠道名称 |
| MinTime | INT | - | - | 否 | 最小时效(天) |
| MaxTime | INT | - | - | 否 | 最大时效(天) |
| ForecastType | VARCHAR | 32 | - | 否 | 预报单号类型(customer/waybill/tracking) |
| ForecastCode | VARCHAR | 128 | - | 否 | 预报单号 |
| Description | TEXT | - | - | 否 | 描述 |
| PreScript | TEXT | - | - | 否 | 入库前脚本 |
| IsActive | TINYINT | - | - | 是 | 是否启用 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.9 渠道买价表 t_service_channel_price(子表,关联 t_service_channel)
渠道买价主表,每个渠道可配置多条买价项(运费、保险费、燃油附加费等)。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| ServiceChannelId | BIGINT | - | 外键 | 是 | 服务渠道ID |
| SerialNumber | INT | - | - | 是 | 序号 |
| Status | TINYINT | - | - | 是 | 状态:0-禁用,1-启用 |
| PriceName | VARCHAR | 64 | - | 是 | 价格名称 |
| CostItem | VARCHAR | 64 | - | 是 | 费用项 |
| CostUnit | VARCHAR | 16 | - | 是 | 费用单位:kg/票/件 |
| Currency | VARCHAR | 16 | - | 是 | 币种:RMB/USD/EUR |
| ChargingTime | VARCHAR | 32 | - | 否 | 收费时机:与卖价表 ChargingTime 语义一致(§4.3.4),决定应付费用项在预报/入库/出库哪一阶段写入 t_order_fee(Type=payable)。建议编码:forecast / inbound / outbound,缺省 forecast。 |
| ChargingCondition | VARCHAR | 64 | - | 否 | 收费条件 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.10 渠道买价-计费因素表 t_service_channel_price_factor(子表,关联 t_service_channel_price)
弹窗「基础信息」中的计费因素配置。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| PriceId | BIGINT | - | 外键 | 是 | 渠道买价ID |
| SerialNumber | INT | - | - | 是 | 序号 |
| Factor | VARCHAR | 64 | - | 是 | 因素:货物类型/分区/重量/仓库/客户 |
| FactorValues | JSON | - | - | 否 | 因素值数组 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.11 渠道买价-价格表明细表 t_service_channel_price_detail(子表,关联 t_service_channel_price)
弹窗「价格表」中的价格明细。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| PriceId | BIGINT | - | 外键 | 是 | 渠道买价ID |
| FactorValuesJson | JSON | - | - | 否 | 非客户因素组合 |
| CalculationFormula | VARCHAR | 32 | - | 是 | 计算公式:总价/单价/续单价 |
| CalculatedValue | DECIMAL | 18,4 | - | 否 | 计算值 |
| CustomerGroupValues | JSON | - | - | 否 | 客户组对应价格 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.12 服务渠道发布记录表 t_service_channel_publish_record(子表,关联 t_service_channel)
买价与规则的发布历史。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| ServiceChannelId | BIGINT | - | 外键 | 是 | 服务渠道ID |
| Version | VARCHAR | 32 | - | 是 | 版本号 |
| OperatorType | VARCHAR | 16 | - | 是 | 操作类型:price(价格)/rules(规则) |
| Status | VARCHAR | 16 | - | 是 | 状态:生效/回滚/无效 |
| PublishUser | VARCHAR | 64 | - | 是 | 发布人 |
| PublishTime | DATETIME | - | - | 是 | 发布时间 |
| Description | VARCHAR | 512 | - | 否 | 版本备注 |
| Content | JSON | - | - | 否 | 发布内容JSON快照 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.13 分区表(黑名单区/偏远分区/价格分区共用)t_kpi_area
三类分区共用本表,仅通过
AreaType区分业务含义。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| AreaType | VARCHAR | 32 | - | 是 | 类型: blacklist/remote/price |
| Name | VARCHAR | 128 | - | 是 | 分区名称 |
| SystemName | VARCHAR | 128 | - | 否 | 系统名称 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
AreaType 枚举:blacklist(黑名单区)、remote(偏远分区)、price(价格分区)
5.2.14 分区明细表 t_kpi_area_info
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| AreaId | BIGINT | - | 外键 | 是 | 分区ID |
| CountryCode | VARCHAR | 8 | - | 否 | 国家二字码 |
| CountryName | VARCHAR | 64 | - | 否 | 国家名称 |
| Province | VARCHAR | 128 | - | 否 | 省份 |
| City | VARCHAR | 128 | - | 否 | 城市 |
| LeftPostcode | VARCHAR | 32 | - | 否 | 左侧邮编 |
| RightPostcode | VARCHAR | 32 | - | 否 | 右侧邮编 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.15 计重规则表 t_weight_rule
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| Name | VARCHAR | 128 | - | 是 | 规则名称 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.16 计重规则明细表 t_weight_rule_info(子表,关联 t_weight_rule)
计重规则子页面,仅配置条件表达式、计费重取值、材积系数;不再使用「客户/客户组」列。同一
RuleId下多行按Id升序逐条尝试,第一条使条件为真的明细生效(算法见 §4.4.3.1 步骤 7)。运行时通过本单绑定t_sales_product.WeightRuleId选用对应t_weight_rule(不同销售产品可绑定不同规则)。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| RuleId | BIGINT | - | 外键 | 是 | 计重规则ID |
| Condition | VARCHAR | 256 | - | 是 | 条件表达式(如:gw>vw) |
| BillableWeight | VARCHAR | 64 | - | 是 | 计费重取值(如:vw、gw) |
| VolumetricFactor | VARCHAR | 32 | - | 是 | 材积系数(如:6000) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.17 计重进位表 t_weight_rounding
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| Name | VARCHAR | 128 | - | 是 | 进位名称 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.18 计重进位明细表 t_weight_rounding_info(子表,关联 t_weight_rounding)
计重进位子页面,按重量区间配置单一进位值
Public(不再按客户组分列)。运行时通过本单绑定t_sales_product.WeightRoundingId选用对应t_weight_rounding(算法见 §4.4.3.1 步骤 8)。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| RoundingId | BIGINT | - | 外键 | 是 | 计重进位ID |
| StartValue | DECIMAL | 18,4 | - | 是 | 起始值(kg) |
| EndValue | DECIMAL | 18,4 | - | 是 | 结束值(kg) |
| Public | VARCHAR | 32 | - | 否 | 进位值(kg,如 0.5 表示按 0.5kg 向上取整) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.19 自动触发表 t_auto_trigger
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| Status | TINYINT | - | - | 是 | 是否启用 |
| Operation | VARCHAR | 32 | - | 否 | 操作: 拦截/警告/问题件 |
| TriggerTiming | VARCHAR | 32 | - | 否 | 触发时机: 下单/入库/出库 |
| TriggerCondition | TEXT | - | - | 否 | 触发条件 |
| PromptMessage | VARCHAR | 512 | - | 否 | 提示信息 |
| Notifier | VARCHAR | 128 | - | 否 | 通知人 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.2.20 标签模板表 t_label_template
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| Name | VARCHAR | 128 | - | 是 | 模板名称 |
| TemplateJson | JSON | - | - | 否 | vg-print 模板 JSON |
| TemplateType | VARCHAR | 32 | - | 否 | 尾程/客户/入库/出库/sku |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
5.3 核心接口设计
5.3.1 销售产品
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 产品列表 | GET | /channel/sales-product/list | 产品列表 |
| 产品详情 | GET | /channel/sales-product/detail | 产品详情 |
| 新增产品 | POST | /channel/sales-product/create | 新增产品 |
| 更新产品 | POST | /channel/sales-product/update | 更新产品(包含产品配置 tab 保存) |
| 删除产品 | POST | /channel/sales-product/delete | 删除产品 |
5.3.1.1 产品列表(GET /channel/sales-product/list)
1 接口请求示例
请求 /channel/sales-product/list(GET,Query 参数)
?page=1&pageSize=20&productGroup=专线&keyword=&isActive=1
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"productCode": "US-AIR-P",
"productName": "美国空运专线(普货)",
"productGroup": "专线",
"minTimeliness": 3,
"maxTimeliness": 7,
"customerWaybill": "系统面单",
"blacklistAreaId": 1,
"remoteAreaId": 2,
"priceAreaId": 3,
"weightRuleId": 1,
"weightRoundingId": 1,
"productDescription": "美国空运普货专线",
"isActive": 1,
"scheme": "costLowest",
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 10
}
}
2 接口业务逻辑
核心流程
- 接收分页与筛选参数后构建查询条件(productGroup、keyword、isActive)。
校验与异常
- 按分页参数查询销售产品列表,返回
items与total。
5.3.1.2 产品详情(GET /channel/sales-product/detail)
1 接口请求示例
请求 /channel/sales-product/detail(GET,Query 参数)
?id=1
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"productCode": "US-AIR-P",
"productName": "美国空运专线(普货)",
"productGroup": "专线",
"minTimeliness": 3,
"maxTimeliness": 7,
"customerWaybill": "系统面单",
"blacklistAreaId": 1,
"remoteAreaId": 2,
"priceAreaId": 3,
"weightRuleId": 1,
"weightRoundingId": 1,
"productDescription": "美国空运普货专线",
"preStorageScript": "",
"isActive": 1,
"scheme": "costLowest",
"createTime": "2024-01-01 12:00:00",
"createBy": "admin",
"updateTime": "2024-01-01 12:00:00",
"updateBy": "admin"
}
}
2 接口业务逻辑
核心流程
- 根据
id查询产品主数据及扩展配置,组装详情对象返回。
校验与异常
- 若产品不存在或不可访问,返回业务错误码。
5.3.1.3 新增产品(POST /channel/sales-product/create)
1 接口请求示例
请求 /channel/sales-product/create(POST)
{
"productCode": "US-AIR-P",
"productName": "美国空运专线(普货)",
"productGroup": "专线",
"minTimeliness": 3,
"maxTimeliness": 7,
"customerWaybill": "系统面单",
"blacklistAreaId": 1,
"remoteAreaId": 2,
"priceAreaId": 3,
"weightRuleId": 1,
"weightRoundingId": 1,
"productDescription": "美国空运普货专线",
"preStorageScript": "",
"isActive": 1,
"scheme": "costLowest"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 校验产品编码唯一性与必填字段后新增产品记录。
校验与异常
- 初始化产品配置与默认状态,写入审计字段。
5.3.1.4 更新产品(POST /channel/sales-product/update)
1 接口请求示例
请求 /channel/sales-product/update(POST)
{
"id": 1,
"productCode": "US-AIR-P",
"productName": "美国空运专线(普货)",
"productGroup": "专线",
"minTimeliness": 3,
"maxTimeliness": 7,
"customerWaybill": "系统面单",
"blacklistAreaId": 1,
"remoteAreaId": 2,
"priceAreaId": 3,
"weightRuleId": 1,
"weightRoundingId": 1,
"productDescription": "美国空运普货专线",
"preStorageScript": "",
"isActive": 1,
"scheme": "costLowest"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据
id校验产品存在性后更新可变字段(包含产品配置 tab 的保存内容)。
校验与异常
- 记录操作人和更新时间,并触发配置缓存刷新。
5.3.1.5 删除产品(POST /channel/sales-product/delete)
1 接口请求示例
请求 /channel/sales-product/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 校验产品是否可删除(无有效关联配置/任务)后执行逻辑删除。
校验与异常
- 更新删除标识及审计字段,避免物理删除带来的历史数据丢失。
5.3.2 产品卖价(子表接口)
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 价格项列表 | GET | /channel/sales-product/price/list | 按产品ID获取价格项列表 |
| 新增价格项 | POST | /channel/sales-product/price/create | 新增价格项(含基础信息+计费因素+价格表) |
| 更新价格项 | POST | /channel/sales-product/price/update | 更新价格项 |
| 删除价格项 | POST | /channel/sales-product/price/delete | 删除价格项 |
| 切换价格项状态 | POST | /channel/sales-product/price/toggleStatus | 启用/禁用价格项 |
5.3.2.1 价格项列表(GET /channel/sales-product/price/list)
1 接口请求示例
请求 /channel/sales-product/price/list(GET,Query 参数)
?salesProductId=1
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"salesProductId": 1,
"serialNumber": 1,
"status": 1,
"priceName": "运费",
"costItem": "freight",
"costUnit": "kg",
"currency": "RMB",
"chargingTime": "出库",
"chargingCondition": "",
"factors": [
{
"id": 1,
"priceId": 1,
"serialNumber": 1,
"factor": "货物类型",
"factorValues": ["普货", "敏感货"]
}
],
"details": [
{
"id": 1,
"priceId": 1,
"factorValuesJson": {"分区": "欧洲", "货物类型": "普货", "重量": "0-0.5"},
"calculationFormula": "单价",
"calculatedValue": 62,
"customerGroupValues": {"客户组1": 60, "客户组2": 65}
}
],
"version": "20260425143000",
"publishTime": "2026-04-25 14:30:00",
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
]
}
}
2 接口业务逻辑
核心流程
- 按
salesProductId查询价格项主表,并聚合返回计费因素与价格明细子数据。 - 结果按
serialNumber升序组织,便于前端按配置顺序渲染。
校验与异常
- 校验
salesProductId必填且产品存在;不存在时返回业务错误。 - 仅返回未删除记录,查询异常返回统一错误码。
5.3.2.2 新增价格项(POST /channel/sales-product/price/create)
1 接口请求示例
请求 /channel/sales-product/price/create(POST)
{
"salesProductId": 1,
"serialNumber": 1,
"status": 1,
"priceName": "运费",
"costItem": "freight",
"costUnit": "kg",
"currency": "RMB",
"chargingTime": "出库",
"chargingCondition": "",
"factors": [
{
"serialNumber": 1,
"factor": "货物类型",
"factorValues": ["普货", "敏感货"]
},
{
"serialNumber": 2,
"factor": "分区",
"factorValues": ["欧洲", "美国"]
}
],
"details": [
{
"factorValuesJson": {"分区": "欧洲", "货物类型": "普货", "重量": "0-0.5"},
"calculationFormula": "单价",
"calculatedValue": 62,
"customerGroupValues": {"客户组1": 60, "客户组2": 65}
}
]
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 新增价格项主记录,并写入对应
factors与details子记录。 - 同步写入审计字段,保持主从数据一致性。
校验与异常
- 校验
salesProductId、priceName、costItem、costUnit等必填字段。 - 校验同产品下
serialNumber不冲突;冲突时返回业务错误。
5.3.2.3 更新价格项(POST /channel/sales-product/price/update)
1 接口请求示例
请求 /channel/sales-product/price/update(POST)
{
"id": 1,
"salesProductId": 1,
"serialNumber": 1,
"status": 1,
"priceName": "运费",
"costItem": "freight",
"costUnit": "kg",
"currency": "RMB",
"chargingTime": "出库",
"chargingCondition": "",
"factors": [],
"details": []
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按
id更新价格项主数据,并按最新请求重建/同步因素与明细子数据。 - 保留版本追溯能力,更新后可参与后续发布流程。
校验与异常
- 校验
id存在且归属salesProductId。 - 校验更新后配置合法(计算公式、阶梯区间、客户组取值等),不合法时返回业务错误。
5.3.2.4 删除价格项(POST /channel/sales-product/price/delete)
1 接口请求示例
请求 /channel/sales-product/price/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按价格项
id执行逻辑删除,并处理关联子表数据的可见性。
校验与异常
- 校验
id存在且允许删除(如未处于不可删状态)。 - 删除失败返回统一业务错误码。
5.3.2.5 切换价格项状态(POST /channel/sales-product/price/toggleStatus)
1 接口请求示例
请求 /channel/sales-product/price/toggleStatus(POST)
{
"id": 1,
"status": 0
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按
id更新价格项启用状态(status),并刷新相关缓存。
校验与异常
- 校验
status仅允许合法枚举值(启用/禁用)。 - 校验
id存在,不存在时返回业务错误。
5.3.3 排货规则(子表接口)
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 获取排货规则 | GET | /channel/sales-product/allocation/get | 按产品ID获取排货方案及服务商列表 |
| 保存排货规则 | POST | /channel/sales-product/allocation/save | 保存排货方案及服务商(保存并可选发布) |
5.3.3.1 获取排货规则(GET /channel/sales-product/allocation/get)
1 接口请求示例
请求 /channel/sales-product/allocation/get(GET,Query 参数)
?salesProductId=1
响应
{
"code": 0,
"msg": "success",
"data": {
"salesProductId": 1,
"scheme": "costLowest",
"providers": [
{
"id": 1,
"salesProductId": 1,
"serialNumber": 1,
"providerName": "一代物流",
"serviceChannelId": 10,
"serviceChannelName": "DHL美国专线",
"weight": 100,
"customerIds": [1, 2],
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
]
}
}
2 接口业务逻辑
核心流程
- 根据
salesProductId查询排货方案与服务商列表并按顺序返回。
校验与异常
- 校验
salesProductId必填且产品存在;不存在时返回业务错误。
5.3.3.2 保存排货规则(POST /channel/sales-product/allocation/save)
1 接口请求示例
请求 /channel/sales-product/allocation/save(POST)
{
"salesProductId": 1,
"publish": false,
"scheme": "costLowest",
"providers": [
{
"id": 0,
"serialNumber": 1,
"providerName": "一代物流",
"serviceChannelId": 10,
"weight": 100,
"customerIds": [1, 2]
}
]
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 保存排货策略与服务商配置,按
id判定新增或更新。 - 当
publish=true时触发规则发布并生成版本记录。
校验与异常
- 校验
salesProductId、scheme与providers合法性。 - 保存失败回滚事务并返回统一错误信息。
5.3.4 发布记录(子表接口)
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 价格发布记录列表 | GET | /channel/sales-product/publish/price/list | 按产品ID获取价格发布历史 |
| 规则发布记录列表 | GET | /channel/sales-product/publish/rules/list | 按产品ID获取规则发布历史 |
| 发布 | POST | /channel/sales-product/publish | 发布当前配置(价格或规则) |
| 回滚到版本 | POST | /channel/sales-product/publish/rollback | 回滚到指定版本 |
5.3.4.1 价格发布记录列表(GET /channel/sales-product/publish/price/list)
1 接口请求示例
请求 /channel/sales-product/publish/price/list(GET,Query 参数)
?salesProductId=1&page=1&pageSize=20
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"salesProductId": 1,
"version": "20231227112339",
"operatorType": "price",
"status": "生效",
"publishUser": "admin",
"publishTime": "2023-12-27 11:23:39",
"description": "价格调整",
"content": {},
"createTime": "2023-12-27 11:23:39"
}
],
"total": 5
}
}
2 接口业务逻辑
核心流程
- 按产品ID分页查询价格类发布历史,返回版本与发布人信息。
校验与异常
- 校验
salesProductId与分页参数合法性,异常时返回统一错误码。
5.3.4.2 规则发布记录列表(GET /channel/sales-product/publish/rules/list)
1 接口请求示例
请求 /channel/sales-product/publish/rules/list(GET,Query 参数)
?salesProductId=1&page=1&pageSize=20
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 2,
"salesProductId": 1,
"version": "20231228103000",
"operatorType": "rules",
"status": "生效",
"publishUser": "admin",
"publishTime": "2023-12-28 10:30:00",
"description": "规则调整",
"content": {},
"createTime": "2023-12-28 10:30:00"
}
],
"total": 3
}
}
2 接口业务逻辑
核心流程
- 按产品ID分页查询规则类发布历史,
operatorType固定为rules。
校验与异常
- 校验
salesProductId与分页参数合法性,异常时返回统一错误码。
5.3.4.3 发布(POST /channel/sales-product/publish)
1 接口请求示例
请求 /channel/sales-product/publish(POST)
{
"salesProductId": 1,
"operatorType": "price",
"description": "价格调整"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 将当前配置发布为新版本并写入发布记录。
校验与异常
- 校验
salesProductId、operatorType必填且可发布。
5.3.4.4 回滚到版本(POST /channel/sales-product/publish/rollback)
1 接口请求示例
请求 /channel/sales-product/publish/rollback(POST)
{
"salesProductId": 1,
"recordId": 1,
"operatorType": "price"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 将配置回滚到指定发布版本并生成回滚记录。
校验与异常
- 校验
recordId版本存在且与产品、类型一致,不一致时返回业务错误。
5.3.5 服务渠道
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 渠道列表 | GET | /channel/service-channel/list | 渠道列表(含渠道组层级) |
| 渠道详情 | GET | /channel/service-channel/detail | 渠道详情 |
| 新增渠道 | POST | /channel/service-channel/create | 新增渠道 |
| 更新渠道 | POST | /channel/service-channel/update | 更新渠道(包含渠道配置 tab 保存) |
| 删除渠道 | POST | /channel/service-channel/delete | 删除渠道 |
| 服务商分组列表 | GET | /channel/service-channel/group/list | 获取服务商分组列表(下拉/筛选) |
| 新增服务商 | POST | /channel/service-channel/group/create | 新增服务商分组(写入 t_service_channel_group,保存应用ID与API服务商ID) |
| 编辑服务商 | POST | /channel/service-channel/group/update | 编辑服务商分组(更新名称/应用ID/API服务商ID) |
| 删除服务商 | POST | /channel/service-channel/group/delete | 删除服务商分组(若分组下存在渠道需禁止删除) |
5.3.5.1 渠道列表(GET /channel/service-channel/list)
1 接口请求示例
请求 /channel/service-channel/list(GET,Query 参数)
?page=1&pageSize=20&groupId=&keyword=&isActive=1
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"groupId": 1,
"groupName": "DHL渠道组",
"channelCode": "DHL-US",
"channelName": "DHL美国专线",
"minTime": 3,
"maxTime": 7,
"forecastType": "waybill",
"forecastCode": "",
"description": "DHL美国专线渠道",
"isActive": 1,
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 10
}
}
2 接口业务逻辑
核心流程
- 按分页与筛选条件查询渠道列表,返回渠道及所属分组信息。
校验与异常
- 校验分页参数合法性,异常时返回统一错误码。
5.3.5.2 渠道详情(GET /channel/service-channel/detail)
1 接口请求示例
请求 /channel/service-channel/detail(GET,Query 参数)
?id=1
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"groupId": 1,
"groupName": "DHL渠道组",
"channelCode": "DHL-US",
"channelName": "DHL美国专线",
"minTime": 3,
"maxTime": 7,
"forecastType": "waybill",
"forecastCode": "",
"description": "DHL美国专线渠道",
"preScript": "",
"isActive": 1,
"createTime": "2024-01-01 12:00:00",
"createBy": "admin",
"updateTime": "2024-01-01 12:00:00",
"updateBy": "admin"
}
}
2 接口业务逻辑
核心流程
- 根据渠道
id查询渠道详情与配置信息。
校验与异常
- 校验
id必填且存在,不存在时返回业务错误。
5.3.5.3 新增渠道(POST /channel/service-channel/create)
1 接口请求示例
请求 /channel/service-channel/create(POST)
{
"groupId": 1,
"channelCode": "DHL-US",
"channelName": "DHL美国专线",
"minTime": 3,
"maxTime": 7,
"forecastType": "waybill",
"forecastCode": "",
"description": "DHL美国专线渠道",
"preScript": "",
"isActive": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 新增渠道基础配置并写入审计字段。
校验与异常
- 校验
groupId、channelCode、channelName等必填字段,编码冲突时返回业务错误。
5.3.5.4 服务商分组列表(GET /channel/service-channel/group/list)
1 接口请求示例
请求 /channel/service-channel/group/list(GET,Query 参数)
?keyword=&appId=&apiServiceProviderId=
响应
{
"code": 0,
"msg": "success",
"data": [
{
"id": 1,
"name": "壹号",
"appId": 8,
"apiServiceProviderId": 41,
"createTime": "2026-05-04 14:15:45",
"updateTime": "1900-01-01 00:00:00"
}
]
}
2 接口业务逻辑
核心流程
- 查询
t_service_channel_group未删除分组,可按keyword、appId、apiServiceProviderId过滤,按id倒序返回。
校验与异常
- 过滤参数格式非法时返回业务错误;无数据时返回空数组。
5.3.5.5 新增服务商(POST /channel/service-channel/group/create)
1 接口请求示例
请求 /channel/service-channel/group/create(POST)
{
"name": "DHL服务商",
"appId": 1,
"apiServiceProviderId": 12
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 在
t_service_channel_group新增服务商分组并写入应用ID与API服务商ID。
校验与异常
- 校验
name、appId、apiServiceProviderId必填且有效。
5.3.5.6 编辑服务商(POST /channel/service-channel/group/update)
1 接口请求示例
请求 /channel/service-channel/group/update(POST)
{
"id": 1,
"name": "DHL服务商(更新)",
"appId": 1,
"apiServiceProviderId": 12
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据分组
id更新服务商名称、应用ID与API服务商ID。
校验与异常
- 校验
id存在且可编辑,不存在时返回业务错误。
5.3.5.7 删除服务商(POST /channel/service-channel/group/delete)
1 接口请求示例
请求 /channel/service-channel/group/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据分组
id执行逻辑删除。
校验与异常
- 若分组下存在渠道则禁止删除并返回业务错误。
5.3.5.8 更新渠道(POST /channel/service-channel/update)
1 接口请求示例
请求 /channel/service-channel/update(POST)
{
"id": 1,
"groupId": 1,
"channelCode": "DHL-US",
"channelName": "DHL美国专线",
"minTime": 3,
"maxTime": 7,
"forecastType": "waybill",
"forecastCode": "",
"description": "DHL美国专线渠道",
"preScript": "",
"isActive": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据
id更新渠道基础信息与渠道配置 tab 数据。
校验与异常
- 校验
id存在及字段合法性,更新失败返回业务错误。
5.3.5.9 删除渠道(POST /channel/service-channel/delete)
1 接口请求示例
请求 /channel/service-channel/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 校验渠道是否可删除后执行逻辑删除并保留历史审计信息。
校验与异常
- 存在关联配置或不可删除状态时返回业务错误。
5.3.6 渠道买价(子表接口)
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 买价项列表 | GET | /channel/service-channel/price/list | 按渠道ID获取买价项列表 |
| 新增买价项 | POST | /channel/service-channel/price/create | 新增买价项(含基础信息+计费因素+价格表) |
| 更新买价项 | POST | /channel/service-channel/price/update | 更新买价项 |
| 删除买价项 | POST | /channel/service-channel/price/delete | 删除买价项 |
| 切换买价项状态 | POST | /channel/service-channel/price/toggleStatus | 启用/禁用买价项 |
5.3.6.1 买价项列表(GET /channel/service-channel/price/list)
1 接口请求示例
请求 /channel/service-channel/price/list(GET,Query 参数)
?serviceChannelId=1
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"serviceChannelId": 1,
"serialNumber": 1,
"status": 1,
"priceName": "运费",
"costItem": "freight",
"costUnit": "kg",
"currency": "RMB",
"chargingTime": "出库",
"chargingCondition": "",
"factors": [],
"details": [],
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
]
}
}
2 接口业务逻辑
核心流程
- 按
serviceChannelId查询买价项及其因素、明细子项。
校验与异常
- 校验
serviceChannelId必填且渠道存在;异常返回统一错误码。
5.3.6.2 新增买价项(POST /channel/service-channel/price/create)
1 接口请求示例
请求 /channel/service-channel/price/create(POST)
{
"serviceChannelId": 1,
"serialNumber": 1,
"status": 1,
"priceName": "运费",
"costItem": "freight",
"costUnit": "kg",
"currency": "RMB",
"chargingTime": "出库",
"chargingCondition": "",
"factors": [
{
"serialNumber": 1,
"factor": "货物类型",
"factorValues": ["普货", "敏感货"]
}
],
"details": [
{
"factorValuesJson": {"分区": "欧洲", "货物类型": "普货", "重量": "0-0.5"},
"calculationFormula": "单价",
"calculatedValue": 45,
"customerGroupValues": {}
}
]
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 新增买价主记录并写入因素、明细子表。
校验与异常
- 校验必填参数与序号冲突规则,校验失败返回业务错误。
5.3.6.3 更新买价项(POST /channel/service-channel/price/update)
1 接口请求示例
请求 /channel/service-channel/price/update(POST)
{
"id": 1,
"serviceChannelId": 1,
"serialNumber": 1,
"status": 1,
"priceName": "运费",
"costItem": "freight",
"costUnit": "kg",
"currency": "RMB",
"chargingTime": "出库",
"chargingCondition": "",
"factors": [],
"details": []
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按
id更新买价主数据并同步子项明细。
校验与异常
- 校验
id存在且归属渠道一致,校验失败返回业务错误。
5.3.6.4 删除买价项(POST /channel/service-channel/price/delete)
1 接口请求示例
请求 /channel/service-channel/price/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据
id逻辑删除买价项并处理关联子项可见性。
校验与异常
- 校验
id存在且允许删除。
5.3.6.5 切换买价项状态(POST /channel/service-channel/price/toggleStatus)
1 接口请求示例
请求 /channel/service-channel/price/toggleStatus(POST)
{
"id": 1,
"status": 0
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 按
id更新买价项启用状态并刷新缓存。
校验与异常
- 校验
status枚举与id存在性,不合法时返回业务错误。
5.3.7 服务渠道发布记录(子表接口)
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 价格发布记录列表 | GET | /channel/service-channel/publish/price/list | 按渠道ID获取买价发布历史 |
| 规则发布记录列表 | GET | /channel/service-channel/publish/rules/list | 按渠道ID获取规则发布历史 |
| 发布 | POST | /channel/service-channel/publish | 发布当前配置(买价或规则) |
| 回滚到版本 | POST | /channel/service-channel/publish/rollback | 回滚到指定版本 |
5.3.7.1 价格发布记录列表(GET /channel/service-channel/publish/price/list)
1 接口请求示例
请求 /channel/service-channel/publish/price/list(GET,Query 参数)
?serviceChannelId=1&page=1&pageSize=20
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"serviceChannelId": 1,
"version": "20231227112339",
"operatorType": "price",
"status": "生效",
"publishUser": "admin",
"publishTime": "2023-12-27 11:23:39",
"description": "买价调整",
"content": {},
"createTime": "2023-12-27 11:23:39"
}
],
"total": 5
}
}
2 接口业务逻辑
核心流程
- 按渠道ID分页查询买价发布记录并返回版本信息。
校验与异常
- 校验
serviceChannelId与分页参数合法性。
5.3.7.2 规则发布记录列表(GET /channel/service-channel/publish/rules/list)
1 接口请求示例
请求 /channel/service-channel/publish/rules/list(GET,Query 参数)
?serviceChannelId=1&page=1&pageSize=20
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 2,
"serviceChannelId": 1,
"version": "20231228103000",
"operatorType": "rules",
"status": "生效",
"publishUser": "admin",
"publishTime": "2023-12-28 10:30:00",
"description": "规则调整",
"content": {},
"createTime": "2023-12-28 10:30:00"
}
],
"total": 3
}
}
2 接口业务逻辑
核心流程
- 按渠道ID分页查询规则发布记录,
operatorType固定为rules。
校验与异常
- 校验
serviceChannelId与分页参数合法性。
5.3.7.3 发布(POST /channel/service-channel/publish)
1 接口请求示例
请求 /channel/service-channel/publish(POST)
{
"serviceChannelId": 1,
"operatorType": "price",
"description": "买价调整"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 发布当前渠道配置并生成新的发布版本记录。
校验与异常
- 校验
serviceChannelId、operatorType必填且可发布。
5.3.7.4 回滚到版本(POST /channel/service-channel/publish/rollback)
1 接口请求示例
请求 /channel/service-channel/publish/rollback(POST)
{
"serviceChannelId": 1,
"recordId": 1,
"operatorType": "price"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 回滚到指定版本并生成回滚操作记录。
校验与异常
- 校验
recordId与渠道、类型匹配关系,异常时返回业务错误。
5.3.8 黑名单区 / 偏远分区 / 价格分区(共用 KpiArea)
共用
/channel/kpi-area/*接口,仅通过请求/响应中的areaType(对应表字段AreaType)区分分区类型。
| 类型 | areaType |
|---|---|
| 黑名单区 | blacklist |
| 偏远分区 | remote |
| 价格分区 | price |
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 创建分区 | POST | /channel/kpi-area/create | 创建分区 |
| 修改分区 | POST | /channel/kpi-area/update | 修改分区 |
| 删除分区 | POST | /channel/kpi-area/delete | 删除分区 |
| 分区列表 | POST | /channel/kpi-area/list | 分区列表 |
| 新增分区明细 | POST | /channel/kpi-area/info/add | 新增分区明细 |
| 修改分区明细 | POST | /channel/kpi-area/info/update | 修改分区明细 |
| 删除分区明细 | POST | /channel/kpi-area/info/delete | 删除分区明细 |
| 分区明细列表 | POST | /channel/kpi-area/info/list | 分区明细列表 |
5.3.8.1 创建分区(POST /channel/kpi-area/create)
1 接口请求示例
请求 /channel/kpi-area/create(POST)
{
"areaType": "blacklist",
"name": "黑名单区1",
"systemName": "系统黑名单"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据
areaType创建分区主记录。
校验与异常
- 校验
areaType、name必填且合法。
5.3.8.2 修改分区(POST /channel/kpi-area/update)
1 接口请求示例
请求 /channel/kpi-area/update(POST)
{
"id": 1,
"areaType": "blacklist",
"name": "黑名单区1",
"systemName": "系统黑名单"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据
id更新分区名称与系统名称。
校验与异常
- 校验
id存在且与areaType匹配。
5.3.8.3 删除分区(POST /channel/kpi-area/delete)
1 接口请求示例
请求 /channel/kpi-area/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据
id执行分区逻辑删除。
校验与异常
- 分区存在明细时按业务规则拦截或级联处理。
5.3.8.4 分区列表(POST /channel/kpi-area/list)
1 接口请求示例
请求 /channel/kpi-area/list(POST)
{
"areaType": "blacklist",
"page": 1,
"pageSize": 20
}
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"areaType": "blacklist",
"name": "黑名单区1",
"systemName": "系统黑名单",
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 5
}
}
2 接口业务逻辑
核心流程
- 按
areaType分页查询分区列表。
校验与异常
- 校验分页参数与
areaType合法性。
5.3.8.5 新增分区明细(POST /channel/kpi-area/info/add)
1 接口请求示例
请求 /channel/kpi-area/info/add(POST)
{
"areaId": 1,
"countryCode": "US",
"countryName": "美国",
"province": "加州",
"city": "洛杉矶",
"leftPostcode": "90001",
"rightPostcode": "90099"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 向指定分区新增明细记录(国家/省市/邮编区间)。
校验与异常
- 校验
areaId存在且区间数据合法。
5.3.8.6 修改分区明细(POST /channel/kpi-area/info/update)
1 接口请求示例
请求 /channel/kpi-area/info/update(POST)
{
"id": 1,
"areaId": 1,
"countryCode": "US",
"countryName": "美国",
"province": "加州",
"city": "洛杉矶",
"leftPostcode": "90001",
"rightPostcode": "90099"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据明细
id更新分区明细字段。
校验与异常
- 校验
id存在,更新内容合法。
5.3.8.7 删除分区明细(POST /channel/kpi-area/info/delete)
1 接口请求示例
请求 /channel/kpi-area/info/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据明细
id执行逻辑删除。
校验与异常
- 校验
id存在,不存在时返回业务错误。
5.3.8.8 分区明细列表(POST /channel/kpi-area/info/list)
1 接口请求示例
请求 /channel/kpi-area/info/list(POST)
{
"areaId": 1,
"page": 1,
"pageSize": 20
}
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"areaId": 1,
"countryCode": "US",
"countryName": "美国",
"province": "加州",
"city": "洛杉矶",
"leftPostcode": "90001",
"rightPostcode": "90099",
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 10
}
}
2 接口业务逻辑
核心流程
- 按
areaId分页查询分区明细列表。
校验与异常
- 校验
areaId与分页参数合法性。
5.3.9 计重规则 / 计重进位
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 规则列表 | POST | /channel/weight-rule/list | 规则列表 |
| 创建规则 | POST | /channel/weight-rule/create | 创建规则 |
| 更新规则 | POST | /channel/weight-rule/update | 更新规则 |
| 删除规则 | POST | /channel/weight-rule/delete | 删除规则 |
| 规则明细列表 | POST | /channel/weight-rule/info/list | 规则明细列表 |
| 新增明细 | POST | /channel/weight-rule/info/add | 新增明细 |
| 更新明细 | POST | /channel/weight-rule/info/update | 更新明细 |
| 删除明细 | POST | /channel/weight-rule/info/delete | 删除明细 |
| 进位列表 | POST | /channel/weight-rounding/list | 进位列表 |
| 创建进位 | POST | /channel/weight-rounding/create | 创建进位 |
| 更新进位 | POST | /channel/weight-rounding/update | 更新进位 |
| 删除进位 | POST | /channel/weight-rounding/delete | 删除进位 |
| 进位明细列表 | POST | /channel/weight-rounding/info/list | 进位明细列表 |
| 新增进位明细 | POST | /channel/weight-rounding/info/add | 新增进位明细 |
| 更新进位明细 | POST | /channel/weight-rounding/info/update | 更新进位明细 |
| 删除进位明细 | POST | /channel/weight-rounding/info/delete | 删除进位明细 |
5.3.9.1 规则列表(POST /channel/weight-rule/list)
1 接口请求示例
请求 /channel/weight-rule/list(POST)
{
"page": 1,
"pageSize": 20
}
响应
{
"code": 0,
"msg": "success",
"data": { "items": [{ "id": 1, "name": "标准计重规则" }], "total": 5 }
}
2 接口业务逻辑
核心流程
- 分页查询计重规则主表。
校验与异常
- 校验分页参数合法性。
5.3.9.2 创建规则(POST /channel/weight-rule/create)
1 接口请求示例
请求 /channel/weight-rule/create(POST)
{ "name": "标准计重规则" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 新增计重规则并写入审计信息。
校验与异常
- 校验
name必填且不重复。
5.3.9.3 更新规则(POST /channel/weight-rule/update)
1 接口请求示例
请求 /channel/weight-rule/update(POST)
{ "id": 1, "name": "标准计重规则" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 根据
id更新规则信息。
校验与异常
- 校验
id存在。
5.3.9.4 删除规则(POST /channel/weight-rule/delete)
1 接口请求示例
请求 /channel/weight-rule/delete(POST)
{ "id": 1 }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 对规则执行逻辑删除。
校验与异常
- 校验是否存在关联明细。
5.3.9.5 规则明细列表(POST /channel/weight-rule/info/list)
1 接口请求示例
请求 /channel/weight-rule/info/list(POST)
{ "ruleId": 1, "page": 1, "pageSize": 20 }
响应
{
"code": 0,
"msg": "success",
"data": { "items": [{ "id": 1, "ruleId": 1, "condition": "gw>vw", "billableWeight": "gw", "volumetricFactor": "6000" }], "total": 3 }
}
2 接口业务逻辑
核心流程
- 按
ruleId分页查询规则明细。
校验与异常
- 校验
ruleId必填且有效。
5.3.9.6 新增明细(POST /channel/weight-rule/info/add)
1 接口请求示例
请求 /channel/weight-rule/info/add(POST)
{ "ruleId": 1, "condition": "gw>vw", "billableWeight": "vw", "volumetricFactor": "6000" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 新增规则明细。
校验与异常
- 校验
ruleId与字段合法性。
5.3.9.7 更新明细(POST /channel/weight-rule/info/update)
1 接口请求示例
请求 /channel/weight-rule/info/update(POST)
{ "id": 1, "ruleId": 1, "condition": "gw>vw", "billableWeight": "vw", "volumetricFactor": "6000" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 根据
id更新规则明细。
校验与异常
- 校验
id存在且归属正确。
5.3.9.8 删除明细(POST /channel/weight-rule/info/delete)
1 接口请求示例
请求 /channel/weight-rule/info/delete(POST)
{ "id": 1 }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 删除规则明细(逻辑删除)。
校验与异常
- 校验
id存在。
5.3.9.9 进位列表(POST /channel/weight-rounding/list)
1 接口请求示例
请求 /channel/weight-rounding/list(POST)
{ "page": 1, "pageSize": 20 }
响应
{
"code": 0,
"msg": "success",
"data": { "items": [{ "id": 1, "name": "标准进位" }], "total": 5 }
}
2 接口业务逻辑
核心流程
- 分页查询计重进位主表。
校验与异常
- 校验分页参数。
5.3.9.10 创建进位(POST /channel/weight-rounding/create)
1 接口请求示例
请求 /channel/weight-rounding/create(POST)
{ "name": "标准进位" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 新增进位规则。
校验与异常
- 校验
name必填。
5.3.9.11 更新进位(POST /channel/weight-rounding/update)
1 接口请求示例
请求 /channel/weight-rounding/update(POST)
{ "id": 1, "name": "标准进位" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 根据
id更新进位规则。
校验与异常
- 校验
id存在。
5.3.9.12 删除进位(POST /channel/weight-rounding/delete)
1 接口请求示例
请求 /channel/weight-rounding/delete(POST)
{ "id": 1 }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 逻辑删除进位规则。
校验与异常
- 校验是否可删除。
5.3.9.13 进位明细列表(POST /channel/weight-rounding/info/list)
1 接口请求示例
请求 /channel/weight-rounding/info/list(POST)
{ "roundingId": 1, "page": 1, "pageSize": 20 }
响应
{
"code": 0,
"msg": "success",
"data": { "items": [{ "id": 1, "roundingId": 1, "startValue": 0, "endValue": 1, "public": "0.5" }], "total": 5 }
}
2 接口业务逻辑
核心流程
- 按
roundingId分页查询进位明细。
校验与异常
- 校验
roundingId存在。
5.3.9.14 新增进位明细(POST /channel/weight-rounding/info/add)
1 接口请求示例
请求 /channel/weight-rounding/info/add(POST)
{ "roundingId": 1, "startValue": 0, "endValue": 1, "public": "0.5" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 新增进位明细。
校验与异常
- 校验区间与
public进位值合法性。
5.3.9.15 更新进位明细(POST /channel/weight-rounding/info/update)
1 接口请求示例
请求 /channel/weight-rounding/info/update(POST)
{ "id": 1, "roundingId": 1, "startValue": 0, "endValue": 1, "public": "0.5" }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 根据
id更新进位明细。
校验与异常
- 校验
id存在且归属正确。
5.3.9.16 删除进位明细(POST /channel/weight-rounding/info/delete)
1 接口请求示例
请求 /channel/weight-rounding/info/delete(POST)
{ "id": 1 }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 删除进位明细(逻辑删除)。
校验与异常
- 校验
id存在。
5.3.10 自动触发
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 列表 | GET | /channel/auto-trigger/list | 列表 |
| 新增 | POST | /channel/auto-trigger/create | 新增 |
| 更新 | POST | /channel/auto-trigger/update | 更新 |
| 删除 | POST | /channel/auto-trigger/delete | 删除 |
| 切换启用状态 | POST | /channel/auto-trigger/toggleStatus | 切换启用状态 |
5.3.10.1 列表(GET /channel/auto-trigger/list)
1 接口请求示例
请求 /channel/auto-trigger/list(GET,Query 参数)
?page=1&pageSize=20&operation=&triggerTiming=
响应
{
"code": 0,
"msg": "success",
"data": { "items": [{ "id": 1, "operation": "拦截", "triggerTiming": "下单" }], "total": 5 }
}
2 接口业务逻辑
核心流程
- 分页查询自动触发规则列表。
校验与异常
- 校验分页与筛选参数合法。
5.3.10.2 新增(POST /channel/auto-trigger/create)
1 接口请求示例
请求 /channel/auto-trigger/create(POST)
{
"status": 1,
"operation": "拦截",
"triggerTiming": "下单",
"triggerCondition": "weight>30",
"promptMessage": "重量超过30kg,请确认",
"notifier": "admin@example.com"
}
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 新增自动触发规则。
校验与异常
- 校验关键字段必填。
5.3.10.3 更新(POST /channel/auto-trigger/update)
1 接口请求示例
请求 /channel/auto-trigger/update(POST)
{
"id": 1,
"status": 1,
"operation": "拦截",
"triggerTiming": "下单",
"triggerCondition": "weight>30",
"promptMessage": "重量超过30kg,请确认",
"notifier": "admin@example.com"
}
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 根据
id更新自动触发规则。
校验与异常
- 校验
id存在且可编辑。
5.3.10.4 删除(POST /channel/auto-trigger/delete)
1 接口请求示例
请求 /channel/auto-trigger/delete(POST)
{ "id": 1 }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 逻辑删除自动触发规则。
校验与异常
- 校验
id存在且可删除。
5.3.10.5 切换启用状态(POST /channel/auto-trigger/toggleStatus)
1 接口请求示例
请求 /channel/auto-trigger/toggleStatus(POST)
{ "id": 1, "status": 0 }
响应
{ "code": 0, "msg": "success", "data": null }
2 接口业务逻辑
核心流程
- 按
id切换规则启用状态。
校验与异常
- 校验
status枚举合法性。
5.3.11 标签设计
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 保存标签模板 | POST | /channel/label-template/save | 保存标签模板 |
1 接口请求示例
请求 /channel/label-template/save(POST)
{
"id": 0,
"name": "尾程标签模板1",
"templateType": "lastMile",
"templateJson": {}
}
参数说明:
id模板ID,0为新增;templateType类型:lastMile(尾程)/customer(客户)/inbound(入库)/outbound(出库)/sku;templateJsonvg-print 导出的模板 JSON。
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"name": "尾程标签模板1",
"templateType": "lastMile",
"templateJson": {},
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
}
2 接口业务逻辑
核心流程
- 按本节接口定义执行业务处理流程,完成参数解析、数据查询/写入与结果返回。
校验与异常
- 对必填参数、状态流转与数据存在性进行校验;异常场景返回统一错误码与错误信息。
6 操作模块
6.1 核心需求说明
- 入库扫描:扫描运单号完成入库,记录实重、尺寸、销售产品、目的国、仓库、操作人、操作时间;须覆盖
Type=receive行并重算计费重,并 默认将计重结果同步覆盖ship与downstream(规则见 §4.3.4、§4.4.3.1),再按配置调用 §4.3.4.1(应收,receive)与 §4.3.4.2(应付,downstream,ChargingStage=inbound);支持查看最近入库记录。 - 出库扫描:扫描运单号完成出库,记录实重、尺寸、销售产品、目的国、服务渠道ID、仓库、操作人、操作时间(
t_outbound_record在入库记录字段基础上另存ServiceChannelId,见 §6.2.2);须覆盖Type=ship行并重算计费重,并 默认将计重结果同步覆盖downstream(实测尺重见请求体,未传则可用receive行拷贝到ship,见 §6.3.2.1),再按配置调用 §4.3.4.1(应收,ship)与 §4.3.4.2(应付,downstream,ChargingStage=outbound);支持查看最近出库记录。 - 标签打印:按运单号/客户单号/跟踪号/其他单号选择标签模板打印;记录打印结果与操作人。
6.2 表结构设计
6.2.1 入库记录表 t_inbound_record
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| WaybillNo | VARCHAR | 64 | - | 是 | 运单号 |
| Weight | DECIMAL | 10,2 | - | 否 | 实重(kg) |
| Length | DECIMAL | 10,2 | - | 否 | 长(cm) |
| Width | DECIMAL | 10,2 | - | 否 | 宽(cm) |
| Height | DECIMAL | 10,2 | - | 否 | 高(cm) |
| SalesProductId | BIGINT | - | 外键 | 否 | 销售产品ID |
| DestinationCountry | VARCHAR | 8 | - | 否 | 目的国 |
| WarehouseId | BIGINT | - | 外键 | 否 | 仓库ID |
| OperateTime | DATETIME | - | - | 是 | 操作时间 |
| OperatorId | BIGINT | - | 外键 | 否 | 操作人ID |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
6.2.2 出库记录表 t_outbound_record
与
t_inbound_record对齐:除业务含义为「出库」外,件重尺与业务维度字段与入库记录表一致;另存ServiceChannelId,关联t_service_channel.Id,记录本单出库时所选/所绑定的服务渠道,便于对账与列表筛选。
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| WaybillNo | VARCHAR | 64 | - | 是 | 运单号 |
| Weight | DECIMAL | 10,2 | - | 否 | 实重(kg),与本次出库写入 t_order_weight.Type=ship 的 ActualWeight 来源一致(复量或拷贝自收货) |
| Length | DECIMAL | 10,2 | - | 否 | 长(cm) |
| Width | DECIMAL | 10,2 | - | 否 | 宽(cm) |
| Height | DECIMAL | 10,2 | - | 否 | 高(cm) |
| SalesProductId | BIGINT | - | 外键 | 否 | 销售产品ID |
| DestinationCountry | VARCHAR | 8 | - | 否 | 目的国 |
| ServiceChannelId | BIGINT | - | 外键(t_service_channel.Id) |
否 | 服务渠道ID;请求可选传入,未传时建议服务端按订单已绑定服务渠道或排货结果兜底 |
| WarehouseId | BIGINT | - | 外键 | 否 | 仓库ID |
| OperateTime | DATETIME | - | - | 是 | 操作时间 |
| OperatorId | BIGINT | - | 外键 | 否 | 操作人ID |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
6.2.3 标签打印记录表 t_label_print_record
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| WaybillNo | VARCHAR | 64 | - | 是 | 运单号 |
| CustomerOrderNo | VARCHAR | 64 | - | 否 | 客户单号 |
| TrackingNo | VARCHAR | 64 | - | 否 | 跟踪号 |
| OtherNumber | VARCHAR | 64 | - | 否 | 其他单号 |
| LabelTemplateId | BIGINT | - | 外键 | 否 | 标签模板ID |
| PrintSuccess | TINYINT | - | - | 是 | 是否打印成功 |
| PrintTime | DATETIME | - | - | 是 | 打印时间 |
| OperatorId | BIGINT | - | 外键 | 否 | 操作人ID |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
6.3 核心接口设计
6.3.1 入库扫描
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 入库 | POST | /operation/inbound/create | 入库 |
| 最近入库记录 | GET | /operation/inbound/recent-list | 最近入库记录 |
6.3.1.1 入库(POST /operation/inbound/create)
1 接口请求示例
请求 /operation/inbound/create(POST)
{
"waybillNo": "LP1234567890",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10,
"salesProductId": 1,
"destinationCountry": "US",
"warehouseId": 1
}
参数说明:
waybillNo运单号;weight实重(kg);length/width/height长宽高(cm);salesProductId销售产品ID;destinationCountry目的国二字码;warehouseId仓库ID。操作时间、操作人由服务端从当前会话获取。
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"waybillNo": "LP1234567890",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10,
"salesProductId": 1,
"destinationCountry": "US",
"warehouseId": 1,
"operateTime": "2024-01-01 12:00:00",
"operatorId": 1,
"createTime": "2024-01-01 12:00:00"
}
}
2 接口业务逻辑
核心流程
- 解析
waybillNo等参数,定位订单(及绑定销售产品、已落库的t_order_weight四行)。 - 写入
t_inbound_record(实重、尺寸、销售产品、目的国、仓库、操作人、操作时间等)。 - 覆盖
t_order_weight中本单Type=receive行:Length、Width、Height、ActualWeight以本次入库实测为准(与请求体weight、length、width、height对齐),Cubic = Length × Width × Height / 1000000。 - 对该
receive行按本单绑定WeightRuleId/WeightRoundingId(及 rules 快照或子表明细)执行 §4.4.3.1 步骤 7、8 相同算法,重算VolumetricWeight、ChargeableWeight(不修改forecast行,除非另有「改单重算」流程)。 - 默认:将
receive行当前Length、Width、Height、ActualWeight、Cubic、VolumetricWeight、ChargeableWeight拷贝覆盖 本单Type=ship与Type=downstream两行(与收货计重对齐;出库时再按 §6.3.2.1 分化ship)。 - 若存在
ChargingTime=inbound的费用项:先执行 §4.3.4.1(卖价,重量/计重因子取Type=receive);再执行 §4.3.4.2(买价,重量/件重尺仅Type=downstream)。两行ChargingStage均为inbound(与买价项chargingTime一致)。
校验与异常
- 对必填参数、订单状态、单号与订单关联、仓库权限等进行校验;件重尺非法、计重规则未命中、进位无匹配等按业务错误返回。
6.3.1.2 最近入库记录(GET /operation/inbound/recent-list)
1 接口请求示例
请求 /operation/inbound/recent-list(GET,Query 参数)
?limit=20&warehouseId=
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"waybillNo": "LP1234567890",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10,
"salesProductId": 1,
"salesProductName": "美国空运专线(普货)",
"destinationCountry": "US",
"warehouseId": 1,
"warehouseName": "深圳仓",
"operateTime": "2024-01-01 12:00:00",
"operatorId": 1,
"operatorName": "张三",
"createTime": "2024-01-01 12:00:00"
}
]
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
6.3.2 出库扫描
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 出库 | POST | /operation/outbound/create | 出库 |
| 最近出库记录 | GET | /operation/outbound/recent-list | 最近出库记录 |
6.3.2.1 出库(POST /operation/outbound/create)
1 接口请求示例
请求 /operation/outbound/create(POST)
{
"waybillNo": "LP1234567890",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10,
"salesProductId": 1,
"destinationCountry": "US",
"serviceChannelId": 100,
"warehouseId": 1
}
参数说明:
waybillNo运单号;weight实重(kg);length/width/height长宽高(cm);salesProductId销售产品ID;destinationCountry目的国二字码;serviceChannelId服务渠道ID(对应t_service_channel.Id,可选,未传时服务端按订单绑定/排货兜底并写入t_outbound_record);warehouseId仓库ID(可选,不传则从订单或默认仓库获取)。weight、length、width、height可选:若出库前需以发货复量覆盖ship行则传入;均未传时,先将本单Type=receive行当前件重尺拷贝覆盖ship行,再进入计重。salesProductId、destinationCountry可选,未传时建议服务端用订单绑定/收件国兜底。操作时间、操作人由服务端从当前会话获取。
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"waybillNo": "LP1234567890",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10,
"salesProductId": 1,
"destinationCountry": "US",
"serviceChannelId": 100,
"warehouseId": 1,
"operateTime": "2024-01-01 12:00:00",
"operatorId": 1,
"createTime": "2024-01-01 12:00:00"
}
}
2 接口业务逻辑
核心流程
- 解析
waybillNo、定位订单与t_order_weight。 - 写入
t_outbound_record(实重、尺寸、销售产品、目的国、服务渠道ID、仓库、操作人、操作时间;件重尺与业务维度与t_inbound_record对齐,并含ServiceChannelId,取值以请求、订单绑定及出库时ship行最终件重尺为准)。 - 覆盖
t_order_weight中本单Type=ship行:若请求携带weight/length/width/height,则以之为准写入该行并更新Cubic;否则将Type=receive行当前件重尺 拷贝覆盖 至ship行(含Cubic),再进入计重。 - 对该
ship行按WeightRuleId/WeightRoundingId执行 §4.4.3.1 步骤 7、8 相同算法,重算VolumetricWeight、ChargeableWeight。 - 默认:将
ship行当前Length、Width、Height、ActualWeight、Cubic、VolumetricWeight、ChargeableWeight拷贝覆盖 本单Type=downstream行。 - 若存在
ChargingTime=outbound的费用项:先执行 §4.3.4.1(卖价,重量/计重因子取Type=ship);再执行 §4.3.4.2(买价,仅downstream)。ChargingStage=outbound。
校验与异常
- 对必填参数、订单状态、出库前置条件(如已入库)等进行校验;计重失败时返回明确错误信息。
6.3.2.2 最近出库记录(GET /operation/outbound/recent-list)
1 接口请求示例
请求 /operation/outbound/recent-list(GET,Query 参数)
?limit=20&warehouseId=
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"waybillNo": "LP1234567890",
"weight": 2.5,
"length": 20,
"width": 15,
"height": 10,
"salesProductId": 1,
"salesProductName": "美国空运专线(普货)",
"destinationCountry": "US",
"serviceChannelId": 100,
"serviceChannelName": "XX组-USPS",
"warehouseId": 1,
"warehouseName": "深圳仓",
"operateTime": "2024-01-01 12:00:00",
"operatorId": 1,
"operatorName": "张三",
"createTime": "2024-01-01 12:00:00"
}
]
}
}
响应字段在 §6.3.1.2 最近入库记录 列表基础上增加
serviceChannelId/serviceChannelName(联查t_service_channel及展示名,命名可与实现一致),仅业务来源为出库。
2 接口业务逻辑
核心流程
- 分页/条数限制与
GET /operation/inbound/recent-list一致;返回t_outbound_record行及联查名称字段。
校验与异常
- 对
limit、warehouseId等查询参数及数据权限校验;异常返回统一错误码与错误信息。
6.3.3 标签打印
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 打印标签 | POST | /operation/print-label/print | 打印标签 |
| 最近打印记录 | GET | /operation/print-label/recent-list | 最近打印记录 |
| 标签模板列表 | GET | /operation/print-label/template-list | 标签模板列表 |
6.3.3.1 打印标签(POST /operation/print-label/print)
1 接口请求示例
请求 /operation/print-label/print(POST)
{
"number": "LP1234567890",
"numberType": "waybill",
"labelTemplateId": 1
}
参数说明:
number运单号/客户单号/跟踪号/其他单号;numberType单号类型:waybill(运单号)/customerOrder(客户单号)/tracking(跟踪号)/other(其他单号);labelTemplateId标签模板ID,可选,不传则按 templateType 取默认模板。也可传templateType:lastMile(尾程)/customer(客户)/inbound(入库)/outbound(出库)/sku。
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"waybillNo": "LP1234567890",
"customerOrderNo": "",
"trackingNo": "",
"otherNumber": "",
"labelTemplateId": 1,
"labelTemplateName": "尾程标签模板1",
"printSuccess": 1,
"printTime": "2024-01-01 12:00:00",
"operatorId": 1,
"createTime": "2024-01-01 12:00:00"
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
6.3.3.2 最近打印记录(GET /operation/print-label/recent-list)
1 接口请求示例
请求 /operation/print-label/recent-list(GET,Query 参数)
?limit=20&labelTemplateId=
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"waybillNo": "LP1234567890",
"customerOrderNo": "CUST001",
"trackingNo": "TRK001",
"otherNumber": "",
"labelTemplateId": 1,
"labelTemplateName": "尾程标签模板1",
"printSuccess": 1,
"printTime": "2024-01-01 12:00:00",
"operatorId": 1,
"operatorName": "张三",
"createTime": "2024-01-01 12:00:00"
}
]
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
6.3.3.3 标签模板列表(GET /operation/print-label/template-list)
1 接口请求示例
请求 /operation/print-label/template-list(GET,Query 参数)
?templateType=lastMile
参数说明:
templateType可选,筛选模板类型:lastMile/customer/inbound/outbound/sku。不传则返回全部可用模板。
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"name": "尾程标签模板1",
"templateType": "lastMile",
"templateJson": {},
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
]
}
}
2 接口业务逻辑
核心流程
- 按接口定义执行业务流程,完成参数解析、数据处理与结果返回。
校验与异常
- 对必填参数、状态与数据存在性进行校验,异常场景返回统一错误码与错误信息。
7 充值管理
7.1 核心需求说明
- 充值流程:客户提交充值金额 → 选择支付方式(微信/支付宝)→ 上传充值截图 → 提交审核 → 管理员审核(通过/驳回)→ 审核通过后更新客户余额。
- 充值记录:完整留存充值全流程信息,支持查询、导出;充值状态包含:待审核、审核通过、审核驳回。
7.2 表结构设计
7.2.1 充值记录表 t_recharge_record
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| CustomerId | BIGINT | - | 外键(客户主键,权威定义见 RBAC/客户域) | 是 | 充值归属客户;主账号/子账号口径以权限系统约定为准 |
| SerialNumber | VARCHAR | 64 | - | 是 | 流水号,规则:RECHARGE+日期+随机6位数字 |
| RechargeTime | DATETIME | - | - | 是 | 充值提交时间,默认当前时间 |
| PayType | TINYINT | - | - | 是 | 支付方式:1-微信,2-支付宝 |
| RechargeAmount | DECIMAL | 18,2 | - | 是 | 充值金额,≥0.01 |
| RechargeScreenshot | VARCHAR | 255 | - | 否 | 充值截图URL(存储文件服务器地址) |
| RechargeStatus | TINYINT | - | - | 是 | 充值状态:0-待审核,1-审核通过,2-审核驳回 |
| Remark | VARCHAR | 512 | - | 否 | 备注(客户/审核人填写) |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
| AuditTime | DATETIME | - | - | 否 | 审核时间 |
| AuditBy | VARCHAR | 32 | - | 否 | 审核人(管理员账号) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
7.3 核心接口设计
| 接口名称 | 请求方式 | 请求路径 | 请求参数 | 响应参数 | 接口说明 |
|---|---|---|---|---|---|
| 提交充值申请 | POST | /recharge/recharge/submit | customerId, payType, rechargeAmount, screenshotUrl, remark | code, msg, data.serialNumber | 生成流水号,保存充值记录,状态为待审核 |
| 审核充值申请 | POST | /recharge/recharge-record/approve 或 reject | id, auditStatus, auditBy, remark | code, msg | 审核通过则更新客户余额,更新审核时间、状态、审核人 |
| 查询充值记录 | GET | /recharge/recharge-record/list | customerId, serialNumber, startTime, endTime, status | list, total | 多条件分页查询充值记录 |
| 导出充值记录 | GET | /recharge/export | customerId, startTime, endTime | 文件流 | 导出充值记录为Excel文件 |
6.3.1.1 提交充值申请(POST /recharge/recharge/submit)
1 接口请求示例
请求 /recharge/recharge/submit(POST)
{
"customerId": 1,
"rechargeAmount": 500,
"payType": 1,
"rechargeScreenshot": "https://example.com/upload/screenshot.jpg",
"remark": "充值500元"
}
参数说明:
customerId客户ID(客户端提交时可不传,取当前登录客户);rechargeAmount充值金额,≥0.01;payType支付方式:1-微信,2-支付宝;rechargeScreenshot充值截图URL;remark备注。
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"serialNumber": "RECHARGE2024010100123456",
"customerId": 1,
"rechargeAmount": 500.00,
"payType": 1,
"rechargeScreenshot": "https://example.com/upload/screenshot.jpg",
"rechargeStatus": 0,
"remark": "充值500元",
"rechargeTime": "2024-01-01 12:00:00",
"createTime": "2024-01-01 12:00:00"
}
}
2 接口业务逻辑
核心流程
- 创建充值记录并生成流水号,初始状态为待审核。
校验与异常
- 校验金额、支付方式与截图信息合法性,不合法时返回业务错误。
6.3.1.2 审核充值申请-通过(POST /recharge/recharge-record/approve)
1 接口请求示例
请求 /recharge/recharge-record/approve(POST)
{
"id": 1,
"remark": "审核通过"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 审核通过后更新充值状态与审核信息,并增加客户余额。
校验与异常
- 校验记录状态必须为待审核;重复审核或状态冲突时返回业务错误。
6.3.1.3 审核充值申请-驳回(POST /recharge/recharge-record/reject)
1 接口请求示例
请求 /recharge/recharge-record/reject(POST)
{
"id": 1,
"remark": "截图不清晰,请重新上传"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 审核驳回后更新充值状态与审核备注,不变更客户余额。
校验与异常
- 校验记录状态与审核权限,非法操作时返回业务错误。
6.3.1.4 查询充值记录(GET /recharge/recharge-record/list)
1 接口请求示例
请求 /recharge/recharge-record/list(GET,Query 参数)
?page=1&pageSize=20&customerId=1&serialNumber=&rechargeStatus=0&startTime=2024-01-01&endTime=2024-01-31
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"customerId": 1,
"customerCode": "W2501",
"customerPhone": "13800138000",
"serialNumber": "RECHARGE2024010100123456",
"rechargeTime": "2024-01-01 12:00:00",
"payType": 1,
"payTypeName": "微信",
"rechargeAmount": 500.00,
"rechargeScreenshot": "https://example.com/upload/screenshot.jpg",
"rechargeStatus": 0,
"rechargeStatusName": "待审核",
"remark": "充值500元",
"auditTime": null,
"auditBy": null,
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 20
}
}
2 接口业务逻辑
核心流程
- 按客户、流水号、状态和时间区间进行分页查询,返回记录列表与总数。
校验与异常
- 校验时间区间与分页参数合法性,查询异常时返回统一错误码。
6.3.1.5 导出充值记录(GET /recharge/export)
1 接口请求示例
请求 /recharge/export(GET,Query 参数)
?customerId=1&startTime=2024-01-01&endTime=2024-01-31
响应
返回 Excel 文件流,Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
2 接口业务逻辑
核心流程
- 根据筛选条件导出充值记录为 Excel 文件流。
校验与异常
- 校验导出条件与数据权限,导出失败时返回统一错误信息。
8 系统主数据
8.1 核心需求说明
- 仓库地址:管理仓库收货地址信息,包括主仓/中转仓/退货仓/其他类型;支持收件人、联系电话、收货地址、客服电话、客服微信及二维码等配置。
- 国家管理:维护国家基础资料(中文名称、英文名称、二字代码),供渠道分区、下单地址等模块复用。
- 字典管理:维护
t_dict,供全平台下拉与状态映射复用。与客户、内部员工相关的DictType及编码含义在docs/rbac系统设计-050901.md定义与迭代;OMS 仅保证业务侧按DictType+DictCode引用时与实现一致。本篇表结构中DictType示例以 仓库、通知等纯业务枚举 为主。
8.2 表结构设计
8.2.1 与 RBAC 文档的职责划分
权限系统(认证、内部用户、客户主数据、角色权限、菜单、组织等)全部由 docs/rbac系统设计-050901.md 承担;OMS 「8 系统主数据」 只描述 业务侧主数据:国家、字典、通知、仓库地址 等(见下)。
8.2.2 国家表 t_country
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| ChineseName | VARCHAR | 128 | - | 是 | 中文名称 |
| EnglishName | VARCHAR | 128 | - | 是 | 英文名称 |
| CountryCode | VARCHAR | 2 | - | 是 | 国家二字代码(ISO 3166-1 alpha-2) |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
8.2.3 字典表 t_dict
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| DictType | VARCHAR | 64 | - | 是 | 字典类型(如 notice_type、warehouse_type 等 OMS 业务枚举;与客户/员工相关的 DictType 由 RBAC 文档 统一约定) |
| DictSort | INT | - | - | 是 | 字典排序,值越小越靠前 |
| DictCode | VARCHAR | 64 | - | 是 | 字典编码(同类型下唯一) |
| DictName | VARCHAR | 128 | - | 是 | 字典名称 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
8.2.4 公告通知表 t_notice
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| NoticeType | VARCHAR | 16 | - | 是 | 通知类型:notice-公告,message-站内信 |
| Title | VARCHAR | 200 | - | 是 | 标题 |
| Content | TEXT | - | - | 是 | 内容 |
| IsPopup | TINYINT | - | - | 是 | 是否弹窗:0-否,1-是 |
| ReceiverType | VARCHAR | 16 | - | 是 | 接收对象:user-用户,customer-客户 |
| ReceiverIds | JSON | - | - | 是 | 接收人 ID 列表 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
8.2.5 通知已读明细表 t_notice_read
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| NoticeId | BIGINT | - | 外键(关联 t_notice.Id) |
是 | 通知 ID |
| ReceiverType | VARCHAR | 16 | - | 是 | 接收对象:user-用户,customer-客户 |
| ReceiverId | BIGINT | - | - | 是 | 已读主体 ID(用户 ID/客户 ID) |
| ReadTime | DATETIME | - | - | 是 | 已读时间 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
8.2.6 仓库地址表 t_warehouse_address
| 字段名 | 字段类型 | 长度 | 主键/外键 | 非空 | 说明 |
|---|---|---|---|---|---|
| Id | BIGINT | - | 主键 | 是 | 自增唯一标识 |
| WarehouseName | VARCHAR | 128 | - | 是 | 仓库名称 |
| WarehouseType | VARCHAR | 32 | - | 是 | main/transit/return/other |
| Recipient | VARCHAR | 64 | - | 否 | 收件人 |
| ContactPhone | VARCHAR | 32 | - | 否 | 联系电话 |
| ShippingAddress | TEXT | - | - | 否 | 收货地址 |
| ServicePhone | VARCHAR | 32 | - | 否 | 客服电话 |
| ServiceWechat | VARCHAR | 64 | - | 否 | 客服微信 |
| ServiceWechatFiles | JSON | - | - | 否 | 微信二维码图片 |
| IsDeleted | TINYINT | - | - | 是 | 是否删除:0-否,1-是,默认0 |
| CreateUserId | INT | - | - | 是 | 创建人 |
| CreateTime | DATETIME | - | - | 是 | 创建时间 |
| UpdateUserId | INT | - | - | 否 | 更新人 |
| UpdateTime | DATETIME | - | - | 否 | 更新时间 |
8.3 核心接口设计
登录、刷新、登出、当前主体(含
/auth/*或/rbac/auth/*等):路径与契约见docs/rbac系统设计-050901.md与线上 Swagger;不在本篇逐条列出。
| 接口名称 | 请求方式 | 请求路径 | 说明 |
|---|---|---|---|
| 国家列表 | GET | /system/country/list | 查询国家列表 |
| 字典列表 | GET | /system/dict/list | 按类型分页查询字典 |
| 新增字典 | POST | /system/dict/create | 新增字典项 |
| 更新字典 | POST | /system/dict/update | 更新字典项 |
| 删除字典 | POST | /system/dict/delete | 删除字典项 |
| 仓库列表 | GET | /system/warehouse/list | 仓库列表 |
| 仓库详情 | GET | /system/warehouse/detail | 仓库详情 |
| 新增仓库 | POST | /system/warehouse/create | 新增 |
| 更新仓库 | POST | /system/warehouse/update | 更新 |
| 删除仓库 | POST | /system/warehouse/delete | 删除 |
| 通知列表 | GET | /system/notice/list | 分页查询通知 |
| 新增通知 | POST | /system/notice/create | 新增公告/站内信 |
| 编辑通知 | POST | /system/notice/update | 编辑公告/站内信 |
| 删除通知 | POST | /system/notice/delete | 删除公告/站内信 |
| 确认已读 | POST | /system/notice/read-confirm | 当前用户/客户确认已读 |
8.4 系统主数据接口详细设计(/system/* 等)
范围:本章
/system/*及t_country/t_dict/t_notice/t_warehouse_address;认证、令牌、权限码、客户域/用户域 HTTP 见docs/rbac系统设计-050901.md与 OpenAPI/Swagger。
8.4.1.1 国家列表(GET /system/country/list)
1 接口请求示例
请求 /system/country/list(GET)
无请求参数,返回全部国家字段。
响应
{
"code": 0,
"msg": "success",
"data": [
{
"id": 1,
"chineseName": "中国",
"englishName": "China",
"countryCode": "CN"
},
{
"id": 2,
"chineseName": "美国",
"englishName": "United States",
"countryCode": "US"
}
]
}
2 接口业务逻辑
核心流程
- 查询
t_country全量有效数据,按countryCode或englishName排序返回。
校验与异常
- 仅返回未删除记录;无数据时返回空数组。
8.4.1.2 字典列表(GET /system/dict/list)
1 接口请求示例
请求 /system/dict/list(GET,Query 参数)
?page=1&pageSize=20&dictType=warehouse_type&keyword=主仓
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"dictType": "warehouse_type",
"dictSort": 1,
"dictCode": "main",
"dictName": "主仓",
"createTime": "2026-04-27 10:00:00",
"updateTime": "2026-04-27 10:00:00"
}
],
"total": 1
}
}
2 接口业务逻辑
核心流程
- 按
dictType、关键词分页查询t_dict,按dictSort升序、id降序返回。
校验与异常
- 校验分页参数合法性;仅返回未删除记录,查询异常时返回统一错误码。
8.4.1.3 新增字典(POST /system/dict/create)
1 接口请求示例
请求 /system/dict/create(POST)
{
"dictType": "warehouse_type",
"dictSort": 1,
"dictCode": "main",
"dictName": "主仓"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 新增字典项并写入创建审计信息。
校验与异常
- 校验
dictType、dictSort、dictCode、dictName必填及格式合法性。 - 校验同一
dictType下dictCode唯一,重复时返回业务错误。
8.4.1.4 更新字典(POST /system/dict/update)
1 接口请求示例
请求 /system/dict/update(POST)
{
"id": 1,
"dictType": "warehouse_type",
"dictSort": 2,
"dictCode": "transit",
"dictName": "中转仓"
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据字典 ID 更新字典类型、排序、编码、名称及审计信息。
校验与异常
- 校验
id存在且未删除,更新字段合法。 - 若更新后
dictType + dictCode与其他记录冲突,返回业务错误。
8.4.1.5 删除字典(POST /system/dict/delete)
1 接口请求示例
请求 /system/dict/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据字典 ID 执行逻辑删除并保留历史审计信息。
校验与异常
- 校验
id存在与删除前置条件,不存在或已删除时返回业务错误。
8.4.1.6 仓库列表(GET /system/warehouse/list)
1 接口请求示例
请求 /system/warehouse/list(GET,Query 参数)
?page=1&pageSize=20&warehouseType=main&keyword=
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 1,
"warehouseName": "深圳主仓",
"warehouseType": "main",
"warehouseTypeName": "主仓",
"recipient": "张三",
"contactPhone": "0755-12345678",
"shippingAddress": "广东省深圳市南山区xxx路xxx号",
"servicePhone": "400-xxx-xxxx",
"serviceWechat": "itfx_service",
"serviceWechatFiles": ["https://example.com/qrcode1.jpg"],
"createTime": "2024-01-01 12:00:00",
"updateTime": "2024-01-01 12:00:00"
}
],
"total": 5
}
}
2 接口业务逻辑
核心流程
- 按仓库类型与关键词分页查询仓库地址信息列表。
校验与异常
- 校验分页参数与筛选条件合法性,异常时返回统一错误码。
8.4.1.7 仓库详情(GET /system/warehouse/detail)
1 接口请求示例
请求 /system/warehouse/detail(GET,Query 参数)
?id=1
响应
{
"code": 0,
"msg": "success",
"data": {
"id": 1,
"warehouseName": "深圳主仓",
"warehouseType": "main",
"recipient": "张三",
"contactPhone": "0755-12345678",
"shippingAddress": "广东省深圳市南山区xxx路xxx号",
"servicePhone": "400-xxx-xxxx",
"serviceWechat": "itfx_service",
"serviceWechatFiles": ["https://example.com/qrcode1.jpg"],
"createTime": "2024-01-01 12:00:00",
"createBy": "admin",
"updateTime": "2024-01-01 12:00:00",
"updateBy": "admin"
}
}
2 接口业务逻辑
核心流程
- 根据仓库 ID 查询仓库详情,返回完整地址与客服信息。
校验与异常
- 校验
id必填且存在,不存在时返回业务错误。
8.4.1.8 新增仓库(POST /system/warehouse/create)
1 接口请求示例
请求 /system/warehouse/create(POST)
{
"warehouseName": "深圳主仓",
"warehouseType": "main",
"recipient": "张三",
"contactPhone": "0755-12345678",
"shippingAddress": "广东省深圳市南山区xxx路xxx号",
"servicePhone": "400-xxx-xxxx",
"serviceWechat": "itfx_service",
"serviceWechatFiles": ["https://example.com/qrcode1.jpg"]
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 新增仓库地址配置并写入创建审计信息。
校验与异常
- 校验仓库名称、类型及地址字段完整性,不合法时返回业务错误。
8.4.1.9 更新仓库(POST /system/warehouse/update)
1 接口请求示例
请求 /system/warehouse/update(POST)
{
"id": 1,
"warehouseName": "深圳主仓",
"warehouseType": "main",
"recipient": "张三",
"contactPhone": "0755-12345678",
"shippingAddress": "广东省深圳市南山区xxx路xxx号",
"servicePhone": "400-xxx-xxxx",
"serviceWechat": "itfx_service",
"serviceWechatFiles": ["https://example.com/qrcode1.jpg"]
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据仓库 ID 更新仓库基础信息与联系方式。
校验与异常
- 校验
id存在与更新字段合法性,更新失败时返回业务错误。
8.4.1.10 删除仓库(POST /system/warehouse/delete)
1 接口请求示例
请求 /system/warehouse/delete(POST)
{
"id": 1
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据仓库 ID 执行逻辑删除并保留历史记录。
校验与异常
- 校验
id存在与删除前置条件,冲突时返回业务错误。
8.4.1.11 通知列表(GET /system/notice/list)
1 接口请求示例
请求 /system/notice/list(GET,Query 参数)
?page=1&pageSize=20¬iceType=notice&receiverType=user&keyword=活动
响应
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"id": 101,
"noticeType": "notice",
"noticeTypeName": "公告",
"title": "五一放假通知",
"content": "仓库 5 月 1 日-5 月 3 日暂停收货。",
"isPopup": 1,
"receiverType": "user",
"receiverTypeName": "用户",
"receiverIds": [1001, 1002, 1003],
"readCount": 2,
"receiverCount": 3,
"createTime": "2026-04-25 12:00:00",
"updateTime": "2026-04-25 12:00:00"
}
],
"total": 1
}
}
2 接口业务逻辑
核心流程
- 按通知类型、接收对象、关键词分页查询
t_notice。 - 已读数通过聚合
t_notice_read(按NoticeId+ReceiverId去重)计算,接收人总数按receiverIds统计。
校验与异常
- 校验分页参数合法性,仅返回未删除记录;异常时返回统一错误码。
8.4.1.12 新增通知(POST /system/notice/create)
1 接口请求示例
请求 /system/notice/create(POST)
{
"noticeType": "notice",
"title": "五一放假通知",
"content": "仓库 5 月 1 日-5 月 3 日暂停收货。",
"isPopup": 1,
"receiverType": "user",
"receiverIds": [1001, 1002, 1003]
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 新增公告/站内信并写入接收对象与接收人列表。
校验与异常
- 校验
noticeType、title、content、isPopup、receiverType、receiverIds必填及枚举合法性。 receiverIds为空或包含无效用户/客户时返回业务错误。
8.4.1.13 编辑通知(POST /system/notice/update)
1 接口请求示例
请求 /system/notice/update(POST)
{
"id": 101,
"noticeType": "message",
"title": "账单补充说明",
"content": "请于本周内完成 4 月账单核对。",
"isPopup": 0,
"receiverType": "customer",
"receiverIds": [2001, 2002]
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据通知 ID 更新通知主体内容与接收范围。
- 如接收人发生变化,清理
t_notice_read中不在新接收范围内的已读明细。
校验与异常
- 校验
id存在且未删除,更新字段合法。 - 已发布通知可编辑但必须保留至少 1 个接收人。
8.4.1.14 删除通知(POST /system/notice/delete)
1 接口请求示例
请求 /system/notice/delete(POST)
{
"id": 101
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 根据通知 ID 执行逻辑删除,保留历史审计信息。
校验与异常
- 校验
id必填且存在,不存在或已删除时返回业务错误。
8.4.1.15 确认已读(POST /system/notice/read-confirm)
1 接口请求示例
请求 /system/notice/read-confirm(POST)
{
"id": 101
}
响应
{
"code": 0,
"msg": "success",
"data": null
}
2 接口业务逻辑
核心流程
- 当前登录用户/客户调用后,在
t_notice_read中按NoticeId + ReceiverType + ReceiverId幂等写入已读记录,并记录readTime。
校验与异常
- 校验通知存在且未删除。
- 校验当前主体在通知接收范围内,不在范围内时返回无权限错误。
9 需求迭代与变更记录
9.1 需求迭代目录(按日期管理)
迭代编号建议使用
YYYYMMDD-序号,按日期倒序维护;不同功能迭代可使用-01、-02递增。
| 迭代日期 | 迭代编号 | 迭代功能 | 变更模块 | 备注 |
|---|
| 2026-04-30 | 20260430-03 | 获取渠道分组 | 渠道模块 | 之前漏写该接口 |
| — | — | 与客户、内部用户、认证、RBAC 相关的迭代 | — | 一律在 docs/rbac系统设计-050901.md 维护;OMS 本篇仅记录业务域迭代 |
9.2 20260427-03 差异明细(按表结构与接口)
对比范围:
oms表结构与接口设计20260427.mdvsoms表结构与接口设计20260430.md。与认证、客户、内部用户、RBAC 相关的历史差异不再在此归档,见docs/rbac系统设计-050901.md。
9.2.1 表结构差异
新增表(0)
- 无
更新表(0)
- 无
删除表(0)
- 无
9.2.2 接口差异
新增接口(1)
GET | /channel/service-channel/group/list(获取渠道分组列表)
更新接口(0)
- 无
删除接口(0)
- 无
10 附录
10.1 接口路径规范(kebab-case 汇总)
| 模块 | 路径前缀 | 示例 |
|---|---|---|
| 订单 | /order/ | list, detail, pay, pre-declare, cancel-intercept, delete, price-check, fee/batch-recalculate |
| 渠道-销售产品 | /channel/sales-product/ | list, detail, create, update, delete, price/list, allocation/get |
| 渠道-服务渠道 | /channel/service-channel/ | list, detail, create, update, delete, group/create, group/update, group/delete, price/list |
| 渠道-计重 | /channel/weight-rule/, weight-rounding/ | list, create, update, delete, info/list |
| 渠道-自动触发 | /channel/auto-trigger/ | list, create, update, delete, toggle-status |
| 渠道-分区(KpiArea) | /channel/kpi-area/ | create, update, delete, list, info/add, info/update, info/delete, info/list |
| 渠道-标签 | /channel/label-template/save | |
| 操作 | /operation/ | inbound/create, inbound/recent-list, outbound/create, print-label/print |
| 权限与客户域(非 OMS) | — | docs/rbac系统设计-050901.md(/customer/*、/rbac/* 等) |
| 充值 | /recharge/ | recharge/submit, recharge-record/list, approve, reject |
| 系统 | /system/ | country/list, warehouse/list, warehouse/detail, warehouse/create, warehouse/update, warehouse/delete, notice/list, notice/create, notice/update, notice/delete, notice/read-confirm |
10.2 分区类型说明(黑名单/偏远/价格)
| 页面 | areaType | 说明 |
|---|---|---|
| 黑名单区 | blacklist | 黑名单分区 |
| 偏远分区 | remote | 偏远分区 |
| 价格分区 | price | 用于计价/价格表关联的分区 |
调用 KpiArea 接口时,通过 areaType 区分不同业务分区,无需新建表或接口。
10.3 状态码与枚举
10.3.1 订单状态
| status | 中文 |
|---|---|
| draft | 草稿 |
| predeclared | 已预报 |
| received | 已收货 |
| pendingPayment | 待支付 |
| pendingShip | 待发货 |
| pendingOnline | 待上网 |
| shipping | 运输中 |
| deliverySuccess | 派送成功 |
| deliveryFailed | 派送失败 |
| problematic | 问题件 |
| deleted | 已删除 |
| claimed | 已理赔 |
10.3.2 充值状态
| payStatus | 中文 |
|---|---|
| 0 | 待审核 |
| 1 | 成功 |
| 2 | 失败 |
10.3.3 仓库类型
| warehouseType | 中文 |
|---|---|
| main | 主仓 |
| transit | 中转仓 |
| return | 退货仓 |
| other | 其他 |
10.3.4 通知类型
| noticeType | 中文 |
|---|---|
| notice | 公告 |
| message | 站内信 |
10.3.5 接收对象类型
| receiverType | 中文 |
|---|---|
| user | 内部登录主体(取值语义与主体类型定义见 RBAC 文档) |
| customer | 客户登录主体(同上) |
与 RBAC 三类主体:权限规范另有 customer_sub(子账号) 登录主体(见 docs/rbac系统设计-050901.md)。t_notice / 已读表 当前 ReceiverType 仅列 user / customer 时:ReceiverIds 是否包含子账号 Id、抑或一律按主客户 Id 广播,由产品与 /system/notice/* 实现约定;若需显式区分 customer_sub,应同步改 OMS OpenAPI 与本文 8.2.4/8.2.5 字段说明。
说明:客户分组、客户状态等客户主数据枚举 不在 OMS 附录维护,见 docs/rbac系统设计-050901.md。
文档版本:v1.1 | 最后更新:2026-04-27