[FIX] sale_coupon: add tests
Previous commit fixed some bugs on `sale_coupon` (#2224). This commit add some tests to be sure these bugs are fixed and won't appear again. task-1866977 Related to #2224
This commit is contained in:
@@ -4,5 +4,4 @@
|
||||
import test_program_without_code_operations
|
||||
import test_program_with_code_operations
|
||||
import test_program_rules
|
||||
import test_program_rewards
|
||||
import test_program_numbers
|
||||
|
||||
+266
-11
@@ -2,6 +2,8 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.addons.sale_coupon.tests.common import TestSaleCouponCommon
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
|
||||
@@ -9,6 +11,8 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
super(TestSaleCouponProgramNumbers, self).setUp()
|
||||
|
||||
self.iPadMini = self.env.ref('product.product_product_6').copy()
|
||||
self.iPod = self.env.ref('product.product_product_11').copy()
|
||||
self.wirelessKeyboard = self.env.ref('product.product_product_9').copy()
|
||||
self.computerCase = self.env.ref('product.product_product_16').copy()
|
||||
self.littleServer = self.env.ref('product.consu_delivery_02').copy()
|
||||
self.steve = self.env['res.partner'].create({
|
||||
@@ -64,7 +68,7 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
self.env['sale.coupon.apply.code'].sudo().apply_coupon(order, 'test_10pc')
|
||||
self.assertEqual(len(order.order_line.ids), 3, "We should 3 lines as we should have a new line for promo code reduction")
|
||||
self.assertEqual(order.amount_total, 864, "Only paid product should have their price discounted")
|
||||
order.order_line.filtered(lambda x: 'Discount' in x.name).unlink() # Remove Discount
|
||||
order.order_line.filtered(lambda x: 'Discount' in x.name).unlink() # Remove Discount
|
||||
|
||||
# Check free product is removed since we are below minimum required quantity
|
||||
sol1.product_uom_qty = 3
|
||||
@@ -113,7 +117,7 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
self.assertEqual(len(order.order_line.ids), 4, "We should have 4 lines as we should have a new line for promo code reduction")
|
||||
|
||||
# Check you can still have auto applied promotion if you have a promo code set to the order
|
||||
sol4 = self.env['sale.order.line'].create({
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.iPadMini.id,
|
||||
'name': 'iPad Mini',
|
||||
'product_uom_qty': 4.0,
|
||||
@@ -155,11 +159,16 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
sol1._compute_tax_id()
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2, "We should now get the reduction line since we have 320$ tax included (ipad is 320$ tax included)")
|
||||
# (320 +15% tax) - (20% of (320 + 15% tax) = 368 + 73.6 = 294.4
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# iPod | 1 | 320.00 | 15% excl | 320.00 | 368.00 | 48.00
|
||||
# 20% discount on ipad | 1 | -64.00 | 15% excl | -64.00 | -73.60 | -9.60
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL | 256.00 | 294.40 | 38.40
|
||||
self.assertEqual(order.amount_total, 294.4, "Check discount has been applied correctly (eg: on taxes aswell)")
|
||||
|
||||
# test coupon with code works the same as auto applied_programs
|
||||
p_specific_product.write({'promo_code_usage':'code_needed', 'promo_code':'20pc'})
|
||||
p_specific_product.write({'promo_code_usage': 'code_needed', 'promo_code': '20pc'})
|
||||
order.order_line.filtered(lambda l: l.is_reward_line).unlink()
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 1, "Reduction should be removed since we deleted it and it is now a promo code usage, it shouldn't be automatically reapplied")
|
||||
@@ -168,21 +177,267 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2, "We should now get the reduction line since we have 320$ tax included (ipad is 320$ tax included)")
|
||||
|
||||
#check discount applied only on ipad
|
||||
sol2 = self.env['sale.order.line'].create({
|
||||
# check discount applied only on ipad
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.computerCase.id,
|
||||
'name': 'Computer Case',
|
||||
'product_uom_qty': 10.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
order.recompute_coupon_lines()
|
||||
# (10x25) + (320 +15% tax) - (20% of (320 + 15% tax) = 250 + 368 - 73.6 = 544.4
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# Computer Case | 10 | 25.00 | / | 250.00 | 250.00 | /
|
||||
# iPad | 1 | 320.00 | 15% excl | 320.00 | 368.00 | 48.00
|
||||
# 20% discount on ipad | 1 | -64.00 | 15% excl | -64.00 | -73.60 | -9.60
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL | 506.00 | 544.40 | 38.40
|
||||
self.assertEqual(order.amount_total, 544.4, "We should only get reduction on ipad")
|
||||
sol1.product_uom_qty = 10
|
||||
order.recompute_coupon_lines()
|
||||
# (10x25) + (10x (320 +15% tax)) - (20% of (10x (320 + 15% tax))) - 2 free iPads = 250 + 3680 - 736 - 736 = 2458
|
||||
self.assertEqual(order.amount_total, 2458, "Changing ipad quantity should change discount amount correctly")
|
||||
|
||||
# Note: Since we now have 2 free ipads, we should discount only 8 of the 10 ipads in carts since we don't want to discount free ipads
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# Computer Case | 10 | 25.00 | / | 250.00 | 250.00 | /
|
||||
# iPad | 10 | 320.00 | 15% excl | 3200.00 | 3680.00 | 480.00
|
||||
# Free iPad | 2 | -320.00 | 15% excl | -640.00 | -736.00 | -96.00
|
||||
# 20% discount on ipad | 1 | -512.00 | 15% excl | -512.00 | -588.80 | -78.80
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL | 2298.00 | 2605.20 | 305.20
|
||||
self.assertEqual(order.amount_total, 2605.20, "Changing ipad quantity should change discount amount correctly")
|
||||
p_specific_product.discount_max_amount = 200
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(order.amount_total, 2994, "The discount should be limited to $200")
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# Computer Case | 10 | 25.00 | / | 250.00 | 250.00 | /
|
||||
# iPad | 10 | 320.00 | 15% excl | 3200.00 | 3680.00 | 480.00
|
||||
# Free iPad | 2 | -320.00 | 15% excl | -640.00 | -736.00 | -96.00
|
||||
# 20% discount on ipad | 1 | -200.00 | 15% excl | -200.00 | -230.00 | -30.00
|
||||
# limited to 200 HTVA
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL | 2610.00 | 2964.00 | 354.00
|
||||
self.assertEqual(order.amount_total, 2964, "The discount should be limited to $200 tax excluded")
|
||||
self.assertEqual(order.amount_untaxed, 2610, "The discount should be limited to $200 tax excluded (2)")
|
||||
|
||||
def test_program_numbers_one_discount_line_per_tax(self):
|
||||
order = self.empty_order
|
||||
# Create taxes
|
||||
self.tax_15pc_excl = self.env['account.tax'].create({
|
||||
'name': "15% Tax excl",
|
||||
'amount_type': 'percent',
|
||||
'amount': 15,
|
||||
})
|
||||
self.tax_50pc_excl = self.env['account.tax'].create({
|
||||
'name': "50% Tax excl",
|
||||
'amount_type': 'percent',
|
||||
'amount': 50,
|
||||
})
|
||||
self.tax_35pc_incl = self.env['account.tax'].create({
|
||||
'name': "35% Tax incl",
|
||||
'amount_type': 'percent',
|
||||
'amount': 35,
|
||||
'price_include': True,
|
||||
})
|
||||
|
||||
# Set tax and prices on products as neeed for the test
|
||||
(self.product_A + self.iPadMini + self.iPod + self.wirelessKeyboard + self.computerCase).write({'list_price': 100})
|
||||
(self.iPadMini + self.computerCase).write({'taxes_id': [(4, self.tax_15pc_excl.id, False)]})
|
||||
self.iPod.taxes_id = self.tax_10pc_incl
|
||||
self.wirelessKeyboard.taxes_id = None
|
||||
self.product_A.taxes_id = (self.tax_35pc_incl + self.tax_50pc_excl)
|
||||
|
||||
# Add products in order
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.iPadMini.id,
|
||||
'name': 'iPad',
|
||||
'product_uom_qty': 7.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
sol2 = self.env['sale.order.line'].create({
|
||||
'product_id': self.iPod.id,
|
||||
'name': 'iPod',
|
||||
'product_uom_qty': 5.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.wirelessKeyboard.id,
|
||||
'name': 'Wireless Keyboard',
|
||||
'product_uom_qty': 10.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.product_A.id,
|
||||
'name': 'product A with multiple taxes',
|
||||
'product_uom_qty': 3.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.computerCase.id,
|
||||
'name': 'Computer Case',
|
||||
'product_uom_qty': 2.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
|
||||
# Create needed programs
|
||||
self.p2.active = False
|
||||
self.p_ipad = self.env['sale.coupon.program'].create({
|
||||
'name': 'Buy 1 ipad, get one for free',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'reward_type': 'product',
|
||||
'program_type': 'promotion_program',
|
||||
'reward_product_id': self.iPadMini.id,
|
||||
'rule_products_domain': '[["name","ilike","ipad mini"]]',
|
||||
})
|
||||
self.p_ipod = self.env['sale.coupon.program'].create({
|
||||
'name': 'Buy 1 ipod, get one for free',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'reward_type': 'product',
|
||||
'program_type': 'promotion_program',
|
||||
'reward_product_id': self.iPod.id,
|
||||
'rule_products_domain': '[["name","ilike","ipod"]]',
|
||||
})
|
||||
self.p_keyboard = self.env['sale.coupon.program'].create({
|
||||
'name': 'Buy 1 keyboard, get one for free',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'reward_type': 'product',
|
||||
'program_type': 'promotion_program',
|
||||
'reward_product_id': self.wirelessKeyboard.id,
|
||||
'rule_products_domain': '[["name","ilike","keyboard"]]',
|
||||
})
|
||||
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# iPod | 5 | 100.00 | 10% incl | 454.55 | 500.00 | 45.45
|
||||
# Keyboards | 10 | 100.00 | / | 1000.00 | 1000.00 | /
|
||||
# iPad | 7 | 100.00 | 15% excl | 700.00 | 805.00 | 105.00
|
||||
# Computer Case | 2 | 100.00 | 15% excl | 200.00 | 230.00 | 30.00
|
||||
# Product A | 3 | 100.00 | 35% incl | 222.22 | 450.00 | 227.78
|
||||
# 50% excl
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL | 2576.77 | 2985.00 | 408.23
|
||||
|
||||
self.assertEqual(order.amount_total, 2985, "The order total without any programs should be 2985")
|
||||
self.assertEqual(order.amount_untaxed, 2576.77, "The order untaxed total without any programs should be 2576.77")
|
||||
self.assertEqual(len(order.order_line.ids), 5, "The order without any programs should have 5 lines")
|
||||
|
||||
# Apply all the programs
|
||||
order.recompute_coupon_lines()
|
||||
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# Free iPod | 2 | -100.00 | 10% incl | -181.82 | -200.00 | -18.18
|
||||
# Free Keyboard | 5 | -100.00 | / | -500.00 | -500.00 | /
|
||||
# Free iPad | 3 | -100.00 | 15% excl | -300.00 | -345.00 | -45.00
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL AFTER APPLYING FREE PRODUCT PROGRAMS | 1594.95 | 1940.00 | 345.05
|
||||
|
||||
self.assertEqual(order.amount_total, 1940.00, "The order total with programs should be 1940")
|
||||
self.assertEqual(order.amount_untaxed, 1594.95, "The order untaxed total with programs should be 1594.95")
|
||||
self.assertEqual(len(order.order_line.ids), 8, "Order should contains 5 regular product lines and 3 free product lines")
|
||||
|
||||
# Apply 10% on top of everything
|
||||
self.env['sale.coupon.apply.code'].sudo().apply_coupon(order, 'test_10pc')
|
||||
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# 10% on tax 10% incl | 1 | -30.00 | 10% incl | -27.27 | -30.00 | -2.73
|
||||
# 10% on no tax | 1 | -50.00 | / | -50.00 | -50.00 | /
|
||||
# 10% on tax 15% excl | 1 | -40.00 | 15% excl | -60.00 | -69.00 | -9.00
|
||||
# 10% on tax 35%+50% | 1 | -30.00 | 35% incl | -22.22 | -45.00 | -22.78
|
||||
# 50% excl
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL AFTER APPLYING 10% GLOBAL PROGRAM | 1435.46 | 1746.00 | -310.55
|
||||
|
||||
self.assertEqual(order.amount_total, 1746, "The order total with programs should be 1746")
|
||||
self.assertEqual(order.amount_untaxed, 1435.46, "The order untaxed total with programs should be 1435.46")
|
||||
self.assertEqual(len(order.order_line.ids), 12, "Order should contains 5 regular product lines, 3 free product lines and 4 discount lines (one for every tax)")
|
||||
|
||||
# Now we want to apply a 20% discount only on iPad
|
||||
self.env['sale.coupon.program'].create({
|
||||
'name': '20% reduction on ipad in cart',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'reward_type': 'discount',
|
||||
'program_type': 'promotion_program',
|
||||
'discount_type': 'percentage',
|
||||
'discount_percentage': 20.0,
|
||||
'discount_apply_on': 'specific_product',
|
||||
'discount_specific_product_id': self.iPadMini.id,
|
||||
})
|
||||
order.recompute_coupon_lines()
|
||||
# Note: we have 7 regular ipads and 3 free ipads. We should then discount only 4 really paid iPads
|
||||
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# 20% on iPad | 1 | -80.00 | 15% excl | -80.00 | -92.00 | -12.00
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL AFTER APPLYING 20% ON IPAD | 1355.45 | 1654.00 | -298.55
|
||||
|
||||
self.assertEqual(order.amount_total, 1654, "The order total with programs should be 1654")
|
||||
self.assertEqual(order.amount_untaxed, 1355.46, "The order untaxed total with programs should be 1435.45")
|
||||
self.assertEqual(len(order.order_line.ids), 13, "Order should have a new discount line for 20% on iPad")
|
||||
|
||||
# Check that if you delete one of the discount tax line and recompute, it got added back.
|
||||
order.order_line.filtered(lambda l: '10%' in l.name)[0].unlink()
|
||||
self.assertEqual(len(order.order_line.ids), 12, "One of the 10% discount line per tax should be removed")
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 13, "The 10% discount line that got removed should be recomputed and added back")
|
||||
|
||||
# Check that if you change a product qty, his discount tax line got updated
|
||||
sol2.product_uom_qty = 7
|
||||
order.recompute_coupon_lines()
|
||||
# iPod | 5 | 100.00 | 10% incl | 454.55 | 500.00 | 45.45
|
||||
# Free iPod | 2 | -100.00 | 10% incl | -181.82 | -200.00 | -18.18
|
||||
# 10% on tax 10% incl | 1 | -30.00 | 10% incl | -27.27 | -30.00 | -2.73
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL OF IPOD LINES | 245.46 | 270.00 | 24.54
|
||||
# ==> Should become:
|
||||
# iPod | 7 | 100.00 | 10% incl | 636.36 | 700.00 | 63.64
|
||||
# Free iPod | 3 | -100.00 | 10% incl | -272.73 | -300.00 | -27.27
|
||||
# 10% on tax 10% incl | 1 | -40.00 | 10% incl | -36.36 | -40.00 | -3.64
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL OF IPOD LINES AFTER ADDING 2 IPODS | 327.27 | 360.00 | 32.73
|
||||
# --------------------------------------------------------------------------------
|
||||
# => DIFFERENCES BEFORE/AFTER | 81.81 | 90.00 | 8.19
|
||||
self.assertEqual(order.amount_untaxed, 1355.46 + 81.81, "The order should have one more paid ipod with 10% incl tax and discounted by 10%")
|
||||
|
||||
# Check that if you remove a product, his reward lines got removed, especially the discount per tax one
|
||||
sol2.unlink()
|
||||
order.recompute_coupon_lines()
|
||||
# Name | Qty | price_unit | Tax | HTVA | TVAC | TVA |
|
||||
# --------------------------------------------------------------------------------
|
||||
# Keyboards | 10 | 100.00 | / | 1000.00 | 1000.00 | /
|
||||
# iPad | 7 | 100.00 | 15% excl | 700.00 | 805.00 | 105.00
|
||||
# Computer Case | 2 | 100.00 | 15% excl | 200.00 | 230.00 | 30.00
|
||||
# Product A | 3 | 100.00 | 35% incl | 222.22 | 450.00 | 227.78
|
||||
# 50% excl
|
||||
# Free Keyboard | 5 | -100.00 | / | -500.00 | -500.00 | /
|
||||
# Free iPad | 3 | -100.00 | 15% excl | -300.00 | -345.00 | -45.00
|
||||
# 10% on no tax | 1 | -50.00 | / | -50.00 | -50.00 | /
|
||||
# 10% on tax 15% excl | 1 | -40.00 | 15% excl | -60.00 | -69.00 | -9.00
|
||||
# 10% on tax 35%+50% | 1 | -30.00 | 35% incl | -22.22 | -45.00 | -22.78
|
||||
# 50% excl
|
||||
# 20% on iPad | 1 | -80.00 | 15% excl | -80.00 | -92.00 | -12.00
|
||||
# --------------------------------------------------------------------------------
|
||||
# TOTAL | 1110.00 | 1384.00 | 274.00
|
||||
self.assertEqual(order.amount_total, 1384, "The order total with programs should be 1654")
|
||||
self.assertEqual(order.amount_untaxed, 1110, "The order untaxed total with programs should be 1435.45")
|
||||
self.assertEqual(len(order.order_line.ids), 10, "Order should contains 10 lines: 4 products lines, 2 free products lines, 3 10% discount lines and a 20% discount line")
|
||||
|
||||
def test_program_numbers_extras(self):
|
||||
# Check that you can't apply a global discount promo code if there is already an auto applied global discount
|
||||
self.p1.copy({'promo_code_usage': 'no_code_needed', 'name': 'Auto applied 10% global discount'})
|
||||
order = self.empty_order
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.iPadMini.id,
|
||||
'name': 'iPad',
|
||||
'product_uom_qty': 1.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2, "We should get 1 iPad line and 1 10% auto applied global discount line")
|
||||
self.assertEqual(order.amount_total, 288, "320$ - 10%")
|
||||
with self.assertRaises(UserError):
|
||||
# Can't apply a second global discount
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': 'test_10pc'
|
||||
}).process_coupon()
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.addons.sale_coupon.tests.common import TestSaleCouponCommon
|
||||
|
||||
class TestSaleCouponProgramRules(TestSaleCouponCommon):
|
||||
# Test all the kind of reward a customer can receive.
|
||||
# The product reward is already tested in the basic operations test
|
||||
|
||||
def test_program_rewards(self):
|
||||
# Test case: Based on the partners domain
|
||||
|
||||
self.immediate_promotion_program.write({'reward_type': "discount"})
|
||||
|
||||
order = self.empty_order
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_A.id,
|
||||
'name': '1 Product A',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
}),
|
||||
(0, False, {
|
||||
'product_id': self.product_B.id,
|
||||
'name': '2 Product B',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 3, "The promo offert should have been applied as the partner is correct, the discount is not created")
|
||||
|
||||
|
||||
def test_program_rewards_discount(self):
|
||||
|
||||
# Test case 1: 1% discount on total order
|
||||
program = self.env['sale.coupon.program'].create({
|
||||
'name': 'Buy at least 1000 EUR, ',
|
||||
'rule_minimum_amount': 1000.0,
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'reward_type': 'discount',
|
||||
'discount_type': 'percentage',
|
||||
'discount_percentage': 1.0,
|
||||
'discount_apply_on': 'on_order',
|
||||
'active': True,
|
||||
})
|
||||
order = self.env['sale.order'].create({
|
||||
'partner_id': self.steve.id
|
||||
})
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.product_A.id,
|
||||
'name': '1 Product A',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 11.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
self.env['sale.order.line'].create({
|
||||
'product_id': self.product_B.id,
|
||||
'name': '2 Product B',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
'order_id': order.id,
|
||||
})
|
||||
@@ -10,6 +10,19 @@ class TestProgramWithCodeOperations(TestSaleCouponCommon):
|
||||
# apply the reward when the code is correct or remove the reward automatically when the reward is
|
||||
# not valid anymore.
|
||||
|
||||
def test_program_usability(self):
|
||||
# After clicking "Generate coupons", there is no domain so it shows "Match all records".
|
||||
# But when you click, domain is false (default field value; empty string) so it won't generate anything.
|
||||
# This is even more weird because if you add something in the domain and then delete it,
|
||||
# you visually come back to the initial state except the domain became '[]' instead of ''.
|
||||
# In this case, it will generate the coupon for every partner.
|
||||
# Thus, we should ensure that if you leave the domain untouched, it generates a coupon for each partner
|
||||
# as hinted on the screen ('Match all records (X records)')
|
||||
self.env['sale.coupon.generate'].with_context(active_id=self.code_promotion_program.id).create({
|
||||
'generation_type': 'nbr_customer',
|
||||
}).generate_coupon()
|
||||
self.assertEqual(len(self.code_promotion_program.coupon_ids), len(self.env['res.partner'].search([])), "It should have generated a coupon for every partner")
|
||||
|
||||
def test_program_basic_operation_coupon_code(self):
|
||||
# Test case: Generate a coupon for my customer, and add a reward then remove it automatically
|
||||
|
||||
@@ -19,6 +32,7 @@ class TestProgramWithCodeOperations(TestSaleCouponCommon):
|
||||
'generation_type': 'nbr_customer',
|
||||
'partners_domain': "[('id', 'in', [%s])]" % (self.steve.id),
|
||||
}).generate_coupon()
|
||||
coupon = self.code_promotion_program.coupon_ids
|
||||
|
||||
# Test the valid code on a wrong sales order
|
||||
wrong_partner_order = self.env['sale.order'].create({
|
||||
@@ -26,7 +40,7 @@ class TestProgramWithCodeOperations(TestSaleCouponCommon):
|
||||
})
|
||||
with self.assertRaises(UserError):
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=wrong_partner_order.id).create({
|
||||
'coupon_code': self.code_promotion_program.coupon_ids.code
|
||||
'coupon_code': coupon.code
|
||||
}).process_coupon()
|
||||
|
||||
# Test now on a valid sales order
|
||||
@@ -40,57 +54,158 @@ class TestProgramWithCodeOperations(TestSaleCouponCommon):
|
||||
})
|
||||
]})
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': self.code_promotion_program.coupon_ids.code
|
||||
'coupon_code': coupon.code
|
||||
}).process_coupon()
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2)
|
||||
self.assertEqual(coupon.state, 'used')
|
||||
|
||||
# Remove the product A from the sale order
|
||||
order.write({'order_line': [(2, order.order_line[0].id, False)]})
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 0)
|
||||
self.assertEqual(coupon.state, 'new')
|
||||
|
||||
def test_on_next_order_reward_promotion_program(self):
|
||||
# The flow:
|
||||
# 1. Create a program `A` that gives a free `Product B` on next order if you buy a an `product A`
|
||||
# This program should be code_needed with code `free_B_on_next_order`
|
||||
# 2. Create a program `B` that gives 10% discount on next order automatically
|
||||
# 3. Create a SO with a `third product` and recompute coupon, you SHOULD get a coupon (from program `B`) for your next order that will discount 10%
|
||||
# 4. Try to apply `A`, it should error since we did not buy any product A.
|
||||
# 5. Add a product A to the cart and try to apply `A` again, this time it should work
|
||||
# 6. Verify you have 2 generated coupons and validate the SO (so the 2 generated coupons will be valid)
|
||||
# 7. Create a new SO (with the same partner) and try to apply coupon generated by `A`. it SHOULD error since we don't have any `Product B` in the cart
|
||||
# 8. Add a Product B in the cart
|
||||
# 9. Try to apply once again coupon generated by `A`, it should give you the free product B
|
||||
# 10. Try to apply coupon generated by `B`, it should give you 10% discount.
|
||||
# => SO will then be 0$ until we recompute the order lines
|
||||
|
||||
# 1.
|
||||
self.immediate_promotion_program.write({
|
||||
'promo_applicability': 'on_next_order',
|
||||
'promo_code_usage': 'code_needed',
|
||||
'promo_code': 'free_B_on_next_order',
|
||||
})
|
||||
# 2.
|
||||
self.p1 = self.env['sale.coupon.program'].create({
|
||||
'name': 'Code for 10% on next order',
|
||||
'discount_type': 'percentage',
|
||||
'discount_percentage': 10.0,
|
||||
'program_type': 'promotion_program',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'promo_applicability': 'on_next_order',
|
||||
})
|
||||
# 3.
|
||||
order = self.empty_order.copy()
|
||||
self.third_product = self.env['product.product'].create({
|
||||
'name': 'Thrid Product',
|
||||
'list_price': 5,
|
||||
'sale_ok': True
|
||||
})
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.third_product.id,
|
||||
'name': '1 Third Product',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(self.p1.coupon_ids.ids), 1, "You should get a coupon for you next order that will offer 10% discount")
|
||||
# 4.
|
||||
with self.assertRaises(UserError):
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': 'free_B_on_next_order'
|
||||
}).process_coupon()
|
||||
# 5.
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_A.id,
|
||||
'name': '1 Product A',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': 'free_B_on_next_order'
|
||||
}).process_coupon()
|
||||
# 6.
|
||||
self.assertEqual(len(order.generated_coupon_ids), 2, "You should get a second coupon for your next order that will offer a free Product B")
|
||||
order.action_confirm()
|
||||
# 7.
|
||||
order_bis = self.empty_order
|
||||
with self.assertRaises(UserError):
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order_bis.id).create({
|
||||
'coupon_code': order.generated_coupon_ids[1].code
|
||||
}).process_coupon()
|
||||
# 8.
|
||||
order_bis.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_B.id,
|
||||
'name': '1 Product B',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
# 9.
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order_bis.id).create({
|
||||
'coupon_code': order.generated_coupon_ids[1].code
|
||||
}).process_coupon()
|
||||
self.assertEqual(len(order_bis.order_line), 2, "You should get a free Product B")
|
||||
# 10.
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order_bis.id).create({
|
||||
'coupon_code': order.generated_coupon_ids[0].code
|
||||
}).process_coupon()
|
||||
self.assertEqual(len(order_bis.order_line), 3, "You should get a 10% discount line")
|
||||
self.assertEqual(order_bis.amount_total, 0, "SO total should be null: (Paid product - Free product = 0) + 10% of nothing")
|
||||
|
||||
def test_on_next_order_reward_promotion_program_with_requirements(self):
|
||||
self.immediate_promotion_program.write({
|
||||
'promo_applicability': 'on_next_order',
|
||||
'promo_code_usage': 'code_needed',
|
||||
'promo_code': 'free_B_on_next_order',
|
||||
'rule_minimum_amount': 700,
|
||||
'rule_minimum_amount_tax_inclusion': 'tax_excluded'
|
||||
})
|
||||
order = self.empty_order.copy()
|
||||
self.product_A.lst_price = 700
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_A.id,
|
||||
'name': '1 Product A',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': 'free_B_on_next_order'
|
||||
}).process_coupon()
|
||||
self.assertEqual(len(self.immediate_promotion_program.coupon_ids.ids), 1, "You should get a coupon for you next order that will offer a free product B")
|
||||
order_bis = self.empty_order
|
||||
order_bis.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_B.id,
|
||||
'name': '1 Product B',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
with self.assertRaises(UserError):
|
||||
# It should error since we did not validated the previous SO, so the coupon is `reserved` but not `new`
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order_bis.id).create({
|
||||
'coupon_code': order.generated_coupon_ids[0].code
|
||||
}).process_coupon()
|
||||
order.action_confirm()
|
||||
# It should not error even if the SO does not have the requirements (700$ and 1 product A), since these requirements where only used to generate the coupon that we are now applying
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order_bis.id).create({
|
||||
'coupon_code': order.generated_coupon_ids[0].code
|
||||
}).process_coupon()
|
||||
self.assertEqual(len(order_bis.order_line), 2, "You should get 1 regular product_B and 1 free product_B")
|
||||
order_bis.recompute_coupon_lines()
|
||||
self.assertEqual(len(order_bis.order_line), 2, "Free product from a coupon generated from a promotion program on next order should not dissapear")
|
||||
|
||||
def test_on_next_order_reward_promo_program(self):
|
||||
# Test case: Apply a program that generates a coupon, which is used afterward
|
||||
|
||||
self.immediate_promotion_program.write({
|
||||
'promo_applicability': 'on_next_order',
|
||||
'promo_code_usage': 'code_needed',
|
||||
'promo_code': 'bleurk',
|
||||
})
|
||||
|
||||
order = self.empty_order
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_A.id,
|
||||
'name': '1 Product A',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': 'bleurk'
|
||||
}).process_coupon()
|
||||
# Ensure that the coupon is correctly generated
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(self.immediate_promotion_program.coupon_ids.ids), 1)
|
||||
|
||||
generated_coupon = self.immediate_promotion_program.coupon_ids[0]
|
||||
order = self.env['sale.order'].create({
|
||||
'partner_id': self.steve.id
|
||||
})
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_B.id,
|
||||
'name': '1 Product B',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
|
||||
'coupon_code': generated_coupon.code
|
||||
})
|
||||
# Ensure that the generated coupon is valid
|
||||
order.recompute_coupon_lines()
|
||||
self.assertEqual(len(order.order_line.ids), 2)
|
||||
# TODO: remove me in master, this was never executed due to bad indentation (the method is not indented under the class)
|
||||
# note that this flow did not worked and was not implemented.. now tested with `test_on_next_order_reward_promotion_program()`
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user