补货信息

Odoo 补货信息为什么不是“看个预测图”:stock.replenishment.info、lead days 与跨仓补货提示讲透

很多人点开 Odoo 的 Replenishment Information,只把它当成一个“补货图表弹窗”。但官方源码里,它其实把 lead days 拆解、历史出库估算、min/max 曲线以及跨仓补货选项拼到了一起。本文把这个向导真正解决的问题讲透。

库存
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

Odoo 里的 Replenishment Information,不是一个“把预测库存换个图画出来”的小工具。

它更像是:

给 orderpoint 提供一个可解释的补货决策面板。

这个面板同时回答四类问题:

  • 这条补货规则当前为什么会建议补货;
  • 这件货的 lead time 是怎么算出来的;
  • min/max 区间在当前需求速度下大概能撑多久;
  • 如果本仓缺货,别的供给仓有没有 route 可以补。

所以它的核心价值不是“展示”,而是把 orderpoint 这套补货判断解释给人看


为什么很多人会误解它只是预测图

因为界面上最显眼的部分通常是:

  • 一条补货曲线;
  • 一个 lead time 区块;
  • 若干可选补货来源。

看起来像一个 BI 小窗。

但源码顺序告诉你,它不是先画图,再补一些说明;而是先把 orderpoint 的关键判断拆出来,再把这些判断序列化成前端可读 JSON。

也就是说,这个向导的思路是:

  • 先复用 orderpoint 的业务语义;
  • 再把“为什么建议这样补”翻译给用户看。

这和单纯报表完全不是一回事。


入口在哪里:action_stock_replenishment_info()

入口在 addons/stock/models/stock_orderpoint.pyaction_stock_replenishment_info()

它不是直接丢一个通用 dashboard,而是:

  1. 以当前 orderpoint 为上下文;
  2. 创建一条 stock.replenishment.info transient 记录;
  3. 把弹窗标题改成“某产品在某仓的补货信息”;
  4. 打开这个特定 record。

这说明一个非常关键的边界:

补货信息不是独立规划对象,它是 orderpoint 的解释层。

如果没有 orderpoint,这个弹窗也没有稳定的业务锚点。


第一步:它先把 lead days 解释出来

stock_replenishment_info.py 里,_get_lead_days_and_description() 会调用:

  • orderpoint._get_lead_days_values()
  • orderpoint.rule_ids._get_lead_days(...)

然后 _compute_json_lead_days() 再把结果整理成 JSON。

这里最重要的不是“拿到了一个天数”,而是它会尽量保留描述链条

  • 今天是什么时候;
  • lead horizon date 是哪天;
  • 中间每一段延迟是怎么累计出来的;
  • 当前 trigger 是 manual 还是 auto;
  • 当前预测量、建议补货量、min/max 分别是多少。

这层设计很有 Odoo 风格:

  • 业务引擎内部还是规则计算;
  • 但面向用户时,不只给结论,也给解释路径。

所以当用户问“为什么建议今天就下采购”时,这个向导理论上就是给你拆解释链的。


virtual 标记揭示了一个常被忽略的细节

_compute_json_lead_days() 里还有个很容易被忽视的字段:

  • virtual = orderpoint.trigger == 'manual' and orderpoint.create_uid.id == SUPERUSER_ID

这不是无意义的小标记。

它在暗示:

  • 有些 orderpoint 并不是长期维护的正式规则;
  • 它可能是系统为了某些手动补货场景临时产生的“虚拟补货视角”。

换句话说,补货信息向导并不只服务于“长期稳定 orderpoint”,它也能解释某些临时补货上下文。

这正是它和纯静态规则页不同的地方。


第二步:它不是看未来需求,而是用历史区间估算日需求

_get_period_of_time()_compute_json_replenishment_graph() 组成了图表核心。

它支持多种基准区间:

  • 最近 7 天;
  • 最近 30 天;
  • 最近 3 个月;
  • 最近 12 个月;
  • 去年同期 / 下月 / 下下月 / 上年季度。

然后它对 stock.move_read_group() 聚合:

  • location_dest_id.usage = customer 视为发出去的量;
  • location_id.usage = customer 视为从客户退回来的量。

最后用:

  • quantity_out - quantity_returned
  • 再除以天数
  • 再乘上 percent_factor

得到 daily_demand

