开票策略误区

Odoo 开票策略为什么最容易在“按订购”与“按交付”之间翻车:invoice policy 的边界误区讲透

很多团队觉得 invoice policy 只是产品上的一个单选项:按订购数量开票,或按交付数量开票。但从源码看,它会直接改写 qty_to_invoice、upselling、费用重计费和服务产品提示语义。本文专门讲清 order vs delivered qty 最容易踩坑的边界。

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

先说结论

在 Odoo 里,invoice_policy 绝对不只是“开票时取哪个数量”这么简单。

它至少会影响:

  • qty_to_invoice 怎样计算
  • untaxed_amount_to_invoice 怎样计算
  • 订单行何时显示 to invoice
  • 订单行何时显示 upselling
  • 服务、耗材、费用重计费分别如何得到 qty_delivered

所以很多项目里真正翻车的点,不是用户不会选“按订购”还是“按交付”,而是:

团队以为自己在切换一个发票偏好,实际上是在切换一整条销售兑现逻辑。


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

核心参考文件包括:

  • /home/ubuntu/odoo-temp/addons/sale/models/product_template.py
  • /home/ubuntu/odoo-temp/addons/sale/models/sale_order_line.py
  • /home/ubuntu/odoo-temp/addons/sale/wizard/res_config_settings.py

最关键的源码信号有:

  • product.template.invoice_policy 只有 orderdelivery
  • sale.order.line._compute_qty_to_invoice() 明确按 policy 走两套数量逻辑
  • _compute_invoice_status() 只有 order 场景才会出现 upselling
  • qty_delivered_method 在基础 sale 中会因 manual / analytic / stock / timesheet 等扩展而变化
  • res.config.settings.default_invoice_policy 只是产品默认值,不会回写历史订单

第一层:invoice policy 是产品属性,不是订单开票模式

很多实施会把开票策略讲成:

  • 这张销售单按订购开票
  • 那张销售单按交付开票

但源码里真正挂这个字段的,是 product.template.invoice_policy

这意味着最先要搞清楚的一点是:

Odoo 默认不是“整张订单统一开票策略”,而是“每个产品自己决定这条销售行怎样进入待开票”。

所以一张订单里完全可能同时出现:

  • 某些行按订购数量开票
  • 某些行按交付数量开票

如果实施方脑子里只有“订单级开票模式”,后面看待开票数量时就特别容易误判。


第二层:qty_to_invoice 才是最核心的行为差异

sale.order.line._compute_qty_to_invoice() 里逻辑很直白:

  • 若产品 invoice_policy == 'order'
  • qty_to_invoice = product_uom_qty - qty_invoiced
  • 否则
  • qty_to_invoice = qty_delivered - qty_invoiced

这就是标准 Odoo 最本质的分叉点。

也就是说:

按订购开票

只要订单确认,系统就可以基于订购量认定“有多少该开票”。

按交付开票

系统先问的不是“卖了多少”,而是“已经被承认为交付了多少”。

这两个世界观完全不同。

前者强调商业承诺。 后者强调履约事实。


第三层:别把 qty_delivered 想成永远来自仓库出库

很多人一看到 delivered quantities,就自动联想到发货。

但基础 sale 里的 qty_delivered_method 已经说明,标准语义并不只属于库存:

  • expense line 可能走 analytic
  • 服务 / 耗材在纯 sale 基础模块里可能是 manual
  • 安装 sale_stock 后,耗材常会走 stock moves
  • 安装 sale_timesheet 后,服务还可能走 timesheet

这就带来一个特别常见的误区:

  • 顾问以为“按交付开票”就一定等着仓库出库单完成

其实不是。 对于不同产品类型与已安装模块,“交付”的事实来源可能完全不同。

所以实施里最该先确认的不是概念,而是:

  • 这类产品的 qty_delivered_method 到底是什么
  • 谁在驱动这个数量增长

第四层:服务产品最容易在这里被误配

product.template 里对服务产品的提示写得很清楚:

  • invoice_policy == 'order' 时,服务是“售出后即可按订购数量开票”
  • invoice_policy == 'delivery' 时,强调的是“基于交付数量,而不是订购数量”

这看起来像常识,但落地时最容易出问题。

因为很多团队卖的是:

  • 固定包服务
  • 预售工时包
  • 后续按实际工时结算的咨询服务
  • 先签单后逐步交付的实施服务

