You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Odoo 13中实现员工全层级下属自动填充至Many2many字段?

Odoo 13员工档案全层级下属Many2many字段计算方案

问题背景

在Odoo 13员工档案模块中,需实现:

  • 新增Many2one字段关联员工自身(上级),配套One2many字段reportee_ids关联直接下属
  • 新增Many2many字段employee_child_ids,自动填充当前员工的所有层级下属(含子级、孙级等)

员工层级结构

A      B       C        D
       |      |       |        |
      / | \ / | \   / | \      / \
     E  F G H I  J  K L M     N   O
    /|\  /|\          |       /\
   P Q R S T U        V       W X

预期效果

  • A的employee_child_ids:E,F,G,P,Q,R,S,T,U
  • B的employee_child_ids:H,I,J
  • C的employee_child_ids:K,L,M,V
  • E的employee_child_ids:P,Q,R
  • N的employee_child_ids:W,X

现有代码缺陷

原代码逻辑方向错误(从下往上递归)、数据处理混乱、错误操作关联用户记录,无法实现需求:

reportee_ids = fields.One2many('hr.employee','reporting_officer_id',string="Reportees")
employee_child_ids = fields.Many2many('hr.employee')

def compute_reportees(self,emp,list1=None):
    rm_id = emp.reporting_officer_id
    if list1 is None:
        list1 = []
    if emp.id != rm_id.id:
        list1 += emp.reportee_ids.ids + rm_id.reportee_ids.ids
        rm_id.user_id.write({'employee_child_ids':list1})
        self.compute_reportees(rm_id,list1)
    else:
        return list1

修正方案

核心思路

采用从上往下递归的方式,从当前员工开始,逐层收集所有直接、间接下属的ID,最终赋值给Many2many字段。使用Odoo标准的计算字段模式,确保数据自动更新。

修正后代码

from odoo import models, fields, api

class HrEmployee(models.Model):
    _inherit = 'hr.employee'

    reporting_officer_id = fields.Many2one('hr.employee', string='上级')
    reportee_ids = fields.One2many('hr.employee', 'reporting_officer_id', string='直接下属')
    employee_child_ids = fields.Many2many(
        'hr.employee',
        compute='_compute_all_subordinates',
        store=True,
        string='所有下属'
    )

    @api.depends('reportee_ids', 'reportee_ids.reportee_ids')
    def _compute_all_subordinates(self):
        """计算所有层级下属的计算方法,依赖字段确保数据自动更新"""
        for emp in self:
            subordinate_ids = []
            self._collect_subordinates_recursive(emp, subordinate_ids)
            # 去重后赋值,避免层级异常导致的重复ID
            emp.employee_child_ids = [(6, 0, list(set(subordinate_ids)))]

    def _collect_subordinates_recursive(self, emp, subordinate_list):
        """递归收集所有层级下属ID"""
        # 添加当前员工的直接下属ID
        subordinate_list.extend(emp.reportee_ids.ids)
        # 递归处理每个直接下属的下属
        for reportee in emp.reportee_ids:
            self._collect_subordinates_recursive(reportee, subordinate_list)

代码说明

  1. 字段定义:明确reporting_officer_id为上级关联字段,reportee_ids为直接下属的One2many关联,employee_child_ids设为计算字段并开启store=True持久化存储
  2. 依赖配置:通过@api.depends指定依赖字段,确保下属层级变动时自动触发计算
  3. 计算逻辑:
    • _compute_all_subordinates遍历当前记录集,初始化下属ID列表后调用递归函数
    • _collect_subordinates_recursive先收集当前员工的直接下属,再对每个下属递归调用自身,收集其所有层级下属
  4. 赋值方式:使用Odoo Many2many字段标准赋值格式[(6, 0, ids_list)],直接替换所有关联记录
  5. 去重处理:通过list(set(subordinate_ids))避免因异常层级结构导致的重复ID

优化建议

  • 若员工层级变动频繁,保留store=True可提升查询性能;若变动极少,可移除store=True改为实时计算
  • 如需批量更新历史员工数据,可新增按钮触发批量计算:
    def action_batch_update_subordinates(self):
        all_employees = self.env['hr.employee'].search([])
        all_employees._compute_all_subordinates()
    

内容的提问来源于stack exchange,提问作者KbiR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:40:29