summaryrefslogtreecommitdiff
path: root/addons/sale_coupon
diff options
context:
space:
mode:
authorVictor Feyens <vfe@odoo.com>2020-10-07 17:21:20 +0000
committerVictor Feyens <vfe@odoo.com>2020-10-19 12:46:42 +0000
commit679ebc3381179f6b18364c6f2b4d4f7f34274698 (patch)
treefff7d43d14bb1b9d5dc295dbb3db4528b22ec659 /addons/sale_coupon
parentd3daa3793b8fbc9308ec0fb8935d6991b834f3a5 (diff)
[FIX] sale_coupon: avoid duplicated checks/filters
Avoid filtering/checking the same condition multiple times on the same records... This allows to avoid n more fetch of all applicable coupon programs from the database (because _check_promo_code is called on each program in a loop). Also apply the date filter directly in SQL: * The computation of inherited fields (_inherits) by the orm is intrinsically slow. The fields rule_date_from and rule_date_to checked in the _filter_on_validity_dates python filter are inherited from sale.coupon.program.rule model. * Filtering recordsets in SQL is faster. closes odoo/odoo#60247 X-original-commit: 294628df479fba4db5e7859f1fc2d2b13bae8c6f Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Diffstat (limited to 'addons/sale_coupon')
-rw-r--r--addons/sale_coupon/models/coupon_program.py9
-rw-r--r--addons/sale_coupon/models/sale_order.py18
2 files changed, 20 insertions, 7 deletions
diff --git a/addons/sale_coupon/models/coupon_program.py b/addons/sale_coupon/models/coupon_program.py
index 37b90551a42..68ef639a075 100644
--- a/addons/sale_coupon/models/coupon_program.py
+++ b/addons/sale_coupon/models/coupon_program.py
@@ -30,7 +30,6 @@ class CouponProgram(models.Model):
def _check_promo_code(self, order, coupon_code):
message = {}
- applicable_programs = order._get_applicable_programs()
if self.maximum_use_number != 0 and self.order_count >= self.maximum_use_number:
message = {'error': _('Promo code %s has been expired.') % (coupon_code)}
elif not self._filter_on_mimimum_amount(order):
@@ -57,8 +56,9 @@ class CouponProgram(models.Model):
message = {'error': _("The customer doesn't have access to this reward.")}
elif not self._filter_programs_on_products(order):
message = {'error': _("You don't have the required product quantities on your sales order. If the reward is same product quantity, please make sure that all the products are recorded on the sales order (Example: You need to have 3 T-shirts on your sales order if the promotion is 'Buy 2, Get 1 Free'.")}
- else:
- if self not in applicable_programs and self.promo_applicability == 'on_current_order':
+ elif self.promo_applicability == 'on_current_order' and not self.env.context.get('applicable_coupon'):
+ applicable_programs = order._get_applicable_programs()
+ if self not in applicable_programs:
message = {'error': _('At least one of the required conditions is not met to get the reward!')}
return message
@@ -160,7 +160,8 @@ class CouponProgram(models.Model):
# Minimum requirement should not be checked if the coupon got generated by a promotion program (the requirement should have only be checked to generate the coupon)
if not next_order:
programs = programs and programs._filter_on_mimimum_amount(order)
- programs = programs and programs._filter_on_validity_dates(order)
+ if not self.env.context.get("no_outdated_coupons"):
+ programs = programs and programs._filter_on_validity_dates(order)
programs = programs and programs._filter_unexpired_programs(order)
programs = programs and programs._filter_programs_on_partners(order)
# Product requirement should not be checked if the coupon got generated by a promotion program (the requirement should have only be checked to generate the coupon)
diff --git a/addons/sale_coupon/models/sale_order.py b/addons/sale_coupon/models/sale_order.py
index 36bdb713421..d5711874e2e 100644
--- a/addons/sale_coupon/models/sale_order.py
+++ b/addons/sale_coupon/models/sale_order.py
@@ -254,8 +254,12 @@ class SaleOrder(models.Model):
This method is used to return the valid applicable programs on given order.
"""
self.ensure_one()
- programs = self.env['coupon.program'].search([
- ('company_id', 'in', [self.company_id.id, False])
+ programs = self.env['coupon.program'].with_context(
+ no_outdated_coupons=True,
+ ).search([
+ ('company_id', 'in', [self.company_id.id, False]),
+ '|', ('rule_date_from', '=', False), ('rule_date_from', '<=', self.date_order),
+ '|', ('rule_date_to', '=', False), ('rule_date_to', '>=', self.date_order),
], order="id")._filter_programs_from_common_rules(self)
# no impact code...
# should be programs = programs.filtered if we really want to filter...
@@ -265,8 +269,13 @@ class SaleOrder(models.Model):
def _get_applicable_no_code_promo_program(self):
self.ensure_one()
- programs = self.env['coupon.program'].search([
+ programs = self.env['coupon.program'].with_context(
+ no_outdated_coupons=True,
+ applicable_coupon=True,
+ ).search([
('promo_code_usage', '=', 'no_code_needed'),
+ '|', ('rule_date_from', '=', False), ('rule_date_from', '<=', self.date_order),
+ '|', ('rule_date_to', '=', False), ('rule_date_to', '>=', self.date_order),
'|', ('company_id', '=', self.company_id.id), ('company_id', '=', False),
])._filter_programs_from_common_rules(self)
return programs
@@ -288,6 +297,9 @@ class SaleOrder(models.Model):
programs = order._get_applicable_no_code_promo_program()
programs = programs._keep_only_most_interesting_auto_applied_global_discount_program()
for program in programs:
+ # VFE REF in master _get_applicable_no_code_programs already filters programs
+ # why do we need to reapply this bunch of checks in _check_promo_code ????
+ # We should only apply a little part of the checks in _check_promo_code...
error_status = program._check_promo_code(order, False)
if not error_status.get('error'):
if program.promo_applicability == 'on_next_order':