diff --git a/addons/auth_ldap/models/res_company_ldap.py b/addons/auth_ldap/models/res_company_ldap.py index 2145196e22e..4b75d9d9a54 100644 --- a/addons/auth_ldap/models/res_company_ldap.py +++ b/addons/auth_ldap/models/res_company_ldap.py @@ -63,8 +63,7 @@ class CompanyLDAP(models.Model): :rtype: list of dictionaries """ - ldaps = self.sudo().search([('ldap_server', '!=', False)], order='sequence') - res = ldaps.read([ + res = self.sudo().search_read([('ldap_server', '!=', False)], [ 'id', 'company', 'ldap_server', @@ -76,7 +75,7 @@ class CompanyLDAP(models.Model): 'user', 'create_user', 'ldap_tls' - ]) + ], order='sequence') return res def _connect(self, conf): diff --git a/addons/calendar/models/res_partner.py b/addons/calendar/models/res_partner.py index b0c7125f56e..692a1689521 100644 --- a/addons/calendar/models/res_partner.py +++ b/addons/calendar/models/res_partner.py @@ -23,7 +23,10 @@ class Partner(models.Model): def _compute_meeting(self): if self.ids: - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) + # prefetch 'parent_id' + all_partners = self.with_context(active_test=False).search_fetch( + [('id', 'child_of', self.ids)], ['parent_id'], + ) query = self.env['calendar.event']._search([]) # ir.rules will be applied query_str, params = query.subselect() @@ -43,7 +46,6 @@ class Partner(models.Model): meetings[m[0]].add(m[1]) # Add the events linked to the children of the partner - all_partners.read(['parent_id']) for p in all_partners: partner = p while partner: diff --git a/addons/crm/models/res_partner.py b/addons/crm/models/res_partner.py index 3582b398f56..e332a79172d 100644 --- a/addons/crm/models/res_partner.py +++ b/addons/crm/models/res_partner.py @@ -45,8 +45,9 @@ class Partner(models.Model): def _compute_opportunity_count(self): # retrieve all children partners and prefetch 'parent_id' on them - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) - all_partners.read(['parent_id']) + all_partners = self.with_context(active_test=False).search_fetch( + [('id', 'child_of', self.ids)], ['parent_id'], + ) opportunity_data = self.env['crm.lead'].with_context(active_test=False)._read_group( domain=[('partner_id', 'in', all_partners.ids)], diff --git a/addons/gamification/models/gamification_challenge.py b/addons/gamification/models/gamification_challenge.py index f6f37e5d87f..ba71207abe0 100644 --- a/addons/gamification/models/gamification_challenge.py +++ b/addons/gamification/models/gamification_challenge.py @@ -513,13 +513,16 @@ class Challenge(models.Model): domain.append(('user_id', '=', user.id)) - goal = Goals.search(domain, limit=1) + goal = Goals.search_fetch(domain, ['current', 'completeness', 'state'], limit=1) if not goal: continue if goal.state != 'reached': return [] - line_data.update(goal.read(['id', 'current', 'completeness', 'state'])[0]) + line_data.update({ + fname: goal[fname] + for fname in ['id', 'current', 'completeness', 'state'] + }) res_lines.append(line_data) continue diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index 78cc8fcde44..fe7b0692a3d 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -594,11 +594,12 @@ class MailActivity(models.Model): def activity_format(self): activities = self.read() - mail_template_ids = set([template_id for activity in activities for template_id in activity["mail_template_ids"]]) - mail_template_info = self.env["mail.template"].browse(mail_template_ids).read(['id', 'name']) - mail_template_dict = dict([(mail_template['id'], mail_template) for mail_template in mail_template_info]) - for activity in activities: - activity['mail_template_ids'] = [mail_template_dict[mail_template_id] for mail_template_id in activity['mail_template_ids']] + self.mail_template_ids.fetch(['name']) + for record, activity in zip(self, activities): + activity['mail_template_ids'] = [ + {'id': mail_template.id, 'name': mail_template.name} + for mail_template in record.mail_template_ids + ] return activities @api.model diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index d9d76ab3d56..ede8f076056 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -742,26 +742,23 @@ class Message(models.Model): messages.set_message_done() return messages.ids - notifications = self.env['mail.notification'].sudo().search(notif_domain) + notifications = self.env['mail.notification'].sudo().search_fetch(notif_domain, ['mail_message_id']) notifications.write({'is_read': True}) - ids = [n['mail_message_id'] for n in notifications.read(['mail_message_id'])] - self.env['bus.bus']._sendone(self.env.user.partner_id, 'mail.message/mark_as_read', { - 'message_ids': [id[0] for id in ids], + 'message_ids': notifications.mail_message_id.ids, 'needaction_inbox_counter': self.env.user.partner_id._get_needaction_count(), }) - return ids - def set_message_done(self): """ Remove the needaction from messages for the current partner. """ partner_id = self.env.user.partner_id - notifications = self.env['mail.notification'].sudo().search([ + notifications = self.env['mail.notification'].sudo().search_fetch([ ('mail_message_id', 'in', self.ids), ('res_partner_id', '=', partner_id.id), - ('is_read', '=', False)]) + ('is_read', '=', False), + ], ['mail_message_id']) if not notifications: return @@ -782,9 +779,8 @@ class Message(models.Model): starred_messages = self.search([('starred_partner_ids', 'in', partner_id)]) starred_messages.write({'starred_partner_ids': [Command.unlink(partner_id)]}) - ids = [m.id for m in starred_messages] self.env['bus.bus']._sendone(self.env.user.partner_id, 'mail.message/toggle_star', { - 'message_ids': ids, + 'message_ids': starred_messages.ids, 'starred': False, }) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 2b3ed38fc6b..f738f3bef27 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -132,37 +132,34 @@ class MailThread(models.AbstractModel): """ # TOFIX make it work with not in assert operator != "not in", "Do not search message_follower_ids with 'not in'" - followers = self.env['mail.followers'].sudo().search([ - ('res_model', '=', self._name), - ('partner_id', operator, operand)]) - # using read() below is much faster than followers.mapped('res_id') - return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])] + # prefetch 'res_id' for the performance of mapped() below + followers = self.env['mail.followers'].sudo().search_fetch( + [('res_model', '=', self._name), ('partner_id', operator, operand)], + ['res_id'], + ) + return [('id', 'in', followers.mapped('res_id'))] @api.depends('message_follower_ids') def _compute_message_is_follower(self): - followers = self.env['mail.followers'].sudo().search([ - ('res_model', '=', self._name), - ('res_id', 'in', self.ids), - ('partner_id', '=', self.env.user.partner_id.id), - ]) - # using read() below is much faster than followers.mapped('res_id') - following_ids = [res['res_id'] for res in followers.read(['res_id'])] + followers = self.env['mail.followers'].sudo().search_fetch( + [('res_model', '=', self._name), ('res_id', 'in', self.ids), ('partner_id', '=', self.env.user.partner_id.id)], + ['res_id'], + ) + following_ids = set(followers.mapped('res_id')) for record in self: record.message_is_follower = record.id in following_ids @api.model def _search_message_is_follower(self, operator, operand): - followers = self.env['mail.followers'].sudo().search([ - ('res_model', '=', self._name), - ('partner_id', '=', self.env.user.partner_id.id), - ]) + followers = self.env['mail.followers'].sudo().search_fetch( + [('res_model', '=', self._name), ('partner_id', '=', self.env.user.partner_id.id)], + ['res_id'], + ) # Cases ('message_is_follower', '=', True) or ('message_is_follower', '!=', False) if (operator == '=' and operand) or (operator == '!=' and not operand): - # using read() below is much faster than followers.mapped('res_id') - return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])] + return [('id', 'in', followers.mapped('res_id'))] else: - # using read() below is much faster than followers.mapped('res_id') - return [('id', 'not in', [res['res_id'] for res in followers.read(['res_id'])])] + return [('id', 'not in', followers.mapped('res_id'))] def _compute_has_message(self): self.env['mail.message'].flush_model() @@ -172,7 +169,7 @@ class MailThread(models.AbstractModel): WHERE res_id = any(%s) AND mm.model=%s """, [self.ids, self._name]) - channel_ids = [r[0] for r in self.env.cr.fetchall()] + channel_ids = {r[0] for r in self.env.cr.fetchall()} for record in self: record.has_message = record.id in channel_ids diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index fdc4b1cd449..c503f5213c9 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -1104,10 +1104,11 @@ class MailComposer(models.TransientModel): self._cr.execute("SELECT email FROM mail_blacklist WHERE active=true") blacklist = {x[0] for x in self._cr.fetchall()} if blacklist: - targets = self.env[self.model].browse(mail_values_dict.keys()).read(['email_normalized']) + targets = self.env[self.model].browse(mail_values_dict.keys()) + targets.fetch(['email_normalized']) # First extract email from recipient before comparing with blacklist - blacklisted_rec_ids.update(target['id'] for target in targets - if target['email_normalized'] in blacklist) + blacklisted_rec_ids.update(target.id for target in targets + if target.email_normalized in blacklist) return blacklisted_rec_ids def _get_done_emails(self, mail_values_dict): diff --git a/addons/mrp_subcontracting/report/mrp_report_bom_structure.py b/addons/mrp_subcontracting/report/mrp_report_bom_structure.py index 7122abb6e59..c753f0c1243 100644 --- a/addons/mrp_subcontracting/report/mrp_report_bom_structure.py +++ b/addons/mrp_subcontracting/report/mrp_report_bom_structure.py @@ -91,13 +91,14 @@ class ReportBomStructure(models.AbstractModel): route_info = product_info.get(parent_product.id, {}).get(parent_bom.id, {}) if route_info and route_info['route_type'] == 'subcontract': subcontracting_loc = route_info['supplier'].partner_id.property_stock_subcontractor - subloc_product = product.with_context(location=subcontracting_loc.id, warehouse=False).read(['free_qty', 'qty_available'])[0] + subloc_product = product.with_context(location=subcontracting_loc.id, warehouse=False) + subloc_product.fetch(['free_qty', 'qty_available']) stock_loc = f"subcontract_{subcontracting_loc.id}" if not product_info[product.id]['consumptions'].get(stock_loc, False): product_info[product.id]['consumptions'][stock_loc] = 0 return { - 'free_qty': product.uom_id._compute_quantity(subloc_product['free_qty'], bom_uom), - 'on_hand_qty': product.uom_id._compute_quantity(subloc_product['qty_available'], bom_uom), + 'free_qty': product.uom_id._compute_quantity(subloc_product.free_qty, bom_uom), + 'on_hand_qty': product.uom_id._compute_quantity(subloc_product.qty_available, bom_uom), 'stock_loc': stock_loc, } diff --git a/addons/point_of_sale/models/account_tax.py b/addons/point_of_sale/models/account_tax.py index c95074d157f..3cd0d4841a9 100644 --- a/addons/point_of_sale/models/account_tax.py +++ b/addons/point_of_sale/models/account_tax.py @@ -13,12 +13,10 @@ class AccountTax(models.Model): 'include_base_amount', 'is_base_affected', ]) if forbidden_fields & set(vals.keys()): - tax_ids = self.env['pos.order.line'].sudo().search([ + open_lines = self.env['pos.order.line'].sudo().search([ ('order_id.session_id.state', '!=', 'closed') - ]).read(['tax_ids']) - # Flatten the list of taxes, see https://stackoverflow.com/questions/952914 - tax_ids = set([i for sl in [t['tax_ids'] for t in tax_ids] for i in sl]) - if tax_ids & set(self.ids): + ]) + if not set(self.ids).isdisjoint(open_lines.tax_ids.ids): raise UserError(_( 'It is forbidden to modify a tax used in a POS order not posted. ' 'You must close the POS sessions before modifying the tax.' diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py index 7635ad2ea08..1c10acb5ea6 100644 --- a/addons/point_of_sale/models/pos_session.py +++ b/addons/point_of_sale/models/pos_session.py @@ -1586,21 +1586,29 @@ class PosSession(models.Model): return loaded_data def _get_attributes_by_ptal_id(self): - product_attributes = self.env['product.attribute'].search([('create_variant', '=', 'no_variant')]) - product_attributes_by_id = {product_attribute.id: product_attribute for product_attribute in product_attributes} - domain = [('attribute_id', 'in', product_attributes.mapped('id'))] - product_template_attribute_values = self.env['product.template.attribute.value'].search(domain) - key = lambda ptav: (ptav.attribute_line_id.id, ptav.attribute_id.id) + # performance trick: prefetch fields with search_fetch() and fetch() + product_attributes = self.env['product.attribute'].search_fetch( + [('create_variant', '=', 'no_variant')], + ['name', 'display_type'], + ) + product_template_attribute_values = self.env['product.template.attribute.value'].search_fetch( + [('attribute_id', 'in', product_attributes.ids)], + ['attribute_id', 'attribute_line_id', 'product_attribute_value_id', 'price_extra'], + ) + product_template_attribute_values.product_attribute_value_id.fetch(['name', 'is_custom', 'html_color']) + + key1 = lambda ptav: (ptav.attribute_line_id.id, ptav.attribute_id.id) + key2 = lambda ptav: (ptav.attribute_line_id.id, ptav.attribute_id) res = {} - for key, group in groupby(sorted(product_template_attribute_values, key=key), key=key): - attribute_line_id, attribute_id = key + for key, group in groupby(sorted(product_template_attribute_values, key=key1), key=key2): + attribute_line_id, attribute = key values = [{**ptav.product_attribute_value_id.read(['name', 'is_custom', 'html_color'])[0], 'price_extra': ptav.price_extra} for ptav in list(group)] res[attribute_line_id] = { 'id': attribute_line_id, - 'name': product_attributes_by_id[attribute_id].name, - 'display_type': product_attributes_by_id[attribute_id].display_type, - 'values': values + 'name': attribute.name, + 'display_type': attribute.display_type, + 'values': values, } return res diff --git a/addons/point_of_sale/models/res_partner.py b/addons/point_of_sale/models/res_partner.py index 8c7348a563a..5ba9d4040fd 100644 --- a/addons/point_of_sale/models/res_partner.py +++ b/addons/point_of_sale/models/res_partner.py @@ -16,9 +16,10 @@ class ResPartner(models.Model): def _compute_pos_order(self): # retrieve all children partners and prefetch 'parent_id' on them - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) - all_partners.read(['parent_id']) - + all_partners = self.with_context(active_test=False).search_fetch( + [('id', 'child_of', self.ids)], + ['parent_id'], + ) pos_order_data = self.env['pos.order']._read_group( domain=[('partner_id', 'in', all_partners.ids)], fields=['partner_id'], groupby=['partner_id'] diff --git a/addons/portal_rating/controllers/portal_rating.py b/addons/portal_rating/controllers/portal_rating.py index 2e8e4884730..6225f9c0243 100644 --- a/addons/portal_rating/controllers/portal_rating.py +++ b/addons/portal_rating/controllers/portal_rating.py @@ -9,7 +9,10 @@ class PortalRating(http.Controller): @http.route(['/website/rating/comment'], type='json', auth="user", methods=['POST'], website=True) def publish_rating_comment(self, rating_id, publisher_comment): - rating = request.env['rating.rating'].search([('id', '=', int(rating_id))]) + rating = request.env['rating.rating'].search_fetch( + [('id', '=', int(rating_id))], + ['publisher_comment', 'publisher_id', 'publisher_datetime'], + ) if not rating: return {'error': _('Invalid rating')} rating.write({'publisher_comment': publisher_comment}) diff --git a/addons/product/models/product_product.py b/addons/product/models/product_product.py index 24234927944..996474c3243 100644 --- a/addons/product/models/product_product.py +++ b/addons/product/models/product_product.py @@ -444,23 +444,21 @@ class ProductProduct(models.Model): result = [] - # Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields - # Use `load=False` to not call `name_get` for the `product_tmpl_id` - self.sudo().read(['name', 'default_code', 'product_tmpl_id'], load=False) + # prefetch the fields used by the `name_get` + self.sudo().fetch(['name', 'default_code', 'product_tmpl_id']) - product_template_ids = self.sudo().mapped('product_tmpl_id').ids + product_template_ids = self.sudo().product_tmpl_id.ids if partner_ids: - supplier_info = self.env['product.supplierinfo'].sudo().search([ - ('product_tmpl_id', 'in', product_template_ids), - ('partner_id', 'in', partner_ids), - ]) - # Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields - # Use `load=False` to not call `name_get` for the `product_tmpl_id` and `product_id` - supplier_info.sudo().read(['product_tmpl_id', 'product_id', 'product_name', 'product_code'], load=False) + # prefetch the fields used by the `name_get` + supplier_info = self.env['product.supplierinfo'].sudo().search_fetch( + [('product_tmpl_id', 'in', product_template_ids), ('partner_id', 'in', partner_ids)], + ['product_tmpl_id', 'product_id', 'company_id', 'product_name', 'product_code'], + ) supplier_info_by_template = {} for r in supplier_info: supplier_info_by_template.setdefault(r.product_tmpl_id, []).append(r) + for product in self.sudo(): variant = product.product_template_attribute_value_ids._get_combination_name() @@ -496,6 +494,7 @@ class ProductProduct(models.Model): 'default_code': product.default_code, } result.append(_name_get(mydict)) + return result @api.model diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index 8aaec3390e2..a38d729d1b8 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -485,7 +485,7 @@ class ProductTemplate(models.Model): def name_get(self): # Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields - self.browse(self.ids).read(['name', 'default_code']) + self.fetch(['name', 'default_code']) return [(template.id, '%s%s' % (template.default_code and '[%s] ' % template.default_code or '', template.name)) for template in self] diff --git a/addons/project/models/res_partner.py b/addons/project/models/res_partner.py index 0259842c659..44a510dd9fd 100644 --- a/addons/project/models/res_partner.py +++ b/addons/project/models/res_partner.py @@ -16,9 +16,10 @@ class ResPartner(models.Model): def _compute_task_count(self): # retrieve all children partners and prefetch 'parent_id' on them - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) - all_partners.read(['parent_id']) - + all_partners = self.with_context(active_test=False).search_fetch( + [('id', 'child_of', self.ids)], + ['parent_id'], + ) task_data = self.env['project.task']._read_group( domain=[('partner_id', 'in', all_partners.ids)], fields=['partner_id'], groupby=['partner_id'] diff --git a/addons/purchase/models/res_partner.py b/addons/purchase/models/res_partner.py index 355b8c93e01..3f47adbefc9 100644 --- a/addons/purchase/models/res_partner.py +++ b/addons/purchase/models/res_partner.py @@ -11,9 +11,10 @@ class res_partner(models.Model): def _compute_purchase_order_count(self): # retrieve all children partners and prefetch 'parent_id' on them - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) - all_partners.read(['parent_id']) - + all_partners = self.with_context(active_test=False).search_fetch( + [('id', 'child_of', self.ids)], + ['parent_id'], + ) purchase_order_groups = self.env['purchase.order']._read_group( domain=[('partner_id', 'in', all_partners.ids)], fields=['partner_id'], groupby=['partner_id'] @@ -30,9 +31,10 @@ class res_partner(models.Model): def _compute_supplier_invoice_count(self): # retrieve all children partners and prefetch 'parent_id' on them - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) - all_partners.read(['parent_id']) - + all_partners = self.with_context(active_test=False).search_fetch( + [('id', 'child_of', self.ids)], + ['parent_id'], + ) supplier_invoice_groups = self.env['account.move']._read_group( domain=[('partner_id', 'in', all_partners.ids), ('move_type', 'in', ('in_invoice', 'in_refund'))], diff --git a/addons/sale/models/res_partner.py b/addons/sale/models/res_partner.py index c4b7a5ab390..b143a05b41a 100644 --- a/addons/sale/models/res_partner.py +++ b/addons/sale/models/res_partner.py @@ -19,9 +19,10 @@ class ResPartner(models.Model): def _compute_sale_order_count(self): # retrieve all children partners and prefetch 'parent_id' on them - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) - all_partners.read(['parent_id']) - + all_partners = self.with_context(active_test=False).search_fetch( + [('id', 'child_of', self.ids)], + ['parent_id'], + ) sale_order_groups = self.env['sale.order']._read_group( domain=expression.AND([self._get_sale_order_domain_count(), [('partner_id', 'in', all_partners.ids)]]), fields=['partner_id'], groupby=['partner_id'] diff --git a/addons/sale/populate/sale_order.py b/addons/sale/populate/sale_order.py index 2c93abc4999..99f04b3d885 100644 --- a/addons/sale/populate/sale_order.py +++ b/addons/sale/populate/sale_order.py @@ -83,7 +83,7 @@ class SaleOrderLine(models.Model): ('product_tmpl_id', 'in', self.env.registry.populated_models["product.template"]) ]).ids - self.env['product.product'].browse(product_ids).read(['uom_id']) # prefetch all uom_id + self.env['product.product'].browse(product_ids).fetch(['uom_id']) # prefetch all uom_id def get_product_uom(values, counter, random): return self.env['product.product'].browse(values['product_id']).uom_id.id diff --git a/addons/spreadsheet_account/models/res_company.py b/addons/spreadsheet_account/models/res_company.py index cd7d049208e..d59642256ab 100644 --- a/addons/spreadsheet_account/models/res_company.py +++ b/addons/spreadsheet_account/models/res_company.py @@ -13,7 +13,7 @@ class ResCompany(models.Model): ) existing_companies = companies.exists() # prefetch both fields - existing_companies.read(["fiscalyear_last_day", "fiscalyear_last_month"]) + existing_companies.fetch(["fiscalyear_last_day", "fiscalyear_last_month"]) results = [] for data, company in zip(payload, companies): diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 12374a69e08..fadc3ae60b0 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -481,7 +481,7 @@ Please change the quantity done or the rounding precision of your unit of measur self.forecast_expected_date = False # Prefetch product info to avoid fetching all product fields - self.product_id.read(['type', 'uom_id'], load=False) + self.product_id.fetch(['type', 'uom_id']) not_product_moves = self.filtered(lambda move: move.product_id.type != 'product') for move in not_product_moves: @@ -2167,17 +2167,24 @@ Please change the quantity done or the rounding precision of your unit of measur product_ids = self.product_id wh_location_query = self.env['stock.location']._search([('id', 'child_of', warehouse.view_location_id.id)]) + # Prefetch data to avoid future request in_domain, out_domain = self.env['stock.forecasted_product_product']._move_confirmed_domain( None, product_ids.ids, wh_location_query ) - outs = self.env['stock.move'].search(out_domain, order='reservation_date, priority desc, date, id') - reserved_outs = self.env['stock.move'].search( + outs = self.env['stock.move'].search_fetch( + out_domain, + ['product_id', 'product_uom', 'product_qty', 'state'], + order='reservation_date, priority desc, date, id', + ) + reserved_outs = self.env['stock.move'].search_fetch( out_domain + [('state', 'in', ('partially_available', 'assigned'))], + ['product_id', 'product_uom'], order='priority desc, date, id') - ins = self.env['stock.move'].search(in_domain, order='priority desc, date, id') - # Prefetch data to avoid future request - (outs - self).read(['product_id', 'product_uom', 'product_qty', 'state'], load=False) # remove self because data is already fetch - ins.read(['product_id', 'product_qty', 'date', 'move_dest_ids'], load=False) + ins = self.env['stock.move'].search_fetch( + in_domain, + ['product_id', 'product_qty', 'date', 'move_dest_ids'], + order='priority desc, date, id', + ) currents = product_ids.with_context(warehouse=warehouse.id)._get_only_qty_available() diff --git a/addons/web/models/ir_http.py b/addons/web/models/ir_http.py index 73a0fa7ebc1..373d4817b57 100644 --- a/addons/web/models/ir_http.py +++ b/addons/web/models/ir_http.py @@ -180,5 +180,8 @@ class Http(models.AbstractModel): def get_currencies(self): Currency = self.env['res.currency'] - currencies = Currency.search([]).read(['symbol', 'position', 'decimal_places']) - return {c['id']: {'symbol': c['symbol'], 'position': c['position'], 'digits': [69,c['decimal_places']]} for c in currencies} + currencies = Currency.search_fetch([], ['symbol', 'position', 'decimal_places']) + return { + c.id: {'symbol': c.symbol, 'position': c.position, 'digits': [69, c.decimal_places]} + for c in currencies + }