采购订单 · 需求文档(IM-01)
采购订单以 ERP 为权威数据源,WMS 通过接口同步订单头与行明细,不在 WMS 内手工新建或编辑订单基本信息;WMS 在订单执行侧提供 "关闭订单" 操作(本地标记,不回写 ERP)。核心约束:单据编号来自 ERP、货主维度用于多租户隔离、基本信息只读、关闭为 WMS 本地动作。
模块定位
采购订单是「入库管理」分类的首个模块,也是 WMS 收货作业的上游依据。它不做采购订单的生产方,只做 ERP 采购订单的消费方与执行状态补充方——WMS 提供"关闭订单"等本地执行标记,供入库收货、追溯、计费引用。
要解决的问题
- 采购订单若在 ERP / WMS 各录各的,收货时无法核对"该收什么、收多少",导致多收、漏收、错收。
- 多货主(3PL)场景下,不同货主的采购订单必须靠 owner 维度隔离,避免串单、串货。
- ERP 已取消或终止的订单若仍在 WMS 可收货,会造成无效作业与库存虚增;需要 WMS 侧可"关闭订单"拦截。
- 运营人员误改订单基础信息,事后无法判断以谁为准。
目标(可衡量)
- 采购订单主数据 100% 来自 ERP 接口,WMS 零手工录入基本信息。
- 支持按 货主 / 单据编号 / 供应商名称 / 单据日期区间 / 状态 五维组合查询,毫秒级定位目标订单。
- 基本信息只读、"关闭订单"本地标记可审计,权责清晰。
- 同步过程可监控、可回溯(时间、结果、失败明细)。
2.1 核心约束与设计原则
① 数据来源 —— 接口获取 ERP 采购订单。WMS 不生产采购订单,只消费。ERP 是采购订单的权威源,WMS 通过接口(拉取/接收)落地订单头与行明细。v1 默认单向同步(ERP → WMS),WMS 不回写订单主数据("关闭订单"为本地执行标记,见 2.5)。
② 货主维度 —— owner_id 由 WMS 提供。采购订单按 (order_no, owner_id) 联合唯一标识。order_no 来自 ERP;owner_id 由 WMS 侧提供,关联"货主主数据",同步时通过「货主 ↔ ERP 来源映射」归属,支撑多货主隔离与跨货主不可见。
③ 只读控制 —— 订单基本信息部分不可编辑。所有来自 ERP 的订单字段(单据编号、供应商、日期、金额、明细等)在 WMS 内锁定/置灰;WMS 仅维护"本地执行维度"(关闭标记、关闭人/时间、关联入库单)。
④ 关闭为本地动作 —— 不回写 ERP。"关闭订单"是 WMS 侧的执行拦截标记(close_flag),用于阻止已被 ERP 取消/终止或无需再收货的订单继续生成入库单;它不回写 ERP,ERP 侧状态以 erp_status 原样保留。是否需双向回写列入开放问题(见 2.5 / 五)。
2.2 数据模型 —— 采购订单头(联合主键 order_no + owner_id)
订单头以 (order_no, owner_id) 为联合主键。字段按"可编辑性"分为两类:
| # | 字段 | 来源 / 可编辑性 | 说明 |
|---|---|---|---|
| 1 | 单据编号 order_no | ERP · 只读 | 采购订单唯一编码,来自 ERP,联合主键之一;查询条件(模糊) |
| 2 | 货主 owner_id | WMS · 只读(系统) | 由 WMS 提供,关联货主主数据,联合主键之一;查询条件(下拉) |
| 3 | 供应商编码 supplier_code | ERP · 只读 | 供应商唯一编码,来自 ERP |
| 4 | 供应商名称 supplier_name | ERP · 只读 | 来自 ERP;查询条件(模糊) |
| 5 | 单据日期 doc_date | ERP · 只读 | 订单制单日期;查询条件(开始日期 - 结束日期区间) |
| 6 | 预计到货日期 plan_arrive_date | ERP · 只读 | ERP 计划到货日,供收货排程参考 |
| 7 | 订单类型 order_type | ERP · 只读 | 普通采购 / 退货采购 等 |
| 8 | ERP 单据状态 erp_status | ERP · 只读 | ERP 原始状态:已审核 / 部分收货 / 已收货完成 / 已取消 等 |
| 9 | 综合状态 status | WMS · 派生 | = erp_status 叠加 WMS 关闭标记;查询"状态"基于此字段 |
| 10 | 币种 currency | ERP · 只读 | 订单结算币种 |
| 11 | 订单金额 amount | ERP · 只读 | 订单总金额(头级汇总) |
| 12 | 已收货数量 / 金额 | ERP · 只读 | ERP 累计已收货,供收货进度核对 |
| 13 | 创建人 create_by | ERP · 只读 | ERP 制单人 |
| 14 | 审核人 audit_by | ERP · 只读 | ERP 审核人 |
| 15 | 明细行数 line_count | ERP · 只读 | 订单行项目数(头级汇总) |
| 16 | WMS 关闭标记 close_flag | WMS · 可编辑 | 关闭订单操作后标记 Y / N;拦截继续收货 |
| 17 | 关闭人 / 关闭时间 | WMS · 生成 | 执行"关闭订单"的操作人与时间,可审计 |
| 18 | 关联入库单号 related_inbound_no | WMS · 生成 | 收货执行后回填的入库单号,建立订单↔入库关联 |
2.3 数据模型 —— 采购订单明细(行项目,ERP · 只读)
每个采购订单含若干行项目,行项目随订单头由 ERP 同步,全部 ERP · 只读:
| # | 字段 | 来源 | 说明 |
|---|---|---|---|
| 1 | 行号 line_no | ERP · 只读 | 行项目序号 |
| 2 | 商品编码 sku_id | ERP · 只读 | 关联商品管理(BM-01)的 sku_id |
| 3 | 商品名称 | ERP · 只读 | 商品名称 |
| 4 | 规格型号 | ERP · 只读 | 规格 |
| 5 | 计量单位 | ERP · 只读 | 盒 / 瓶 / 箱 等 |
| 6 | 计划数量 plan_qty | ERP · 只读 | 本行计划收货数量 |
| 7 | 已收货数量 received_qty | ERP · 只读 | ERP 累计已收 |
| 8 | 未收货数量 pending_qty | ERP · 只读 | = 计划数量 − 已收货数量 |
| 9 | 单价 price | ERP · 只读 | 含税/不含税单价(按 ERP 口径) |
| 10 | 行金额 line_amount | ERP · 只读 | = 计划数量 × 单价 |
| 11 | 批号 / 效期要求 | ERP · 只读 | 可选,对收货批号/效期的约束 |
| 12 | 行备注 | ERP · 只读 | 行级备注 |
2.4 ERP 接口设计(ERP → WMS 单向)
同步方向:ERP → WMS(v1 单向)。WMS 通过接口拉取或接收采购订单(头 + 明细),不回写订单主数据。
同步方式:支持全量同步 + 增量同步;建议"定时批量 + 变更事件触发(订单审核/取消)"双通道。
主键与映射:order_no 直接取自 ERP 报文;owner_id 不直接来自 ERP,需通过「货主 ↔ ERP 来源映射」绑定——每个货主配置其对应的 ERP 组织 / 供应商 / 门店编码,同步时据此把订单归属到正确的 owner_id。
幂等与落库:以 (order_no, owner_id) 做 upsert;同一订单重复同步不新增记录,只更新字段值(close_flag 等 WMS 本地字段不被接口覆盖)。
失败与容错:单条订单失败不阻断整体批次,记录失败明细(order_no、owner_id、错误原因),支持失败重试;批次级返回成功/失败计数与耗时。
2.5 查询条件与页面布局(重点)
采购订单列表页顶部为查询条件区,支持以下五个查询条件组合检索(均为 ERP 已同步数据的过滤,不做任何写操作):
| # | 查询条件 | 控件类型 | 说明 |
|---|---|---|---|
| 1 | 货主 | 下拉选择 | 取货主主数据;按 owner_id 过滤,同时驱动多租户隔离(仅见有权货主) |
| 2 | 单据编号 | 文本输入(模糊) | 按 order_no 前缀/包含匹配 |
| 3 | 供应商名称 | 文本输入(模糊) | 按 supplier_name 包含匹配 |
| 4 | 单据日期 | 日期区间(开始日期 - 结束日期) | 按 doc_date 落在 [开始日期, 结束日期] 区间过滤;两端可空(空端表示不限制) |
| 5 | 状态 | 下拉选择 | 基于综合状态 status;下拉项至少含:全部 / 未关闭 / 已关闭,并可叠加 ERP 原始状态(已审核 / 部分收货 / 已收货完成 / 已取消)作为细化过滤 |
列表字段(默认展示列):勾选框、单据编号、货主、供应商名称、单据日期、预计到货日期、订单金额、ERP 单据状态、综合状态(含"已关闭"标识)、操作。
操作列 —— 关闭订单:对 未关闭 的订单,操作列显示「关闭订单」按钮;点击后二次确认(提示"关闭后该订单将不再生成入库单,是否确认?"),确认后写入 close_flag=Y、关闭人、关闭时间,并刷新综合状态为"已关闭"。已关闭订单的操作列按钮置灰/隐藏,不可重复关闭。关闭为 WMS 本地标记,不回写 ERP。
2.6 功能清单与详细需求
| # | 功能项 | 优先级 | 需求说明与验收要点 |
|---|---|---|---|
| 1 | ERP 采购订单同步 | P0 | WMS 通过接口从 ERP 获取采购订单头 + 明细;支持全量/增量;以 (order_no, owner_id) upsert。 验收:给定 ERP 报文可正确落库;重复同步不产生重复记录;单条失败不阻断整体并记日志;close_flag 等本地字段不被覆盖。 |
| 2 | 采购订单列表与多条件查询 | P0 | 列表分页展示;支持按 货主 / 单据编号 / 供应商名称 / 单据日期区间 / 状态 组合查询;查询结果受 owner_id 多租户隔离约束。 验收:五个条件可任意组合;日期区间边界正确;状态下拉(全部/未关闭/已关闭 + ERP 原始状态)生效;跨货主不可见彼此订单。 |
| 3 | 采购订单详情(头 + 明细) | P0 | 查看订单头全部字段与行项目明细;只读字段清晰标识来源 ERP。 验收:详情页可展开全部明细行;头/明细只读字段无编辑入口。 |
| 4 | 基本信息只读控制 | P0 | ERP 来源字段在界面置灰/锁定,无编辑入口;接口层同样禁止 WMS 直接改这些字段。 验收:前端无编辑控件;后端对只读字段的写请求拒绝并记录。 |
| 5 | 关闭订单 | P1 | 操作列"关闭订单"按钮:对已关闭订单置灰/隐藏;未关闭订单点击后二次确认,写入 close_flag=Y、关闭人、关闭时间,综合状态更新为"已关闭"。 验收:关闭后该订单不可再生成入库单(与入库收货联动拦截);关闭人/时间可审计;已关闭不可重复关闭;不回写 ERP。 |
| 6 | 同步监控与日志 | P1 | 展示最近同步时间、成功/失败数、失败明细;支持手动触发全量同步与失败重试。 验收:可查看批次结果;失败记录可定位到具体 (order_no, owner_id) 与原因。 |
Future(P2,本期不做但架构预留):关闭订单双向回写 ERP(如需);采购订单与入库单的关联追踪视图;字段级变更对比与审计日志;采购订单导出。
2.7 用户故事
- 作为采购/仓储运营,我希望通过接口把 ERP 采购订单同步进 WMS,以便收货时以订单为依据核对"收什么、收多少",不用手工录入。
- 作为仓储运营,我希望按货主/单据编号/供应商/单据日期区间/状态组合查到某张订单,以便快速定位与核对。
- 作为仓储运营,我希望在 ERP 已取消或无需再收货的订单上点"关闭订单",以便它不再生成入库单、避免无效收货与库存虚增。
- 作为仓储运营,我希望订单基本信息在 WMS 里是只读锁定的,以便任何人都改不了、不会有"两套真相"。
- 作为质量/审计,我希望关闭订单留痕(关闭人、关闭时间),以便事后可追。
- 作为基本信息维护员,当同步失败时我希望看到是哪张 (order_no, owner_id) 出错、为什么,以便及时处理而非整批重来。
2.8 非目标(Non-goals)
- 不在 WMS 新建/编辑采购订单基本信息——ERP 是唯一权威源,WMS 只消费。
- 不回写订单主数据到 ERP(v1 单向;关闭订单为本地标记,是否双向回写列入开放问题)。
- 不做采购价/付款/发票逻辑——属 ERP 域,WMS 仅取收货作业所需字段。
- 不替代货主管理、商品管理——owner_id 来自货主主数据,sku_id 来自商品管理。
- 不直接生成入库单——采购订单是收货依据,入库单生成属入库作业模块,本模块仅提供"关闭"拦截与关联回填。
2.9 主要风险
- ERP 接口不稳定 / 字段缺失 → 同步失败,影响收货核对;缓解:失败隔离 + 重试 + 告警。
- owner_id 映射错误 → 订单归属错乱、跨货主串单;缓解:映射缺失即跳过并告警,不允许模糊归属。
- 只读字段被绕过修改 → 与 ERP 不一致;缓解:前端置灰 + 后端写拦截 + 同步覆盖兜底。
- 关闭订单与入库作业未联动 → 已关闭订单仍生成入库单;缓解:入库收货严格校验 close_flag,关闭即拦截。
- 大数据量全量同步性能 → 分页/分批、增量优先。
上游:货主管理(system_owner)
- owner_id 由 WMS 侧提供,来源于货主主数据;本模块依赖货主管理维护货主档案与「货主 ↔ ERP 来源映射」。
- 货主管理未就绪时,订单同步无法正确归属 owner_id,本模块应安全跳过并告警(不误归属)。
上游:ERP 采购系统
- 采购订单(头 + 明细)的权威数据源为 ERP;同步方向 ERP → WMS(v1 单向)。
- ERP 订单的审核、取消、收货进度等状态以 erp_status / 已收货数量 原样同步,WMS 仅追加本地标记。
下游:入库作业(收货 / 上架)
- 采购订单是入库收货的依据:收货时按订单核对 sku、数量;收货执行后回填 related_inbound_no。
- 订单 close_flag=Y(已关闭)时,入库作业须拦截,不再允许基于该订单生成入库单。
下游:商品管理(BM-01)
- 订单明细的 sku_id 关联商品管理,复用其单位、温区、批号、效期、包装层级等作业属性。
下游:追溯码中台
- 基于采购订单收货的商品,其追溯码绑定依赖本订单提供的 (sku, owner) 与商品包装层级。
关联:计费(3PL)
- 订单金额/数量可辅助计费核对;计费逻辑不在此模块内实现。
- 性能:全量同步须分页/分批处理,单批失败不影响整体;列表查询需支持分页与索引(按 owner_id、order_no、supplier_name、doc_date),万级数据下响应可控。
- 数据一致性:同步完成后 WMS 只读副本须与 ERP 主源一致;覆盖策略明确(ERP→只读字段覆盖,WMS 本地字段不覆盖)。
- 安全性与权限:基本信息前后端双重锁定(前端置灰 + 后端写拦截);多租户隔离——所有查询与写操作须按 owner_id / tenant_id 维度隔离,跨货主不可见彼此订单;"关闭订单"操作须有权限控制与审计。
- 可用性与容错:ERP 接口异常时同步可失败隔离、记录明细、支持手动重试,且查询功能不依赖同步实时成功;接口调用需超时与降级处理。
- 可维护性与扩展性:字段映射表可配置,便于 ERP 字段增减;接口协议(REST / 消息队列)可替换;新增 WMS 本地字段不影响只读逻辑。
- 审计与监控:同步批次、失败明细可追溯;关闭订单的关闭人/关闭时间留痕;同步成功率/及时率可观测。
- 兼容性:兼容增量与全量两种同步模式;字段增减向后兼容,不因新增可选字段导致旧报文失败。
评审核对清单
- 联合主键 (order_no, owner_id) 是否覆盖"同订单号多货主"真实场景,是否存在单 owner 即可的简化可能?
- owner_id 与 ERP 的映射基准是否明确(按货主 / 按 ERP 组织 / 按门店)?映射缺失时是否安全跳过而非模糊归属?
- 只读字段是否前后端双重锁定,且同步覆盖作为兜底保障一致性?
- 同步是否幂等(重复同步不重复记录),upsert 逻辑是否正确?close_flag 等本地字段是否明确不被接口覆盖?
- "状态"查询的语义是否清晰:综合状态 = erp_status + close_flag,下拉项(全部/未关闭/已关闭 + ERP 原始状态)是否齐全?
- "关闭订单"是否仅本地标记、不回写 ERP?是否与入库收货严格联动拦截(close_flag=Y 不可生成入库单)?
- 单据日期区间的边界(含/不含端点、空端处理)是否明确?
- 与货主管理、商品管理、入库作业、追溯码中台的关联口径是否对齐?
- 非目标边界是否清晰(不回写 ERP、不生成入库单等),避免范围蔓延?
- 多租户隔离(owner_id / tenant_id)是否满足安全与合规要求?
需用户 / 架构确认的开放问题
- 接口协议与同步频率:REST 拉取 / 消息推送?全量周期与增量触发方式(尤其订单取消/审核事件)?
- "关闭订单"是否需双向回写 ERP?还是仅 WMS 本地标记即可(v1 默认本地标记)?
- 单据日期区间的边界规则:是否闭区间、开始/结束为空时如何处理?
- 状态查询是否需叠加 ERP 原始状态(已审核/部分收货/已收货完成/已取消)作为独立过滤维度?
- 采购订单与入库单的关联回填(related_inbound_no)由谁在何时写入,是否需要一对多?
- 字段权威清单与映射表以谁为准、由谁维护?