采购排错

Odoo 采购异常别只盯一张单:Receipt Status、Invoice Status 与 qty_received / qty_invoiced 的排错顺序

采购单卡在 pending、partial、full、to invoice、invoiced 时,很多人会到处点界面。本文给你一条基于源码字段关系的采购排错顺序。

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

先说结论

采购单出现这些状态时,最容易把人搞乱:

  • receipt_status = pending / partial / full
  • invoice_status = no / to invoice / invoiced

很多人一急,就开始:

  • 在 PO 里翻
  • 在收货单里翻
  • 在 Vendor Bill 里翻
  • 最后越翻越乱

更高效的办法其实是:

不要先按单据找,而要先按“状态是由哪个字段算出来的”去找。

这就是源码式排错。


第一步:先分清 receipt_status 和 invoice_status 根本不是同一层

purchase_stock/models/purchase_order.pyreceipt_status 的计算很直白:

  • 没有 picking,或全取消:False
  • 全部 done/cancel:full
  • 至少有一个 done:partial
  • 否则:pending

也就是说它看的主要是:

  • 收货 picking 有没有生成
  • 这些 picking 现在处于什么状态

它并不直接看账单。

purchase/models/purchase_order.pyinvoice_status,核心是看:

  • 订单状态
  • 各行 qty_to_invoice 是否还非零

所以它盯的是:

  • 还剩多少可开 / 应冲的数量

它并不直接看 picking header 有没有 done。

这两个状态经常同时出问题,但根子未必在同一个地方。


第二步:如果 receipt_status 不对,先查 picking,不要先查账单

如果你觉得“明明收了货,为什么还是 pending / partial”,排查顺序建议这样走:

  1. 这张 PO 有没有 picking_ids
  2. picking 是否都还是 waiting / assigned / done / cancel
  3. 有没有只做了部分回单,导致一些 picking done、一些没 done
  4. 是否存在 return picking,把你直觉里的“已经收完”又冲淡了

因为 receipt_status 本质上是 单头级收货执行状态,不是行级开票状态。


第三步:如果 invoice_status 不对,先查采购行三件套

比起单头,invoice_status 更应该先去看采购行:

  • qty_received
  • qty_invoiced
  • qty_to_invoice

为什么?因为订单头的 invoice_status,其实就是对这些行结果的汇总表达。

你真正要问的不是“PO 为什么显示 to invoice”,而是:

  • 哪一行还有 qty_to_invoice != 0
  • 这个数为什么不是 0
  • 它是正数,还是负数

正数往往意味着还能继续开票;负数往往意味着之前账开多了,该走 refund 语义。


第四步:qty_received 异常时,再往 stock move 层钻

如果产品接了 purchase_stock,采购行的 qty_received 往往不是纯手工值,而是从 move 反推。

这时就要继续问:

  • qty_received_methodmanual 还是 stock_moves
  • 关联 move 有没有 done
  • 有没有采购退货 move 被减回去
  • 有没有 dropship / return 边界导致某些 move 不计入

也就是说:

采购开票问题表面在 PO 行,很多时候根因却在 stock move 的 done 事实。


第五步:别忽略“状态看起来矛盾,其实是正常组合”

这类组合经常把新人吓到,但并不一定有错。

组合一:receipt_status = pendinginvoice_status = to invoice

可能是按订购数量开票。

组合二:receipt_status = fullinvoice_status = no

可能是已经全部开完票,或当前订单状态不再允许继续开票。

组合三:receipt_status = partialinvoice_status = invoiced

如果产品按 ordered quantities 开票,这并不稀奇。

很多“异常感”其实只是你拿错了控制口径。


一个很实战的排错顺序

以后遇到采购卡单,建议就按这个顺序:

  1. 先看是哪种状态异常:receipt 还是 invoice
  2. receipt 异常:先查 picking_ids 和 picking state
  3. invoice 异常:先查 qty_to_invoice 非零的采购行
  4. 行数量异常:再往 qty_received / qty_invoiced
  5. qty_received 异常:最后才钻 stock.move

这样你会比“打开十个页面乱点”快很多。


一句话记忆法

采购排错时,receipt_status 是 picking 执行状态的投影,invoice_status 是采购行可开票数量的投影;先分清投影来源,再查根因。

DISCUSSION

评论区

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