坏账核销

Odoo 坏账核销为什么不是把发票余额“手改成 0”:write-off、核销关系和坏账分录边界讲透

很多人做坏账时第一反应是把发票标成已付清,或者直接把 residual 改掉。但从 Odoo 的会计设计看,坏账核销本质上是新增一条对手分录并参与核销,而不是篡改原始应收事实。

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

结论先行

在 Odoo 里,坏账核销不是“把发票改成已结清”,而是:

保留原始应收事实,再新增一条坏账/核销分录,与原发票应收行一起进入 reconciliation,让余额被“对掉”,而不是被“改掉”。

所以真正的关键词不是“清零”,而是:

  • 原始发票还在
  • 应收行还在
  • 只是多了一条对手分录
  • 两者通过核销关系闭环

这也是会计系统和普通业务系统最大的区别之一: 状态可以变化,但原始事实不能被偷偷抹掉。


第一层:为什么坏账不能靠手改 residual

很多人第一次做坏账会有这种冲动:

  • 客户收不回来了
  • 那就把发票余额改成 0
  • 或者强行把 payment_state 设成 paid

这在会计设计上是危险的。

因为应收账款本来表达的是:

  • 我曾经确认过一笔收入或债权
  • 对方本来应该付钱
  • 现在这笔钱回不来了

如果你只是把余额手工抹平,系统就只剩一个结果,却丢了过程。

而坏账恰恰最需要保留过程:

  1. 原来确实有应收
  2. 后来确认收不回
  3. 因此转成坏账损失或坏账准备相关处理

所以 Odoo 更符合会计常识的做法,一定是新增一条对手分录,而不是改写原发票本身。


第二层:write-off 在源码里表达的到底是什么

/home/ubuntu/odoo-temp/addons/account/models/account_payment.py 可以看到,Odoo 在付款分录准备阶段会显式处理 write_off_line_vals

源码的意思很直白:

  • 正常付款会有 liquidity line
  • 会有 counterpart line
  • 如果存在额外差额处理,还可以再加 write-off line

并且 _seek_for_lines() 还会把一张 payment move 里的行拆成三类:

  • 流动资金行
  • 应收/应付对手行
  • write-off 行

这说明在官方设计里,write-off 不是修改原应收行的属性,而是作为一条独立会计行存在

这个思路放到坏账核销上就很好理解了:

  • 发票那条应收行保留原貌
  • 你新增一条落到坏账科目或相关处理科目的分录
  • 让这条新分录去跟原应收做核销

这样账面就既能看到“原来欠过多少钱”,也能看到“后来为什么不欠了”。


第三层:坏账核销的本质其实是 reconciliation,不是标签切换

很多人把坏账理解成一种“状态”。

但在 Odoo 源码视角下,它更像一种匹配关系的完成

为什么?

因为发票是不是还欠钱,不是靠文字说明决定的,而是靠应收应付行的 residual 与 reconcile 关系决定的。

你可以把它想成这样:

  • 发票先产生一条应收行
  • 后续如果客户真的付款,就由付款分录去匹配它
  • 如果客户不付款但公司决定核销,就由坏账分录去匹配它

两种路径不同,但底层共同点一样:

都是通过对手分录去消化原来的应收余额。

这就是为什么坏账核销和真实收款,在技术结构上会有某种相似性: 它们都不是“改发票”,而是“给发票找一个会计上的对手方”。


第四层:为什么坏账核销后还能看出它不是正常收款

这也是 Odoo 这种设计特别好的地方。

如果你只是把发票改成 paid,看起来像是“钱收到了”。 但坏账根本不是收到了钱。

它应该表达的是:

  • 应收不再挂着
  • 但不是因为银行进账
  • 而是因为公司决定将其核销为损失或其他指定处理

只要你采用“新增 write-off / adjustment line + reconciliation”的结构,报表和审计链路就能保留差异:

  • 正常收款走银行/现金方向
  • 坏账核销走损失或准备方向

两者最后都可能让发票 residual 归零, 但为什么归零,在会计分录结构里是一眼能看出来的。


第五层:为什么部分坏账比全额坏账更能看出设计价值

如果一张发票 10,000 元,客户只付了 7,000 元,剩下 3,000 元确认收不回:

这时最容易看出 Odoo 设计的好处。

系统不是在原发票上直接写一句“已收 70%,坏账 30%”。 而是允许你形成三层事实:

  1. 原始应收 10,000
  2. 实际付款核销 7,000
  3. 坏账分录再核销剩余 3,000

最终 residual 归零,但轨迹完整保留。

这比“把发票状态直接改掉”强太多了,因为它支持:

  • 对账
  • 审计
  • 坏账统计
  • 历史追溯

常见误区

误区 1:坏账核销就是把发票标成 paid

不是。 paid 更像“已经被会计对手分录完全消化”,但这个对手分录未必是收款。

误区 2:write-off 就是把原始行改写

不是。 write-off 的设计重点正是“新增一条独立行”。

误区 3:坏账核销会让原发票失真

恰恰相反。 正因为不去改原发票,原始事实才更清楚。

误区 4:只有银行对账才需要 reconcile

错。 坏账核销本质上同样要靠 reconciliation 关闭应收应付余额。

误区 5:只要 residual 变成 0,路径就无所谓

非常危险。 会计上最重要的不是只有结果,还包括“是怎么到这个结果的”。


实战判断顺序

遇到坏账处理需求时,可以按这个顺序想:

1. 先问:原发票应收事实要不要保留

答案几乎总是要保留。

2. 再问:这次是正常收款、折让、退款,还是坏账

别把不同业务后果用同一个按钮强行解决。

3. 再确认:你新增的对手分录落在哪个科目

这是会计含义的核心。

4. 再看:最终是部分核销还是全额核销

不同场景对应不同 reconciliation 结果。

5. 最后才看发票界面状态

状态只是结果呈现,不是会计动作本身。


一句话记忆法

坏账核销不是把应收改没,而是给原应收补上一条坏账对手分录,再通过 reconciliation 把它关掉。

DISCUSSION

评论区

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