odoo18/addons_extensions/menu_control_center/models/models.py

193 lines
7.6 KiB
Python

from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class MenuAccessControl(models.Model):
_name = 'menu.access.control'
_description = 'Menu Access Control'
_rec_name = 'master_control_id'
master_control_id = fields.Many2one('master.control', string='Master Control', required=True)
department_ids = fields.Many2many('hr.department', string='Departments')
available_user_ids = fields.Many2many(
'res.users',
compute='_compute_available_user_ids',
string='Available Users',
)
user_ids = fields.Many2many(
'res.users',
'menu_access_control_res_users_rel',
'access_control_id',
'user_id',
string='Users',
)
access_menu_line_ids = fields.One2many(
'menu.access.line',
'access_control_id',
string='Menus',
domain=[('menu_id.parent_id', '=', False)],
)
access_sub_menu_line_ids = fields.One2many(
'menu.access.line',
'access_control_id',
string='Sub Menus',
domain=[('menu_id.parent_id', '!=', False)],
)
@api.depends('master_control_id', 'master_control_id.user_ids')
def _compute_available_user_ids(self):
for record in self:
record.available_user_ids = record.master_control_id.user_ids
@api.onchange('master_control_id')
def _onchange_master_control_id(self):
for record in self:
available_users = record.master_control_id.user_ids
record.user_ids = record.user_ids.filtered(lambda user: user in available_users)
record._add_department_users()
@api.onchange('department_ids')
def _onchange_department_ids(self):
self._add_department_users()
def _add_department_users(self):
for record in self:
if not record.master_control_id:
record.user_ids = [(5, 0, 0)]
continue
allowed_users = record.master_control_id.user_ids
department_users = self.env['hr.employee'].sudo().search([
('department_id', 'in', record.department_ids.ids),
('user_id', '!=', False),
]).mapped('user_id')
record.user_ids = (record.user_ids.filtered(lambda user: user in allowed_users) | (department_users & allowed_users))
def _sync_menu_lines_from_master(self):
line_model = self.env['menu.access.line']
for record in self:
master_lines = (record.master_control_id.menu_line_ids | record.master_control_id.submenu_line_ids).filtered('show_menu')
existing_lines = {line.menu_id.id: line for line in record.access_menu_line_ids | record.access_sub_menu_line_ids}
valid_menu_ids = set(master_lines.mapped('menu_id').ids)
for line in (record.access_menu_line_ids | record.access_sub_menu_line_ids):
if line.menu_id.id not in valid_menu_ids:
line.unlink()
refreshed_lines = {line.menu_id.id: line for line in record.access_menu_line_ids | record.access_sub_menu_line_ids}
parent_lines = {}
for master_line in master_lines.filtered(lambda line: not line.menu_id.parent_id):
access_line = refreshed_lines.get(master_line.menu_id.id)
if not access_line:
access_line = line_model.create({
'access_control_id': record.id,
'menu_id': master_line.menu_id.id,
'show_menu': True,
})
parent_lines[master_line.menu_id.id] = access_line
for master_line in master_lines.filtered(lambda line: line.menu_id.parent_id):
parent_root_menu = master_line.menu_id
while parent_root_menu.parent_id:
parent_root_menu = parent_root_menu.parent_id
parent_line = parent_lines.get(parent_root_menu.id)
access_line = refreshed_lines.get(master_line.menu_id.id)
if not access_line:
line_model.create({
'access_control_id': record.id,
'menu_id': master_line.menu_id.id,
'show_menu': True,
'parent_line_id': parent_line.id if parent_line else False,
})
@api.model_create_multi
def create(self, vals_list):
records = super().create(vals_list)
records._sync_menu_lines_from_master()
self.env['ir.ui.menu'].sudo().clear_caches()
return records
def write(self, vals):
result = super().write(vals)
if {'master_control_id', 'department_ids'} & set(vals):
self._sync_menu_lines_from_master()
self._validate_users_belong_to_master()
self.env['ir.ui.menu'].sudo().clear_caches()
return result
@api.constrains('master_control_id', 'user_ids')
def _validate_users_belong_to_master(self):
for record in self:
allowed_users = record.master_control_id.user_ids
invalid_users = record.user_ids.filtered(lambda user: user not in allowed_users)
if invalid_users:
raise ValidationError(
_('Users in Menu Access Control must belong to the selected Master Control.')
)
def action_refresh_from_master(self):
self._sync_menu_lines_from_master()
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Menus refreshed from Master Control.'),
'type': 'success',
'sticky': False,
},
}
def unlink(self):
result = super().unlink()
self.env['ir.ui.menu'].sudo().clear_caches()
return result
class MenuAccessLine(models.Model):
_name = 'menu.access.line'
_description = 'Menu Access Line'
_rec_name = 'menu_id'
_order = 'menu_id'
access_control_id = fields.Many2one('menu.access.control', ondelete='cascade')
menu_id = fields.Many2one('ir.ui.menu', string='Menu', required=True)
show_menu = fields.Boolean(string='Show Menu', default=True)
parent_menu_id = fields.Many2one('ir.ui.menu', related='menu_id.parent_id', string='Parent Menu', store=True)
parent_line_id = fields.Many2one('menu.access.line', string='Parent Line')
master_control_id = fields.Many2one('master.control', related='access_control_id.master_control_id', store=True)
_sql_constraints = [
('menu_access_line_unique', 'unique(access_control_id, menu_id)', 'Menu already exists in this access control.'),
]
def open_submenus_popup_view(self):
self.ensure_one()
return {
'name': _('Sub Menus'),
'type': 'ir.actions.act_window',
'res_model': 'menu.access.line',
'view_mode': 'list,form',
'views': [
(self.env.ref('menu_control_center.view_submenu_line_list').id, 'list'),
],
'target': 'new',
'domain': [('parent_line_id', '=', self.id)],
'context': {'default_parent_line_id': self.id},
}
@api.model_create_multi
def create(self, vals_list):
records = super().create(vals_list)
self.env['ir.ui.menu'].sudo().clear_caches()
return records
def write(self, vals):
result = super().write(vals)
self.env['ir.ui.menu'].sudo().clear_caches()
return result
def unlink(self):
result = super().unlink()
self.env['ir.ui.menu'].sudo().clear_caches()
return result