How do I hide a `ir.actions.act_window` defined in another module

Pretty simple question. In odoo/addons/portal/wizard/portal_wizard_views.xml there is the following action:

<act_window id="partner_wizard_action"
    name="Grant portal access"
    binding_model="res.partner"
    res_model="portal.wizard"
    view_mode="form" target="new"
    groups="base.group_partner_manager"/>

How do I hide it??

More Information

Other answers I've seen recommend unlinking the record completely, but not only could I not figure out the best way to do this, most importantly I would like to remove the action in such a way so that if my module is uninstalled, the action is show again as if nothing ever happened. I don't want my module doing anything to other modules that would require them to be reinstalled. Especially in this case, since the portal module is depended up by sale and account, among other critical modules.

I've also seen answers recommending just redefining the record with the same id but prefixed with the other module's name in order to override the action. In this case I guess that would look something like this:

<act_window id="portal.partner_wizard_action"
    name="Grant portal access 2"
    binding_model="res.partner"
    res_model="portal.wizard"
    view_mode="form" target="new"
    groups="base.group_partner_manager"/>

However, I couldn't even get this to work. It doesn't replace the existing action in the contextual menu; instead it just adds a new action, resulting in there now being two (both "Grant portal access" and "Grant portal access 2"). And I'm not sure how I would hide the action using this method either.

Edit: I found that for some unknown reason the original action in my Odoo instance no longer had an external ID. That is why it wasn't being "overridden" when I tried redefining the record. I resolved this my uninstalling my custom module, deleting both of the actions, and then updating the portal module. This caused the action to be re-created with the external ID present again, and when I reinstalled my custom module I could then override it.

However, this doesn't solve my problem of updating the action in a "non-destructive" way. When I uninstall my custom module, changes that it made to the action persist until the original portal module is upgraded again. This is bad, because someone uninstalling the custom module would need to know that the portal module must be upgraded to revert some of the changes.


I figured it out... sort of.

First, for some reason the original partner_wizard_action from the portal module in my case had somehow lost it's external ID/ref/xml_id. I have no clue how that happened, but to resolve it I had to uninstall my custom module, delete the "Grant portal access" action and the "Grant portal access 2" action, and then upgrade the portal module. This re-created the partner_wizard_action with the correct external ID.

I could then override the action as expected with the following code:

<record id="portal.partner_wizard_action" model="ir.actions.act_window">
    <field name="binding_model_id" eval="False"/>
</record>

This unbinds the action from the res.partner model, causing the action to no longer show up in the contextual menu. However, it does still exist.

This "solution" comes with a huge caveat, however. When I uninstall my custom module now, the action does not get reverted to how it was before it was overridden. So it will still be hidden, unless the portal module is explicitly upgraded again.

To get around this, I'm considering writing a uninstall_hook in my module manifest to set the action's binding_model_id back to the correct value. It sucks that there doesn't seem to be a better way to do this, however.

Edit: I was successfully able to have the action revert itself at module uninstallation using the following uninstall_hook:

from odoo import api, SUPERUSER_ID

def uninstall_hook(cr, registry):
    env = api.Environment(cr, SUPERUSER_ID, {})
    env.ref("portal.partner_wizard_action").binding_model_id = env.ref("base.model_res_partner").id

In case you are not aware, you would put this function in __init__.py at the root of your module and then add "uninstall_hook": "uninstall_hook" to your __manifest__.py file.