轻易云
注册体验

从补货建议到采购单:与 ERP 采购模块的闭环集成教程

· 系统管理员· 20 次浏览· 约 3 分钟读完
ERP补货模型API 编排金蝶云星空幂等

为什么"最后一公里"决定补货系统的成败

很多补货项目死在最后一公里:建议算得不错,但业务还要手工把建议抄进 ERP 建采购单——抄错行、漏单、重复单随之而来,建议与单据脱节后,追溯链断裂,系统很快退回 Excel。闭环的要求是:确认后的补货方案必须能一键变成 ERP 里合规的采购订单,并且到货数据能回流修正下一轮计算

本文以金蝶云星空(K3Cloud WebAPI)为例走通这条链路,思路同样适用于用友、SAP 等其他 ERP。

链路总览

  1. 方案确认:补货方案行级确认完成(无未结算行),进入待下单状态。
  2. 拆单:按供应商 × 仓库(orderKey)把方案行拆分为采购订单——一张 PO 只能有一个供应商、一个收货仓。
  3. 建单:调用 ERP WebAPI 保存采购订单(Save)。
  4. 提交审核:Submit → Audit,让单据进入 ERP 的正式业务流程。
  5. 到货回填:定时拉取采购单/入库单状态,回写"已到货量",关闭建议的生命周期。

金蝶云星空采购订单 API 要点

金蝶云星空 WebAPI 的通用单据操作以 FormId 定位单据类型,采购订单的 FormId 为 PUR_PurchaseOrder。核心操作:

操作用途说明
Save保存(新增/修改)单据返回单据内码与编号
Submit提交单据触发工作流/校验
Audit审核单据单据生效,可被下游引用
ExecuteBillQuery查询单据状态回填与对账用

保存采购订单的请求体核心结构(节选):

json
{
  "FormId": "PUR_PurchaseOrder",
  "Data": {
    "NeedUpDateFields": [],
    "Model": {
      "FBillTypeID": { "FNUMBER": "CGDD01_SYS" },
      "FDate": "2026-07-30",
      "FSupplierId": { "FNumber": "S000123" },
      "FPurchaseOrgId": { "FNumber": "100" },
      "FPOOrderEntry": [
        {
          "FMaterialId": { "FNumber": "SKU-10086" },
          "FQty": 200,
          "FTaxPrice": 12.5,
          "FDeliveryDate": "2026-08-06",
          "FEntryNote": "补货方案 RP-20260730-003 行号 42"
        }
      ]
    }
  }
}

要点:FSupplierIdFMaterialIdFPurchaseOrgId 等基础资料字段用 FNumber 编码关联,因此补货侧的主数据编码必须与 ERP 编码严格对齐——这是映射层的第一个硬约束。

字段映射与幂等设计

映射层的三个硬约束

  1. 编码对齐:SKU、供应商、仓库、计量单位全部以 ERP 编码为准,补货系统内做一层映射表,接口失败时优先怀疑映射缺失。
  2. 单据类型:标准采购单 CGDD01_SYS 与委外、直运等类型分开,拆单时按业务场景选择。
  3. 价格与税率:含税单价、税率从供应商协议价目表带出,不要让运算层"猜价"。

幂等:重试不产生重复单

补货拆单必须设计幂等键,推荐做法:每个方案行生成稳定的 orderKey = hash(planBatchId + rowNo),下单前按 orderKey 查本地单据登记表:

ts
// 伪代码:幂等建单
async function createPurchaseOrder(line: ConfirmedLine) {
  const existing = await poRegistry.findByOrderKey(line.orderKey);
  if (existing?.erpBillNo) return existing.erpBillNo; // 已建单,直接复用

  const payload = buildPoPayload(line); // 字段映射
  const saved = await kingdee.save("PUR_PurchaseOrder", payload);
  await poRegistry.upsert({
    orderKey: line.orderKey,
    erpBillId: saved.Id,
    erpBillNo: saved.BillNo,
    status: "SAVED",
  });

  await kingdee.submit("PUR_PurchaseOrder", saved.Id);
  await kingdee.audit("PUR_PurchaseOrder", saved.Id);
  await poRegistry.markStatus(line.orderKey, "AUDITED");
  return saved.BillNo;
}

注意 Save / Submit / Audit 是三个独立调用,任何一步失败都要能从登记表的状态恢复:Save 成功而 Submit 失败时,重试只补 Submit/Audit,绝不重新 Save——这是重复单的主要来源。

到货回填:闭环的另一半

建单只是前半环,后半环是到货数据回流:

  1. 定时任务(如每小时)用 ExecuteBillQuery 拉取在途采购单的累计入库数量,或直接从采购入库单(STK_InStock)按源单关联聚合。
  2. 回写补货系统的"已到货量",剩余到货量 = 合计到货量 − 已到货量,进入下一轮在途计算。
  3. 超期未到货、到货量异常的采购单行触发预警,交人工跟进。

只有到货数据稳定回流,补货公式里的"在途"才是可信的——否则下一轮计算会把已在路上的货再补一遍。

上线检查清单

  • 主数据编码映射表覆盖全部 SKU / 供应商 / 仓库
  • orderKey 幂等键与单据登记表就绪
  • Save/Submit/Audit 分步状态可断点恢复
  • 失败告警到人,重复单有对账脚本兜底
  • 到货回填任务运行正常,在途口径经业务确认

闭环打通之后,补货系统才真正从"建议工具"升级为"执行系统":建议、单据、到货三账对齐,每一行采购都能回到当初的方案行——这既是对账的基础,也是模型持续优化的数据燃料。

相关 API 文档

本文为原创内容,转载请注明出处:/insights/all/replenishment-to-purchase-order-erp-loop

评论