diff --git a/addons_extensions/menu_control_center/__init__.py b/addons_extensions/menu_control_center/__init__.py
new file mode 100644
index 000000000..9a7e03ede
--- /dev/null
+++ b/addons_extensions/menu_control_center/__init__.py
@@ -0,0 +1 @@
+from . import models
\ No newline at end of file
diff --git a/addons_extensions/menu_control_center/__manifest__.py b/addons_extensions/menu_control_center/__manifest__.py
new file mode 100644
index 000000000..385729848
--- /dev/null
+++ b/addons_extensions/menu_control_center/__manifest__.py
@@ -0,0 +1,28 @@
+{
+ 'name': 'Menu Access Control',
+ 'version': '1.0',
+ 'summary': 'Control menu visibility based on users or companies',
+ 'description': """
+ This module allows administrators to configure menu visibility
+ based on selected users or companies. Active parent menus can
+ be generated and assigned for access control.
+ """,
+ 'category': 'Tools',
+ 'author': 'PRANAY',
+ 'website': 'https://ftprotech.in',
+ 'depends': ['base','hr'],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'data/data.xml',
+ 'views/menu_access_control_views.xml',
+ ],
+ # 'assets': {
+ # 'web.assets_backend': [
+ # 'menu_control_center/static/src/js/menu_service.js',
+ # ],
+ # },
+ 'installable': True,
+ 'application': True,
+ 'auto_install': False,
+ 'license': 'LGPL-3',
+}
diff --git a/addons_extensions/menu_control_center/data/data.xml b/addons_extensions/menu_control_center/data/data.xml
new file mode 100644
index 000000000..4cc52ea05
--- /dev/null
+++ b/addons_extensions/menu_control_center/data/data.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons_extensions/menu_control_center/models/__init__.py b/addons_extensions/menu_control_center/models/__init__.py
new file mode 100644
index 000000000..52e35f001
--- /dev/null
+++ b/addons_extensions/menu_control_center/models/__init__.py
@@ -0,0 +1,2 @@
+from . import models
+from . import menu
\ No newline at end of file
diff --git a/addons_extensions/menu_control_center/models/menu.py b/addons_extensions/menu_control_center/models/menu.py
new file mode 100644
index 000000000..c82f101c0
--- /dev/null
+++ b/addons_extensions/menu_control_center/models/menu.py
@@ -0,0 +1,67 @@
+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:
+ hide_menus_list = 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
+
+ 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)
\ No newline at end of file
diff --git a/addons_extensions/menu_control_center/models/models.py b/addons_extensions/menu_control_center/models/models.py
new file mode 100644
index 000000000..a1f11067e
--- /dev/null
+++ b/addons_extensions/menu_control_center/models/models.py
@@ -0,0 +1,65 @@
+# 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"
+ )
+
+ def action_generate_menus(self):
+ """Button to fetch active top-level menus and populate access lines."""
+ menu_lines = []
+ active_menus = self.env['ir.ui.menu'].search([
+ ('parent_id', '=', False), # top-level menus
+ ('active', '=', True)
+ ])
+ for menu in active_menus:
+ menu_lines.append((0, 0, {
+ 'menu_id': menu.id,
+ 'is_main_menu': True
+ }))
+ self.access_menu_line_ids = menu_lines
+
+
+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)
diff --git a/addons_extensions/menu_control_center/security/ir.model.access.csv b/addons_extensions/menu_control_center/security/ir.model.access.csv
new file mode 100644
index 000000000..d7edab9d1
--- /dev/null
+++ b/addons_extensions/menu_control_center/security/ir.model.access.csv
@@ -0,0 +1,4 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_menu_access_control,access.menu.access.control,model_menu_access_control,hr.group_hr_manager,1,1,1,1
+access_menu_access_line,access.menu.access.line,model_menu_access_line,hr.group_hr_manager,1,1,1,1
+access_menu_control_units,access.menu.control.units,model_menu_control_units,hr.group_hr_manager,1,1,1,1
\ No newline at end of file
diff --git a/addons_extensions/menu_control_center/static/src/js/menu_service.js b/addons_extensions/menu_control_center/static/src/js/menu_service.js
new file mode 100644
index 000000000..fb647a3ec
--- /dev/null
+++ b/addons_extensions/menu_control_center/static/src/js/menu_service.js
@@ -0,0 +1,44 @@
+///** @odoo-module **/
+//
+//import { browser } from "@web/core/browser/browser";
+//import { makeEnv, startServices } from "@web/env";
+//import { session } from "@web/session";
+//import { _t } from "@web/core/l10n/translation";
+//import { browser } from "@web/core/browser/browser";
+//import { MenuService } from "@web/services/menu_service";
+//
+//export const menuService = {
+// dependencies: MenuService.dependencies,
+// start(env, deps) {
+// const menu = super.start(env, deps);
+//
+// // Override the getApps method
+// const originalGetApps = menu.getApps;
+// menu.getApps = async function() {
+// // Get the original apps
+// let apps = await originalGetApps.call(this);
+//
+// // Fetch your custom menu access data
+// const accessData = await this.orm.call(
+// 'menu.access.control',
+// 'get_user_access_menus',
+// []
+// );
+//
+// // If access data exists, filter the apps
+// if (accessData && accessData.allowed_menu_ids) {
+// apps = apps.filter(app =>
+// accessData.allowed_menu_ids.includes(app.id)
+// );
+// }
+//
+// return apps;
+// };
+//
+// return menu;
+// },
+//};
+//
+//// Register the service
+//import { registry } from "@web/core/registry";
+//registry.category("services").add("menu", menuService, { force: true });
\ No newline at end of file
diff --git a/addons_extensions/menu_control_center/views/menu_access_control_views.xml b/addons_extensions/menu_control_center/views/menu_access_control_views.xml
new file mode 100644
index 000000000..7dd71421d
--- /dev/null
+++ b/addons_extensions/menu_control_center/views/menu_access_control_views.xml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+