销售预付款

Odoo 预付款发票为什么不是“先开一张钱”:Down Payment、is_downpayment 和最终扣减到底怎么串起来

很多人把 Odoo 预付款理解成先开一张金额发票,但在销售链里它其实有独立行语义、专门向导和最终扣减逻辑。本文把它讲透。

Odoo 开发 会计 销售
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

Odoo 的 Down Payment 不是“提前随便开一张金额票”。

它真正表达的是:

在正式交付和最终结算之前,先为销售订单建立一笔有明确来源、可被后续抵扣的预收款语义。

所以预付款不是插队开票,而是先行结算的一段销售金额


为什么它不是普通发票行

源码里你会看到:

  • sale.advance.payment.inv 向导
  • sale.order.line.is_downpayment
  • account.move._is_downpayment()
  • 最终发票里对 down payment 的单独处理

这说明 Odoo 并不是把预付款混在普通销售行里,而是给它一整套独立语义。

也就是说,系统想明确知道:

  • 哪些行是正式销售内容
  • 哪些行只是预付款
  • 到最终结算时该怎么把两者对上

为什么要有 is_downpayment

sale.order.line 上的 is_downpayment 很关键。

它不是一个装饰标签,而是在告诉系统:

这条销售行不是正常交付行,而是一条为了预付款开票而存在的特殊结算行。

这会影响:

  • 是否参与正常可开票金额逻辑
  • 是否单独分组显示
  • 最终发票时如何扣减

所以预付款不是“假装卖了个服务产品”这么简单,尽管表面上它常常落在一个 Deposit 产品上。


向导为什么不是多余的

sale.advance.payment.inv 向导会要求你选:

  • 固定金额
  • 百分比
  • 是否扣减历史 down payment

这说明 Odoo 把预付款设计成一种可控的开票策略,而不是一条死规则。

它要解决的问题包括:

  • 先收 30%
  • 先收固定 1 万
  • 最终开整单时,把已收部分扣掉

所以这个向导本质上是在帮你决定“这次预收款要怎么切进销售单”。


为什么最终发票里会单独出现预付款区块

sale_order.py 里,官方会把 down payment 行和普通行分开处理,甚至创建专门 section。

这背后的含义非常明确:

预付款虽然属于这张销售订单,但它和实际交付内容不是同一种东西。

最终开票时,系统会:

  • 展示已发生的 down payment
  • 再对正式应开金额做扣减

所以预付款不是重复收费,而是提前计收、最终抵扣。


新手最容易误解的 4 件事

1. 以为预付款就是随便开一张金额票

其实它必须回挂销售单,并可被后续结算识别。

2. 以为 down payment 行和普通销售行一样

它有独立语义和扣减逻辑。

3. 以为最终发票要手工减掉预付款

Odoo 本来就有自动处理这条链的设计。

4. 以为预付款开票就等于交付完成

预付款只解决先收款,不代表交付语义已经完成。


一句话记忆法

Down Payment 不是先乱开一张票,而是先把销售金额的一部分独立结算出来,并在最终发票时按规则扣回去。

DISCUSSION

评论区

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