0
votes

I am implementing a module on OpenERP 7.0 to manage requests. Each request may (or may not) have an owner. The owner of a request belongs to some group and in a given moment he might want to give away his request to some other user in the same group. My question goes precisely in that direction. Having to select a user from res.users, is there a way to narrow his search possibilities to the users that belong to the same group he does?


Adding a little more info:

I have 4 groups set up in OpenERP: User, HR Group, Logistics, and Manager In some stage of processing, only users belonging to the HR group (and obviously Manager group) can take action on requests. As I said before, users of HR group make take responsability of a requests becoming owners of it, at this stage, only the owner can make changes on this request. He may, however, need to give the ownership of this request to some other user, belonging to the same HR group. In order to do that, I am opening a wizard where he has to select a user from res.users. Since I will have about 4k users, it would be nicer to narrow his search to the users with the same permissions (also belonging to OpenERP's group created in this module).

Here is the python code of my wizard:

from openerp.osv import osv
from openerp.osv import fields
from openerp.tools.translate import _
import netsvc

class give_request(osv.osv_memory):
    _name='give.request'

    _columns = {
        'assign_to': fields.many2one('res.users', 'Assign request to', help='Person who will be responsible for the next action'), 
        }
    
    def save_info(self, cr, uid, ids, context=None):
        if 'active_id' in context:
            assign_to=self.browse(cr,uid,ids)[0].assign_to
            #import pdb; pdb.set_trace()
            self.pool.get('generic.request').write(cr,uid,context['active_id'],{'assign_to' : assign_to.id})
            wf_service = netsvc.LocalService('workflow')
            wf_service.trg_validate(uid,'generic.request',context['active_id'],'give_request',cr)    
        return {
                'type': 'ir.actions.act_window_close',
         }

give_request()

And the XML view:

<?xml version="1.0" encoding="utf-8"?>
<openerp>
    <data>

        <!-- Give request -->
        <record id="view_give_request_wizard" model="ir.ui.view">
            <field name="name">give_request_wizard.form</field>
            <field name="model">give.request</field>
            <field name="type">form</field>
            <field name="arch" type="xml">
                <form string="Select user" version="7.0">
                    <group >
                        <separator string="Please select the person you want to set the ownership of the request" colspan="2"/>
                        <!--<field name="assign_to" string="Assign to" domain="[('groups_id', 'in', [uid.groups_id])]" />-->
                        <field name="assign_to" string="Assign to"  /> 
                        <newline/>
                    </group>
                    
                    <div style="text-align:right">
                        <button  icon="gtk-cancel" special="cancel" string="Cancel"/>
                        <button  icon="gtk-ok" name="save_info" string="Give the request" type="object" /> 
                    </div>
               </form>
            </field>
        </record>

        <record id="action_give_request" model="ir.actions.act_window">
            <field name="name">Give ownership of the request</field>
            <field name="type">ir.actions.act_window</field>
            <field name="res_model">give.request</field>
            <field name="view_type">form</field>
            <field name="view_mode">form</field>
            <field name="view_id" ref="view_give_request_wizard"/>
            <field name="target">new</field> 
        </record>

        <act_window id="action_give_request"
                name="Give request"
                res_model="give.request" 
                view_mode="form" 
                target="new"
        />

    </data>
</openerp>

I tried to apply a domain filter on my assign_to filter <field name="assign_to" string="Assign to" domain="[('groups_id', 'in', [user.groups_id])]" /> (and later with uid.groups_id), but it didn't work.

Thanks in advance.


New edit, to adapt my code to nitesh's hints.

Now the python code of my wizard looks like this:

class give_request(osv.osv_memory):
    _name='give.request'

    def search(self, cr, uid, domain, offset=0, limit=None, order=None, context=None, count=False):
        cr.execute("SELECT gid FROM res_groups_users_rel WHERE uid="+str(uid))
        group=cr.fetchall()
        names = []
        #import pdb; pdb.set_trace()
        for group_id in group:
            cr.execute("SELECT name FROM res_groups WHERE id="+str(group_id[0]))
            group_name = cr.fetchall()
            names.append(group_name[0][0])
        #Now "names" will contain al the group that the user has assigned to
        #Check if "Hr Group" is present in that group or not
        if 'UC Human Resources' in names:
            domain += [('group','=','UC Human Resources')]
        
        return super(give_request, self).search(cr, uid, domain, offset, limit, order, context, count)

    _columns = {
        #'assign_to': fields.many2one('res.users', 'Assign request to', help='Person who will be responsible for the next action'), 
        'assign_to': fields.function(search, 'Assign request to', help='Person who will be responsible for the next action', type="integer", obj="res.users",  method=True),

        }
    
    def save_info(self, cr, uid, ids, context=None):
        if 'active_id' in context:
            assign_to=self.browse(cr,uid,ids)[0].assign_to
            #import pdb; pdb.set_trace()
            self.pool.get('generic.request').write(cr,uid,context['active_id'],{'assign_to' : assign_to.id})
            wf_service = netsvc.LocalService('workflow')
            wf_service.trg_validate(uid,'generic.request',context['active_id'],'give_request',cr)    
        return {
                'type': 'ir.actions.act_window_close',
         }


give_request()

And didn't make any changes to my XML, since I'm not sure if it is needed or not.

Anyway, with the change I've done, now XML is displayed like thisenter image description here (With a "0" in front of the field of a dropdown, wich is not what I expected, I hoped to get a dropdown here...) And another strange thing is that even thou I added pdb inside the definition of search function it doesn't stop when the wizard loads (shouldn't it stop, since it is called by the field.function?) it stops when I click the save button I guess the assign_to=self.browse(cr,uid,ids)[0].assign_to line of the save_info function calls it (?) and then, when I do the debug, I guess I get an infinite loop.

Otherwise, without the pdb, I get the following trace (after I click the save button):

2014-06-11 14:19:08,063 753 ERROR may_9 openerp.osv.osv: Uncaught exception
Traceback (most recent call last):
  File "/opt/openerp/v7/server/openerp/osv/osv.py", line 131, in wrapper
    return f(self, dbname, *args, **kwargs)
  File "/opt/openerp/v7/server/openerp/osv/osv.py", line 197, in execute
    res = self.execute_cr(cr, uid, obj, method, *args, **kw)
  File "/opt/openerp/v7/server/openerp/osv/osv.py", line 185, in execute_cr
    return getattr(object, method)(cr, uid, *args, **kw)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 3606, in read
    result = self._read_flat(cr, user, select, fields, context, load)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 3726, in _read_flat
    res2 = self._columns[f].get(cr, self, ids, f, user, context=context, values=res)
  File "/opt/openerp/v7/server/openerp/osv/fields.py", line 1133, in get
    result = self._fnct(obj, cr, uid, ids, name, self._arg, context)
  File "/home/lfc/openerp/v7/addons/processos_uc/wizard/give_req_wiz.py", line 23, in search
    return super(give_request, self).search(cr, uid, domain, offset, limit, order, context, count)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 2356, in search
    return self._search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 4847, in _search
    query = self._where_calc(cr, user, args, context=context)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 4676, in _where_calc
    e = expression.expression(cr, user, domain, self, context)
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 642, in __init__
    self.parse(cr, uid, context=context)
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 742, in parse
    self.stack = [ExtendedLeaf(leaf, self.root_model) for leaf in self.expression]
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 528, in __init__
    self.check_leaf()
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 584, in check_leaf
    raise ValueError("Invalid leaf %s" % str(self.leaf))
ValueError: Invalid leaf 16
2014-06-11 14:19:08,068 753 ERROR may_9 openerp.netsvc: Invalid leaf 16
Traceback (most recent call last):
  File "/opt/openerp/v7/server/openerp/netsvc.py", line 292, in dispatch_rpc
    result = ExportService.getService(service_name).dispatch(method, params)
  File "/opt/openerp/v7/server/openerp/service/web_services.py", line 626, in dispatch
    res = fn(db, uid, *params)
  File "/opt/openerp/v7/server/openerp/osv/osv.py", line 188, in execute_kw
    return self.execute(db, uid, obj, method, *args, **kw or {})
  File "/opt/openerp/v7/server/openerp/osv/osv.py", line 131, in wrapper
    return f(self, dbname, *args, **kwargs)
  File "/opt/openerp/v7/server/openerp/osv/osv.py", line 197, in execute
    res = self.execute_cr(cr, uid, obj, method, *args, **kw)
  File "/opt/openerp/v7/server/openerp/osv/osv.py", line 185, in execute_cr
    return getattr(object, method)(cr, uid, *args, **kw)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 3606, in read
    result = self._read_flat(cr, user, select, fields, context, load)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 3726, in _read_flat
    res2 = self._columns[f].get(cr, self, ids, f, user, context=context, values=res)
  File "/opt/openerp/v7/server/openerp/osv/fields.py", line 1133, in get
    result = self._fnct(obj, cr, uid, ids, name, self._arg, context)
  File "/home/lfc/openerp/v7/addons/processos_uc/wizard/give_req_wiz.py", line 23, in search
    return super(give_request, self).search(cr, uid, domain, offset, limit, order, context, count)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 2356, in search
    return self._search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 4847, in _search
    query = self._where_calc(cr, user, args, context=context)
  File "/opt/openerp/v7/server/openerp/osv/orm.py", line 4676, in _where_calc
    e = expression.expression(cr, user, domain, self, context)
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 642, in __init__
    self.parse(cr, uid, context=context)
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 742, in parse
    self.stack = [ExtendedLeaf(leaf, self.root_model) for leaf in self.expression]
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 528, in __init__
    self.check_leaf()
  File "/opt/openerp/v7/server/openerp/osv/expression.py", line 584, in check_leaf
    raise ValueError("Invalid leaf %s" % str(self.leaf))
ValueError: Invalid leaf 16

Not being an expert on python and everyday that passes realising not an expert on OpenERP either, I don't know what I'm doing wrong? Anyone? Thanks in advance!

1
What do you mean by group? Groups which are already implemented in OpenERP/Odoo or new relation to a new model (like request.usergroup or whatever)?CZoellner
I mean OpenERP groups. I edited my question to add a more detailed description and code.Filipe Castanheira

1 Answers

2
votes

You can get it done by the below code.Basically we can get to know all the groups of the User who as logged in.From that try to find the group u want is assigned to him or not.

code:

cr.execute("SELECT gid FROM res_groups_users_rel WHERE uid="+str(uid))
group=cr.fetchall()
names = []
for group_id in group:
    cr.execute("SELECT name FROM res_groups WHERE id="+str(group_id[0]))
    group_name = cr.fetchall()
    names.append(group_name[0][0])
#Now "names" will contain al the group that the user has assigned to
#Check if "Hr Group" is present in that group or not
if 'HR group' in names:
  #Execute your code

Then u need to set the domain.Please make sure that u have a field which tell which group it is.I'm assumimg group is a filed which tells me which group it belongs to.

 def search(self, cr, uid, domain, offset=0, limit=None, order=None, context=None, count=False):
cr.execute("SELECT gid FROM res_groups_users_rel WHERE uid="+str(uid))
    group=cr.fetchall()
    names = []
    for group_id in group:
        cr.execute("SELECT name FROM res_groups WHERE id="+str(group_id[0]))
        group_name = cr.fetchall()
        names.append(group_name[0][0])
    #Now "names" will contain al the group that the user has assigned to
    #Check if "Hr Group" is present in that group or not
    if 'HR group' in names:
        domain += [('group','=','HR group')]
    return super(sale_order, self).search(cr, uid, domain, offset, limit, order, context, count)