odoo18/addons_extensions/menu_control_center/models/menu.py

70 lines
3.2 KiB
Python

from odoo import models, fields, api, tools, _
from collections import defaultdict
class IrUiMenu(models.Model):
_inherit = 'ir.ui.menu'
@api.model
@tools.ormcache('frozenset(self.env.user.groups_id.ids)', 'debug')
def _visible_menu_ids(self, debug=False):
""" Return the ids of the menu items visible to the user. """
# retrieve all menus, and determine which ones are visible
context = {'ir.ui.menu.full_list': True}
menus = self.with_context(context).search_fetch([], ['action', 'parent_id']).sudo()
# first discard all menus with groups the user does not have
group_ids = set(self.env.user._get_group_ids())
if not debug:
parent_menus = self.env['menu.access.control'].sudo().search([('user_ids','ilike',self.env.user.id)]).access_menu_line_ids.filtered(lambda menu: not(menu.is_main_menu)).menu_id.ids
sub_menus = self.env['menu.access.control'].sudo().search([('user_ids','ilike',self.env.user.id)]).access_sub_menu_line_ids.filtered(lambda menu: not(menu.is_main_menu)).menu_id.ids
hide_menus_list = list(set(parent_menus + sub_menus))
menus = menus.filtered(lambda menu: (menu.id not in hide_menus_list))
group_ids = group_ids - {
self.env['ir.model.data']._xmlid_to_res_id('base.group_no_one', raise_if_not_found=False)}
menus = menus.filtered(
lambda menu: not (menu.groups_id and group_ids.isdisjoint(menu.groups_id._ids)))
# take apart menus that have an action
actions_by_model = defaultdict(set)
for action in menus.mapped('action'):
if action:
actions_by_model[action._name].add(action.id)
existing_actions = {
action
for model_name, action_ids in actions_by_model.items()
for action in self.env[model_name].browse(action_ids).exists()
}
action_menus = menus.filtered(lambda m: m.action and m.action in existing_actions)
folder_menus = menus - action_menus
visible = self.browse()
# process action menus, check whether their action is allowed
access = self.env['ir.model.access']
MODEL_BY_TYPE = {
'ir.actions.act_window': 'res_model',
'ir.actions.report': 'model',
'ir.actions.server': 'model_name',
}
# performance trick: determine the ids to prefetch by type
prefetch_ids = defaultdict(list)
for action in action_menus.mapped('action'):
prefetch_ids[action._name].append(action.id)
for menu in action_menus:
action = menu.action
action = action.with_prefetch(prefetch_ids[action._name])
model_name = action._name in MODEL_BY_TYPE and action[MODEL_BY_TYPE[action._name]]
if not model_name or access.check(model_name, 'read', False):
# make menu visible, and its folder ancestors, too
visible += menu
menu = menu.parent_id
while menu and menu in folder_menus and menu not in visible:
visible += menu
menu = menu.parent_id
return set(visible.ids)