项目深度

Odoo 多公司项目为什么不是“项目换个公司就完事”:company、分析账户与任务归属会一起联动

项目多公司场景里,最容易低估的不是权限,而是 company、analytic account、partner 和 task 会彼此牵动。看懂官方测试,才能知道为什么有些项目不能改公司、为什么任务会掉成 private task。

项目
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

Odoo 里的多公司项目,不是给 project.project.company_id 改个值就结束。

如果你去看 /home/ubuntu/odoo-temp/addons/project/tests/test_multicompany.pyaddons/project/models/project_project.py,会发现官方维护的是一组联动约束:

  • 项目公司 company_id
  • 项目分析账户 account_id
  • 客户 partner_id
  • 任务 project.task.company_id
  • 以及用户当前允许访问的公司上下文

所以多公司下最常见的几个“怪现象”其实都很合理:

  • 项目不能改公司
  • 任务跟着项目一起换公司
  • 某个任务改公司后直接脱离项目,变成 private task
  • 分析账户一旦已有分录,项目公司就不能随便挪

本质上,Odoo 在保护的不是表面字段,而是:经营归属、分析口径和权限边界的一致性。


第一层:项目公司不是装饰字段,而是经营边界

在很多实施讨论里,项目的公司字段常被误解成“主要用来筛选视图”。

实际上不是。

从测试可以看出,项目公司至少影响三类事情:

  • 用户是否有权创建 / 修改该项目
  • 分析账户的公司是否要同步
  • 项目下任务的公司归属是否要重算

这说明 company_id 是经营边界,不是皮肤设置。

所以当用户说:

这个项目其实应该放到 B 公司,直接改一下吧

你真正需要问的是:

  • 它已经挂了分析账户吗?
  • 这个分析账户有分录吗?
  • 这个账户是否被多个项目共用?
  • 下面任务是否已经形成了别的公司归属?

第二层:为什么分析账户会把项目公司“钉住”

project_project.py_compute_company_id_inverse_company_id 很值得反复看。

官方明确表达了一个原则:

  • 如果分析账户有公司,项目通常要跟着这个公司走
  • 如果你想把项目公司改掉,但分析账户已有分析分录,或者被多个项目共用,系统会阻止

原因其实非常朴素:

1. 分析账户代表的是经营归属

项目不是孤立对象,它背后往往连接:

  • 工时
  • 成本
  • 收入
  • 利润分析

一旦这些东西已经发生,再硬改公司,就等于改经营口径。

2. 一个账户挂多个项目时,不能允许单边漂移

如果同一个 analytic account 绑了多个项目,你把其中一个项目挪到别的公司,就会破坏“一套分析账对应一个一致归属”的前提。

所以系统报错,不是死板,而是在防止经营数据变脏。


第三层:为什么任务会跟着项目改公司

多公司测试里有个很容易被忽视的重点:

  • 给任务设置项目时,任务公司会被自动对齐到项目公司
  • 移动任务到另一个项目时,任务公司也会切换
  • 父任务换项目时,子任务公司也会跟着联动

这说明在 Odoo 看来:

项目任务默认不是独立经营实体,而是项目边界下的执行记录。

因此大多数情况下,任务公司应该继承项目,而不是各玩各的。

这也是为什么“任务换项目”从来不只是 UI 上换个 Many2one,它会带着公司语义一起重算。


第四层:为什么任务一改单独公司,可能直接掉成 private task

这是很多人第一次看到会震惊的行为。

测试里明确验证了:

  • 如果项目已有公司
  • 你把任务手工改成另一个公司
  • 这个任务可能会脱离项目,变成 project_id = False 的 private task

为什么?

因为系统必须在两个事实之间选一个:

  • 任务属于项目
  • 任务属于另一个公司

当这两个事实冲突时,Odoo 选择保留公司一致性,而不是保留“挂在项目下面”的表象。

这其实很合理。

否则你会得到一种更糟糕的数据:

  • 名义上挂在 A 公司项目下
  • 实际上任务属于 B 公司
  • 权限、统计、分析、过滤全部混乱

所以它宁可把任务打回 private,也不允许这种混挂长期存在。


第五层:partner 也是约束链的一部分

还有一个很常被忽略的约束:

  • 如果项目或任务绑定了有公司归属的 partner
  • 那么 company 不能随便和 partner.company_id 冲突

这背后的思路很一致:

  • 客户归属要对
  • 项目归属要对
  • 分析账户归属要对
  • 任务归属也要对

只有这样,客户维度、公司维度和利润维度才不会打架。


第六层:多公司排错时,最有效的顺序是什么

如果你遇到:

  • 改项目公司报错
  • 项目创建后 company 不如预期
  • 任务移动后公司变了
  • 任务突然不在项目里了

建议按这个顺序查:

1. 先看用户允许的公司上下文

很多“不能操作”并不是模型限制,而是当前用户根本不在 allowed_company_ids 里。

2. 再看项目的分析账户

确认:

  • 是否已有 account_id
  • 账户公司是谁
  • 是否已有 analytic lines
  • 是否被多个项目共用

3. 再看 partner 是否带公司

客户如果本身带公司限制,会把项目和任务的可改动空间进一步收紧。

4. 最后看任务是不是因为公司冲突被打成 private

这一步尤其容易在“手工改任务公司”或“跨项目移动子任务”时出现。


实施建议:不要把“调公司”当日常修数据手段

很多团队上线后,会把 company 当成一个可随时修正的普通字段。我的建议是别这么干。

更稳的做法是:

  • 新建项目前先确认所属公司
  • 分析账户策略先定清楚
  • 尽量避免多个公司之间“先做后改归属”
  • 真要迁移,先评估 analytic lines 和项目共享关系

否则你修的不是一个字段,而是在撬一整条经营链路。


最后一句

多公司项目的复杂点,不在权限本身,而在 Odoo 很清楚地知道:

项目不是孤立卡片,而是分析、客户、任务和经营归属的交汇点。

所以当系统不让你随便改公司时,通常不是在为难你,而是在阻止后面更难收拾的数据错位。

DISCUSSION

评论区

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