From 54c74bb4338089908e0e4ce48ccc3d92374561ea Mon Sep 17 00:00:00 2001 From: "Loan (lse)" Date: Fri, 21 Aug 2020 15:24:56 +0000 Subject: [PATCH] [FIX] sale_coupon: Better performance On instances with a lot of coupons programs, performance issue arise while using eccommerce (adding item in basket ant opening it in particular). In the client case, he have ~2000 of them. Opening the basket with 1 product take: Before this commit: ~10s After this commit: ~2s ( pyflame is available in the ticket attachment ) `_get_valid_products` use the v13 `filtered_domain` method Average execution time: Before change: 0.001 s After change: 0.0001 s => 10x times gained The average execution time of `_is_valid_product` is 0.002 s (20 times slower than `_get_valid_products` for the same result). => All use of `_is_valid_product` were replaced by `_get_valid_products` In this commit targeting master, we also completely remove `_is_valid_product` as it effectively is no longer used and there are no stable compatibility requirements. OPW-2323599 closes odoo/odoo#56460 X-original-commit: c3a9738e25dbd773e3ee7c2175e62219346ef764 Signed-off-by: Adrian Torres (adt) --- addons/coupon/models/coupon_program.py | 12 ++---------- addons/sale_coupon/models/coupon_program.py | 2 +- addons/sale_coupon/models/sale_order.py | 4 ++-- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/addons/coupon/models/coupon_program.py b/addons/coupon/models/coupon_program.py index 3232ab63947..dc0a36efa82 100644 --- a/addons/coupon/models/coupon_program.py +++ b/addons/coupon/models/coupon_program.py @@ -139,16 +139,8 @@ class CouponProgram(models.Model): else: return True - def _is_valid_product(self, product): - # NOTE: if you override this method, think of also overriding _get_valid_products - if self.rule_products_domain: - domain = ast.literal_eval(self.rule_products_domain) + [('id', '=', product.id)] - return bool(self.env['product.product'].search_count(domain)) - else: - return True - def _get_valid_products(self, products): if self.rule_products_domain: - domain = ast.literal_eval(self.rule_products_domain) + [('id', 'in', products.ids)] - return self.env['product.product'].search(domain) + domain = ast.literal_eval(self.rule_products_domain) + return products.filtered_domain(domain) return products diff --git a/addons/sale_coupon/models/coupon_program.py b/addons/sale_coupon/models/coupon_program.py index ae348eae340..e600f7b3000 100644 --- a/addons/sale_coupon/models/coupon_program.py +++ b/addons/sale_coupon/models/coupon_program.py @@ -121,7 +121,7 @@ class CouponProgram(models.Model): ordered_rule_products_qty = sum(products_qties[product] for product in valid_products) # Avoid program if 1 ordered foo on a program '1 foo, 1 free foo' if program.promo_applicability == 'on_current_order' and \ - program._is_valid_product(program.reward_product_id) and program.reward_type == 'product': + program.reward_type == 'product' and program._get_valid_products(program.reward_product_id): ordered_rule_products_qty -= program.reward_product_quantity if ordered_rule_products_qty >= program.rule_min_quantity: valid_programs |= program diff --git a/addons/sale_coupon/models/sale_order.py b/addons/sale_coupon/models/sale_order.py index 6b9e3c6b039..742781355ae 100644 --- a/addons/sale_coupon/models/sale_order.py +++ b/addons/sale_coupon/models/sale_order.py @@ -78,10 +78,10 @@ class SaleOrder(models.Model): def _get_reward_values_product(self, program): price_unit = self.order_line.filtered(lambda line: program.reward_product_id == line.product_id)[0].price_reduce - order_lines = (self.order_line - self._get_reward_lines()).filtered(lambda x: program._is_valid_product(x.product_id)) + order_lines = (self.order_line - self._get_reward_lines()).filtered(lambda x: program._get_valid_products(x.product_id)) max_product_qty = sum(order_lines.mapped('product_uom_qty')) or 1 # Remove needed quantity from reward quantity if same reward and rule product - if program._is_valid_product(program.reward_product_id): + if program._get_valid_products(program.reward_product_id): # number of times the program should be applied program_in_order = max_product_qty // (program.rule_min_quantity + program.reward_product_quantity) # multipled by the reward qty