Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define multi-company-aware models in OpenERP

I defined several custom objects in OpenERP, which are supposed to be used in a multi-company environment. Accordingly, each object defines a "company_id" field. This is all setup and working fine. Only, the UI just isn't very user friendly, since the user needs to explicitly choose the company the new object instance should belong to.

The company_id fields are set up in the following way:

...
'company_id' : fields.many2one('res.company', string='Company', selection=compute_company_select, required=True)
...


def compute_company_select(self, cr, uid, context):
    c_proxy = self.pool.get('res.company')

    user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
    search = [('id', 'child_of', user.company_id.id)]
    if uid == SUPERUSER_ID:
        search = [] #superuser can assign any company

    ids = c_proxy.search(cr, uid, search, context=context)
    return [(c.id, c.name) for c in c_proxy.browse(cr, uid, ids, context=context)]

I could also solve this by simply defining a domain expression in the field definition, using the search domain from the "compute_company_select" function. Except that the superuser couldn't assign all companies then, if he isn't configured to have access to all of them.

What I want to do now is pre-populate the company_id field with the users company, when he creates a new record. And this seems to be impossible. I have found several possibilities to pre-populate fields with either static values or values that have been defined in module-XML. But there seems to be no option to use a value that is only available during runtime, i.e. the current users record.

I am using OpenERP 6.1.

like image 213
asdfsdfsdfsdfsd3232 Avatar asked Jan 22 '13 16:01

asdfsdfsdfsdfsd3232


1 Answers

Many documents in the official OpenERP addons have similar multi-company features, so you should presumably reuse the same implementation technique, it seems to match your use case.

There are tons of examples in the source code if you search for "company_id" or "company_id.*fields.many2one", for example Sales Shops in the sale module.

In a nutshell, you will need to:

  1. Declare the company_id field as a regular many2one towards res.company. The default security record rules (defined here) will take care of dynamically showing only the companies that are subsidiaries of the user's current company. The user can change their current company to any of their allowed companies at any time in the preferences, to work in a different company context. And since security record rules do not apply for the special admin user, it will always be possible to choose any company when logged in as admin.

    'company_id': fields.many2one('res.company', 'Company', required=False)
    
  2. Automatically select the user's current company as default when creating new records. The framework provides a method for doing exactly that: res.company._company_default_get(). It is possible to define custom rules for selecting a default company for each kind of document, but the default will be the user's current company. So it is as simple as adding this snippet to your model's _defaults:

    'company_id': lambda self,cr,uid,ctx: self.pool['res.company']._company_default_get(cr,uid,object='<your_model>',context=ctx)
    
  3. Add the company_id field to your model's form view. Usually you want to restrict it to the multi-company group, to show it only to users who actually need it:

    <field name="company_id" groups="base.group_multi_company"/>
    

It's supposed to be as simple as that.

like image 145
odony Avatar answered Sep 25 '22 15:09

odony