这说明它做的不是 MRP 那种精细未来计划,而是一种历史驱动的补货速度估算

所以如果业务方把这张图当成“未来订单承诺表”,一定会误解。


这张图真正想表达什么

算出 daily_demand 后,源码会继续:

  • 计算 min/max 差值;
  • 推一个 ordering_period
  • 构造 max 线、min 线、以及锯齿形补货曲线。

这里的图形不是库存事实回放,而是一个策略可视化模型

  • min/max 差距多大;
  • 按当前日消耗速度,大概多久就会从 max 掉到 min;
  • 如果继续按这个节奏补,补货周期会是什么形状。

所以它回答的是:

你的 min/max 设置,在当前需求速度下看起来合不合理。

不是:

未来哪一天一定会剩多少库存。

这个边界非常重要。


为什么它会主动修正 max < min

_compute_json_replenishment_graph() 里,源码直接处理了:

  • 如果 product_max_qty < product_min_qty,就把 product_max_qty 提到 product_min_qty

这不是为了“帮你自动改配置”,而是为了让解释层至少保持自洽。

因为如果 max 小于 min:

  • 图没法画;
  • 补货周期没有业务意义;
  • 用户会看到一套内部矛盾的展示。

这也告诉我们:

  • 补货信息向导是解释器;
  • 解释器会尽量做展示层保护;
  • 但它不能替代你修 orderpoint 配置。

第三步:它把“能从哪里补”也放进来了

很多人没注意到,_compute_wh_replenishment_options() 会根据:

  • orderpoint_id.warehouse_id.resupply_route_ids

为每条 route 创建 stock.replenishment.option 临时记录。

随后每个选项再计算:

  • 对应供给仓的 free_qty
  • 这条 route 对当前产品的 lead_time
  • 如果供给仓可用量不够,给出 warning message。

这一步非常关键。

因为它让补货信息向导不只是“解释为什么缺”,还进一步解释:

  • 如果要补,可能该从哪补;
  • 这些路线里,哪个仓更快、哪个仓量更够。

这就是它比单纯 forecast 报表更实用的原因。


这里的 route 提示为什么不是实际执行结果

stock.replenishment.option 做的是“提示”,不是“承诺”。

因为它只是:

  • 根据 route 找 rule;
  • 算出 free_qty;
  • 算出 lead time;
  • 给出不足提醒。

它没有在这里真正跑 procurement。

真正执行补货动作,还是 orderpoint 或 replenish 逻辑去调用 stock.rule.run()

所以这里的 route 卡片应该被理解为:

面向人类的补货候选解释。

而不是:

系统已经决定一定这么补。


实施里最常见的三个误区

1. 把它当作“未来库存承诺表”

不对。

它基于历史区间和比例因子估算日需求,更偏策略参考。

2. 看到 lead time 就以为采购一定会按这个日期落地

也不对。

lead time 是规则链的计算结果,真实执行还要看:

  • route 命中;
  • 供应商 / 规则完整性;
  • 调度器是否执行;
  • 是否有人手工改过日期。

3. 看到跨仓选项就以为系统会自动改走那条 route

仍然不对。

这个向导只做解释和提示,不在这里直接改补货决策。


调试时应该怎么用这张弹窗

如果你遇到“系统建议补货,但业务觉得不合理”,建议按这个顺序看:

  1. qty_forecastqty_to_order 是否已经偏离认知;
  2. lead_horizon_date 是否被 lead days 拉得过远;
  3. based_onpercent_factor 是否让日需求被放大或缩小;
  4. route 选项里的 free_qtywarning_message 是否暴露跨仓供给问题;
  5. 再回到 orderpoint 本体,看 min/max、route、trigger 是否配错。

也就是说,先用补货信息定位解释层问题,再回到规则层修配置


一句话总结

Odoo 的 stock.replenishment.info 不是一个“漂亮图表弹窗”,而是一个把 orderpoint 补货逻辑拆成:

  • lead days 解释、
  • 历史需求估算、
  • min/max 策略可视化、
  • 跨仓 route 候选提示

可解释补货面板

如果你把它看成简单 forecast 图,就会低估它。

如果你把它看成真实执行引擎,又会高估它。

最准确的理解是:

它站在 orderpoint 与人工判断之间,负责把“系统为什么这样想”翻译出来。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。