销售单里的承诺交期,很多团队会把它理解成一个“给客户看的日期标签”。
但在 Odoo 里,commitment_date 不是静态备注,而是会一路影响:
- 销售行上的可承诺日期展示;
- 采购/拣货/发货链路的计划日期;
- 出库 move 的
date_deadline; - 安全提前期(security lead)下的实际排产时间;
- 甚至延迟提醒和前台小部件看到的“会不会晚”。
从 /home/ubuntu/odoo-temp/addons/sale_stock/models/sale_order.py 与 sale_order_line.py 看,这条链路比很多人想的紧得多。
一、销售行上的 scheduled_date 并不是拍脑袋算的
sale_order_line.py 里的 _compute_qty_at_date() 把逻辑写得很明确:
- 如果订单有
commitment_date,就把它当作交付日期基准; - 如果没有,就退回
_expected_date()这类预计链路。
也就是说,销售界面上你看到的可用量、预计可供时间、scheduled_date,并不是独立于承诺交期存在的。
承诺交期一改,很多可视化结果都会跟着重算。
二、确认后真正落到供应链的,是 date_deadline 与 date_planned
sale_order_line.py 的 _prepare_procurement_values() 更关键。
它会把:
date_deadline = order.commitment_date or _expected_date()date_planned = date_deadline - company.security_lead
一起塞进后续 procurement / stock rule 使用的 values 里。
这意味着:
date_deadline
更像“这条需求最晚要在什么时候满足”。
date_planned
更像“为了满足那个 deadline,系统应该更早什么时候开始动”。
这里减掉的 security_lead,就是很多企业常说的“给供应链留缓冲”。
所以如果公司配置了 2 天安全提前期,客户承诺 3 月 20 日收货,系统实际就可能按 3 月 18 日去排前置动作。
三、订单已确认后,再改 commitment_date,会直接改 customer 目的地 move 的 deadline
sale_order.py 的 write() 里有一段很实在的逻辑:
- 如果这次改了
commitment_date; - 就把相关、未完成、未取消、且目标位置是 customer 的 move 的
date_deadline一并更新。
这说明 Odoo 的态度不是“交期改了,只改销售单抬头显示”。
而是:
交期变化要同步传导到已经生成的物流需求。
所以你现场看到“销售改了交期,仓库单据日期也变了”,这不是偶然副作用,而是官方源码的明确设计。
四、customer_lead 也会参与这条日期链
同一个文件里,_inverse_customer_lead() 也体现了类似思路:
- 如果订单已经是
sale状态; - 且没有
commitment_date; - 那么改
customer_lead时,会把相关 move 的date_deadline改成date_order + customer_lead。
这说明在 Odoo 里,承诺交期和客户提前期不是两套互不相干的日期字段。
更准确地说:
- 有
commitment_date时,它优先成为目标 deadline; - 没有时,系统退回“订单日期 + customer_lead”的估算模式。
五、为什么前台明明显示“能按时”,仓库却说来不及
这个矛盾常见,原因通常有三类:
1)你看到的是销售行估算,不是完整下游已执行状态
sale.order.line 的小部件会根据 move 预测、forecast、scheduled_date 来展示,但这不等于所有下游动作都已稳定完成。
2)安全提前期改变了内部计划日期
客户看到的是 deadline,仓库实际跟的是更早的 date_planned 语义。
3)已生成的下游单据状态不一致
源码里只会批量改那些未 done、未 cancel、且面向 customer 的 move。已经完成或取消的链路当然不会被重写。
所以现场会出现“有些单跟着变,有些没变”的情况。
六、最常见的几个误解
1)“commitment_date 只是展示字段”
不对。它会参与销售可承诺计算,也会进供应链计划值。
2)“改了承诺交期,系统自然会把所有相关日期都一锅端重排”
也不完全对。源码会改一部分明确目标的 move,但不是神奇地把所有历史动作都重建一遍。
3)“security lead 只是报表字段”
不对。它直接影响 date_planned,也就影响内部动作该提前多久启动。
七、实战里怎么排“交期为什么变了/没变”
我建议按这条线查:
- 订单有没有
commitment_date; - 销售行的
scheduled_date当前是按commitment_date还是按_expected_date()算; - procurement values 里的
date_deadline/date_planned应该是什么; - 公司
security_lead配了几天; - 相关 move 是否已 done/cancel,因此不再参与回写;
- 现场看到的问题到底是销售预测问题,还是实际物流单据问题。
总结
Odoo 里的交期字段,从来不是一个“客户备注”。
从源码看,这条链是连起来的:
commitment_date影响销售行的scheduled_date与预测展示;_prepare_procurement_values()把它转成date_deadline与date_planned;security_lead决定内部计划比客户承诺提前多少;- 订单后续改交期时,相关 customer move 的 deadline 还会被同步更新。
如果只记一句,就记这句:
客户看到的是承诺日期,系统调度看的却是一整条“deadline + 提前量 + 下游 move 回写”的日期链。
DISCUSSION
评论区