它们虽然都叫“服务”,但商业语义完全不一样。

适合 order

  • 一次性顾问包
  • 固定金额培训
  • 签约即确认收入范围的服务包

更适合 delivery

  • 按工时、按里程碑、按实际完成量结算
  • 需要 delivered quantity 真实驱动开票的服务

如果你只因为“这是服务”就统一选一种 policy,后面不是提前开票,就是永远等不到待开票。


第五层:upselling 只出现在按订购开票,不是按交付开票

_compute_invoice_status() 里有一个非常容易被忽略的分支:

  • 只有当产品 invoice_policy == 'order'
  • qty_delivered > product_uom_qty
  • 才会把状态变成 upselling

这背后的意思很明确:

upselling 在这里不是“你多卖了”,而是“你多交付了,但合同按订购开票,系统提醒你有扩单机会”。

如果本来就是 delivery policy,那么多交付本身就会自然增加可开票数量,不需要靠 upselling 信号提醒。

所以很多人把 upsell 看成 CRM 意义上的销售机会,其实在 sale.order.line 里,它更像是:

  • 一种订单兑现与合同数量不一致的提醒
  • 而且只属于按订购开票的世界

第六层:default_invoice_policy 只是默认值,不会自动修正历史逻辑

res.config.settings 里的 default_invoice_policy 经常被误以为是“公司开票总开关”。

但它真正做的只是:

  • 作为 product.template 的默认值来源

这意味着它不会:

  • 批量改掉历史产品的 invoice policy
  • 回写已经生成的销售订单行逻辑
  • 自动让旧单的 qty_to_invoice 重走另一套规则

所以如果一家企业上线前把默认值设错了,后面再改设置,通常并不能消掉历史混乱。

真正要看的还是:

  • 哪些产品已经是什么 policy
  • 现有订单行在创建时拿到的是什么产品语义

第七层:费用重计费是“按交付开票”最容易被低估的分支

sale 基础模块里,expense line 的 qty_delivered_method 会被设成 analytic

这说明对某些费用重计费场景来说:

  • delivered quantity 不是人工填的
  • 也不是出库单推的
  • 而是从 analytic line 聚合出来的

这类场景最容易踩坑的地方在于,业务人员以为:

  • 我卖的是一个服务产品,怎么“交付数量”还会跟费用、分析行、报销挂在一起?

但源码的答案是:

  • 因为这里的“交付”表达的是可向客户主张的实际消耗事实,不一定非得是物流动作。

如果不了解这层,很多人会在报销重计费时错误地把产品改成 order policy,只为了让发票早点出来,最后把实际消耗与开票边界弄乱。


新手最容易误解的 6 件事

1. invoice policy 是订单级设置

不是,标准字段在产品上,订单行按产品语义运行。

2. 按交付开票就是等仓库发货

不一定,服务、费用、工时都可能有自己的 delivered quantity 计算方式。

3. 改了系统默认开票策略,历史单就会变正常

不会。默认值只影响以后创建的产品/记录。

4. 服务产品都该按订购开票

不对,很多按工时或按实际完成量结算的服务更适合 delivery

5. upselling 跟 CRM 销售漏斗是同一个概念

不是。这里它主要是订单量与交付量错位后的提醒。

6. 按交付开票一定更“严谨”

也不一定。如果你的商业承诺本来就是签约即应开票,硬用 delivery 反而会造成运营摩擦。


实战里我建议怎么选

适合按订购数量开票

  • 固定价格、固定范围、签约即确认收入边界
  • 交付量不需要成为发票前置条件
  • 更在意签约承诺,而不是逐次兑现量

适合按交付数量开票

  • 实际完成量才是结算依据
  • 工时、费用、出库、阶段性交付必须成为开票前提
  • 需要用 delivered quantity 做业务控制

上线前一定要确认的 3 件事

  • 产品的真实结算语义是什么
  • 对应的 qty_delivered_method 会由谁驱动
  • 财务和销售看到的“应开票”是不是同一个业务口径

最后一句话

Odoo 的 invoice policy 设计,其实不是在问“发票喜欢按什么开”,而是在问:

客户的付款主张,到底来自签约承诺,还是来自被系统承认的实际交付。

把这个问题想清楚,orderdelivery 就很好选。 想不清楚,再高级的自动化也会把待开票数量越算越乱。

DISCUSSION

评论区

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