做ERP的人都知道,采购入库这个模块看起来流程清晰,实际落地的时候,坑一个接一个。
尤其是在国内新零售、跨境电商、大批量B2B采购这类场景里,采购入库往往会涉及多仓协同、供应商分批发货、ERP和WMS系统对接。单据流转稍微设计不好,库存数据就会出问题,财务对账就会打架,仓库和采购互相甩锅。
这篇文章想把这个问题拆开来聊。
从采购订单、采购收货通知单、采购入库单这三层单据讲起,到WMS回传的两种处理方式,再到最后那个很多团队都没想清楚的问题:
关单这个动作,到底应该放在哪里?
在我们的设计里,采购入库这条链路,在ERP侧一般会拆成三层单据:
采购订单→采购收货通知单→采购入库单
为什么要拆成三层?
因为现实里的供应商送货,很多时候不是一次送完的。
比如一张采购订单采了1000件,供应商可能分三批发货,第一批400件,第二批400件,第三批200件。如果直接拿采购订单去对接仓库,仓库其实并不知道这次来的货对应哪一批、应该收多少、收完以后订单应该是什么状态。
所以我们需要从采购订单里拆出采购收货通知单。
采购订单表达的是采购意图,采购收货通知单表达的是本次收货指令,采购入库单记录的是最终执行结果。
采购收货通知单生成之后,会下推给WMS。WMS收到通知单,生成自己的入库作业单,然后仓库开始执行收货、质检、上架。
执行完成后,WMS把结果回传给ERP,ERP再根据回传数据生成采购入库单,完成库存记录。
整个流程如下:
流程图画出来很干净,但问题就藏在WMS回传这一步里。
实际情况是,WMS往往不是一次把结果推回来的。
原因大概有两种。
一种是仓库操作本身就是分批完成的。货是分几辆车送到的,仓库卸一批、扫一批、收一批,系统也就分批产生收货结果。
另一种是WMS接口本身是事件驱动设计。收货完成推一次,质检完成再推一次,上架完成再推一次,每个节点都会触发回传,而不是等整张单据全部完成后再统一推送。
不管哪种原因,ERP这边面对的都是同一个问题:
同一张采购收货通知单,WMS推过来好几次数据,我怎么处理?
如果每次回传都生成一张采购入库单,那一张采购收货通知单就会对应多张采购入库单。
再往上看,一张采购订单又可能对应多张采购收货通知单。整条链路就会变成这样:
层级深了,不是说不能做,而是每一层的关联关系都要维护。
采购订单要回写累计入库数量,采购收货通知单要累计实收数量,采购入库单要记录每次实收结果。后面查数、对账、追溯都会变复杂。
如果不想让通知单对应多张入库单,另一种做法是:
第一次回传时生成采购入库单,后续回传不新建单据,而是在同一张采购入库单上追加数量或SKU明细。
这个设计看起来减少了单据数量,但会出现一个新问题:
库存到底什么时候加?
每次追加立即加库存,库存是实时的,但入库单还没完结,财务不知道能不能用这个数据。
等入库单完结后再统一加库存,单据状态是干净的,但库存会延迟。货已经上架了,系统里还查不到库存,后续销售、调拨、补货都会受影响。
所以这里最好把库存口径和财务口径拆开。
库存可以按WMS实收结果及时入账,但财务对账、暂估、应付匹配,要通过单据状态控制。不能把“库存可用”和“财务可结算”混成一个动作。
两个选择都有代价,必须显式做取舍,不能假装两个都能满足。
正常来说,WMS分批推数据,最后一次回传应该带完结标识,告诉ERP:
这张单收完了。
最怕的是这个标识一直没来。
可能是WMS侧操作中断了,可能是仓库主管忘了确认,也可能是系统异常没有触发。ERP这边就一直等,单据挂在“收货中”,没有办法自动完结。
这种单据一多,后面就会变成历史包袱。
采购看着烦,仓库查着乱,财务对账的时候还要绕开一堆中间态单据。
既然多次回传这么麻烦,一个自然的想法是:
那就约定好,一张采购收货通知单只允许WMS回传一次。
仓库把货收完、确认完,统一推给ERP。
这个设计语义确实很清楚。通知单和入库单1:1,库存一次性入账,财务对账也简单。
这个方案本身没有问题,真正的挑战来自供应商。
供应商不一定会完全按照你的系统设计来送货。
上午送了一车,仓库收完,按约定触发回传,采购收货通知单完结。下午供应商又送来一车,仓库一看,对应的采购收货通知单已经关了,这批货就没有单据可以收。
这时候只能临时创建新单,或者让采购员重新处理。
所以“一次回传”的约定没有问题,问题是供应商的送货行为打破了这个前提。
更准确地说,不是要求一张采购订单必须一次送齐,而是要求每次实际送货前,都要先生成一张边界清晰的采购收货通知单。
采购订单可以分批,但每次送货都要有对应的通知单。否则仓库现场一定会遇到无单可收的问题。
这是一个信息不对称的问题。
仓库主管能判断的是:今天这批货卸完了,现场没有车在等了,WMS作业可以结束了。
但他不知道:供应商后面是不是还有补货?通知单上差的20件,是应该继续等,还是直接关?
这些信息更多在采购侧。
采购员知道供应商发了多少,知道有没有后续补货,也知道缺量以后要不要继续追。仓库只知道实物收了多少,不掌握采购履约的完整上下文。
所以“一次回传”真正要解决的,不只是系统接口问题,而是送货规范问题。
如果供应商送货前没有按批次形成通知单,仓库就会在执行层被动挨打。
一次回传的系统设计更简单,单据关系清晰,财务对账也容易。
但它能跑通有一个前提:
供应商送货前必须先发起送货通知,在系统里生成对应的采购收货通知单,而且这张通知单要对应一次边界清晰的送货计划。
仓库收完货,触发一次回传,采购收货通知单完结。
如果供应商后来又送了一批,对应的单据已经关了,仓库无单可收,只能重新发起一张新的采购收货通知单,或者走异常收货流程。
多次回传则把这个压力转移到系统侧。
供应商送货节奏可以更灵活,但ERP要处理更复杂的单据关系、数量累计、库存入账、状态联动和完结判断。
| 维度 | 多次回传 | 一次回传 |
|---|---|---|
| 系统复杂度 | 高,需处理追加、累计、完结信号 | 低,单据关系简单 |
| 单据结构 | 采购收货通知单:采购入库单可能1:N | 通常1:1 |
| 库存入账 | 可以分批入账,库存更实时 | 一次性入账,口径更清楚 |
| 财务对账 | 需要状态隔离,中间态不能随便开放 | 相对简单 |
| 完结风险 | 完结信号迟迟不来,单据挂起 | 供应商分批送货,单据提前关闭 |
| 核心约束 | 依赖WMS接口协议完整 | 依赖供应商送货规范落地 |
两种方案没有绝对好坏,关键看你们更能管住哪一侧。
如果能管住供应商送货规范,尽量用一次回传,系统会简单很多。
如果供应商送货节奏不可控,或者WMS天然就是分批作业,那就不要强行追求1:1,系统要老老实实支持多次回传。
这里给两个版本。
建议优先推简单版,推不动再上兼容版。
不要一开始就把系统做得很重。很多复杂设计看起来很稳,最后其实是把业务管理问题全部丢给系统兜底。
前提是先和供应商对齐送货规范。
一张采购订单可以拆成多张采购收货通知单,但每张采购收货通知单要对应一次明确的送货计划。
供应商按通知单送货,仓库按通知单收货,WMS收完后一次性回传,ERP生成一张采购入库单,通知单完结。
这个方案的好处很明显:单据关系清晰,系统逻辑简单,财务对账也容易。
代价也很明确:供应商必须配合送货规范。
如果供应商经常不按通知单送货,或者一张通知单拆成多次到仓,那简单版就会在执行层不断出问题。
如果供应商送货节奏无法保证一次完成,或者WMS本身就是分节点回传,那就需要支持多次回传。
核心设计是:
接口协议层,要求WMS回传时带两个字段:
| 字段 | 说明 |
|---|---|
received_qty |
本次实收数量 |
is_final |
仓库侧是否已完成本次收货操作 |
ERP处理逻辑,每次收到回传:
is_final=true,或累计数量达到通知数量,触发通知单完结超时关单机制,如果超过约定时间仍未收到完结信号,系统自动向仓库发出关单通知,告知后续货物不再接收,采购收货通知单强制完结。
这套方案比简单版复杂,但更能适配真实业务。
供应商分批送货,WMS分批回传,ERP分批生成采购入库单,库存也可以按实际收货节奏入账。
只要接口协议和状态机设计清楚,这条链路是可以跑稳的。
| 维度 | 简单版 | 兼容版 |
|---|---|---|
| 通知单:入库单 | 1:1 | 1:N |
| 回传方式 | WMS一次性回传 | WMS支持多次回传 |
| 库存入账 | 一次性入账 | 分批入账 |
| 完结时机 | 回传完成即完结 | 根据数量、is_final、超时机制判断 |
| 系统复杂度 | 低 | 高 |
| 前提条件 | 供应商配合送货规范 | 接口协议和状态机要设计清楚 |
采购入库这条链路里,最容易被忽视的,其实不是收货,而是关单。
很多团队一开始只会讨论:
采购订单怎么下推?
通知单怎么生成?
WMS怎么回传?
采购入库单怎么入账?
但真正上线以后,问题往往出在:
这张单到底什么时候算结束?谁有权让它结束?结束以后,后面的货还能不能收?
这才是采购入库单据流转里最容易踩坑的地方。
WMS能告诉ERP的是执行事实。
比如这次收了多少,哪些SKU收了,哪些SKU少了,哪些批次入库了,仓库作业是否已经完成。
ERP要承接的是业务闭环。
比如采购收货通知单是否完结,采购订单累计入库数量是否回写,后续还能不能继续收货,缺量是否要进入异常处理。
这两个东西不能混在一起。
所以更准确的说法是:
WMS负责反馈执行事实,ERP负责完成业务闭环。
如果累计实收数量已经等于通知数量,ERP可以自动完结。
如果WMS回传is_final=true,说明仓库侧本次收货操作已经完成,ERP可以根据接口协议触发通知单完结。
如果长时间没有收到完结信号,ERP可以按超时规则通知仓库关单,并强制完结采购收货通知单,避免单据长期挂起。
这里的关键不是“谁点了按钮”,而是关单规则必须在ERP侧被清楚定义。
WMS可以反馈作业结果,也可以反馈完结标识,但最终这张采购收货通知单怎么完结、完结后怎么影响采购订单、库存和财务口径,必须由ERP来承接。
这也是很多项目容易出问题的地方。
接口一开始没说清楚,后来就变成:
WMS说我已经推完了。
ERP说我不知道你这是不是最后一次。
采购说供应商后面可能还有货。
仓库说我现场已经收完了。
最后每个系统都觉得自己没错,但单据就是卡住了。
采购入库这件事,表面看是采购订单、采购收货通知单、采购入库单之间的流转问题。
但真正落到系统设计里,最关键的是三件事:
第一,单据语义有没有拆清楚。
采购订单是采购意图,采购收货通知单是收货指令,采购入库单是执行结果。三层单据不能混用,否则后面的状态一定会乱。
第二,WMS回传协议有没有对齐。
到底是一次回传,还是多次回传?每次回传代表什么?回传数量是本次数量,还是累计数量?is_final代表什么?异常时怎么补偿?这些不提前说清楚,后面一定会靠代码补洞。
第三,关单规则有没有定义清楚。
什么时候自动关?什么时候按is_final关?什么时候超时强制关?关单以后后续到货怎么处理?这些规则如果没有在ERP侧设计清楚,后面就会变成仓库、采购、系统三方互相拉扯。
做供应链ERP久了会发现,很多「系统复杂度」本质上是「沟通欠债」。
当初没有把接口语义、完结时机、异常处理说清楚,后来就只能靠状态机、补偿逻辑和人工介入去兜底。系统看起来是跑起来了,但每次出问题,都要重新翻旧账。
所以如果你正在设计采购入库这条链路,有一件事比把流程图画漂亮更重要:
把WMS侧、采购侧、仓库侧的人拉到一起,把回传字段、完结规则、异常处理,一条一条对清楚。
复杂不一定是坏事。
但如果复杂的原因是「当初没说清楚」,那就值得停下来重新对一遍。