Make invisible a field when one of the options is true in Odoo - odoo

I want to make invisible a field if one of those options are true, I don't know if this is possible.
I try:
<field name="x_field1" string="something" attrs="{'invisible': [('x_field2','!=','value'),'|',('x_field3','=','value'),'|',('x_field4','=','value')]}"/>
And this:
<field name="x_field1" string="something" attrs="{'invisible': ['|',('x_field2','!=','value'),('x_field3','=','value'),('x_field4','=','value')]}"/>
Without success.

From Odoo Domains documentation:
'|'logical OR, arity 2.
You have three options, so you need to use two | operators, like the following:
['|', '|', ('x_field2', '!=', 'value'), ('x_field3', '=', 'value'), ('x_field4', '=', 'value')]

Related

Using invisible attribute with '&' in Odoo view

I am trying to make a button in an Odoo view invisible when two conditions are both met.I am able to make the field invisible when either of the conditions are met like this:
attrs="{'invisible': [('status', '!=', 'validated'),('api_result', '!=', 'Valid')]}"
I want the button to be visible only when status == "validated" && api_result == "Valid"
But when I try to introduce the "&" I get an error. There's a long traceback which I'm not attaching now because I assume there is something wrong with my syntax:
attrs="{'invisible': ['&',('status', '!=', 'validated'),('api_result', '!=', 'Valid')]}"
I admit that I find the syntax 'challenging' and haven't been able to find any clear documentation, so I would appreciate a pointer.
You can do that using or as below:
attrs="{'invisible': ['|',('status', '!=', 'validated'),('api_result', '!=', 'Valid')]}"

How to conditionally hide rows in One2Many field tree in a form view? [duplicate]

In my module I want to filter one2many records based on current date.
This is my xml code
<field name="record_ids" domain="[('end_date', '>', cur_date)]">
<tree string="records_tree">
<field name="record_id"/>
<field name="record"/>
<field name="start_date"/>
<field name="end_date"/>
</tree>
</field>
cur_date is a functional field I added to get current date.
My problem is records are not filtered in the view. Also it doesn't show any error message
you are define the domain in the XML file .
so this domain it's not work .
please define in the .py file .
For Example :
'record_ids':fields.one2many('model_name','model_id','Record',domain=[('end_date', '>=', 'cur_date')])
here the cur_date you need to define one function field which show the current date.
So Please check this may be it's help full to you :).
I also faced this problem, and the solution is put domain in .py file, in .xml domain is not working properly.
import_transaction_log_ids = fields.One2many(comodel_name = 'transaction.log','sale_order_id', string = 'Import Transaction Log',domain=[('operation_type','=','import')])
in example operation_type field is in transaction.log model.
Write domain in end_date field, like this:
<field name="record_ids" >
<tree string="records_tree">
<field name="record_id"/>
<field name="record"/>
<field name="start_date"/>
<field name="end_date" domain="[('end_date', '>', cur_date)]"/>
</tree>
</field>
i think it will help you..
you can pass only those field in domain those are store in Database.
So in that case cur_date is not store in Database.
Then also you need to pass into domain so you need to store cur_date field from py.
first of all, one2many fields are not for selection purpose. We can create the new records or update the existing records in one2many field. so we cannot apply domain to a one2many field.
eg: sale_order_line field in sale.order
moreover one2many fields, functional_fields [**if store=True not specified ] wont store in the table.
Many2one or Many2Many are used for selecting the records [ as well as creating new ones ], so here we can apply domain and we can restrict the user to select some type of records
eg: Many2one- product_id field in sale.order.line
many2many - user_ids field in res.users
So, in order to get your task, try many2many and apply domain, then the records will be filtered
domain contains 'field name' 'expression' 'value'.
instead of value you given a field
<field name="record_ids" domain="[('field', 'expression', value)]">
Add it in python:
Eg:
xn_cutting_ids = fields.One2many('mrp.bom.line', 'bom_id', 'Cutting Lines', domain=lambda self:[('xn_stage','=','cut')])
Use domain = lambda else there is a chance of error while using string values in domain.
Here xn_stage is in mrp.bom.line model.
On Odoo V11
Define a function that returns a domain in the one2many field definition.
class GroupContract(models.Model):
_name = 'group.contract'
#api.multi
def _domain_move_ids(self):
"""Odoo default domain for many2one field is [('contract_id', '=', self.id)].
This function adds new criteria according to your needs"""
res = []
if len(self) == 1: # do not compute in tree view
ids = self.env['stock.move'].search([
('state', '=', 'done'),
('date', '>=', self.start_date),
('date', '<=', self.end_date)
]).ids # choose your own criteria
res = [('id', 'in', ids)]
return res
start_date = fields.Date(string="Start date", required=True)
end_date = fields.Date(string="End date", required=True)
move_ids = fields.One2many(comodel_name='stock.move', inverse_name='contract_id', string="Moves",
domain=lambda self: self._domain_move_ids())

