odooodoo-14

Optional Dependencies in Odoo 14 CE


Is there any way to make optional dependencies in Odoo 14 CE?

I know that there is a dependency attribute in the manifest file that we need to specify, and yes, I have been using it to the best of my abilities.

However, I sometimes need to write some code for only when a module is installed, but even if it isn't then the rest of the code should function properly without such module.

For example, My custom module will add a field in sale and account, but if this database has purchase installed then it will also add a field in it too. Pretty simple concept, right, but I can't find a way to do it in a single module.


Solution

  • You can use post_init_hook, which is executed right after the module’s installation, to check if the purchase (purchase.order is in registry) module is installed and add the custom field. You can even load an XML file to add the custom field by inheritance using the convert_xml_import function which convert and import XML files.

    It is similar to adding the field manually to the corresponding model and view.

    When you uninstall the module, the custom field will not be deleted and to do so, you will need to use the uninstall_hook, you will also need to delete the view manually because of the following user error:

    User Error
    Cannot rename/delete fields that are still present in views
    Fields: purchase.order.x_reference
    View: purchase.order.form

    First set the post_init_hook, uninstall_hook functions inside the __manifest__.py file:

    'post_init_hook': '_module_post_init',
    'uninstall_hook': '_module_uninstall_hook',
    

    Then define those functions inside the __init__.py file:

    import os
    from odoo import fields, api, SUPERUSER_ID, tools, modules
    from odoo.tools.misc import file_open
    
    
    def _module_uninstall_hook(cr, registry):
        if 'purchase.order' in registry:
            env = api.Environment(cr, SUPERUSER_ID, {})
            env.ref('stackoverflow_14.purchase_order_form').unlink()
            env['ir.model.fields'].search([('name', '=', 'x_reference')]).unlink()
    
    
    def _module_post_init(cr, registry):
        if 'purchase.order' in registry:
            env = api.Environment(cr, SUPERUSER_ID, {})
            mp = env['ir.model'].search([('model', '=', 'purchase.order')], limit=1)
            mp.write({'field_id': [(0, 0, {
                'name': 'x_reference',
                'field_description': "Reference",
                'ttype': 'char',
            })]})
            pathname = os.path.join(modules.get_module_path('stackoverflow_14'), 'views', 'purchase_order.xml')
            with file_open(pathname, 'rb') as fp:
                tools.convert.convert_xml_import(cr, 'stackoverflow_14', fp)
    

    The purchase_order.xml file defined inside views use the view inheritance to add the custom field to the purchase_order_form form view:

    <?xml version="1.0" encoding="utf-8" ?>
    <odoo>
        <data>
            <record id="purchase_order_form" model="ir.ui.view">
                <field name="name">purchase.order.form</field>
                <field name="model">purchase.order</field>
                <field name="inherit_id" ref="purchase.purchase_order_form"/>
                <field name="arch" type="xml">
                    <field name="partner_ref" position="after">
                        <field name="x_reference"/>
                    </field>
                </field>
            </record>
        </data>
    </odoo>