193 lines
7.6 KiB
Python
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
|