Skip to content

Commit

Permalink
[FIX] sale_loyalty: prevent coupon removal on double apply
Browse files Browse the repository at this point in the history
Addresses the issue where reapplying an already applied coupon
in the website shop led to the disappearance of the discount.
With this fix, the discount remains applied, and the system
continues to inform the user that the coupon has already been
used, preventing confusion and maintaining consistency in the
discount application process.

task-3621246

closes #159861

X-original-commit: 64d1feb
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
  • Loading branch information
mathysPaul authored and Feyensv committed Mar 31, 2024
1 parent d65c1b5 commit cb9fe62
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 4 deletions.
4 changes: 2 additions & 2 deletions addons/sale_loyalty/models/sale_order.py
Expand Up @@ -991,7 +991,7 @@ def _try_apply_program(self, program, coupon=None):
if not program.filtered_domain(self._get_program_domain()):
return {'error': _('The program is not available for this order.')}
elif program in self._get_applied_programs():
return {'error': _('This program is already applied to this order.')}
return {'error': _('This program is already applied to this order.'), 'already_applied': True}
# Check for applicability from the program's triggers/rules.
# This step should also compute the amount of points to give for that program on that order.
status = self._program_check_compute_points(program)[program]
Expand Down Expand Up @@ -1059,7 +1059,7 @@ def _try_apply_code(self, code):
if 'error' in apply_result and (not program.is_nominative or (program.is_nominative and not coupon)):
if rule:
self.code_enabled_rule_ids -= rule
if coupon:
if coupon and not apply_result.get('already_applied', False):
self.applied_coupon_ids -= coupon
return apply_result
coupon = apply_result.get('coupon', self.env['loyalty.card'])
Expand Down
60 changes: 58 additions & 2 deletions addons/website_sale_loyalty/tests/test_shop_sale_coupon.py
@@ -1,10 +1,14 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import timedelta

from odoo import fields
from odoo import fields, http
from odoo.exceptions import ValidationError
from odoo.tests import HttpCase, tagged, TransactionCase
from odoo.fields import Command
from odoo.tests import HttpCase, tagged

from odoo.addons.sale.tests.test_sale_product_attribute_value_config import TestSaleProductAttributeValueCommon
from odoo.addons.website.tools import MockRequest
from odoo.addons.website_sale_loyalty.controllers.main import WebsiteSale


@tagged('post_install', '-at_install')
Expand Down Expand Up @@ -366,3 +370,55 @@ def test_03_remove_coupon(self):

msg = "The coupon should've been removed from the order"
self.assertEqual(len(order.applied_coupon_ids), 0, msg=msg)

def test_04_apply_coupon_code_twice(self):
"""This test ensures that applying a coupon with code twice will:
1. Raise an error
2. Not delete the coupon
"""
website = self.env['website'].browse(1)

# Create product
product = self.env['product.product'].create({
'name': 'Product',
'list_price': 100,
'sale_ok': True,
'taxes_id': [],
})

order = self.empty_order
order.write({
'website_id': website.id,
'order_line': [
Command.create({
'product_id': product.id,
}),
]
})

WebsiteSaleController = WebsiteSale()

installed_modules = set(self.env['ir.module.module'].search([
('state', '=', 'installed'),
]).mapped('name'))
for _ in http._generate_routing_rules(installed_modules, nodb_only=False):
pass

with MockRequest(self.env, website=website, sale_order_id=order.id) as request:
# Check the base cart value
self.assertEqual(order.amount_total, 100.0, "The base cart value is incorrect.")

# Apply coupon for the first time
WebsiteSaleController.pricelist(promo=self.coupon.code)

# Check that the coupon has been applied
self.assertEqual(order.amount_total, 90.0, "The coupon is not applied.")

# Apply the coupon again
WebsiteSaleController.pricelist(promo=self.coupon.code)
WebsiteSaleController.cart()
error_msg = request.session.get('error_promo_code')

# Check that the coupon stay applied
self.assertEqual(bool(error_msg), True, "Apply a coupon twice should display an error message")
self.assertEqual(order.amount_total, 90.0, "Apply a coupon twice shouldn't delete it")

0 comments on commit cb9fe62

Please sign in to comment.