先说结论
在 Odoo 里,库存分配最关键的一条主链路就是:
stock.picking.action_assign()stock.move._action_assign()stock.quant相关预留逻辑
如果你想搞懂“为什么这张单据能分配成功”“为什么生成这些 move line”“为什么这批货从这个 lot 出”,就必须把这条链路看透。
第一步:picking.action_assign()
这是单据层入口。
它做的事情并不复杂,核心就是:
把当前 picking 下面需要处理的 move 找出来,然后让这些 move 去做库存分配。
所以它本身不是库存算法中心,而是一个“调度入口”。
你可以把它理解成:
- picking 负责组织任务
- 具体怎么分货,交给 move
第二步:move._action_assign()
真正的核心从这里开始。
_action_assign() 通常会处理这些事:
- 当前 move 还差多少没预留
- 这个 move 是否需要绕过 reservation
- 它是普通 MTS 还是 MTO
- 有没有上游 move 限制
- 应该从哪里找可预留库存
也就是说,这一步是在做:
“我要不要分?还要分多少?我可以从哪儿分?”
第三步:算缺口
通常代码里会先计算还缺多少:
- 计划数量是多少
- 已经预留了多少
- 当前还差多少
这个差值决定接下来 quant 层到底要不要继续找货。
如果已经够了,那就不用继续。 如果还差,就进入 quant 预留流程。
第四步:quant 层找货
当 _action_assign() 决定要继续预留时,接下来最关键的事情就是:
去
stock.quant里找符合条件的可用库存。
这里通常会涉及:
- 产品
- 源库位
- lot
- package
- owner
- strict 模式
- removal strategy
所以 quant 层更像一个“库存筛选器 + 分配器”。
第五步:按移除策略排序
就算你找到了很多 quant,也不表示都可以随便拿。
Odoo 还会考虑仓库或库位上的移除策略,比如:
- FIFO
- LIFO
- closest
- least packages
这一步本质上在回答:
“如果多个 quant 都能拿,先拿谁?”
这也是你排查“为什么系统不是按我想的顺序分货”的第一站。
第六步:生成 move.line
当 quant 层确定可用库存后,Odoo 就会把结果拆成一个或多个 stock.move.line。
拆分维度通常包括:
- location
- lot
- package
- owner
所以你在界面上看到的详细作业,其实就是 quant 分配结果的展开形式。
为什么这条链路最值得死磕
因为库存问题里最常见的问法,几乎都能回到这条链路:
- 为什么不能分配?
- 为什么只分了一部分?
- 为什么从这个 lot 出?
- 为什么 move 没有 line?
- 为什么 line 拆成多条?
本质上都是:
- move 怎么判断缺口
- quant 怎么找货
- line 怎么拆出来
建议你怎么读源码
最有效的方式不是一口气把整个 stock 模块看完,而是抓主线:
- 先从
picking.action_assign()看起 - 跳到
move._action_assign() - 再进入 quant 的查找与预留
- 最后再回来看 move line 生成
你要的不是“全部看懂”,而是先把骨架搭起来。
实战排查时怎么用
以后你碰到库存问题,可以按这条顺序排:
- picking 有没有触发 assign
- move 还缺多少
- move 的源库位对不对
- quant 里有没有可用库存
- removal strategy 有没有影响顺序
- move line 是怎么拆出来的
只要按这个顺序排,大部分问题都不会迷路。
总结
Odoo 库存预留最关键的主链路,不在 picking 层,而是在:
- move 怎么判断需要分多少
- quant 怎么决定从哪拿
- move line 怎么把结果落地
所以真正要学透库存分配,核心就是把 _action_assign() 这条主链路读通。
DISCUSSION
评论区