212 lines
9.3 KiB
Python
212 lines
9.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import api, fields, models
|
|
from pypinyin import pinyin,lazy_pinyin
|
|
from odoo.osv import expression
|
|
from odoo.exceptions import ValidationError, UserError
|
|
|
|
# 作为顶级根节点、在下属部门显示名中不带出的上级部门(只显示本部门,不拼上级)
|
|
# 精确匹配:与部门名完全相同才算根级
|
|
ROOT_DEPARTMENTS = {'集团本部', '客户服务中心'}
|
|
# 前缀匹配:以这些字样开头的部门都算根级(覆盖 天河粮储/天河物管/天河投资 等公司)
|
|
ROOT_DEPARTMENT_PREFIXES = ('天河',)
|
|
|
|
|
|
def _is_root_department(department):
|
|
"""判断上级部门是否属于根级(根级不拼进下级显示名)。"""
|
|
name = department.name or ''
|
|
return name in ROOT_DEPARTMENTS or name.startswith(ROOT_DEPARTMENT_PREFIXES)
|
|
|
|
|
|
class YuthonHrDepartment(models.Model):
|
|
_inherit = "hr.department"
|
|
# 部门显示名只带一级上级("上级 / 本部门"),最多一层;无上级则只显示本部门
|
|
_rec_name = 'hierarchical_name'
|
|
_order = 'department_code asc'
|
|
|
|
name = fields.Char(string="部门名称", tracking=True, required=True)
|
|
department_phone = fields.Char(string="部门电话")
|
|
department_fax = fields.Char(string="部门传真")
|
|
department_location = fields.Char(string="部门地址")
|
|
department_function = fields.Char(string="部门职能")
|
|
is_institution = fields.Boolean(string="是否机构")
|
|
is_global_department = fields.Boolean(string="是否全局部门")
|
|
create_date = fields.Date(string="创建时间", default=fields.Date.today())
|
|
start_date = fields.Date(string="生效日期", default=fields.Date.today())
|
|
expiration_date = fields.Date(string="失效日期", default=fields.Date.today())
|
|
end_date = fields.Date(string="结束时间")
|
|
department_code = fields.Char(string="部门序号")
|
|
company_id = fields.Many2one('res.company', string="公司", index=True, default=lambda self: self.env.company, store=True)
|
|
pinyin_name = fields.Char(string="拼音名称", compute='_compute_pinyin', index=True, store=True)
|
|
is_company = fields.Boolean(string="本公司", default=True, compute='_compute_is_company', search='_search_part_of_company')
|
|
hierarchical_name = fields.Char(string="层级名称", compute='_compute_hierarchical_name', store=True, index=True)
|
|
|
|
@api.depends_context('uid', 'company')
|
|
@api.depends('company_id')
|
|
def _compute_is_company(self):
|
|
active_company_ids = self.env.companies
|
|
for employee in self:
|
|
employee.is_company = employee.company_id in active_company_ids
|
|
|
|
def _search_part_of_company(self, operator, value):
|
|
if operator not in ('=', '!=') or not isinstance(value, bool):
|
|
raise UserError(('Operation not supported'))
|
|
company_ids = self.env.companies.ids
|
|
if not value:
|
|
operator = '!=' if operator == '=' else '='
|
|
if operator == '=':
|
|
return [('company_id', 'in', company_ids)]
|
|
else:
|
|
return [('company_id', 'not in', company_ids)]
|
|
|
|
@api.constrains('create_date', 'end_date')
|
|
def _check_start_end_time(self):
|
|
for record in self:
|
|
if record.create_date and record.end_date and record.create_date > record.end_date:
|
|
raise models.ValidationError("开始时间不能大于结束时间!")
|
|
|
|
def do_department_to_res_groups(self):
|
|
"""
|
|
批量生成新的权限组
|
|
:return:
|
|
"""
|
|
for record in self:
|
|
res_groups_objs = self.sudo().env["res.groups"].search([("department_ids", "in", record.ids)])
|
|
user_ids = self.sudo().env["hr.employee"].search([("department_id", "=", record.id)]).user_id.ids
|
|
if not res_groups_objs:
|
|
# 查询当前部门下的员工的数量
|
|
self.sudo().env["res.groups"].create({
|
|
"name": record.name,
|
|
"department_ids": [(4, id) for id in record.ids] ,
|
|
"users": [(4, id) for id in user_ids]
|
|
})
|
|
else:
|
|
for res_groups_obj in res_groups_objs:
|
|
res_groups_obj.sudo().write({
|
|
"users": [(4, id) for id in user_ids]
|
|
})
|
|
|
|
|
|
@api.onchange('department_code', 'parent_id')
|
|
def _onchange_department_code(self):
|
|
for code in self:
|
|
if code.parent_id.department_code:
|
|
code.department_code = code.parent_id.department_code + (code.department_code.split('.')[-1] if code.department_code else '')
|
|
else:
|
|
code.department_code = code.department_code
|
|
|
|
@api.depends('name')
|
|
def _compute_pinyin(self):
|
|
for employee in self:
|
|
if employee.name:
|
|
employee.pinyin_name = ''.join(lazy_pinyin(employee.name))
|
|
|
|
@api.depends('name', 'parent_id.name')
|
|
def _compute_hierarchical_name(self):
|
|
for department in self:
|
|
parent = department.parent_id
|
|
# 上级为空 或 上级属于根级部门(集团本部/天河系公司等)→ 只显示本部门
|
|
if parent and not _is_root_department(parent):
|
|
department.hierarchical_name = '%s(%s)' % (department.name, parent.name)
|
|
else:
|
|
department.hierarchical_name = department.name
|
|
|
|
def action_recompute_hierarchical_name(self):
|
|
"""手动重算所有部门的层级显示名(改了 ROOT_DEPARTMENTS 规则后,store 字段旧值不会自动重算,用此动作触发)。
|
|
|
|
可在 设置→技术→动作→服务器动作 找到「重算部门层级显示名」并运行,
|
|
或直接在该模型的列表/表单「动作」菜单中点击。
|
|
"""
|
|
all_depts = self.sudo().search([])
|
|
all_depts._compute_hierarchical_name()
|
|
self.env.cr.commit()
|
|
return {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'title': '部门层级名重算完成',
|
|
'message': '已重算 %d 个部门' % len(all_depts),
|
|
'type': 'success',
|
|
'sticky': False,
|
|
}
|
|
}
|
|
|
|
@api.model
|
|
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
|
|
domain = domain or []
|
|
if name:
|
|
has_chinese = any('\u4e00' <= char <= '\u9fff' for char in name)
|
|
if has_chinese:
|
|
# 包含中文:使用模糊匹配
|
|
search_domain = [('name', operator, name)]
|
|
else:
|
|
# 纯字母/数字:使用精确匹配
|
|
search_domain = ['|',
|
|
('pinyin_name', operator, name),
|
|
('name', '=', name)]
|
|
domain = expression.AND([search_domain, domain])
|
|
return self._search(domain, limit=limit, order=order)
|
|
|
|
@api.constrains('department_code')
|
|
def _check_department_code_uniqueness(self):
|
|
for record in self:
|
|
if record.department_code:
|
|
existing_records = self.search([
|
|
('department_code', '=', record.department_code),
|
|
('id', '!=', record.id)
|
|
])
|
|
if existing_records:
|
|
raise ValidationError("部门序号必须唯一!")
|
|
|
|
@api.onchange('department_code')
|
|
def _onchange_department_code(self):
|
|
for record in self:
|
|
if record.department_code:
|
|
employee_ids = self.env['hr.employee'].search([('department_id', '=', record.id.origin), ('company_id', '=', record.company_id.id)])
|
|
for employee in employee_ids:
|
|
if employee.number and len(employee.number) >= 2:
|
|
old_suffix = employee.number[-2:]
|
|
employee.number = record.department_code + old_suffix
|
|
|
|
def open_record(self):
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"res_model": 'hr.department',
|
|
"res_id": self.id,
|
|
"name":"部门详情",
|
|
"view_mode": "form",
|
|
}
|
|
|
|
def put_department_change(self):
|
|
form_id = self.env.ref('yuthon_hr_employee_approval.view_yuthon_department_change_form').id
|
|
department_list = []
|
|
for record in self:
|
|
department_list.append([0, 0, {'department_id': record.id,}])
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"name": "部门变成审批",
|
|
"res_model": "yuthon.department.change",
|
|
"views": [[form_id, "form"]],
|
|
"context": {
|
|
'default_approval_ids': department_list,
|
|
}
|
|
}
|
|
|
|
def all_put_department_change(self):
|
|
department_list = []
|
|
department_ids = self.env["hr.department"].browse(
|
|
self._context.get('active_ids', self._context.get('active_id')))
|
|
for record in department_ids:
|
|
department_list.append([0, 0, {'department_id': record.id,}])
|
|
form_id = self.env.ref('yuthon_hr_employee_approval.view_yuthon_department_change_form').id
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"name": "部门变成审批",
|
|
"res_model": "yuthon.department.change",
|
|
"views": [[form_id, "form"]],
|
|
"context": {
|
|
'default_approval_ids': department_list,
|
|
}
|
|
}
|
|
|
|
|