Odoo Migration: Remove Deprecated Groups and Rules

Cleaning Up Old Groups in Odoo

When migrating an Odoo project from an older version to a newer one, you may encounter groups that were used temporarily or are no longer relevant in the new version. Keeping these unused groups can cause:

  • Confusing or overlapping user permissions.
  • Orphaned record rules and access rights that no longer apply.
  • Security misconfigurations that expose records unintentionally.
  • Unnecessary clutter in the database that slows down maintenance and future upgrades.

To keep your environment clean and secure, remove deprecated groups during migration, unlink them from users, and delete their related record rules and access controls.

In this blog, we’ll walk through a post-migration cleanup script that does exactly that.

Why Cleanup Deprecated Groups?

  • Security: Old groups may carry record rules that expose sensitive data.
  • Clarity: Users should only see the groups they need.
  • Maintainability: Removing unused configurations reduces complexity for future upgrades.

Post-Migration Cleanup Script

Below is a script example from the Numla project migration. It performs four actions in a safe order:

  • Unlinks the group from record rules.
  • Removes the group from assigned users.
  • Deletes related access control entries.
  • Deletes the group itself.
import logging
from odoo import api, SUPERUSER_ID
_logger = logging.getLogger(__name__)
def migrate(cr, version):
    env = api.Environment(cr, SUPERUSER_ID, {})
    group_xml_id = 'numla_project.group_sale_salesman_extended'
    group = env.ref(group_xml_id, raise_if_not_found=False)
    if not group:
        _logger.info(f"numla_project: [POST-MIGRATION] Group {group_xml_id} not found, skipping cleanup.")
        return
    _logger.info(f"numla_project: [POST-MIGRATION] Cleaning up group {group_xml_id} (ID: {group.id})")
    # Step 1: Unlink group from ir.rule (rule_group_rel)
    rules = env['ir.rule'].search([( 'groups', 'in', group.id )])
    for rule in rules:
        rule.write({'groups': [(3, group.id)]})
        _logger.info(f" - Unlinked group from ir.rule: {rule.name}")
    # Step 2: Unlink group from users (res_users_groups_rel)
    users = env['res.users'].search([( 'groups_id', 'in', group.id )])
    for user in users:
        user.write({'groups_id': [(3, group.id)]})
        _logger.info(f" - Unlinked group from user: {user.login}")
    # Step 3: Remove access control entries (ir.model.access)
    access_entries = env['ir.model.access'].search([( 'group_id', '=', group.id )])
    for access in access_entries:
        _logger.info(f" - Deleting access control: {access.name} (Model: {access.model_id.model})")
        access_entries.unlink()
    # Step 4: Delete the group
    group_name = group.name
    group.unlink()
    _logger.info(f"numla_project: [POST-MIGRATION] Successfully deleted group: {group_name}")

Step-by-Step Explanation

1. Find the Group

We locate the deprecated group using its XML ID:

2. Unlink Group from Record Rules

Any ir.rule tied to this group is updated to remove the relationship. This prevents hidden filtering or exposure of records after the group is gone.

3. Remove Group from Users

We do not touch user accounts. We only unlink the group, which preserves user access through other groups that remain valid.

4. Delete Access Control Entries

Any ir.model.access rows tied to the group are removed, so there are no stale allow rules floating around.

5. Delete the Group

Once nothing depends on it, the group can be safely deleted.

Practical Safeguards Before You Run This

  • Run on a staging database first and validate critical user journeys.
  • Back up the database so you can roll back if needed.
  • Search for any implied groups, menus, or automated actions that still reference the group, and clean those up if found.
  • Review server logs after migration to confirm there are no access errors.

Final Thoughts

Cleaning up deprecated groups is a small but critical step in Odoo migrations. By unlinking rules, removing access rights, and safely deleting unused groups, you keep your environment secure, maintainable, and ready for future upgrades. Following the safeguards above ensures you won’t disrupt live operations while running the script.

Found this article useful?

Explore more development guides and solutions from our team.

Check out more posts
تسجيل الدخول حتى تترك تعليقاً
Reserve Stock in Odoo Before Sales Order Confirmation