先说结论
很多人以为 Fiscal Position 一旦命中,就会把一张发票上的税和科目“整体替换”。
实际上 Odoo 的设计更像:
税映射和科目映射是两条并行但不完全重叠的规则链,它们分别作用在不同类型的行,并在不同阶段介入。
所以你会看到一种很典型的现象:
- 产品收入/费用行换了
- 税行跟着税映射变了
- 但应收应付行不一定按同一逻辑改
这不是不一致,而是分录语义本来就分层。
为什么用户最容易在“整张发票”视角下误解它
在前台,Fiscal Position 往往只表现成一个头部字段。
于是人很容易形成一个错觉:
- 这像一张“整单重映射开关”
但源码不是按“整单”处理的,而是按line type 处理的。
同一张发票里,至少有:
- product/base lines
- tax lines
- payment term lines
- 可能还有 rounding / discount 等辅助行
Fiscal Position 并不会对所有行做同一种映射。
tax mapping 主要改的是税链,而不是所有会计科目
在税计算链里,Fiscal Position 的 map_tax() 负责把原税替换成目标税。
这一步影响的是:
- 发票行使用哪些税
- 随后生成哪些 tax line
- 税 repartition 进一步怎么拆会计行
所以 tax mapping 的真正影响面是:
改税对象,从而改后面整条税分录生成链。
它不直接等于“把所有 journal item 的 account_id 一把重写”。
account mapping 主要改的是基础业务行落账科目
在 account_move_line._compute_account_id() 里,产品行拿科目时,会调用产品账户解析,并把 fiscal position 传进去。
这意味着产品行的收入/费用科目选择,可能在:
- 产品模板账户
- 类别账户
- fiscal position account mapping
共同作用下确定。
所以 account mapping 更像:
重定向 base line 应该记到哪个收入/费用科目。
它首先作用于业务行,而不是自动统治所有派生行。
payment term line 为什么又是另一套边界
payment_term 行的科目不是产品收入/费用科目,而是应收/应付结算科目。
在 _compute_account_id() 中,Odoo 会先根据单据类型选:
- receivable
- payable
再从 partner property、company fallback 等链路拿到账户,最后如果有 fiscal position,再对这个账户执行 map_account()。
这很关键。
因为它说明:
- payment term line 也可能被 fiscal position 映射
- 但它的起点不是产品科目,而是伙伴结算科目
所以你看到“产品行和 payment term 行都变了”,不代表它们在走同一条 account selection 链。
为什么 tax line 也不是简单地“跟 account mapping 走”
税行首先来自 tax mapping 之后的税模型与 repartition 规则。
也就是说,tax line 的存在、金额、税务科目,本来就先受:
- 哪个税被选中
- 税 repartition 如何定义
支配。
所以在思维顺序上,应该理解成:
- Fiscal Position 先可能把税对象换掉
- 新税再通过 repartition 产出 tax line
- tax line 的科目来源是税配置,不是简单复用 base line account mapping
这也是为什么有人会困惑:
- “我都映射了收入科目,税行为什么没跟着变成同一个科目?”
因为 tax line 本来就不该那样工作。
真正容易出错的是“顺序感”
很多实施问题并不是配置错,而是理解顺序错。
比较靠谱的顺序应该是:
- 先确定 fiscal position 是否命中
- 再看税是不是先被
map_tax()替换 - 再看 product/base line 科目是否被
map_account()改写 - 再看 payment term line 的 receivable/payable 科目有没有再被
map_account()改写 - 最后再看 tax line 是由哪套税 repartition 产出的
如果你反过来把所有 journal item 当作一层统一映射,几乎一定越查越乱。
最常见的 4 个误区
1. 以为 fiscal position 只影响税
错。它也会影响某些 account mapping。
2. 以为 fiscal position 会平等影响所有分录行
错。不同 line type 的起点与规则链不同。
3. 以为 tax line 科目来自产品科目映射
错。税行更先受税与 repartition 配置支配。
4. 以为 payment term line 不会被 fiscal position 影响
也不对。它可能被映射,但走的是 receivable/payable 的选科目链。
一句话记忆
Fiscal Position 不是“整单统一换壳器”,而是分别在 base line、tax line、payment term line 上按不同时点和不同起点生效的分层映射器。
DISCUSSION
评论区