先说结论
Odoo 的采购建议补货不是“库存负了就补一点”那么简单。
在 purchase_stock 里,系统会综合看:
- 你用哪种建议模式;
- 最近一段时间的真实需求;
- 当前现货;
- 已在途数量;
- 甚至草稿、已发送、待审批 RFQ 里的采购量。
所以建议值的本质不是一个静态库存规则,而是:
在当前仓库和供应商语境下,对“未来缺口”做的一次近似预算。
第一步:suggested_qty 有两套完全不同的思维模式
_compute_suggested_quantity() 先看 context 里的 suggest_based_on。
模式一:actual_demand
这时系统主要盯着 virtual_available。
如果虚拟可用量已经小于 0,就把缺口按 suggest_percent 放大或缩小,然后向上取整。
它更像一种“立刻补洞”的思路:
- 你现在就不够;
- 那先把眼前缺口补上。
模式二:按周 / 月 / 季 / 年历史需求估算
如果不是 actual_demand,系统会先算 monthly_demand,然后:
- 用
suggest_days算出要覆盖多少月份比例; - 再乘
suggest_percent; - 最后扣掉
qty_available + incoming_qty。
这是一种“需求覆盖天数”思路,不再只是盯当前缺货,而是问:
- 未来一段时间可能要消耗多少;
- 现有库存和在途能覆盖多少;
- 剩下的缺口值不值得补。
这两种模式差别很大。
一个偏救火,一个偏预算。
第二步:月需求不是凭空猜,而是从 stock move 历史读出来的
_compute_monthly_demand() 会根据 suggest_based_on 先决定时间窗,比如:
- 最近 30 天;
- 最近 1 周;
- 最近 3 个月;
- 最近 1 年;
- 去年同期 / 去年季度。
然后用 stock.move._read_group() 汇总在这段时间里发生的出货 / 生产消耗相关移动。
默认 location domain 也很有意思,它会把需求理解成:
- 去 customer;
- 去 production;
- 或从一个仓库流向别的仓库。
同时,它明确排除某些回库和 scrap 干扰。
也就是说,Odoo 想估的是“真正把货往外消耗掉的流量”,而不是所有库存变动。
这就是为什么建议补货经常和你肉眼看的单纯出库数不完全一样。
它在刻意逼近“消耗”,不是所有 movement。
第三步:在途量不只看 incoming picking,还把未落单完成的采购承诺算进来
很多人会以为“in progress”只等于已生成入库单。
但 _get_quantity_in_progress() 不是这么算的。
它先调用父类拿基础在途,再额外把采购单行聚合进来。筛选域来自 _get_lines_domain(),会把这些状态纳入:
draftsentto approve
也就是说,只要采购承诺已经形成,即便还没正式变成完成中的收货,也会被视为一种在途信号。
这非常符合采购管理现实。
因为补货决策不该只看“已经发车的货”,还要看:
- 已发 RFQ;
- 正在审批;
- 其实已经有人准备下单。
否则多个采购员很容易在同一个缺口上重复补货。
第四步:为什么同一个产品在不同仓库里建议值会不一样
_get_monthly_demand_moves_location_domain() 和 _get_lines_domain() 都支持 warehouse / location 语境。
所以系统不是在算一个公司级的全局数字,而是在尽量贴近:
- 这个仓;
- 这个补货点;
- 这个最终目的地。
这点尤其重要,因为现实里最容易踩坑的是:
- 总库存看着够;
- 但某个仓其实已经断货;
- 另一个仓的在途不一定能及时支援;
- 同产品在不同仓库的需求曲线完全不一样。
如果你不带仓库语境理解 suggested_qty,就很容易觉得系统“算错了”。
实际上它通常是在算另一个粒度。
第五步:action_set_supplier() 不只是选个 vendor,还会顺手修补采购路线和最小起订量
很多人把“Set Supplier”理解成给补货规则换个供应商。
但源码里它顺手做了两件很关键的事:
1. 如果 orderpoint 当前 route 不是 buy,会自动补一条 buy route
也就是说,系统不只改主数据,还会顺手把“能不能按采购补货”这条路径接上。
2. 如果建议补货量低于供应商最小起订量,会把 qty_to_order 抬到供应商门槛
这说明 Odoo 的立场很明确:
补货建议不是纯库存学问题,它必须尊重供应商交易条件。
所以你看到点了 Set Supplier 之后建议数量突然变大,不一定是 bug,而是供应商 min_qty 被真正纳入了补货结果。
最容易误解的 5 个点
1. 以为 suggested_qty 只由当前缺货决定
错。很多模式下它是按历史需求窗口推算的。
2. 以为 incoming_qty 已经足够代表“在途”
错。采购草稿、已发送 RFQ、待审批采购也可能被算进 in progress。
3. 以为月需求就是最近出库总数
不完全是。系统会按 location 语义过滤,只抓它认为代表真实需求的流量。
4. 以为 Set Supplier 只改供应商字段
错。它还可能自动补 buy route,并把数量抬到最小起订量。
5. 以为 suggested_qty 在所有仓库都应该一样
错。仓库 / 补货点上下文本来就会改结果。
实战排错顺序
如果补货建议看起来“不合理”,建议按这个顺序看:
- 当前
suggest_based_on是 actual demand 还是历史窗口; suggest_days和suggest_percent设置了什么;- 有没有 warehouse / location context;
- 草稿 RFQ、待审批采购是否已被算进 in progress;
- Set Supplier 后是不是触发了 min_qty 或 buy route 补全。
一句话记忆法
Odoo 的采购建议补货不是“看库存”,而是“按需求窗口、在途承诺和供应商约束一起估缺口”。
DISCUSSION
评论区