How to filter Many2one value depend another field? - odoo

please I have a custom module here is a capture :
then I go to Sales order and modify the module sale.order.line i add some fields in relation with my custom module
Now my request is in ligne contrat i want only lignes in the contrat
for example if i choose Contrat 01 only ligne in Contrat 01 like this
here is my code :

You can use a domain in the field definition in your XML:
<field name="contrat_name_id"/>
<field name="contrat_lignes_id" domain="[('ligne_ids', '=', contrat_name_id)]"/>
This will filter contrat_lignes_id to only show records where ligne_ids matches what you entered for contrat_name_id on that line.

What #djames did will work only in this form view if you want
to have this behavior in all your sale.order.line views use python
to do this job for you.
class bons_lines(model.Model):
_inherit = 'sale.order.line'
# your new fields
....
....
#api.onchange('contrat_name_id')
def onchange_contrat_name(self):
if self.contrat_name_id:
# add the domain
self.contrat_lignes_id = False # force the user to reselect the contrat_lignes_id if he changes the contrat name
return {'domain': {'contrat_lignes_id': [('ligne_ids', '=', self.contrat_name_id.id)]}}
else:
# remove the domain
return {'domain': {'contrat_lignes_id': []}}
This way you will not have to add the domain in every XML view you declare.

Related

how to set domain with python in odoo

Is it possible to set domain on the python side without putting it in view?
I tried to set the domain in the customer field (sale order) based on branch in the Customer menu/template
I have tried this but why it doesn't work ?
#api.onchange('partner_id')
def _onchange_cust_domain(self):
for rec in self:
if self.branch_id.id:
cust_list = rec.partner_id.branch_id.id
return {'domain' : {'partner_id' : [('branch_id', '=', cust_list)]}}
To set the partner_id domain when the branch_id field value changes, use the following onchange function:
Example:
#api.onchange('branch_id')
def onchange_branch_id(self):
if self.branch_id:
return {'domain': {'partner_id': ['|', ('branch_id', '=', False), ('branch_id', '=', self.branch_id.id)]}}
Odoo sets by default the following domain from the python code:
['|', ('company_id', '=', False), ('company_id', '=', company_id)]
I think your problem is that you are making a domain for a field partner_id, but in the onchange method of the same field.
It makes no sense to me. So if you put a Customer with branch X, then you can only search customers of branch X for that sale_order (if that domain do the job).
I dont know what are you trying to do exactly, but i think than changing a domain in the same field you are changing the value it is no possible.
Your code would be correct if that domain applies to another field.
This is a working exaple. Notice that onchange field method and field to apply domain are diferent:
#api.onchange('operating_unit_id')
def _applicants_onchange(self):
if self.operating_unit_id:
return {'domain': {'applicant_id': [('default_operating_unit_id', '=', self.operating_unit_id.id)]}}
return {}
Returning a domain using onchange method has been deprecated in Odoo 14.
You can use the new way used by Odoo:
Returning a domain using onchange method has been deprecated in Odoo 14.
You can use this new way.

How to apply an domain on relational field odoo?

Here is my sale.order.line module, I do some modifications
I want to apply a domain on the product that not all product be displayed just products in Ligne contract field for example :
Here in my Contrat line, I Have just one Product so on the Sale order lines only this product (article) must be shown
Use onchane event for this in your sale.order.line
#api.onchange('contrat_id')
def set_domain(self):
# force the user to reselect the producg if he changes the contrat line
self.product_id = False
if self.contrat_id :
return {'domain': {'product_id': [('id', 'in', self.contrat_id.product_ids.ids)]}}
else:
# remove the domain if no contrat is selected
return {'domain': {'product_id': []}}
I'm using my phone sorry if i made a syntax error but I hope you get the idea
Edits
Okay in your contract model you don't have a many2many field to product model as I thought instead you have this one2many field ligne contract
So let suppose that the name of that field is ligne_ids in this one2many relation there is a many2one field to product model let us say its name is product_id.
Use the power of mapped to extract in one line all product ids in the contract lignes.
# many2one -> one2many -> mapped('many2one') this will collect of the records without duplication from the o2m field.
# contract -> contract lignes -> products
self.contrat_lignes_id.ligne_ids.mapped('product_id').ids
Hope this helps you

Show a many2many field as a many2one

I have a field many2many and in a specific view I need to show it as a many2one, or imitate the behavior of the many2one fields (restrict that only one record can be added and if the user select another record, the one that had previously selected will be deleted). In the view I declared:
<field name="employee_ids" widget="many2one" />
but it gave me the following error:
TypeError: 'int' object is not iterable
Is there any way to achieve this?
I think you can force the user to select only one record by
using onchange decorator:
#api.onchange('employee_ids')
def force_one_selection(self):
"""Force the user to select only one record"""
if self.employee_ids and len(self.employee_ids) > 1:
# user has added a new record
self.employee_ids = [(6, 0, self.employee_ids[0].id)] # you can change the index to 1
# and you can return a warning here to tell the user that he should not select more than
# one record

access to many2one fields

I have a many2one field like this
state = fields.Many2one ("ags.traffic.operation.state")
state has the following fields
name = fields.Char
sequence = fields.Integer
type = fields.Selection
in my view i have
<field name = "state" widget = "statusbar" clickable = "True" / >
how can i access those fields to set a default value?
if you want to define the field that gets shown in the drop-down in your view in your model define _rec_name this tells odoo to display that field (in a drop down or in a many2many tag field) when a many2one or one2one relationship is created between that model and another model. for example if you want the sequence number to display in the drop down just set
_recname = 'sequence'
but by default odoo checks the model's field and if it finds a name field (just like you have defined in your model). it uses that as the default display name.
if you want to search records in odoo you can use the search method. please see the documentation for more information about the odoo ORM
https://www.odoo.com/documentation/8.0/reference/orm.html#openerp.models.Model.browse
search(args[, offset=0][, limit=None][, order=None][, count=False])
but a typical example is
search_records = self.env['your.model'].search([('id', 'in', ids)])

Odoo Filter many2one field on load

In my module I have a many2one field to select workers for a particular task. According to the requirement that field should only display the workers in the current user's department. Simply this is the code,
_columns = {
'employee_id': fields.many2one('hr.employee', 'Employee'),
}
My problem is how to perform such filteration for a field on load? I tried using functional field in a domain in view xml. but It seems functional field gets its value when saving the particular record.
Also I tried adding domain to the field itself, here get_current_user_department is a function returns the department id
_columns = {
'employee_id': fields.many2one('hr.employee', 'Employee',domain=[('department_id.id','=',get_current_user_department)]),
}
This generates following error,
TypeError: is not JSON serializable
Any suggestion to make this work? Thanks
Also you can take one field for storing current user department you can set default value of current user department.
default_department_id = fields.Many2one('employee.department',
string='My User',
default='get_department')
Now you need to create function for set default department.
After that you need to write in XML:
<field name="default_department_id" invisible="1"/>
<field name="employee_id"
domain="
[('department_id','=',default_department_id)]
"/>
You have to define a new many2one field to save the current user department ID and put the value of the department at loading with default_get() method.
Then after, you can put this field on a domain to filter employee that are in the same department than the user.