Domain with multiply condition - odoo

I have a domain like this
[('product_id.fix', '!=', False), '|', ('trigger', '=', 'auto'), ('product_id.active', '=', True), ('company_id', '=', 1), ('qty_forecast', '<', 0)]
and I tried it like this
[ '|',('product_id.fix', '!=', False), ('trigger', '=', 'auto'), ('product_id.active', '=', True), ('company_id', '=', 1), ('qty_forecast', '<', 0)]
and my search not getting any result
if i add to domain only [('product_id.fix', '!=', False)] then it return some record.
But basically, I want that search would return any record that suits this part [('product_id.fix', '!=', False)] and plus ('trigger', '=', 'auto'), ('product_id.active', '=', True), ('company_id', '=', 1), ('qty_forecast', '<', 0)
so first search need to find all records that where product_id.fix != False and then all records with other conditions

If you write it like your second expample, you would get:
(condition-1 OR condition-2) AND all-other-conditions
to get:
condition-1 OR all-other conditions
, you should write it like this:
[
'|',
('product_id.fix', '!=', False),
(
('trigger', '=', 'auto'),
('product_id.active', '=', True),
('company_id', '=', 1),
('qty_forecast', '<', 0)
)
]

Related

Odoo 15 Search non-stored compute value that depends on search_count of many2one field

I'm trying to display a view with certain products that have multiple BoM's. I've created a computed field that labels which records should be displayed. I'm trying to create a search function so that the records in interest can be displayed as a filter but am having trouble creating the function.
Currently trying to append record.id's of interest into a list and returning the list within the search domain but that is not working. Any help would be much appreciated. Please see code below and thanks in advance!
I tried the following code but it returns an empty data list. I think there's something wrong with how I'm getting the id of the current record and appending it to the list that is returned.
class products_ppa_bom_check(models.Model):
_inherit = ['product.template']
ppa_multi_bom = fields.Selection([
('true', 'True'),
('false', 'False'),
('na', 'Not Applicable')],
string="PPA Multi BOM Check", compute='_compute_ppa_multi_bom',
search='_search_ppa_multi_bom')
def _compute_ppa_multi_bom(self):
for record in self:
count = record.env['mrp.bom'].search_count(['|', ('product_tmpl_id', '=', record.id), ('byproduct_ids.product_id.product_tmpl_id', '=', record.id)])
if (count > 1) and ('PPA' in str(record.default_code)):
record.ppa_multi_bom = 'true'
elif (count == 1) and ('PPA' in str(record.default_code)):
record.ppa_multi_bom = 'false'
else: record.ppa_multi_bom = 'na'
def _search_ppa_multi_bom(self, operator, value):
ids = []
for record in self:
count = record.env['mrp.bom'].search_count(['|', ('product_tmpl_id', '=', record.id), ('byproduct_ids.product_id.product_tmpl_id', '=', record.id)])
if (count > 1) and ('PPA' in str(record.default_code)):
ids = ids.append(record.id)
return[('id', 'in', ids)]
If you want to use a filter in products with = operator, you can use the below code which I already tested:
You can use bom_count field rather than use search_count method
from odoo import api, fields, models, _
class products_ppa_bom_check(models.Model):
_inherit = ['product.template']
ppa_multi_bom = fields.Selection([
('true', 'True'),
('false', 'False'),
('na', 'Not Applicable')],
string="PPA Multi BOM Check", compute='_compute_ppa_multi_bom',
search='_search_ppa_multi_bom')
def _compute_ppa_multi_bom(self):
for record in self:
if (record.bom_count > 1) and ('PPA' in str(record.default_code)):
record.ppa_multi_bom = 'true'
elif (record.bom_count == 1) and ('PPA' in str(record.default_code)):
record.ppa_multi_bom = 'false'
else:
record.ppa_multi_bom = 'na'
def _search_ppa_multi_bom(self, operator, value):
true_ids = self.env['product.template'].search([]).filtered(
lambda x: x.bom_count > 1 and 'PPA' in str(x.default_code)).ids
false_ids = self.env['product.template'].search([]).filtered(
lambda x: x.bom_count == 1 and x.default_code and 'PPA' in x.default_code).ids
if value == 'true':
ids = true_ids
elif value == 'false':
ids = false_ids
else:
all_ids = self.env['product.template'].search([]).ids
ids = list(set(all_ids) - set(true_ids + false_ids))
return [('id', 'in', ids)]
To add filter to search view:
<record id="product_template_search_view_inherit_bom" model="ir.ui.view">
<field name="name">product.template.search.inherit.bom</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_search_view"/>
<field name="arch" type="xml">
<xpath expr="//filter[#name='consumable']" position="after">
<separator/>
<filter string="Multi BOM" name="ppa_multi_bom" domain="[('ppa_multi_bom', '=', 'true')]"/>
<filter string="One BOM" name="ppa_one_bom" domain="[('ppa_multi_bom', '=', 'false')]"/>
<filter string="NA BOM" name="ppa_na_bom" domain="[('ppa_multi_bom', '=', 'na')]"/>
</xpath>
</field>
</record>

