[FIX] website_sale_coupon: correctly handle multiwebsite
Steps to reproduce: - Create an automatic promotional program P for Website 2. - Place Order for Website 1. - Promotion is applied. Fixes https://github.com/odoo/odoo/issues/55121 Closes https://github.com/odoo/odoo/pull/57895 closes odoo/odoo#60151 X-original-commit: 8a5c53bbc771c0895c001a7f7f43591c5cde2ba6 Forward-port-of: https://github.com/odoo/enterprise/pull/13875 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com> Co-authored-by: Romain Derie <rde@odoo.com> Co-authored-by: Swapnesh Shah <swapneshshah111@gmail.com>
This commit is contained in:
committed by
Jeremy Kersten
co-authored by
Swapnesh Shah
parent
c9b133813b
commit
8a22cf8626
@@ -71,6 +71,16 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
'reward_product_id': self.largeMeetingTable.id,
|
||||
'rule_products_domain': '[["name","ilike","drawer black"]]',
|
||||
})
|
||||
self.discount_coupon_program = self.env['coupon.program'].create({
|
||||
'name': '$100 coupon',
|
||||
'program_type': 'coupon_program',
|
||||
'reward_type': 'discount',
|
||||
'discount_type': 'fixed_amount',
|
||||
'discount_fixed_amount': 100,
|
||||
'active': True,
|
||||
'discount_apply_on': 'on_order',
|
||||
'rule_minimum_amount': 100.00,
|
||||
})
|
||||
|
||||
def test_program_numbers_free_and_paid_product_qty(self):
|
||||
# These tests will focus on numbers (free product qty, SO total, reduction total..)
|
||||
@@ -571,18 +581,8 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
'order_id': order.id,
|
||||
})
|
||||
self.assertEqual(order.amount_total, 165.0, "The order amount is not correct")
|
||||
discount_coupon_program = self.env['coupon.program'].create({
|
||||
'name': '$100 coupon',
|
||||
'program_type': 'coupon_program',
|
||||
'reward_type': 'discount',
|
||||
'discount_type': 'fixed_amount',
|
||||
'discount_fixed_amount': 100,
|
||||
'active': True,
|
||||
'discount_apply_on': 'on_order',
|
||||
'rule_minimum_amount': 100.00,
|
||||
})
|
||||
self.env['coupon.generate.wizard'].with_context(active_id=discount_coupon_program.id).create({}).generate_coupon()
|
||||
coupon = discount_coupon_program.coupon_ids[0]
|
||||
self.env['coupon.generate.wizard'].with_context(active_id=self.discount_coupon_program.id).create({}).generate_coupon()
|
||||
coupon = self.discount_coupon_program.coupon_ids[0]
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': coupon.code
|
||||
}).process_coupon()
|
||||
@@ -604,17 +604,17 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
})
|
||||
self.assertEqual(order.amount_total, 165.0, "The order amount is not correct")
|
||||
|
||||
discount_promotion_program = self.env['coupon.program'].create({
|
||||
'name': '$100 promotion program',
|
||||
'program_type': 'promotion_program',
|
||||
'promo_code_usage': 'code_needed',
|
||||
'promo_code': 'testpromo',
|
||||
'reward_type': 'discount',
|
||||
'discount_type': 'fixed_amount',
|
||||
'discount_fixed_amount': 100,
|
||||
'active': True,
|
||||
'discount_apply_on': 'on_order',
|
||||
'rule_minimum_amount': 100.00,
|
||||
self.env['coupon.program'].create({
|
||||
'name': '$100 promotion program',
|
||||
'program_type': 'promotion_program',
|
||||
'promo_code_usage': 'code_needed',
|
||||
'promo_code': 'testpromo',
|
||||
'reward_type': 'discount',
|
||||
'discount_type': 'fixed_amount',
|
||||
'discount_fixed_amount': 100,
|
||||
'active': True,
|
||||
'discount_apply_on': 'on_order',
|
||||
'rule_minimum_amount': 100.00,
|
||||
})
|
||||
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
@@ -624,18 +624,8 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(order.amount_total, 65.0, "The promotion program should not be removed after recomputation")
|
||||
|
||||
discount_coupon_program = self.env['coupon.program'].create({
|
||||
'name': '$100 coupon',
|
||||
'program_type': 'coupon_program',
|
||||
'reward_type': 'discount',
|
||||
'discount_type': 'fixed_amount',
|
||||
'discount_fixed_amount': 100,
|
||||
'active': True,
|
||||
'discount_apply_on': 'on_order',
|
||||
'rule_minimum_amount': 100.00,
|
||||
})
|
||||
self.env['coupon.generate.wizard'].with_context(active_id=discount_coupon_program.id).create({}).generate_coupon()
|
||||
coupon = discount_coupon_program.coupon_ids[0]
|
||||
self.env['coupon.generate.wizard'].with_context(active_id=self.discount_coupon_program.id).create({}).generate_coupon()
|
||||
coupon = self.discount_coupon_program.coupon_ids[0]
|
||||
with self.assertRaises(UserError):
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': coupon.code
|
||||
@@ -780,7 +770,7 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
'lst_price': 118.0,
|
||||
})
|
||||
|
||||
test10 = self.env['coupon.program'].create({
|
||||
self.env['coupon.program'].create({
|
||||
'name': '10% discount',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'program_type': 'promotion_program',
|
||||
@@ -789,7 +779,7 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
'rule_minimum_amount': 1500.0,
|
||||
'rule_minimum_amount_tax_inclusion': 'tax_included',
|
||||
})
|
||||
test15 = self.env['coupon.program'].create({
|
||||
self.env['coupon.program'].create({
|
||||
'name': '15% discount',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'program_type': 'promotion_program',
|
||||
@@ -798,7 +788,7 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
'rule_minimum_amount': 1750.0,
|
||||
'rule_minimum_amount_tax_inclusion': 'tax_included',
|
||||
})
|
||||
test20 = self.env['coupon.program'].create({
|
||||
self.env['coupon.program'].create({
|
||||
'name': '20% discount',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'program_type': 'promotion_program',
|
||||
@@ -807,7 +797,7 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
'rule_minimum_amount': 2000.0,
|
||||
'rule_minimum_amount_tax_inclusion': 'tax_included',
|
||||
})
|
||||
test25 = self.env['coupon.program'].create({
|
||||
self.env['coupon.program'].create({
|
||||
'name': '25% discount',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'program_type': 'promotion_program',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import sale_coupon
|
||||
from . import sale_coupon_program
|
||||
from . import sale_order
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class SaleCoupon(models.Model):
|
||||
_inherit = 'coupon.coupon'
|
||||
|
||||
def _check_coupon_code(self, order):
|
||||
if self.program_id.website_id and self.program_id.website_id != order.website_id:
|
||||
return {'error': 'This coupon is not valid on this website.'}
|
||||
return super()._check_coupon_code(order)
|
||||
@@ -21,3 +21,16 @@ class CouponProgram(models.Model):
|
||||
domain += program.website_id.website_domain()
|
||||
if self.search(domain):
|
||||
raise ValidationError(_('The program code must be unique by website!'))
|
||||
|
||||
def _filter_programs_on_website(self, order):
|
||||
return self.filtered(lambda program: not program.website_id or program.website_id.id == order.website_id.id)
|
||||
|
||||
@api.model
|
||||
def _filter_programs_from_common_rules(self, order, next_order=False):
|
||||
programs = self._filter_programs_on_website(order)
|
||||
return super(CouponProgram, programs)._filter_programs_from_common_rules(order, next_order)
|
||||
|
||||
def _check_promo_code(self, order, coupon_code):
|
||||
if self.website_id and self.website_id != order.website_id:
|
||||
return {'error': 'This promo code is not valid on this website.'}
|
||||
return super()._check_promo_code(order, coupon_code)
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
from . import test_sale_coupon_multiwebsite
|
||||
from . import test_shop_sale_coupon
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale_coupon.tests.test_program_numbers import TestSaleCouponProgramNumbers
|
||||
from odoo.addons.website.tools import MockRequest
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestSaleCouponMultiwebsite(TestSaleCouponProgramNumbers):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSaleCouponMultiwebsite, self).setUp()
|
||||
self.website = self.env['website'].browse(1)
|
||||
self.website2 = self.env['website'].create({'name': 'website 2'})
|
||||
|
||||
def test_01_multiwebsite_checks(self):
|
||||
""" Ensure the multi website compliance of programs and coupons, both in
|
||||
backend and frontend.
|
||||
"""
|
||||
order = self.empty_order
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.largeCabinet.id,
|
||||
'name': 'Large Cabinet',
|
||||
'product_uom_qty': 2.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
|
||||
def _remove_reward():
|
||||
order.order_line.filtered('is_reward_line').unlink()
|
||||
self.assertEqual(len(order.order_line.ids), 1, "Program should have been removed")
|
||||
|
||||
def _apply_code(code, backend=True):
|
||||
if backend:
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': code
|
||||
}).process_coupon()
|
||||
else:
|
||||
self.env['sale.coupon.apply.code'].sudo().apply_coupon(order, code)
|
||||
|
||||
# ==========================================
|
||||
# ========== Programs (with code) ==========
|
||||
# ==========================================
|
||||
|
||||
# 1. Backend - Generic
|
||||
_apply_code(self.p1.promo_code)
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program")
|
||||
_remove_reward()
|
||||
|
||||
# 2. Frontend - Generic
|
||||
with MockRequest(self.env, website=self.website):
|
||||
_apply_code(self.p1.promo_code, False)
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program (2)")
|
||||
_remove_reward()
|
||||
|
||||
# make program specific
|
||||
self.p1.website_id = self.website.id
|
||||
# 3. Backend - Specific
|
||||
with self.assertRaises(UserError):
|
||||
_apply_code(self.p1.promo_code) # the order has no website_id so not possible to use a website specific code
|
||||
|
||||
# 4. Frontend - Specific - Correct website
|
||||
order.website_id = self.website.id
|
||||
with MockRequest(self.env, website=self.website):
|
||||
_apply_code(self.p1.promo_code, False)
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a specific promo program for the correct website")
|
||||
_remove_reward()
|
||||
|
||||
# 5. Frontend - Specific - Wrong website
|
||||
self.p1.website_id = self.website2.id
|
||||
with MockRequest(self.env, website=self.website):
|
||||
_apply_code(self.p1.promo_code, False)
|
||||
self.assertEqual(len(order.order_line.ids), 1, "Should not get the reward as wrong website")
|
||||
|
||||
# ==============================
|
||||
# =========== Coupons ==========
|
||||
# ==============================
|
||||
|
||||
order.website_id = False
|
||||
self.env['coupon.generate.wizard'].with_context(active_id=self.discount_coupon_program.id).create({
|
||||
'nbr_coupons': 4,
|
||||
}).generate_coupon()
|
||||
coupons = self.discount_coupon_program.coupon_ids
|
||||
|
||||
# 1. Backend - Generic
|
||||
_apply_code(coupons[0].code)
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a generic coupon program")
|
||||
_remove_reward()
|
||||
|
||||
# 2. Frontend - Generic
|
||||
with MockRequest(self.env, website=self.website):
|
||||
_apply_code(coupons[1].code, False)
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a generic coupon program (2)")
|
||||
_remove_reward()
|
||||
|
||||
# make program specific
|
||||
self.discount_coupon_program.website_id = self.website.id
|
||||
# 3. Backend - Specific
|
||||
with self.assertRaises(UserError):
|
||||
_apply_code(coupons[2].code) # the order has no website_id so not possible to use a website specific code
|
||||
|
||||
# 4. Frontend - Specific - Correct website
|
||||
order.website_id = self.website.id
|
||||
with MockRequest(self.env, website=self.website):
|
||||
_apply_code(coupons[2].code, False)
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a specific coupon program for the correct website")
|
||||
_remove_reward()
|
||||
|
||||
# 5. Frontend - Specific - Wrong website
|
||||
self.discount_coupon_program.website_id = self.website2.id
|
||||
with MockRequest(self.env, website=self.website):
|
||||
_apply_code(coupons[3].code, False)
|
||||
self.assertEqual(len(order.order_line.ids), 1, "Should not get the reward as wrong website")
|
||||
|
||||
# ========================================
|
||||
# ========== Programs (no code) ==========
|
||||
# ========================================
|
||||
|
||||
order.website_id = False
|
||||
self.p1.website_id = False
|
||||
self.p1.promo_code = False
|
||||
self.p1.promo_code_usage = 'no_code_needed'
|
||||
|
||||
# 1. Backend - Generic
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program")
|
||||
|
||||
# 2. Frontend - Generic
|
||||
with MockRequest(self.env, website=self.website):
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a generic promo program (2)")
|
||||
|
||||
# make program specific
|
||||
self.p1.website_id = self.website.id
|
||||
# 3. Backend - Specific
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 1, "The order has no website_id so not possible to use a website specific code")
|
||||
|
||||
# 4. Frontend - Specific - Correct website
|
||||
order.website_id = self.website.id
|
||||
with MockRequest(self.env, website=self.website):
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2, "Should get the discount line as it is a specific promo program for the correct website")
|
||||
|
||||
# 5. Frontend - Specific - Wrong website
|
||||
self.p1.website_id = self.website2.id
|
||||
with MockRequest(self.env, website=self.website):
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 1, "Should not get the reward as wrong website")
|
||||
Reference in New Issue
Block a user