How to add a domain to a Many2one field in Odoo? - odoo

I have a custom module to manage students and groups, each group has a list of members (student_ids) and a president (manager_id). The manager should be selected among the list of members. So was traying to add a domain to manager_id field domain="[('id','in',self.student_ids.ids)], so the user can only select a manager from the existing list of students. But that code is giving me an error. What should I do to add that domain to the manager_id field?
class Groups(models.Model):
_name = 'estudiantes.group'
_description = 'Permite manejar los grupos a los que pertenecen los estudiantes'
manager_id = fields.Many2one('estudiantes.student',string='Responsable', domain="[('id','in',self.student_ids.ids)]")
student_ids = fields.Many2many('estudiantes.student', string='Estudiantes')

self is undefined, you can't use it. You should see the following error:
NameError: name 'self' is not defined
You do not need to specify the ids attribute when using an x2many field in the domain, it will be evaluated to a list of ids and if you do that Odoo will raise the following error message:
AttributeError: object has no attribute 'ids'
You have just to specify the field name:
domain="[('id', 'in', student_ids)]"

Related

TypeError: Many2many fields library.book.partner.channel_ids and res.partner.channel_ids use the same table and columns

I'm trying to develop simple library app with Odoo but I get an error with manytomany relationship.
Here are classes:
class Book(models.Model):
_name = "library.book"
publisher_id = fields.Many2one(comodel_name="library.book.partner", string="Publisher")
author_ids = fields.Many2many(comodel_name="library.book.partner", relation='library_book_profile_partner_authors', column1='book_id', column2='partner_id', string="Authors")
class Partner(models.Model):
_name = "library.book.partner"
_inherit = "res.partner"
published_book_ids = fields.One2many("library.book", "publisher_id", string="Published Books")
book_ids = fields.Many2many("library.book", 'partner_books', 'book_id', 'partner_id', string="Authored Books")
This is the error I always get when installing the app
TypeError: Many2many fields library.book.partner.channel_ids and res.partner.channel_ids use the same table and columns
Someone can help to solve this please ?
It's the _inherit = "res.partner". Odoo is inheriting the model with a new model name which means it's creating a new table and copying all fields. For channel_ids it's trying to create the many2many "join" table, but with the same name as in res.partner. That happens because the table name is directly defined in the field (mail_channel_partner).
channel_ids = fields.Many2many('mail.channel', 'mail_channel_partner',
'partner_id', 'channel_id', string='Channels', copy=False)
So to solve the problem you have to "redefine" channel_ids on your new model again and change the table name, for example like:
channel_ids = fields.Many2many(relation='mail_channel_library_book_partner')

explanation of odoo filter domain operator "child_of" and its preference over "in" operator

I am uncertain regarding what child_of does after reading the docs and the use of child_of operator over using in operator for filtering
Odoo v10 domain docs can be found here which states the following for child_of
is a child (descendant) of a value record.
Takes the semantics of the model into account (i.e following the relationship field named by _parent_name)
Consider the model product.product having a many2one field called pos_categ_id that points to model pos.category
To only get products with PoS category id of x, domain value of ['pos_categ_id', 'child_of', x] can be used, however ['pos_categ_id', 'in', [x]] seems to also do the same thing.
In addition to that, in operator can be used for many2many and one2many fields with same format as above example while use of child_of operator for those two field types cause errors.
Example the domain ['session_ids', 'child_of', [572]] where session_ids is a many2many field causes the following error Invalid field 'parent_id' in leaf \"<osv.ExtendedLeaf: ('parent_id', 'in', [572]) on pos_session (ctx: )>\"
So, what is the example case where child_of is preferred over in operator? Both seems to function the same except in can work on all types of relational fields. Second, what does the second line of docs for child_of mean by the phrase following the relationship field named by _parent_name?
No they are not the same, yes they are the same in the simple example that you used:
To only get products with PoS category id of x, domain value of
['pos_categ_id', 'child_of', x] can be used, however ['pos_categ_id',
'in', [x]] seems to also do the same thing.
But consider this case:
# x
# / \
# f b
# / \
# c d
when we do this ['pos_categ_id', 'child_of', x] this will return product that their category is one of this list [x, f, b, c, d] it's equivalent to ['pos_categ_id', 'in', [x, f, b, c, d]].
because they are all child of x (child_of includes x itself).
but this: ['pos_categ_id', 'in', [x]] will return only product that their category is X but will not return product with category b or c ..etc.
To activate this feature in your custom model you should set this attribute
class YourModel(models.Model):
_name = 'some.model'
_parent_name = 'parent_id' # by default its name is parent_id you can change it
_parent_store = True # tell odoo that this model support parent & child relation ship
# same name of _parent_name
parent_id = fields.Many2one('some.model', 'Parent')
Basically child_of functionality is provided by odoo, not python.
But to understand it you must need to knowledge of parent, 'child` relationship in database concept.
If any of your tables are using a self join like below example.
_name = 'my.table'
parent_id = fields.Many2one('my.table', string='Parent Id')
In the above case, your model has connected itself. In this type of cases in Odoo, you can use child_of operator in the domain.
So, it will search in database like parent_id = <your_value>.
For in domain,
You can pass the list of data which you need to search in id field. It similar to any database in operator.
class Partner(models.Model):
_name = 'res.partner'
_parent_name = 'parent_partner_id' # the many2one field used as parent
_parent_store = True
parent_partner_id = fields.Many2one('res.partner', store=True)
parent_path = fields.Char(index=True)

