From 4e693726858d893292ad65f95bbd5d0512e74baf Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Wed, 7 Oct 2020 15:26:47 +0000 Subject: [PATCH] [IMP] sale_coupon: diverse perf improvements * Use set instead of recordset to incrementally join records * avoid filtered and mapped calls when possible * use generators correctly sum([gen]) --> sum(gen) X-original-commit: d3daa3793b8fbc9308ec0fb8935d6991b834f3a5 Co-authored-by: Loan Sens --- addons/sale_coupon/models/coupon_program.py | 44 +++++++++++-------- addons/sale_coupon/models/sale_order.py | 3 +- .../models/sale_coupon_program.py | 2 +- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/addons/sale_coupon/models/coupon_program.py b/addons/sale_coupon/models/coupon_program.py index 885d77b9e1f..37b90551a42 100644 --- a/addons/sale_coupon/models/coupon_program.py +++ b/addons/sale_coupon/models/coupon_program.py @@ -64,27 +64,29 @@ class CouponProgram(models.Model): @api.model def _filter_on_mimimum_amount(self, order): - filtered_programs = self.env['coupon.program'] - no_effect_lines = order._get_no_effect_on_threshold_lines() order_amount = { - 'amount_untaxed' : order.amount_untaxed - sum([line.price_subtotal for line in no_effect_lines]), - 'amount_tax' : order.amount_tax - sum([line.price_tax for line in no_effect_lines]) + 'amount_untaxed' : order.amount_untaxed - sum(line.price_subtotal for line in no_effect_lines), + 'amount_tax' : order.amount_tax - sum(line.price_tax for line in no_effect_lines) } + program_ids = set() for program in self: - lines = order.order_line.filtered(lambda line: - program.reward_type == 'discount' and - (line.product_id == program.discount_line_product_id or - line.product_id == program.reward_id.discount_line_product_id or - (program.program_type == 'promotion_program' and line.is_reward_line) - )) - untaxed_amount = order_amount['amount_untaxed'] - sum([line.price_subtotal for line in lines]) - tax_amount = order_amount['amount_tax'] - sum([line.price_tax for line in lines]) + if program.reward_type != 'discount': + # avoid the filtered + lines = self.env['sale.order.line'] + else: + lines = order.order_line.filtered(lambda line: + line.product_id == program.discount_line_product_id or + line.product_id == program.reward_id.discount_line_product_id or + (program.program_type == 'promotion_program' and line.is_reward_line) + ) + untaxed_amount = order_amount['amount_untaxed'] - sum(line.price_subtotal for line in lines) + tax_amount = order_amount['amount_tax'] - sum(line.price_tax for line in lines) program_amount = program._compute_program_amount('rule_minimum_amount', order.currency_id) if program.rule_minimum_amount_tax_inclusion == 'tax_included' and program_amount <= (untaxed_amount + tax_amount) or program.rule_minimum_amount_tax_inclusion == 'tax_excluded' and program_amount <= untaxed_amount: - filtered_programs |= program + program_ids.add(program.id) - return filtered_programs + return self.browse(program_ids) @api.model def _filter_on_validity_dates(self, order): @@ -116,17 +118,23 @@ class CouponProgram(models.Model): products_qties = dict.fromkeys(products, 0) for line in order_lines: products_qties[line.product_id] += line.product_uom_qty - valid_programs = self.filtered(lambda program: not program.rule_products_domain) - for program in self - valid_programs: + valid_program_ids = set() + for program in self: + if not program.rule_products_domain: + valid_program_ids.add(program.id) + continue valid_products = program._get_valid_products(products) + if not valid_products: + # The program can be directly discarded + continue 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.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 - return valid_programs + valid_program_ids.add(program.id) + return self.browse(valid_program_ids) def _filter_not_ordered_reward_programs(self, order): """ diff --git a/addons/sale_coupon/models/sale_order.py b/addons/sale_coupon/models/sale_order.py index efef2cdebbe..36bdb713421 100644 --- a/addons/sale_coupon/models/sale_order.py +++ b/addons/sale_coupon/models/sale_order.py @@ -361,8 +361,9 @@ class SaleOrder(models.Model): applicable_programs = applicable_programs._keep_only_most_interesting_auto_applied_global_discount_program() programs_to_remove = applied_programs - applicable_programs + reward_product_ids = applied_programs.discount_line_product_id.ids # delete reward line coming from an archived coupon (it will never be updated/removed when recomputing the order) - invalid_lines = order.order_line.filtered(lambda line: line.is_reward_line and line.product_id.id not in (applied_programs).mapped('discount_line_product_id').ids) + invalid_lines = order.order_line.filtered(lambda line: line.is_reward_line and line.product_id.id not in reward_product_ids) if programs_to_remove: product_ids_to_remove = programs_to_remove.discount_line_product_id.ids diff --git a/addons/sale_coupon_delivery/models/sale_coupon_program.py b/addons/sale_coupon_delivery/models/sale_coupon_program.py index d28f74d8910..ca17ed83641 100644 --- a/addons/sale_coupon_delivery/models/sale_coupon_program.py +++ b/addons/sale_coupon_delivery/models/sale_coupon_program.py @@ -19,6 +19,6 @@ class CouponProgram(models.Model): return programs def _check_promo_code(self, order, coupon_code): - if self.reward_type == 'free_shipping' and not order.order_line.filtered(lambda line: line.is_delivery): + if self.reward_type == 'free_shipping' and not any(order.is_delivery for order in order.order_line): return {'error': _('The shipping costs are not in the order lines.')} return super(CouponProgram, self)._check_promo_code(order, coupon_code)