Odoo search domain condition1 and (condition2 or condition3) - odoo

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)

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>

Domain with multiply condition

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)
)
]

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

advanced numpy boolean indexing

I have multiple copies of boolean indexing, and I'm wondering if there is any vectorized way to do the index.
The condition boolean array has shape (3, 2) and both true value and false value have the shape (2, 4)
the desired output shape is (3, 2, 4)
A concrete example:
condition = np.array([[ True, False],
[ False, True],
[ True, False]])
true_value = np.array([[-0.32313401, -1.18761309, 0.4641033 , -0.05341635],
[-0.34072785, 0.45333183, 0.06974008, -1.4338561 ]])
false_value = np.array([[-0.0962484 , 0.5257979 , 1.22036481, 1.41949077],
[ 1.11138278, 0.56253736, 1.57296682, -0.12774857]])
the expected output:
np.array([[[-0.32313401, -1.18761309, 0.4641033 , -0.05341635],
[ 1.11138278, 0.56253736, 1.57296682, -0.12774857]],
[[-0.0962484 , 0.5257979 , 1.22036481, 1.41949077],
[-0.34072785, 0.45333183, 0.06974008, -1.4338561 ]],
[[-0.32313401, -1.18761309, 0.4641033 , -0.05341635],
[ 1.11138278, 0.56253736, 1.57296682, -0.12774857]],
])
was expected to have some where where expected = np.where(condition, true_value, false_value) but it didn't work, right now only value was broadcast to conditions but not the otherway around.
You were very close. In order for np.where to return a 3×2×4 array you need to add a dimension to condition:
expected = np.where(condition[:, :, None], true_value, false_value)
I find a solution via the broadcast product:
expected = condtion[:,:,np.newaxis]*true_value \
+ (~condtion[:,:,np.newaxis])*false_value

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")