two many2many fields with different partner

i have two fields that should be related to res.partner
in partner_ids i want to choose partner and in recipients_ids i want to choose another partner that will get a copy of the document. the problem that in form view if i change partner_ids or recipient_ids both fields became the same. how can i do that i can choose different partners in those fields?
partners_ids = fields.Many2many('res.partner', string='Companys Names')
recipients_ids = fields.Many2many('res.partner', string='Copys for')
You are getting the error because the two field work on the same table in postgres
because odoo create a table for that name like this:
current_model_name_co_model_name_rel
in your case
your_model_res_partner_rel
so you need to tell odoo that every field has it's own relation
partners_ids = fields.Many2many('res.partner', # co_model
'your_model_partners_rel', # relation name change your_model to much your model name
string='Companys Names')
recipients_ids = fields.Many2many('res.partner',
'your_model_recipients_rel',
string='Copys for')
when you create m2m field it's better to specify this value by keyarguement
_name = 'my.model'
# exmple
user_ids = fields.Many2many(comodel_name='res.users', # name of the model
relation='my_model_users_rel', # name of relation in postgres
column1='session_id', # id reference to current mode
column2='user_id', # id reference to co_model
string='Allowed users')

Odoo custom filter domain field on load view

I'm making a module for reservations in Odoo 9 and one field of my model is populated based if it's reserved or no. Basically my model is:
class Reservation(models.Model):
....
room_id = fields.Many2one('reservation.room', string="Room")
I've defined an onchange function that return a domain to filter the room_ids that aren't reserved:
#api.onchange('date')
def _set_available_room(self):
.....
return {'domain': {'room_id': [('id', 'in', res)]}}
This works fine and when I set the date, the rooms are filtered ok. My problem is when I save a reservation and enter again to edit it. The room_id field show all values and only when I change the date the room_id is filtered.
I've tried using the domain attribute in the field definition like this, but it doesn't works:
room_id = fields.Many2one('reservation.room', string="Room", domain=lambda self: self._get_available_slots())
How can I filter this field on the load view using my function than search for available rooms?

Getting the Employee id of the Log User in Odoo - 8

Good Day I have a problem in filtering of Odoo 8 Field
I just want to Select only the Employee id of the Log User i just add this in my XML
<field name="employee_id" style = "width:500px" domain = "[('id', '=', user.id.employee_id.id)]" options="{'no_create': True}"/>
But I have an Error it says
Uncaught Error: NameError: name 'user' is not defined.
Is there a right way to get the Employee Id of a Log User here in Odoo 8 ?
To obtain the employee of the logged user I do this way:
resource = self.env['resource.resource'].search([('user_id','=',self.env.user.id)])
employee = self.env['hr.employee'].search([('resource_id','=',resource.id)])
Of course it is not easy to put it inside a domain, thus maybe you can use a stored computed field to save the user_id of the employee inside your table, then you can write the domain this way:
[('user_id', '=', uid)]
you may try with below domain:
Replace your code
[('id', '=', user.id.employee_id.id)]
with
[('employee_id.user_id','=',user.id)]
This will filter the user of employee. Based on Logged User, it filter for the Employee's User.
It can be done in much simpler way.
Try this
.py file
employee_id = fields.Many2one('hr.employee', string=u"Employé", readonly=True, store=True, default=_employee_get)
def _employee_get(self):
record = self.env['hr.employee'].search([('user_id', '=', self.env.user.login)])
return record[0]