odoo18/addons_extensions/menu_control_center/models/models.py

204 lines
7.1 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# models/models.py
from odoo import models, fields, api, tools, _
from collections import defaultdict
class MenuControlUnits(models.Model):
_name = 'menu.control.units'
_rec_name = 'unit_name'
_sql_constraints = [
('unique_unit_name', 'UNIQUE(unit_name)', "'Unit Name' already defined. Please don't confuse me 😤.")
]
unit_name = fields.Char(string='Unit Name',required=True)
department_ids = fields.Many2many('hr.department')
user_ids = fields.Many2many('res.users')
def generate_department_user_ids(self):
for rec in self:
user_ids = self.env['hr.employee'].sudo().search([('department_id','in',rec.department_ids.ids)]).user_id.ids
self.write({
'user_ids': [(6, 0, user_ids)]
})
class MenuAccessControl(models.Model):
_name = 'menu.access.control'
_description = 'Menu Access Control'
_rec_name = 'control_unit'
_sql_constraints = [
('unique_control_unit', 'UNIQUE(control_unit)', "Only one service can exist with a specific control_unit. Please don't confuse me 🤪.")
]
control_unit = fields.Many2one('menu.control.units',required=True)
user_ids = fields.Many2many('res.users', string="Users", related='control_unit.user_ids')
access_menu_line_ids = fields.One2many(
'menu.access.line', 'access_control_id',
string="Accessible Menus", domain=[('menu_id.parent_id','=',False)]
)
access_sub_menu_line_ids = fields.One2many('menu.access.line', 'access_control_id',
string="Accessible Menus", domain=[('menu_id.parent_id','!=',False)]
)
def _get_all_submenus(self, menu):
"""Returns all submenus recursively for a given menu."""
submenus = self.env['ir.ui.menu'].search([('parent_id', '=', menu.id), ('active', '=', True)])
all_subs = submenus
for sm in submenus:
all_subs |= self._get_all_submenus(sm)
return all_subs
def action_generate_menus(self):
"""
Generate main menus and all submenus (recursive),
and set access_line_id for every submenu.
"""
for rec in self:
# clear old menus
rec.access_menu_line_ids.unlink()
rec.access_sub_menu_line_ids.unlink()
active_menus = self.env['ir.ui.menu'].search([
('parent_id', '=', False),
('active', '=', True)
])
for menu in active_menus:
# 1⃣ Create main menu line
main_line = self.env['menu.access.line'].create({
'access_control_id': rec.id,
'menu_id': menu.id,
'is_main_menu': True,
})
# 2⃣ Fetch all recursive submenus
submenus = self._get_all_submenus(menu)
# 3⃣ Create submenu lines with correct parent
for sm in submenus:
self.env['menu.access.line'].create({
'access_control_id': rec.id,
'menu_id': sm.id,
'is_main_menu': True,
'access_line_id': main_line.id, # important
})
def action_update_menus(self):
line = self.env['menu.access.line']
menu = self.env['ir.ui.menu']
for rec in self:
created_count = 0
# All existing menu IDs across BOTH One2manys
existing_menu_ids = set(
rec.access_menu_line_ids.mapped('menu_id.id') +
rec.access_sub_menu_line_ids.mapped('menu_id.id')
)
# ---------- Step 1: Ensure all top-level menus exist ----------
top_menus = menu.search([
('parent_id', '=', False),
('active', '=', True),
])
for menu in top_menus:
# Create missing MAIN MENU
main_line = line.search([
('access_control_id', '=', rec.id),
('menu_id', '=', menu.id),
('access_line_id', '=', False)
], limit=1)
if not main_line:
main_line = line.create({
'access_control_id': rec.id,
'menu_id': menu.id,
'is_main_menu': True,
})
created_count += 1
existing_menu_ids.add(menu.id)
# ---------- Step 2: Ensure all SUBMENUS exist ----------
submenus = rec._get_all_submenus(menu)
for sm in submenus:
# If submenu is missing → create it
if sm.id not in existing_menu_ids:
line.create({
'access_control_id': rec.id,
'menu_id': sm.id,
'is_main_menu': True,
'access_line_id': main_line.id,
})
created_count += 1
existing_menu_ids.add(sm.id)
# ---------- Notification ----------
if created_count:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Added %s new menu(s) (including submenus)') % created_count,
'type': 'success',
'sticky': False,
}
}
else:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Info'),
'message': _('No new menus found to add.'),
'type': 'info',
'sticky': False,
}
}
class MenuAccessLine(models.Model):
_name = 'menu.access.line'
_description = 'Menu Access Line'
_rec_name = 'menu_id'
access_control_id = fields.Many2one('menu.access.control', ondelete='cascade')
menu_id = fields.Many2one('ir.ui.menu', string="Menu")
is_main_menu = fields.Boolean(string="Is Main Menu", default=True)
parent_menu = fields.Many2one('ir.ui.menu',related='menu_id.parent_id')
access_line_id = fields.Many2one('menu.access.line')
control_unit = fields.Many2one(
'menu.control.units',
related='access_control_id.control_unit',
store=True
)
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": [("access_line_id", "=", self.id)],
"context": {"default_access_line_id": self.id},
}