开票控制

Odoo Bill Control Policy 不是小开关:按订购数量还是按收货数量,会把整条采购开票逻辑改掉

很多采购开票问题,根本不是 Vendor Bill 出错,而是 Bill Control Policy 没理解。本文把 ordered quantities 和 received quantities 对状态、数量和异常的影响讲透。

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

先说结论

在 Odoo 里,Bill Control Policy 不是一个“细节配置”,而是采购开票语义的总开关

它至少会决定三件事:

  1. PO 什么时候进入 to invoice
  2. qty_to_invoice 是看订购数量还是看已收数量
  3. 部分收货、退货、超额开票时,系统把异常暴露在哪里

如果你没先看懂这个开关,后面看到的很多现象都会像 bug:

  • 明明没收货,为什么已经能开 Vendor Bill?
  • 明明退货了,为什么开票状态没变化?
  • 明明只收了 5,为什么系统还允许开 10?

这些很多都不是系统乱来,而是 控制策略不同


真正的分水岭就在 qty_to_invoice

核心逻辑在 purchase/models/purchase_order_line.py

  • purchase_method == 'purchase'
  • qty_to_invoice = product_qty - qty_invoiced
  • 否则
  • qty_to_invoice = qty_received - qty_invoiced

别看就两行,这两行基本决定了采购开票世界的两种宇宙。


宇宙一:按订购数量开票

如果产品配置成 ordered quantities,那系统的立场是:

“采购承诺已经成立,就可以按订购数量推进账单。”

这时你很容易看到:

  • PO 已确认
  • invoice_status = to invoice
  • qty_received = 0

这不是穿帮,而是设计如此。

这种模式通常适合:

  • 服务采购
  • 先账后货的商业关系
  • 对实际仓库收货依赖不强的场景

它的好处是应付流程快,坏处是如果后续收货偏差很大,你就得靠退款、补单、人工对账来收尾。


宇宙二:按收货数量开票

如果产品配置成 received quantities,系统立场就变成:

“先有收货事实,再确认账单数量。”

这时 Vendor Bill 能走多远,取决于采购行上的 qty_received

qty_received 在装了 purchase_stock 后,往往又是从 done 的 stock move 反推出来的,不是人手写一个静态数字。

所以这个模式天生更接近:

  • 收货驱动开票
  • 数量约束更强
  • 与三单匹配语义更一致

为什么很多人会把问题误判成“三单匹配坏了”

因为他们看到的是表象:

  • 账单能不能建
  • PO 状态怎么跳
  • 收货没完成时为什么还能付款

但真正先决定这些表现的,常常不是三单匹配按钮,而是:

  • 产品的采购开票控制方式
  • 采购行当前的 qty_received
  • 采购行当前的 qty_invoiced

也就是说:

Bill Control Policy 决定“什么算可开票数量”,三单匹配更多是在这个基础上继续做控制。


退货时,两种策略为什么结果完全不同

Odoo 官方测试把这个差异写得很明白。

按收货数量开票

test_vendor_bill_delivered_return 里:

  • 先收 10、开票 10
  • 再把净收货改成 5
  • qty_to_invoice 直接变成 -5

也就是系统明确告诉你:账已经多确认了。

按订购数量开票

test_vendor_bill_ordered_return 里:

  • 先收 10、开票 10
  • 再把收货改成 5
  • qty_to_invoice 仍然是 0

为什么?因为这一宇宙根本不看 qty_received 作为主计量口径。

这就是为什么同样一件退货事,不同公司、不同产品配置下,后续账务表现会完全不同。


实战排错时先看这 4 个问题

1. 产品是按 ordered 还是 received 开票?

这是总前提。

2. qty_received 是 manual 还是 stock_moves?

不同来源会让排查入口不同。

3. qty_invoiced 里有没有 in_refund

它会把已开票数量减回来。

4. 你遇到的是“不能开票”,还是“开了不该开的票”?

这两类问题往往分别落在不同策略上。


一句话记忆法

Bill Control Policy 决定的不是“按钮显示什么”,而是 Odoo 到底拿订购事实还是收货事实来定义“这笔采购现在还能开多少账”。

DISCUSSION

评论区

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