结论先行
在 Odoo 里,坏账核销不是“把发票改成已结清”,而是:
保留原始应收事实,再新增一条坏账/核销分录,与原发票应收行一起进入 reconciliation,让余额被“对掉”,而不是被“改掉”。
所以真正的关键词不是“清零”,而是:
- 原始发票还在
- 应收行还在
- 只是多了一条对手分录
- 两者通过核销关系闭环
这也是会计系统和普通业务系统最大的区别之一: 状态可以变化,但原始事实不能被偷偷抹掉。
第一层:为什么坏账不能靠手改 residual
很多人第一次做坏账会有这种冲动:
- 客户收不回来了
- 那就把发票余额改成 0
- 或者强行把 payment_state 设成 paid
这在会计设计上是危险的。
因为应收账款本来表达的是:
- 我曾经确认过一笔收入或债权
- 对方本来应该付钱
- 现在这笔钱回不来了
如果你只是把余额手工抹平,系统就只剩一个结果,却丢了过程。
而坏账恰恰最需要保留过程:
- 原来确实有应收
- 后来确认收不回
- 因此转成坏账损失或坏账准备相关处理
所以 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%”。 而是允许你形成三层事实:
- 原始应收 10,000
- 实际付款核销 7,000
- 坏账分录再核销剩余 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
评论区