i have a many2many table,But i need to give domain as only the partner's record in the model needs to be shown in the many2many table

class HealthProfileInherit(models.Model):
_inherit = 'health.profile'
health_profile_health_test_id = fields.Many2many('health.test',
string ='Laboratory Test')
this the field connecting the 2 tables, how will give domain here? Do I wanna write a function or can give domain inside the field?
The following domain:
domain="[('partner_id', '=', partner_id)]"
will filter records shown in the popup list after you click on the add item button link. only the test records with the profile partner will be visible.
String domains are supposed to be dynamic and evaluated on the client-side only.
By default, users can create records from the popup list and they can select any partner in the partner_id field.
If you want to disable the creation option from the popup list use the no_create option:
options="{'no_create': True}"
If you want to keep the create button and force users to select the profile partner, you can create a new form for the health.test model and set the partner field invisible then pass the default partner value in context and force the many2many field to use that form.
<field name="health_profile_health_test_id"
domain="[('partner_id', '=', partner_id)]"
context="{'form_view_ref': 'module_name.health_test_form', 'default_partner_id': partner_id}"/>
Remember that the form view with the lowest priority will be used as the default form view (The default priority value is 16):
Example:
<record id="health_test_form" model="ir.ui.view">
<field name="name">health.test Form</field>
<field name="model">health.test</field>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<form>
<group>
<field name="partner_id" invisible="True"/>
....
</group>
....
</form>
</field>
</record>
Edit:
String domains are dynamic and evaluated in client-side, for example the "[('partner_id', '=', partner_id)]" string domain will be evaluated to [('partner_id', '=', 26)] and if the list has already selected records, the records will be excluded using ['!', ['id', 'in', list_of_ids]].
But when passing the domain as a list with the many2one field reference, the value will be of type Many2one and the server should raise a RecursionError when trying to get field attributes (tested in v12, v13).
If you look in the Odoo source code you will find many examples using a list domain but with simple values like booleans, strings, etc.

Odoo If statement with category

Hi I am using Odoo10 and I have some products assigned to categorys. On my Sale Order screen I have 2 selection boxes one is Carpet and the other is Flooring. Below is my code for showing cetain fields
#api.onchange('squarebox')
def _onchange_default_code(self):
if self.flooring2:
self.boxes = (self.squaremtr) / (self.squarebox or 1)
self.squaremtrsold = (self.squarebox or 1) * (self.suggestbox)
Instead of using a selection field I was wondering if it is possible to do an IF statement based on Category the product is in. So instead of if self.flooring2:something like
if self.productid is in category Carpet:
First add this two category in Category Master then select this Internal category in Product you want.
Your XML File :
<record id="category_flooring" model="product.category">
<field name="name">Flooring</field>
<field name="type">normal</field>
<field name="property_cost_method">standard</field>
<field name="property_valuation">manual_periodic</field>
</record>
<record id="category_carpet" model="product.category">
<field name="name">Carpet</field>
<field name="type">normal</field>
<field name="property_cost_method">standard</field>
<field name="property_valuation">manual_periodic</field>
</record>
Now your python code goes like this:-
#api.onchange('product_id')
def _onchange_default_code(self):
if self.product_id.categ_id.id == self.env.ref('your_module_name.category_flooring').id:
# Your code belongs to flooring category
elif self.product_id.categ_id.id == self.env.ref('your_module_name.category_carpet').id:
# Your code belongs to carpet category
If I understand correctly, you want to show or hide some fields depending on values from other fields of the same record.
To do so use the invisible attribute on the form view definition, not a python function. I would use a python function decorated with an #api.onchange to calculate other values that depend on squarebox.
See for example addons/sale/views/sale_views.xml around line 227:
<field name="validity_date" attrs="{'invisible': [('state', 'in', ['sale', 'done'])]}"/>
The line above translates to plain English as: Show the validity_date field except when the state field is either sale or done.