Odoo search domain condition1 and (condition2 or condition3)

I am trying to construct an Odoo domain query with a logic of
(Condition 1) AND (Condition 2 OR Condition3)
This is the code I've written:
moves = self.env['account.move'].search(
[(
"&",
('sftp_uploaded', '=', False),
"|",
('move_type', 'in', ['entry']),
('move_type', 'in', ['out_receipt']),
)], limit=200)
Running this returns a strange error
ValueError: <class 'TypeError'>: "unhashable type: 'list'" while
evaluating 'model._sftp_cron_action()'
In the same function the following code works fine
moves = self.env['account.move'].search(
[(
'move_type', 'in', ['out_invoice']),
('sftp_uploaded', '=', False
)], limit=20)
You have one extra pair of parentheses.
moves = self.env['account.move'].search(
[
"&",
('sftp_uploaded', '=', False),
"|",
('move_type', 'in', ['entry']),
('move_type', 'in', ['out_receipt']),
], limit=200)

Odoo - How to search by date

I want to search a list of object based on date field
reservations = self.env['rm.reservation'].search([
('check_in', '=', self.check_in)
])
But when I run the Odoo, I get a runtime error
ValueError: Invalid field rm.reservation.check_in in leaf ('check_in', '=', datetime.date(2021, 12, 20))
This is the check_in field declaration in the reservation model class
check_in = fields.Date(string='Check In', required=True,
default=lambda self: fields.date.today())
Sorry this is my fault, I should call
reservations = self.env['rm.reservation.room.line'].search([
('check_in', '=', self.check_in)
])
And this is solve the problem

Change Many2one domain based on selection field

I want to change M2O field domain based on the user selection from selection field:
#api.onchange('search_by')
def _get_partner(self):
partners = self.env['customer.regist'].search([('name','!=','New')])
partner_list = []
partner_list2 = []
for rec in partners:
partner_list.append(rec.name)
partner_list2.append(rec.phone)
res = {}
if self.search_by == 'code':
res['domain'] = {'search_value': [('name', 'in', partner_list)]}
if self.search_by == 'phone':
res['domain'] = {'search_value': [('phone', 'in', partner_list2)]}
return res
but the domain not change and get the default domain from model
Change your function like this.
#api.onchange('search_by')
def _get_partner(self):
partners = self.env['customer.regist'].search([('name','!=','New')])
partner_list = []
partner_list2 = []
for rec in partners:
partner_list.append(rec.name)
partner_list2.append(rec.phone)
res = {}
if self.search_by == 'code':
domain = {'search_value': [('name', 'in', partner_list)]}
return {'domain': domain}
if self.search_by == 'phone':
domain = {'search_value': [('phone', 'in', partner_list2)]}
return {'domain': domain}
Try doing this :
#api.onchange('search_by')
def _get_partner(self):
partners = self.env['customer.regist'].search([('name','!=','New')])
partner_list = []
partner_list2 = []
for rec in partners:
if rec.name :
partner_list.append(rec.name)
if rec.phone:
partner_list2.append(rec.phone)
res = {}
if self.search_by == 'code':
res['domain'] = {'search_value': [('name', 'in', partner_list)]}
if self.search_by == 'phone':
res['domain'] = {'search_value': [('phone', 'in', partner_list2)]}
return res
Make sure that the 'False' values are never added to the domain, since it might give invalid results

Show the error message

how to show the error message "The room was already booked" . i want to check by ** room_id,** start** , how it is possible?
py file
_columns = {
'room_id' : fields.many2one('room.management', string="Room Booking"),
'duration': fields.integer('Duration'),
'reason': fields.char('Reason',requierd=True ,help="short deatails about booking"),
'start': fields.datetime('Start At',requierd=True),
'end': fields.datetime('End At',requierd=True),
}
You can use a constrains method decorator:
#api.one
#api.constrains('start', 'end', 'room_id')
def _check_room_overlap(self):
overlaping_bookings = self.search_count([
('room_id', '=', self.room_id.id),
('start', '<', self.end),
('end', '>', self.start),
])
if overlaping_bookings:
raise exceptions.ValidationError("The room was already booked")