先说结论
在 Odoo 里,Outstanding Account 不是银行科目的另一个名字。
它更像是在表达:
这笔钱已经进入“付款事实已发生”的状态,但还没有完成银行层面的最终落账。
所以“登记付款”与“银行已经到账 / 已出账”在标准流程里是两层语义。
为什么系统要多这一层
很多人会问:
- 收到客户付款了,不就直接借银行、贷应收吗?
- 付供应商钱了,不就直接贷银行、借应付吗?
现实里问题没这么理想。
因为会计系统经常要面对:
- 钱已经发起,但银行流水还没对上
- 第三方通道需要几天清算
- 会计人员先登记付款,再等对账员认流水
这时如果系统一上来就直接冲银行科目,会把“付款已发起”和“银行已结清”混成一件事。
Odoo 不愿意这么做,于是用了:
outstanding receiptsoutstanding payments
把中间层显式建模出来。
源码里这层是怎么体现的
/home/ubuntu/odoo-temp/addons/account/models/account_payment.py 的 _prepare_move_line_default_vals() 很关键。
官方在生成付款分录时,默认先造两类核心行:
- 一条 liquidity line,但落到
outstanding_account_id - 一条 counterpart line,落到 receivable / payable
这里最重要的不是“有两条分录”,而是:
- 流动性那条先不一定去银行默认科目
- 它先进入 outstanding account
也就是说,付款动作先确认“钱在路上”。
然后在 account_move.py 里,invoice 的 outstanding widget 会去搜索 partner 下尚未核销、可用于匹配的行,最终通过 js_assign_outstanding_line() 这种入口把发票和这些待匹配项接上。
这说明 UI 上看到的“Outstanding credits / debits”并不是前端装饰,而是后台真实会计行的投影。
为什么登记付款不等于银行余额已正确
这正是 Outstanding Account 最容易被误解的地方。
登记付款后,系统通常已经表达了两件事:
- 发票有了一个可核销的付款事实
- 应收应付开始减少或进入
in_payment / paid语义
但还没完全表达第三件事:
- 银行流水是否已经真实匹配
所以标准流程会把“付款登记”和“银行对账结清”拆开。
拆开之后的好处很大:
- 财务可以先确认业务动作
- 出纳 / 对账员可以晚一点认银行流水
- 系统能清楚区分在途与已清算
为什么有时 outstanding account 可以看起来像银行科目
源码里也留了弹性:某些配置下,outstanding account 可能和 journal default account 靠得很近,甚至在特殊实现里表现得像直接进银行。
但这不改变它的设计本义。
本义仍然是:
先把付款事实与最终银行结清拆开。
所以别因为某个项目配置简单,就把 outstanding 误解成“只是银行科目别名”。
新手最容易误解的 4 件事
1. 以为 Register Payment 就代表银行已到账
不一定。很多时候只是进入 outstanding 层。
2. 以为 Outstanding Widget 只是界面提示
不是。背后对应的是真实未核销 journal items。
3. 以为 outstanding account 一定等于银行科目
不是。标准设计里它往往就是过渡层。
4. 以为发票已 paid 就表示银行对账一定完成
不一定。要看具体配置与 reconciliation 流程。
实战排查顺序
如果用户说“为什么钱收了但银行科目没动 / 为什么还有 outstanding”,建议这样查:
- journal 和 payment method 上的 outstanding account 配置
- 付款分录实际落到了哪个 account
- 发票与付款是否已核销
- 银行流水是否已经和 outstanding line 完成对账
- 是否启用了直达银行科目的简化配置
一句话记忆法
Outstanding Account 不是银行别名,而是 Odoo 用来表达“付款事实已发生,但银行结清还没最终确认”的中间层。
DISCUSSION
评论区