Domain for one2many not working Odoo

In my module I want to filter one2many records based on current date.
This is my xml code
<field name="record_ids" domain="[('end_date', '>', cur_date)]">
<tree string="records_tree">
<field name="record_id"/>
<field name="record"/>
<field name="start_date"/>
<field name="end_date"/>
</tree>
</field>
cur_date is a functional field I added to get current date.
My problem is records are not filtered in the view. Also it doesn't show any error message
you are define the domain in the XML file .
so this domain it's not work .
please define in the .py file .
For Example :
'record_ids':fields.one2many('model_name','model_id','Record',domain=[('end_date', '>=', 'cur_date')])
here the cur_date you need to define one function field which show the current date.
So Please check this may be it's help full to you :).
I also faced this problem, and the solution is put domain in .py file, in .xml domain is not working properly.
import_transaction_log_ids = fields.One2many(comodel_name = 'transaction.log','sale_order_id', string = 'Import Transaction Log',domain=[('operation_type','=','import')])
in example operation_type field is in transaction.log model.
Write domain in end_date field, like this:
<field name="record_ids" >
<tree string="records_tree">
<field name="record_id"/>
<field name="record"/>
<field name="start_date"/>
<field name="end_date" domain="[('end_date', '>', cur_date)]"/>
</tree>
</field>
i think it will help you..
you can pass only those field in domain those are store in Database.
So in that case cur_date is not store in Database.
Then also you need to pass into domain so you need to store cur_date field from py.
first of all, one2many fields are not for selection purpose. We can create the new records or update the existing records in one2many field. so we cannot apply domain to a one2many field.
eg: sale_order_line field in sale.order
moreover one2many fields, functional_fields [**if store=True not specified ] wont store in the table.
Many2one or Many2Many are used for selecting the records [ as well as creating new ones ], so here we can apply domain and we can restrict the user to select some type of records
eg: Many2one- product_id field in sale.order.line
many2many - user_ids field in res.users
So, in order to get your task, try many2many and apply domain, then the records will be filtered
domain contains 'field name' 'expression' 'value'.
instead of value you given a field
<field name="record_ids" domain="[('field', 'expression', value)]">
Add it in python:
Eg:
xn_cutting_ids = fields.One2many('mrp.bom.line', 'bom_id', 'Cutting Lines', domain=lambda self:[('xn_stage','=','cut')])
Use domain = lambda else there is a chance of error while using string values in domain.
Here xn_stage is in mrp.bom.line model.
On Odoo V11
Define a function that returns a domain in the one2many field definition.
class GroupContract(models.Model):
_name = 'group.contract'
#api.multi
def _domain_move_ids(self):
"""Odoo default domain for many2one field is [('contract_id', '=', self.id)].
This function adds new criteria according to your needs"""
res = []
if len(self) == 1: # do not compute in tree view
ids = self.env['stock.move'].search([
('state', '=', 'done'),
('date', '>=', self.start_date),
('date', '<=', self.end_date)
]).ids # choose your own criteria
res = [('id', 'in', ids)]
return res
start_date = fields.Date(string="Start date", required=True)
end_date = fields.Date(string="End date", required=True)
move_ids = fields.One2many(comodel_name='stock.move', inverse_name='contract_id', string="Moves",
domain=lambda self: self._domain_move_ids())