[IMP] pos_self_order: Avoid extra _get_attributes_by_ptal_id calls
This commit is a performance fix to improve the speed of opening the pos kiosk or QR code. `_get_attributes` method of pos_self_order's product.product extension will call `self.env["pos.session"]._get_attributes_by_ptal_id()` every time it is called. For *N* products, `_get_attributes` is called *N* times. This can lead to slow performance for high enough *N*, because `_get_attributes_by_ptal_id` method is slow, because it makes many `read` calls to product.attribute.value This commit lifts the call to `_get_attributes_by_ptal_id` higher in the call stack, so that it is only called once as opposed to *N* times. It passes its result into `_get_attributes` via context, which will re-call `_get_attributes_by_ptal_id` if it wasn't in context for backwards compatibility reasons. attributes must be deep copied within `_get_attributes`, because `_add_price_info_to_attributes` mutates the values within, which would invalidate future calls. The deep copy gives a fresh instance for each call, and only copies the applicable attributes so it shouldn't be large. In this particular customer's DB they have 1376 product.product records and their pos config's pricelist (id 36) has 1572 rules in it. Overall, based on the benchmarks below, this commit makes loading the pos about 4-5 times faster. Benchmarks: __Before commit__ _Customer DB_ product.product count == 1376 SQL query count ~= 5034 Time to load pos ~= 44 sec _Customer DB with more products_ product.product count == 3792 SQL query count ~= 9359 Time to load pos ~= 96 sec __After commit__ _Customer DB_ product.product count == 1376 SQL query count ~= 2360 Time to load pos ~= 8 sec _Customer DB with more products_ product.product count == 3792 SQL query count ~= 3906 Time to load pos ~= 22 sec closes odoo/odoo#162962 X-original-commit: f09db068ff3c5a4e8444885c0cdd28e4221cf024 Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com> Signed-off-by: Zachary Hanham (zaha) <zaha@odoo.com>
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
from odoo import api, models, fields
|
||||
from copy import deepcopy
|
||||
|
||||
from odoo.addons.point_of_sale.models.pos_config import PosConfig
|
||||
|
||||
@@ -66,9 +69,16 @@ class ProductProduct(models.Model):
|
||||
def _get_attributes(self, pos_config_sudo: PosConfig) -> List[Dict]:
|
||||
self.ensure_one()
|
||||
|
||||
attributes = self._filter_applicable_attributes(
|
||||
self.env["pos.session"]._get_attributes_by_ptal_id()
|
||||
)
|
||||
attributes = self.env.context.get("cached_attributes_by_ptal_id")
|
||||
|
||||
if attributes is None:
|
||||
attributes = self.env["pos.session"]._get_attributes_by_ptal_id()
|
||||
attributes = self._filter_applicable_attributes(attributes)
|
||||
else:
|
||||
# Performance trick to avoid unnecessary calls to _get_attributes_by_ptal_id()
|
||||
# Needs to be deep-copied because attributes is potentially mutated
|
||||
attributes = deepcopy(self._filter_applicable_attributes(attributes))
|
||||
|
||||
return self._add_price_info_to_attributes(
|
||||
attributes,
|
||||
pos_config_sudo,
|
||||
@@ -200,6 +210,8 @@ class ProductProduct(models.Model):
|
||||
}
|
||||
|
||||
def _get_self_order_data(self, pos_config: PosConfig) -> List[Dict]:
|
||||
attributes_by_ptal_id = self.env["pos.session"]._get_attributes_by_ptal_id()
|
||||
self = self.with_context(cached_attributes_by_ptal_id=attributes_by_ptal_id)
|
||||
return [
|
||||
product._get_product_for_ui(pos_config)
|
||||
for product in self
|
||||
|
||||
Reference in New Issue
Block a user