← Back to team overview

c2c-oerpscenario team mailing list archive

[Bug 485058] Re: Trunk Multi Company Improvement

 

[6.0rc1] Shouldn't addons/base/res/res_company_view.xml be referenced in addons/base/__openerp__.py?
The multi-company menu is not visible until I add it and reload.

-- 
Trunk Multi Company Improvement
https://bugs.launchpad.net/bugs/485058
You received this bug notification because you are a member of C2C
OERPScenario, which is subscribed to the OpenERP Project Group.

Status in OpenObject Addons Modules: Fix Committed

Bug description:
Specifications to Improve Multi-Company in Trunk
=======================================

These specs details security issues for the multi-company only. Others issues (sales -> purchase, outgoing -> incoming) are detailed in others specifications. The security for the multi-company is based on the following concept:
  - multi-company objects have a field called 'company_id': fields.many2one('res.company', 'Company') 
    -> sometimes required, sometimes not. Sometimes with a default value.
  - records are based on record rules that filter objects based on this field.

Modifications in the client and the server so that a user belongs to several companies have already been applied.

Merge Modules
-------------------

We do not need multi-company modules anymore. Every module most be multi-company by default.
In trunk, we must merge multi_company_XXX modules in their respective modules, put directly the
company_id field on the object, no inheritancy of object/view anymore.

Each time you put a company_id field on an object, do:

* A default value (see bellow for more info):
   'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, _name, c)
I don't know if _name will work. Otherwise put the name of the object 'account.invoice'

* Some multi_company fields must be related fields. For example, in sale.order.line:
  'company_id': fields.related('order_id','company_id',type='many2one',object='res.company',string='Company')
Do the same for:
  - purchase.order.line
  - account.invoice.line
  - task.work.line
  

* A record rule like this one for this object:
        <record id="journal_comp_rule_group" model="ir.rule.group">
             <field name="name">Journal multi-company (Children+Parents)</field>
             <field model="ir.model" ref="model_account_journal"/>
             <field eval="True" name="global"/>
         </record>
        <record id="journal_comp_rule" model="ir.rule">
             <field model="ir.model.fields" ref="field_account_journal_company_id"/>
             <field name="domain_force">['|','|',('company_id','=',False),('company_id.child_ids','child_of',[user.company_id.id]),('company_id','child_of',[user.company_id.id])]</field>
             <field name="rule_group" ref="journal_comp_rule_group"/>
         </record>

This rule must be put on all generic objects (partners, products, ...)
For more sensible objects (like all accounting and sales objects), use a rule like this one:
        <record id="journal_comp_rule_group" model="ir.rule.group">
             <field name="name">Journal multi-company (Children)</field>
             <field model="ir.model" ref="model_account_journal"/>
             <field eval="True" name="global"/>
         </record>
         <record id="journal_comp_rule" model="ir.rule">
             <field model="ir.model.fields" ref="field_account_journal_company_id"/>
             <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
             <field name="rule_group" ref="journal_comp_rule_group"/>
         </record>

  -> The way record rules were defined in old multi-company modules was wrong, change all rules to be like the above one.

On the view, add a group on all company_id field, so that users belonging to a single company have a way to hide
all multi-company fields:

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


The multi_company module
-----------------------------------


Develop a multi_company module (or improve the existing one). It has no code nor security rules at all.
It just define demonstration data with a several companies and assign some companies to some products, partners, ...

The default value system
--------------------------------

Put this in the base module, on res.company object:
+    def _company_default_get(self, cr, uid, object=False, context={}):
+        return self.pool.get('res.users').browse(cr, uid, uid).company_id.id

Put this in multi_company module:
+class multi_company_default(osv.osv):
+    _name = 'multi_company.default'
+    _order = 'sequence,id'
+    _columns = {
+        'sequence': fields.integer('Sequence'),
+        'name': fields.char('Name', size=32, required=True),
+        'company_id': fields.many2one('res.company', 'Main Company', required=True),
+        'company_dest_id': fields.many2one('res.company', 'Default Company', required=True),
+        'object_id': fields.many2one('ir.model', 'Object', required=True),
+        'expression': fields.char('Expression', required=True),
+    }
+    _defaults = {
+        'expression': lambda *a: 'True',
+        'sequence': lambda *a: 1
+    }
+multi_company_default()
+
+class res_company(osv.osv):
+    _inherit = 'res.company'
+    def _company_default_get(self, cr, uid, object=False, context={}):
+        proxy = self.pool.get('multi_company.default')
+        ids = proxy.search(cr, uid, [('object_id.name', '=', object)]
+        for rule in proxy.browse(cr, uid, ids, context):
+            user = self.pool.get('res.user').browse(cr, uid, uid)
+            if eval(rule.expression, {'context': context, 'user': user}):
+                return rule.company_dest_id.id
+        return super(res_company, self)._company_default_get(cr, uid, object, context)
+res_company()

Define a menu and a view to configure the multi_company.default object.

Put a security rule a multi_company security rule on this object too.