Odoo18-Base/addons/hr/models/hr_department.py
2025-01-06 10:57:38 +07:00

214 lines
9.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class Department(models.Model):
_name = "hr.department"
_description = "Department"
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = "name"
_rec_name = 'complete_name'
_parent_store = True
name = fields.Char('Department Name', required=True, translate=True)
complete_name = fields.Char('Complete Name', compute='_compute_complete_name', recursive=True, store=True)
active = fields.Boolean('Active', default=True)
company_id = fields.Many2one('res.company', string='Company', index=True, default=lambda self: self.env.company)
parent_id = fields.Many2one('hr.department', string='Parent Department', index=True, check_company=True)
child_ids = fields.One2many('hr.department', 'parent_id', string='Child Departments')
manager_id = fields.Many2one('hr.employee', string='Manager', tracking=True, domain="['|', ('company_id', '=', False), ('company_id', 'in', allowed_company_ids)]")
member_ids = fields.One2many('hr.employee', 'department_id', string='Members', readonly=True)
has_read_access = fields.Boolean(search="_search_has_read_access", store=False, export_string_translation=False)
total_employee = fields.Integer(compute='_compute_total_employee', string='Total Employee',
export_string_translation=False)
jobs_ids = fields.One2many('hr.job', 'department_id', string='Jobs')
plan_ids = fields.One2many('mail.activity.plan', 'department_id')
plans_count = fields.Integer(compute='_compute_plan_count')
note = fields.Text('Note')
color = fields.Integer('Color Index')
parent_path = fields.Char(index=True)
master_department_id = fields.Many2one(
'hr.department', 'Master Department', compute='_compute_master_department_id', store=True)
@api.depends_context('hierarchical_naming')
def _compute_display_name(self):
if self.env.context.get('hierarchical_naming', True):
return super()._compute_display_name()
for record in self:
record.display_name = record.name
def _search_has_read_access(self, operator, value):
supported_operators = ["="]
if operator not in supported_operators or not isinstance(value, bool):
raise NotImplementedError()
if not value:
return [(1, "=", 0)]
if self.env['hr.employee'].has_access('read'):
return [(1, "=", 1)]
departments_ids = self.env['hr.department'].sudo().search([('manager_id', 'in', self.env.user.employee_ids.ids)]).ids
return [('id', 'child_of', departments_ids)]
@api.model
def name_create(self, name):
record = self.create({'name': name})
return record.id, record.display_name
@api.depends('name', 'parent_id.complete_name')
def _compute_complete_name(self):
for department in self:
if department.parent_id:
department.complete_name = '%s / %s' % (department.parent_id.complete_name, department.name)
else:
department.complete_name = department.name
@api.depends('parent_path')
def _compute_master_department_id(self):
for department in self:
department.master_department_id = int(department.parent_path.split('/')[0])
def _compute_total_employee(self):
emp_data = self.env['hr.employee'].sudo()._read_group([('department_id', 'in', self.ids)], ['department_id'], ['__count'])
result = {department.id: count for department, count in emp_data}
for department in self:
department.total_employee = result.get(department.id, 0)
def _compute_plan_count(self):
plans_data = self.env['mail.activity.plan']._read_group([('department_id', 'in', self.ids)], ['department_id'], ['__count'])
plans_count = {department.id: count for department, count in plans_data}
for department in self:
department.plans_count = plans_count.get(department.id, 0)
@api.constrains('parent_id')
def _check_parent_id(self):
if self._has_cycle():
raise ValidationError(_('You cannot create recursive departments.'))
@api.model_create_multi
def create(self, vals_list):
# TDE note: auto-subscription of manager done by hand, because currently
# the tracking allows to track+subscribe fields linked to a res.user record
# An update of the limited behavior should come, but not currently done.
departments = super(Department, self.with_context(mail_create_nosubscribe=True)).create(vals_list)
for department, vals in zip(departments, vals_list):
manager = self.env['hr.employee'].browse(vals.get("manager_id"))
if manager.user_id:
department.message_subscribe(partner_ids=manager.user_id.partner_id.ids)
return departments
def write(self, vals):
""" If updating manager of a department, we need to update all the employees
of department hierarchy, and subscribe the new manager.
"""
# TDE note: auto-subscription of manager done by hand, because currently
# the tracking allows to track+subscribe fields linked to a res.user record
# An update of the limited behavior should come, but not currently done.
if 'manager_id' in vals:
manager_id = vals.get("manager_id")
if manager_id:
manager = self.env['hr.employee'].browse(manager_id)
# subscribe the manager user
if manager.user_id:
self.message_subscribe(partner_ids=manager.user_id.partner_id.ids)
manager_to_unsubscribe = set()
for department in self:
if department.manager_id and department.manager_id.user_id:
manager_to_unsubscribe.update(department.manager_id.user_id.partner_id.ids)
self.message_unsubscribe(partner_ids=list(manager_to_unsubscribe))
# set the employees's parent to the new manager
self._update_employee_manager(manager_id)
return super(Department, self).write(vals)
def _update_employee_manager(self, manager_id):
employees = self.env['hr.employee']
for department in self:
employees = employees | self.env['hr.employee'].search([
('id', '!=', manager_id),
('department_id', '=', department.id),
('parent_id', '=', department.manager_id.id)
])
employees.write({'parent_id': manager_id})
def get_formview_action(self, access_uid=None):
res = super().get_formview_action(access_uid=access_uid)
if (not self.env.user.has_group('hr.group_hr_user') and
self.env.context.get('open_employees_kanban', False)):
res.update({
'name': self.name,
'res_model': 'hr.employee.public',
'view_mode': 'kanban',
'views': [(False, 'kanban'), (False, 'form')],
'context': {'searchpanel_default_department_id': self.id},
'res_id': False,
})
return res
def action_plan_from_department(self):
action = self.env['ir.actions.actions']._for_xml_id('hr.mail_activity_plan_action')
action['context'] = {'default_department_id': self.id, 'search_default_department_id': self.id}
return action
def action_employee_from_department(self):
if self.env['hr.employee'].has_access('read'):
res_model = "hr.employee"
search_view_id = self.env.ref('hr.view_employee_filter').id
else:
res_model = "hr.employee.public"
search_view_id = self.env.ref('hr.hr_employee_public_view_search').id
return {
'name': _("Employees"),
'type': 'ir.actions.act_window',
'res_model': res_model,
'view_mode': 'list,kanban,form',
'views': [(False, 'list'), (False, 'kanban'), (False, 'form')],
'search_view_id': [search_view_id, 'search'],
'context': {
'searchpanel_default_department_id': self.id,
'default_department_id': self.id,
'search_default_group_department': 1,
'search_default_department_id': self.id,
'expand': 1
},
}
def get_children_department_ids(self):
return self.env['hr.department'].search([('id', 'child_of', self.ids)])
def action_open_view_child_departments(self):
self.ensure_one()
return {
"type": "ir.actions.act_window",
"res_model": "hr.department",
"views": [[False, "kanban"], [False, "list"], [False, "form"]],
"domain": [['id', 'in', self.get_children_department_ids().ids]],
"name": "Child departments",
}
def get_department_hierarchy(self):
if not self:
return {}
hierarchy = {
'parent': {
'id': self.parent_id.id,
'name': self.parent_id.name,
'employees': self.parent_id.total_employee,
} if self.parent_id else False,
'self': {
'id': self.id,
'name': self.name,
'employees': self.total_employee,
},
'children': [
{
'id': child.id,
'name': child.name,
'employees': child.total_employee
} for child in self.child_ids
]
}
return hierarchy