销售履约

Odoo 发货策略为什么会改掉客户体验:As soon as possible、When all products are ready 与 commitment_date 讲透

很多人把销售单上的 Shipping Policy 当成一个不重要的小选项,但在官方源码里,它会改变预计交付日期的计算方式、stock move 的 deadline 传播方式,以及客户看到的履约体验。本文把这条销售到库存的关键边界讲清楚。

销售
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

Odoo 销售单上的 Shipping Policy,绝对不是“界面上的一个提示字段”。

它真正决定的是:

客户看到的承诺交付节奏,到底是能先到先发,还是必须等齐再发;而 commitment_date 则是在这条规则之上,给系统一个更强的人工承诺时间。

所以这块的本质,不是 UI 选项,而是销售承诺如何压到库存履约层


这篇文章主要参考了哪些源码

核心参考是:

  • /home/ubuntu/odoo-temp/addons/sale_stock/models/sale_order.py
  • /home/ubuntu/odoo-temp/addons/sale_stock/models/sale_order_line.py
  • /home/ubuntu/odoo-temp/addons/sale/models/sale_order.py
  • /home/ubuntu/odoo-temp/addons/sale_stock/tests/test_sale_order_dates.py
  • /home/ubuntu/odoo-temp/addons/sale_stock/tests/test_sale_stock_lead_time.py

最重要的源码信号有三个:

  1. picking_policy 只有两个值:directone
  2. _select_expected_date() 会根据 policy 选最短还是最长 lead time
  3. 如果修改 commitment_date,系统会把 deadline 传播到相关 stock.move

这说明它影响的不是显示文案,而是实际排程语义。


“As soon as possible” 和 “When all products are ready” 到底差在哪

sale_stock/models/sale_order.py 里,picking_policy 的两个选项分别是:

  • direct:As soon as possible
  • one:When all products are ready

很多人第一次看,会以为这只是:

  • 一个允许部分发货
  • 一个要求整单发货

这当然没错,但还不够。

更准确地说,它们在表达的是:

direct

最早可发为导向,让整条履约链尽快启动。

one

整单齐套为导向,宁可等最慢那部分,也尽量给客户一次性交付。

这不是库存团队的小偏好,而是对客户承诺方式的不同选择。


为什么它会直接影响 expected_date

sale_stock/models/sale_order.py 里,_select_expected_date() 很关键:

  • 如果是 direct,沿用默认逻辑,偏向最早可交付时间
  • 如果是 one,取 max(expected_dates)

这意味着当一张销售单里有多条 line、不同产品有不同 lead time 时:

  • direct 更像“先按最快的开始动”
  • one 更像“等最慢的那一项准备好再定义这单的整体交付节奏”

所以 expected_date 不是一个纯展示字段,它是在帮销售表达:

  • 这张单的承诺,是最快启动
  • 还是整单齐发

commitment_date 为什么比 expected_date 更“硬”

sale/models/sale_order.py 里,commitment_date 的帮助文本就写得很直白:

  • 这是承诺给客户的交付日期
  • 如果设置了,就按它来排 delivery order
  • 不再只依赖产品 lead time

再看 sale_stock/models/sale_order_line.py_compute_qty_at_date()

  • 如果订单有 commitment_date,它就优先拿这个日期作为 scheduled_date
  • 如果没有,才回退到 _expected_date()

这说明:

expected_date 更像系统根据 lead time 算出的“自然结果”;commitment_date 则像销售或运营强行盖下去的“业务承诺”。

两者不是重复字段,而是“系统估算”和“人工承诺”的分层。


为什么改 commitment_date 会影响 stock.move

很多人会忽略 write() 里的这段逻辑。

sale_stock/models/sale_order.py 中,如果修改了 commitment_date,系统会:

  • 找出相关订单行的 move
  • 过滤掉 done / cancel
  • 只取目标是 customer 的 move
  • 把它们的 date_deadline 改成新的承诺日期,或回退到 expected_date

这一步非常关键。

因为它说明 commitment_date 不是销售层自娱自乐。

它会继续向下游说:

  • 这张单什么时候答应客户
  • 相关出库动作的 deadline 应该怎么改

也就是说,销售改了承诺日期,库存排程不是“看情况再说”,而是会收到明确的新约束。


为什么前台可用量提示也会跟着变

sale_stock/models/sale_order_line.py_compute_qty_at_date() 里,系统会根据:

  • order_id.commitment_date
  • _expected_date()
  • 再结合 warehouse 分组
  • 批量读取该日期点的库存可用性

这就意味着:

  • 销售单上的承诺日期一改
  • 行上的 scheduled_datefree_qty_todayvirtual_available_at_date 的解释也跟着变

所以很多销售以为自己只是改了一个“给客户看的日期”,其实连前台库存承诺口径都一起变了。


新手最容易误解的 4 件事

1. 以为 Shipping Policy 只是仓库配置

其实它直接影响销售单整体承诺节奏。

2. 以为 one 只是“不允许部分发货”

更准确地说,它是在把整单最慢项定义为这笔交易的节奏锚点。

3. 以为 commitment_date 只是备注

源码明确表明它会影响 schedule 和 move deadline。

4. 以为 expected_date 和 commitment_date 重复

前者偏系统推算,后者偏业务承诺,层级不同。


实战里该怎么选

我自己的判断标准是这样的:

direct 的场景

  • 客户更在意尽快收到第一批货
  • 允许分批交付
  • 订单里存在明显的快慢物料混合

one 的场景

  • 客户更在意一次性交齐
  • 项目交付需要整套到位
  • 分批交付会制造更多沟通成本

用 commitment_date 的场景

  • 销售已经对客户做了明确承诺
  • 需要压过系统自然计算结果
  • 运营要拿它驱动内部履约 deadline

如果这三件事没分清,团队就会经常出现:

  • 客户理解的交付承诺
  • 销售口头承诺
  • 系统排程出来的日期

三套口径彼此打架。


一句话记忆法

Shipping Policy 决定“按最快还是按最慢来承诺”,commitment_date 决定“这次我明确答应客户哪一天”。

DISCUSSION

评论区

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