人力资源

Odoo 组织架构为什么不怕“经理的经理又回到自己”:看懂递归下属、经理环路与 org chart 边界

很多人以为组织架构树只要 parent_id 一路往下展开就行。Odoo 的 hr_org_chart 明显想得更远:它既要展示直接下属,也要算间接下属,还要防止“CEO 属于某部门、部门又层层回指 CEO”这种递归环路把统计搞炸。源码真正做的是一个可容错的层级遍历器。

人力资源
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

Odoo 的组织架构图并不是“拿 parent_id 递归展开一下”这么简单。

hr_org_chart 源码真正解决的是两个同时成立的问题:

  • 你要能看到 直接下属间接下属
  • 你又不能因为现实组织里出现回环、兼岗、跨部门挂靠,就把整棵树算死循环

所以它的关键不是树形展示,而是:

在不完全理想的数据里,尽量稳定地算出‘谁属于谁的下属链’。

第一层:组织图展示的从来不只是 child_ids

hr_org_chart 扩展里,除了原本的 child_ids,还新增了:

  • subordinate_ids
  • child_count
  • child_all_count
  • is_subordinate

这已经说明官方不是只关心“一层直属关系”,而是同时关心:

  • 当前人有多少直属下属
  • 整个下属链总共有多少人
  • 当前登录用户是不是某人的上级链条中的一环

如果只靠简单的 one2many 展开,这些都很难稳定算对。

第二层:_get_subordinates() 的核心不是递归,而是“递归时记住已经走过谁”

/home/ubuntu/odoo-temp/addons/hr_org_chart/models/hr_org_chart_mixin.py 里的 _get_subordinates() 很值得看。

它在递归过程中维护了一个 parents 集合,并且每次计算直属下属时,会先做:

  • direct_subordinates = self.child_ids - parents

这一步非常关键。

它等于在说:

  • 当前节点的直属下属里
  • 如果已经在上游路径里出现过
  • 就不再继续往下算

换句话说,Odoo 防的不是“没有树”,而是“现实里的层级未必是一棵纯净无环树”。

第三层:为什么官方注释会直接提 CEO/CTO 互相绕回的场景

源码注释举了一个很现实的例子:

  • CEO 管所有人
  • 但 CEO 又可能是某个研发部门成员
  • 研发部门又由 CTO 管
  • CTO 又向 CEO 汇报

这类数据在企业里不算少见,尤其在:

  • 矩阵组织
  • 临时项目挂靠
  • 兼岗管理
  • 历史数据迁移

如果你把组织架构强行当纯树,一旦出现这种回路,间接下属统计、可见性判断、组织图接口都会被拖垮。

第四层:child_countchild_all_count 为什么要分开

child_count 是直属下属数量,child_all_count 是全链路数量。

这两个数字分开,不只是为了 UI 好看,而是因为它们服务的决策不同:

  • child_count 更接近真实带人跨度
  • child_all_count 更接近影响范围或组织深度

如果只保留一个总人数,很多管理视图会误导。

比如一个 VP 可能直属只带 4 个人,但全链路覆盖 150 人;一个 Team Lead 可能直属带 9 人,但没有二级下属。两者管理结构完全不同。

第五层:is_subordinate 为什么要按当前用户算,而不是全局字段

is_subordinate 的计算依赖当前用户的 employee 记录。

也就是说,某员工是不是“我的下属”,不是全局真值,而是 相对于当前登录人 的结果。

这很重要,因为组织图除了展示,还有访问与筛选用途:

  • 哪些人应该在我的团队列表里
  • 哪些审批或管理入口对我可见
  • 哪些统计该按我的管理半径展开

所以这是一个“相对关系字段”,不是静态标签。

第六层:为什么组织图问题经常不是前端 bug,而是层级数据脏了

很多实施遇到的问题是:

  • 组织图人数不对
  • 某人下属重复
  • 某位经理看到了不该看到的人

第一反应往往是怀疑前端组件。

但按源码设计,更多时候应该先查:

  • parent_id 有没有形成环
  • 员工是否同时被挂到多个异常链路
  • 历史离职/返聘记录有没有造成层级残留
  • 用户自己的 employee_id 是否正确

因为只要底层层级关系脏了,再漂亮的组织图都只能把脏数据画出来。

最容易踩的 4 个坑

1)把 parent_id 当成唯一真相

实际企业里的“汇报对象”和“组织归属”并不总是一回事。

2)假设层级永远无环

源码都专门防了,你就别在实施里当它绝不可能发生。

3)只看直属人数,不看全链路人数

这会误判管理跨度。

4)把组织图异常全部甩给前端

多数问题要回到员工层级数据本身排查。

排错顺序

  1. 先查目标员工的 parent_id
  2. 再查上级链是否形成回路
  3. child_idssubordinate_ids 是否逻辑一致
  4. 用当前登录用户视角核对 is_subordinate
  5. 最后再看前端组织图渲染

最后一句话

Odoo 的组织架构不是在画一棵完美的树,而是在脏现实里尽量稳定地维护一条上下级链。懂了这一点,你就知道问题通常出在层级建模,而不是图本身。

DISCUSSION

评论区

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