2466 lines
93 KiB
Python
2466 lines
93 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import date, timedelta
|
|
|
|
from odoo import Command
|
|
from odoo.tests import tagged
|
|
|
|
from odoo.addons.point_of_sale.tests.test_frontend import TestPointOfSaleHttpCommon
|
|
from odoo.addons.point_of_sale.tests.common_setup_methods import setup_product_combo_items
|
|
|
|
|
|
@tagged("post_install", "-at_install")
|
|
class TestUi(TestPointOfSaleHttpCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
# Disable any programs during the test
|
|
cls.env['loyalty.program'].search([]).write({'active': False})
|
|
cls.promo_programs = cls.env["loyalty.program"]
|
|
|
|
# code promo program -> discount on specific products
|
|
cls.code_promo_program = cls.env['loyalty.program'].create({
|
|
'name': 'Promo Code Program - Discount on Specific Products',
|
|
'program_type': 'promotion',
|
|
'trigger': 'with_code',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'mode': 'with_code',
|
|
'code': 'promocode',
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 50,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
'discount_product_ids': cls.whiteboard_pen | cls.magnetic_board | cls.desk_organizer,
|
|
})],
|
|
})
|
|
cls.promo_programs |= cls.code_promo_program
|
|
|
|
# auto promo program on current order
|
|
# -> discount on cheapest product
|
|
cls.auto_promo_program_current = cls.env['loyalty.program'].create({
|
|
'name': 'Auto Promo Program - Cheapest Product',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'rule_ids': [(0, 0, {})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 90,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'cheapest',
|
|
})]
|
|
})
|
|
cls.promo_programs |= cls.auto_promo_program_current
|
|
|
|
# auto promo program on next order
|
|
# -> discount on order (global discount)
|
|
cls.auto_promo_program_next = cls.env['loyalty.program'].create({
|
|
'name': 'Auto Promo Program - Global Discount',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'future',
|
|
'rule_ids': [(0, 0, {})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})]
|
|
})
|
|
cls.promo_programs |= cls.auto_promo_program_next
|
|
cls.promo_programs.write({
|
|
'pos_config_ids': [Command.link(cls.main_pos_config.id)],
|
|
})
|
|
|
|
# coupon program -> free product
|
|
cls.coupon_program = cls.env['loyalty.program'].create({
|
|
'name': 'Coupon Program - Buy 3 Take 2 Free Product',
|
|
'program_type': 'coupons',
|
|
'trigger': 'with_code',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'product_ids': cls.desk_organizer,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 3,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': cls.desk_organizer.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 1.5,
|
|
})],
|
|
'pos_config_ids': [Command.link(cls.main_pos_config.id)],
|
|
})
|
|
|
|
# Create coupons for the coupon program and change the code
|
|
# to be able to use them in the frontend tour.
|
|
cls.env["loyalty.generate.wizard"].with_context(
|
|
{"active_id": cls.coupon_program.id}
|
|
).create({"coupon_qty": 4, 'points_granted': 4.5}).generate_coupons()
|
|
cls.coupon1, cls.coupon2, cls.coupon3, cls.coupon4 = cls.coupon_program.coupon_ids
|
|
cls.coupon1.write({"code": "1234"})
|
|
cls.coupon2.write({"code": "5678"})
|
|
cls.coupon3.write({"code": "1357"})
|
|
cls.coupon4.write({"code": "2468"})
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
# Set the programs to the pos config.
|
|
# Remove fiscal position and pricelist.
|
|
self.main_pos_config.write({
|
|
'tax_regime_selection': False,
|
|
'use_pricelist': False,
|
|
})
|
|
self.main_pos_config.with_user(self.pos_user).open_ui()
|
|
|
|
def create_programs(self, details):
|
|
"""
|
|
Create loyalty programs based on the details given.
|
|
:param details: list of tuple ('name': str, 'program_type': 'gift_card' or 'ewallet')
|
|
"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
programs = {} # map: name -> program
|
|
for (name, program_type) in details:
|
|
program_id = LoyaltyProgram.create_from_template(program_type)['res_id']
|
|
program = LoyaltyProgram.browse(program_id)
|
|
program.write({'name': name})
|
|
programs[name] = program
|
|
return programs
|
|
|
|
def test_pos_loyalty_tour_basic(self):
|
|
"""PoS Loyalty Basic Tour"""
|
|
##
|
|
# Tour Part 1
|
|
# This part will generate coupons for `auto_promo_program_next`
|
|
# that will be used in the second part of the tour.
|
|
#
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
self.start_pos_tour("PosLoyaltyTour1")
|
|
|
|
# check coupon usage
|
|
self.assertEqual(self.coupon1.points, 0, 'The coupon should have consumed its points.')
|
|
self.assertEqual(self.coupon2.points, 4.5, 'The coupon was used but never validated.')
|
|
# check pos_order_count in each program
|
|
self.assertEqual(self.auto_promo_program_current.pos_order_count, 3)
|
|
self.assertEqual(self.auto_promo_program_next.pos_order_count, 0)
|
|
self.assertEqual(self.code_promo_program.pos_order_count, 1)
|
|
self.assertEqual(self.coupon_program.pos_order_count, 1)
|
|
# check number of generated coupons
|
|
self.assertEqual(len(self.auto_promo_program_next.coupon_ids), 5)
|
|
# check number of orders in the session
|
|
pos_session = self.main_pos_config.current_session_id
|
|
self.assertEqual(
|
|
len(pos_session.order_ids), 5, msg="5 orders were made in tour part1."
|
|
)
|
|
|
|
##
|
|
# Tour Part 2
|
|
# The coupons generated in the first part will be used in this tour.
|
|
#
|
|
|
|
# Manually set the code for some `auto_promo_program_next` coupons
|
|
# to be able to use them in defining the part2 tour.
|
|
(
|
|
promo_coupon1,
|
|
promo_coupon2,
|
|
promo_coupon3,
|
|
promo_coupon4,
|
|
*_,
|
|
) = self.auto_promo_program_next.coupon_ids
|
|
promo_coupon1.write({"code": "123456"})
|
|
promo_coupon2.write({"code": "345678"})
|
|
promo_coupon3.write({"code": "567890"})
|
|
promo_coupon4.write({"code": "098765"})
|
|
|
|
self.coupon2.points = 6
|
|
self.coupon3.points = 3
|
|
|
|
# use here the generated coupon
|
|
self.start_pos_tour("PosLoyaltyTour2")
|
|
# check pos_order_count in each program
|
|
self.assertEqual(self.auto_promo_program_current.pos_order_count, 6)
|
|
self.assertEqual(self.auto_promo_program_next.pos_order_count, 2)
|
|
self.assertEqual(self.code_promo_program.pos_order_count, 2)
|
|
self.assertEqual(self.coupon_program.pos_order_count, 3)
|
|
|
|
def test_loyalty_validity_dates_and_use(self):
|
|
# Tests date validity and max usage for an automatic program.
|
|
self.auto_promo_program_current.write({
|
|
'date_to': date.today() - timedelta(days=2),
|
|
'limit_usage': True,
|
|
'max_usage': 1,
|
|
})
|
|
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
|
|
# First tour check that the promotion is not applied
|
|
self.start_pos_tour("PosLoyaltyValidity1")
|
|
|
|
self.auto_promo_program_current.write({
|
|
'date_to': date.today() + timedelta(days=2),
|
|
})
|
|
|
|
# Second tour that does 2 orders, the first should have the rewards, the second should not
|
|
self.start_pos_tour("PosLoyaltyValidity2")
|
|
|
|
def test_loyalty_free_product_rewards(self):
|
|
free_product = self.env['loyalty.program'].create({
|
|
'name': 'Buy 2 Take 1 desk_organizer',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'product_ids': self.desk_organizer,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': self.desk_organizer.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 2,
|
|
})],
|
|
})
|
|
free_other_product = self.env['loyalty.program'].create({
|
|
'name': 'Buy 3 magnetic_board, Take 1 whiteboard_pen',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'product_ids': self.magnetic_board,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': self.whiteboard_pen.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 3,
|
|
})],
|
|
})
|
|
free_multi_product = self.env['loyalty.program'].create({
|
|
'name': '2 items of shelves, get desk_pad/monitor_stand free',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'product_ids': (self.wall_shelf | self.small_shelf).ids,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_tag_id': self.env['product.tag'].create({
|
|
'name': 'reward_product_tag',
|
|
'product_product_ids': (self.desk_pad | self.monitor_stand).ids,
|
|
}).id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 2,
|
|
})],
|
|
})
|
|
|
|
(self.promo_programs | self.coupon_program).write({'active': False})
|
|
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
self.start_pos_tour("PosLoyaltyFreeProductTour")
|
|
|
|
# Keep the tour to generate 4 orders for the free_product and free_other_product programs.
|
|
# 2 of them don't use a program.
|
|
# 1 uses free_product.
|
|
# 1 uses free_other_product.
|
|
# This is to take into account the fact that during tours, we can't test the "non-occurence" of something.
|
|
# It would be nice to have a check like: Validate that a reward is "not" there.
|
|
self.assertEqual(free_product.pos_order_count, 1)
|
|
self.assertEqual(free_other_product.pos_order_count, 2)
|
|
|
|
# There is the 5th order that tests multi_product reward.
|
|
# It attempted to add one reward product, removed it, then add the second.
|
|
# The second reward was synced with the order.
|
|
self.assertEqual(free_multi_product.pos_order_count, 1)
|
|
|
|
def test_loyalty_free_product_loyalty_program(self):
|
|
# In this program, each whiteboard pen gives 1 point.
|
|
# 4 points can be used to get a free whiteboard pen.
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
|
|
loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Buy 4 whiteboard_pen, Take 1 whiteboard_pen',
|
|
'program_type': 'loyalty',
|
|
'trigger': 'auto',
|
|
'applies_on': 'both',
|
|
'rule_ids': [(0, 0, {
|
|
'product_ids': self.whiteboard_pen.ids,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': self.whiteboard_pen.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 4,
|
|
})],
|
|
})
|
|
|
|
(self.promo_programs | self.coupon_program).write({'active': False})
|
|
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAA Test Partner'})
|
|
partner_bbb = self.env['res.partner'].create({'name': 'BBB Test Partner'})
|
|
partner_ccc = self.env['res.partner'].create({'name': 'CCC Test Partner'})
|
|
|
|
# Part 1
|
|
self.start_pos_tour("PosLoyaltyLoyaltyProgram1")
|
|
|
|
aaa_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_aaa.id)
|
|
|
|
self.assertEqual(loyalty_program.pos_order_count, 1)
|
|
self.assertAlmostEqual(aaa_loyalty_card.points, 4)
|
|
|
|
# Part 2
|
|
self.start_pos_tour("PosLoyaltyLoyaltyProgram2")
|
|
|
|
self.assertEqual(loyalty_program.pos_order_count, 2, msg='Only 2 orders should have reward lines.')
|
|
self.assertAlmostEqual(aaa_loyalty_card.points, 1)
|
|
|
|
bbb_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_bbb.id)
|
|
ccc_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_ccc.id)
|
|
|
|
self.assertAlmostEqual(bbb_loyalty_card.points, 3, msg='Reference: Order3_BBB')
|
|
self.assertAlmostEqual(ccc_loyalty_card.points, 4, msg='Reference: Order2_CCC')
|
|
|
|
reward_orderline = self.main_pos_config.current_session_id.order_ids[-1].lines.filtered(lambda line: line.is_reward_line)
|
|
self.assertEqual(len(reward_orderline.ids), 0, msg='Reference: Order4_no_reward. Last order should have no reward line.')
|
|
|
|
# Part 3
|
|
partner_ddd = self.env['res.partner'].create({'name': 'DDD Test Partner'})
|
|
self.env['loyalty.card'].create({
|
|
'partner_id': partner_ddd.id,
|
|
'program_id': loyalty_program.id,
|
|
'points': 100,
|
|
})
|
|
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyChangeRewardQty",
|
|
login="pos_user",
|
|
)
|
|
|
|
def test_loyalty_free_product_zero_sale_price_loyalty_program(self):
|
|
# In this program, each $ spent gives 1 point.
|
|
# 5 points can be used to get a free whiteboard pen.
|
|
# and the whiteboard pen sale price is zero
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
self.whiteboard_pen.write({'lst_price': 1})
|
|
|
|
loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Loyalty Program',
|
|
'program_type': 'loyalty',
|
|
'trigger': 'auto',
|
|
'applies_on': 'both',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_amount': 1,
|
|
'reward_point_mode': 'money',
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': self.whiteboard_pen.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 5,
|
|
})],
|
|
})
|
|
|
|
(self.promo_programs | self.coupon_program).write({'active': False})
|
|
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAA Test Partner'})
|
|
|
|
self.start_pos_tour("PosLoyaltyLoyaltyProgram3")
|
|
|
|
aaa_loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner_aaa.id)
|
|
|
|
self.assertEqual(loyalty_program.pos_order_count, 1)
|
|
self.assertAlmostEqual(aaa_loyalty_card.points, 5.2)
|
|
|
|
def test_pos_loyalty_tour_max_amount(self):
|
|
"""Test the loyalty program with a maximum amount and product with different taxe."""
|
|
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
self.promo_product = self.env["product.product"].create(
|
|
{
|
|
"name": "Promo Product",
|
|
"type": "service",
|
|
"list_price": 30,
|
|
"available_in_pos": True,
|
|
}
|
|
)
|
|
tax01 = self.env["account.tax"].create({
|
|
"name": "C01 Tax",
|
|
"amount": "0.00",
|
|
})
|
|
tax02 = self.env["account.tax"].create({
|
|
"name": "C02 Tax",
|
|
"amount": "0.00",
|
|
})
|
|
|
|
self.productA = self.env["product.product"].create(
|
|
{
|
|
"name": "Product A",
|
|
"is_storable": True,
|
|
"list_price": 15,
|
|
"available_in_pos": True,
|
|
"taxes_id": [(6, 0, [tax01.id])],
|
|
}
|
|
)
|
|
|
|
# create another product with different taxes_id
|
|
self.productB = self.env["product.product"].create(
|
|
{
|
|
"name": "Product B",
|
|
"is_storable": True,
|
|
"list_price": 25,
|
|
"available_in_pos": True,
|
|
"taxes_id": [(6, 0, [tax02.id])]
|
|
}
|
|
)
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Promo Program - Max Amount',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'product_domain': '[["product_variant_ids.name","=","Promo Product"]]',
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount_product_ids': (self.productA | self.productB).ids,
|
|
'required_points': 1,
|
|
'discount': 100,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
'discount_max_amount': 40,
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.start_pos_tour("PosLoyaltyTour3")
|
|
|
|
def test_gift_card_program(self):
|
|
"""
|
|
Test for gift card program.
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
# Deactivate all other programs to avoid interference
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
# But activate the gift_card_product_50 because it's shared among new gift card programs.
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
# Create gift card program
|
|
gift_card_program = self.create_programs([('arbitrary_name', 'gift_card')])['arbitrary_name']
|
|
# Run the tour to create a gift card
|
|
self.start_pos_tour("GiftCardProgramTour1")
|
|
# Check that gift cards are created
|
|
self.assertEqual(len(gift_card_program.coupon_ids), 1)
|
|
# Change the code to 044123456 so that we can use it in the next tour.
|
|
# Make sure it starts with 044 because it's the prefix of the loyalty cards.
|
|
gift_card_program.coupon_ids.code = '044123456'
|
|
# Run the tour to use the gift card
|
|
self.start_pos_tour("GiftCardProgramTour2")
|
|
# Check that gift cards are used
|
|
self.assertEqual(gift_card_program.coupon_ids.points, 46.8)
|
|
|
|
def test_ewallet_program(self):
|
|
"""
|
|
Test for ewallet program.
|
|
- Collect points in EWalletProgramTour1.
|
|
- Use points in EWalletProgramTour2.
|
|
"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
# Deactivate all other programs to avoid interference
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
# But activate the ewallet_product_50 because it's shared among new ewallet programs.
|
|
self.env.ref('loyalty.ewallet_product_50').write({'active': True})
|
|
# Create ewallet program
|
|
ewallet_program = self.create_programs([('arbitrary_name', 'ewallet')])['arbitrary_name']
|
|
# Create test partners
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAAAAA'})
|
|
partner_bbb = self.env['res.partner'].create({'name': 'BBBBBBB'})
|
|
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
# Run the tour to topup ewallets.
|
|
self.start_pos_tour("EWalletProgramTour1")
|
|
# Check that ewallets are created for partner_aaa.
|
|
ewallet_aaa = self.env['loyalty.card'].search([('partner_id', '=', partner_aaa.id), ('program_id', '=', ewallet_program.id)])
|
|
self.assertEqual(len(ewallet_aaa), 1)
|
|
self.assertAlmostEqual(ewallet_aaa.points, 50, places=2)
|
|
# Check that ewallets are created for partner_bbb.
|
|
ewallet_bbb = self.env['loyalty.card'].search([('partner_id', '=', partner_bbb.id), ('program_id', '=', ewallet_program.id)])
|
|
self.assertEqual(len(ewallet_bbb), 1)
|
|
self.assertAlmostEqual(ewallet_bbb.points, 10, places=2)
|
|
# Run the tour consume ewallets.
|
|
self.start_pos_tour("EWalletProgramTour2")
|
|
# Check that ewallets are consumed for partner_aaa.
|
|
self.assertAlmostEqual(ewallet_aaa.points, 0, places=2)
|
|
# Check final balance after consumption and refund eWallet for partner_bbb.
|
|
self.assertAlmostEqual(ewallet_bbb.points, 20, places=2)
|
|
|
|
def test_multiple_gift_wallet_programs(self):
|
|
"""
|
|
Test for multiple gift_card and ewallet programs.
|
|
"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
# Deactivate all other programs to avoid interference
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
# But activate the gift_card_product_50 and ewallet_product_50 because they're shared among new programs.
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
self.env.ref('loyalty.ewallet_product_50').write({'active': True})
|
|
# Create programs
|
|
programs = self.create_programs([
|
|
('gift_card_1', 'gift_card'),
|
|
('gift_card_2', 'gift_card'),
|
|
('ewallet_1', 'ewallet'),
|
|
('ewallet_2', 'ewallet')
|
|
])
|
|
# Create test partners
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAAAAA'})
|
|
partner_bbb = self.env['res.partner'].create({'name': 'BBBBBBB'})
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
# Run the tour to topup ewallets.
|
|
self.start_pos_tour("MultipleGiftWalletProgramsTour")
|
|
# Check the created gift cards.
|
|
self.assertEqual(len(programs['gift_card_1'].coupon_ids), 1)
|
|
self.assertAlmostEqual(programs['gift_card_1'].coupon_ids.points, 10)
|
|
self.assertEqual(len(programs['gift_card_2'].coupon_ids), 1)
|
|
self.assertAlmostEqual(programs['gift_card_2'].coupon_ids.points, 20)
|
|
# Check the created ewallets.
|
|
ewallet_1_aaa = self.env['loyalty.card'].search([('partner_id', '=', partner_aaa.id), ('program_id', '=', programs['ewallet_1'].id)])
|
|
self.assertEqual(len(ewallet_1_aaa), 1)
|
|
self.assertAlmostEqual(ewallet_1_aaa.points, 18, places=2)
|
|
ewallet_2_aaa = self.env['loyalty.card'].search([('partner_id', '=', partner_aaa.id), ('program_id', '=', programs['ewallet_2'].id)])
|
|
self.assertEqual(len(ewallet_2_aaa), 1)
|
|
self.assertAlmostEqual(ewallet_2_aaa.points, 40, places=2)
|
|
ewallet_1_bbb = self.env['loyalty.card'].search([('partner_id', '=', partner_bbb.id), ('program_id', '=', programs['ewallet_1'].id)])
|
|
self.assertEqual(len(ewallet_1_bbb), 1)
|
|
self.assertAlmostEqual(ewallet_1_bbb.points, 50, places=2)
|
|
ewallet_2_bbb = self.env['loyalty.card'].search([('partner_id', '=', partner_bbb.id), ('program_id', '=', programs['ewallet_2'].id)])
|
|
self.assertEqual(len(ewallet_2_bbb), 1)
|
|
self.assertAlmostEqual(ewallet_2_bbb.points, 0, places=2)
|
|
|
|
def test_coupon_change_pricelist(self):
|
|
"""Test coupon program with different pricelists."""
|
|
|
|
product_1 = self.env["product.product"].create(
|
|
{
|
|
"name": "Test Product 1",
|
|
"is_storable": True,
|
|
"list_price": 25,
|
|
"available_in_pos": True,
|
|
}
|
|
)
|
|
|
|
tax01 = self.env["account.tax"].create({
|
|
"name": "C01 Tax",
|
|
"amount": "0.00",
|
|
})
|
|
|
|
product_2 = self.env["product.product"].create(
|
|
{
|
|
"name": "Test Product 2",
|
|
"is_storable": True,
|
|
"list_price": 25,
|
|
"available_in_pos": True,
|
|
"taxes_id": [(6, 0, [tax01.id])],
|
|
}
|
|
)
|
|
|
|
pricelist = self.env["product.pricelist"].create({
|
|
"name": "Test multi-currency",
|
|
"currency_id": self.env.ref("base.USD").id,
|
|
"item_ids": [
|
|
(0, 0, {
|
|
"base": "standard_price",
|
|
"product_id": product_1.id,
|
|
"compute_price": "percentage",
|
|
"percent_price": 50,
|
|
}),
|
|
(0, 0, {
|
|
"base": "standard_price",
|
|
"product_id": product_2.id,
|
|
"compute_price": "percentage",
|
|
"percent_price": 50,
|
|
})
|
|
]
|
|
})
|
|
|
|
self.cash_journal = self.env['account.journal'].create(
|
|
{'name': 'CASH journal', 'type': 'cash', 'code': 'CSH00'})
|
|
self.cash_payment_method = self.env['pos.payment.method'].create({
|
|
'name': 'Cash Test',
|
|
'journal_id': self.cash_journal.id,
|
|
'receivable_account_id': self.main_pos_config.payment_method_ids.filtered(lambda s: s.is_cash_count).receivable_account_id.id
|
|
})
|
|
|
|
self.main_pos_config2 = self.main_pos_config.copy({
|
|
'payment_method_ids': self.cash_payment_method
|
|
})
|
|
|
|
loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Coupon Program - Pricelist',
|
|
'program_type': 'coupons',
|
|
'trigger': 'with_code',
|
|
'applies_on': 'current',
|
|
'pos_ok': True,
|
|
'pos_config_ids': [Command.link(self.main_pos_config2.id)],
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 1,
|
|
'minimum_amount': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 1,
|
|
'discount': 100,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})],
|
|
})
|
|
|
|
self.env["loyalty.generate.wizard"].with_context(
|
|
{"active_id": loyalty_program.id}
|
|
).create({"coupon_qty": 1, 'points_granted': 4.5}).generate_coupons()
|
|
self.coupon1 = loyalty_program.coupon_ids
|
|
self.coupon1.write({"code": "abcda"})
|
|
|
|
self.main_pos_config2.write({
|
|
'use_pricelist': True,
|
|
'available_pricelist_ids': [(4, pricelist.id), (4, self.main_pos_config.pricelist_id.id)],
|
|
'pricelist_id': pricelist.id,
|
|
})
|
|
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
|
|
self.main_pos_config2.with_user(self.pos_user).open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config2.id,
|
|
"PosLoyaltyTour4",
|
|
login="pos_user",
|
|
)
|
|
|
|
def test_promotion_program_with_global_discount(self):
|
|
"""
|
|
- Create a promotion with a discount of 10%
|
|
- Create a product with no taxes
|
|
- Enable the global discount feature, and make sure the Discount product
|
|
has a tax set on it.
|
|
"""
|
|
|
|
if not self.env["ir.module.module"].search([("name", "=", "pos_discount"), ("state", "=", "installed")]):
|
|
self.skipTest("pos_discount module is required for this test")
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
|
|
tax = self.env["account.tax"].create({
|
|
"name": "C01 Tax",
|
|
"amount": "0.00",
|
|
})
|
|
|
|
self.discount_product = self.env["product.product"].create(
|
|
{
|
|
"name": "Discount Product",
|
|
"type": "service",
|
|
"list_price": 0,
|
|
"available_in_pos": True,
|
|
"taxes_id": [(6, 0, [tax.id])],
|
|
}
|
|
)
|
|
|
|
self.cash_journal = self.env['account.journal'].create(
|
|
{'name': 'CASH journal', 'type': 'cash', 'code': 'CSHDI'})
|
|
self.cash_payment_method = self.env['pos.payment.method'].create({
|
|
'name': 'Cash Test',
|
|
'journal_id': self.cash_journal.id,
|
|
'receivable_account_id': self.main_pos_config.payment_method_ids.filtered(
|
|
lambda s: s.is_cash_count).receivable_account_id.id
|
|
})
|
|
|
|
self.main_pos_config2 = self.main_pos_config.copy({
|
|
'payment_method_ids': self.cash_payment_method
|
|
})
|
|
self.main_pos_config2.write({
|
|
'module_pos_discount' : True,
|
|
'discount_product_id': self.discount_product.id,
|
|
'discount_pc': 20,
|
|
})
|
|
|
|
self.loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Coupon Program - Pricelist',
|
|
'program_type': 'coupons',
|
|
'trigger': 'with_code',
|
|
'applies_on': 'current',
|
|
'pos_ok': True,
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 1,
|
|
'minimum_amount': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 1,
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})],
|
|
})
|
|
|
|
self.product = self.env["product.product"].create(
|
|
{
|
|
"name": "Test Product 1",
|
|
"is_storable": True,
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
}
|
|
)
|
|
|
|
self.main_pos_config2.with_user(self.pos_user).open_ui()
|
|
|
|
self.start_pos_tour("PosCouponTour5", pos_config=self.main_pos_config2)
|
|
|
|
def test_loyalty_program_using_same_product(self):
|
|
"""
|
|
- Create a loyalty program giving free product A for 30 points
|
|
- Trigger the condition of the program using the same product A
|
|
"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
self.product_a = self.env["product.product"].create({
|
|
"name": "Test Product A",
|
|
"is_storable": True,
|
|
"list_price": 10,
|
|
"available_in_pos": True,
|
|
})
|
|
|
|
self.loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Loyalty Program Test',
|
|
'program_type': 'loyalty',
|
|
'trigger': 'auto',
|
|
'applies_on': 'both',
|
|
'pos_ok': True,
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 10,
|
|
'minimum_amount': 5,
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'required_points': 30,
|
|
'reward_product_id': self.product_a.id,
|
|
'reward_product_qty': 1,
|
|
})],
|
|
})
|
|
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAA Partner'})
|
|
self.env['loyalty.card'].create({
|
|
'partner_id': partner_aaa.id,
|
|
'program_id': self.loyalty_program.id,
|
|
'points': 30,
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
|
|
self.start_pos_tour("PosLoyaltyFreeProductTour2")
|
|
|
|
def test_refund_with_gift_card(self):
|
|
"""When adding a gift card when there is a refund in the order, the amount
|
|
of the gift card is set to the amount of the refund"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
# Deactivate all other programs to avoid interference
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
# But activate the gift_card_product_50 because it's shared among new gift card programs.
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
# Create gift card program
|
|
self.create_programs([('arbitrary_name', 'gift_card')])
|
|
self.start_pos_tour("GiftCardWithRefundtTour")
|
|
|
|
def test_loyalty_program_specific_product(self):
|
|
#create a loyalty program with a rules of minimum 2 qty that applies on produt A and B and reward 5 points. The reward is 10$ per order in exchange of 2 points on product A and B
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
self.product_a = self.env["product.product"].create({
|
|
"name": "Test Product A",
|
|
"is_storable": True,
|
|
"list_price": 40,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
})
|
|
self.product_b = self.env["product.product"].create({
|
|
"name": "Test Product B",
|
|
"is_storable": True,
|
|
"list_price": 40,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
})
|
|
self.loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Loyalty Program Test',
|
|
'program_type': 'loyalty',
|
|
'trigger': 'auto',
|
|
'pos_ok': True,
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 10,
|
|
'minimum_qty': 2,
|
|
'product_ids': [(6, 0, [self.product_a.id, self.product_b.id])],
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount_mode': 'per_order',
|
|
'required_points': 2,
|
|
'discount': 10,
|
|
'discount_applicability': 'specific',
|
|
'discount_product_ids': (self.product_a | self.product_b).ids,
|
|
}), (0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount_mode': 'per_order',
|
|
'required_points': 5,
|
|
'discount': 30,
|
|
'discount_applicability': 'specific',
|
|
'discount_product_ids': (self.product_a | self.product_b).ids,
|
|
})],
|
|
})
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltySpecificDiscountTour")
|
|
|
|
def test_discount_specific_product_with_free_product(self):
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
self.product_a = self.env['product.product'].create({
|
|
'name': 'Test Product A',
|
|
'is_storable': True,
|
|
'list_price': 40,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.product_b = self.env['product.product'].create({
|
|
'name': 'Test Product B',
|
|
'is_storable': True,
|
|
'list_price': 80,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.product_c = self.env['product.product'].create({
|
|
'name': 'Test Product C',
|
|
'is_storable': True,
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Discount 10%',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 1,
|
|
'minimum_amount': 10,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount_product_ids': self.product_c.ids,
|
|
'required_points': 1,
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Buy product_a Take product_b',
|
|
'program_type': 'buy_x_get_y',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'product_ids': self.product_a.ids,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': self.product_b.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 1,
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour('PosLoyaltySpecificDiscountWithFreeProductTour')
|
|
|
|
def test_2_discounts_specific_global(self):
|
|
self.env['res.partner'].create({'name': 'AAAA'})
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
|
|
product_category = self.env['product.category'].create({
|
|
'name': 'Discount category',
|
|
})
|
|
|
|
self.product_a = self.env['product.product'].create({
|
|
'name': 'Test Product A',
|
|
'is_storable': True,
|
|
'list_price': 5,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.product_b = self.env['product.product'].create({
|
|
'name': 'Test Product B',
|
|
'is_storable': True,
|
|
'list_price': 5,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'categ_id': product_category.id,
|
|
})
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Discount 10%',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 1,
|
|
'minimum_amount': 1,
|
|
'minimum_qty': 5,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 1,
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Discount on category',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 1,
|
|
'minimum_amount': 1,
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 1,
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
'discount_product_category_id': product_category.id,
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyalty2DiscountsSpecificGlobal")
|
|
|
|
def test_point_per_money_spent(self):
|
|
"""Test the point per $ spent feature"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
self.loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Loyalty Program Test',
|
|
'program_type': 'loyalty',
|
|
'trigger': 'auto',
|
|
'applies_on': 'both',
|
|
'pricelist_ids': [(4, self.main_pos_config.pricelist_id.id)],
|
|
'pos_ok': True,
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'money',
|
|
'reward_point_amount': 0.1,
|
|
'minimum_amount': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 100,
|
|
'discount': 1,
|
|
'discount_mode': 'per_point',
|
|
})],
|
|
})
|
|
|
|
self.product_a = self.env["product.product"].create({
|
|
"name": "Test Product A",
|
|
"is_storable": True,
|
|
"list_price": 265,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
})
|
|
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAA Partner'})
|
|
self.env['loyalty.card'].create({
|
|
'partner_id': partner_aaa.id,
|
|
'program_id': self.loyalty_program.id,
|
|
'points': 100,
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltyTour6")
|
|
|
|
def test_coupon_program_without_rules(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
self.env["product.product"].create(
|
|
{
|
|
"name": "Test Product",
|
|
"is_storable": True,
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
}
|
|
)
|
|
|
|
# creating a coupon program without any rule
|
|
loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Coupon Program without rules',
|
|
'program_type': 'coupons',
|
|
'trigger': 'with_code',
|
|
'applies_on': 'current',
|
|
'pos_ok': True,
|
|
'rule_ids': [],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})],
|
|
})
|
|
|
|
self.env["loyalty.generate.wizard"].with_context(
|
|
{"active_id": loyalty_program.id}
|
|
).create({"coupon_qty": 1, 'points_granted': 1}).generate_coupons()
|
|
self.coupon1 = loyalty_program.coupon_ids
|
|
self.coupon1.write({"code": "abcda"})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltyTour7")
|
|
|
|
def test_discount_with_reward_product_domain(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
product_category_base = self.env.ref('product.product_category_1')
|
|
product_category_1 = self.env['product.category'].create({
|
|
'name': 'Office furnitures',
|
|
'parent_id': product_category_base.id
|
|
})
|
|
|
|
self.productA = self.env['product.product'].create(
|
|
{
|
|
'name': 'Product A',
|
|
'is_storable': True,
|
|
'list_price': 15,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'categ_id': product_category_base.id
|
|
}
|
|
)
|
|
|
|
self.productB = self.env['product.product'].create(
|
|
{
|
|
'name': 'Product B',
|
|
'is_storable': True,
|
|
'list_price': 50,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'categ_id': product_category_1.id
|
|
}
|
|
)
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Discount on Specific Products',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 1,
|
|
'discount': 50,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
'discount_product_domain': '["&", ("categ_id", "ilike", "office"), ("name", "ilike", "Product B")]',
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltySpecificDiscountWithRewardProductDomainTour")
|
|
|
|
def test_promotion_program_with_loyalty_program(self):
|
|
"""
|
|
- Create a promotion with a discount of 10%
|
|
- Create a loyalty program with a fixed discount of 10€
|
|
- Apply both programs to the order
|
|
- Check that no "infinity" discount is applied
|
|
"""
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.promo_program = self.env['loyalty.program'].create({
|
|
'name': 'Promo Program',
|
|
'program_type': 'promotion',
|
|
'pos_ok': True,
|
|
'rule_ids': [(0, 0, {
|
|
'minimum_amount': 0,
|
|
'minimum_qty': 0
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})],
|
|
})
|
|
|
|
self.discount_product = self.env["product.product"].create(
|
|
{
|
|
"name": "Discount Product",
|
|
"type": "service",
|
|
"list_price": 0,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
}
|
|
)
|
|
|
|
self.test_product = self.env["product.product"].create(
|
|
{
|
|
"name": "Test Product 1",
|
|
"is_storable": True,
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
}
|
|
)
|
|
|
|
self.loyalty_program = self.env["loyalty.program"].create(
|
|
{
|
|
"name": "Loyalty Program",
|
|
"program_type": "loyalty",
|
|
"pos_ok": True,
|
|
"rule_ids": [(0, 0, {
|
|
"minimum_amount": 1,
|
|
"minimum_qty": 1,
|
|
"reward_point_mode": "order",
|
|
"reward_point_amount": 500,
|
|
})],
|
|
"reward_ids": [(0, 0, {
|
|
"required_points": 500,
|
|
"reward_type": "discount",
|
|
"discount": "10",
|
|
"discount_mode": "per_order",
|
|
})],
|
|
}
|
|
)
|
|
|
|
partner = self.env['res.partner'].create({'name': 'AAA Partner'})
|
|
self.env['loyalty.card'].create({
|
|
'partner_id': partner.id,
|
|
'program_id': self.loyalty_program.id,
|
|
'points': 500,
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
|
|
self.start_pos_tour("PosLoyaltyPromotion")
|
|
|
|
def test_promo_with_free_product(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.tax01 = self.env["account.tax"].create({
|
|
"name": "C01 Tax",
|
|
"amount": "15.00",
|
|
})
|
|
self.product_a = self.env["product.product"].create(
|
|
{
|
|
"name": "Product A",
|
|
"is_storable": True,
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
"taxes_id": [(6, 0, self.tax01.ids)],
|
|
}
|
|
)
|
|
self.product_b = self.env["product.product"].create(
|
|
{
|
|
"name": "Product B",
|
|
"is_storable": True,
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
}
|
|
)
|
|
self.free_product = self.env['loyalty.program'].create({
|
|
'name': 'Free Product A',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': self.product_a.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 1,
|
|
})],
|
|
})
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Discount 50%',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'reward_point_amount': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 1,
|
|
'discount': 50,
|
|
'discount_mode': 'percent',
|
|
})],
|
|
})
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltyTour8")
|
|
|
|
def test_discount_specific_products(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
product_category_base = self.env.ref('product.product_category_1')
|
|
product_category_1 = self.env['product.category'].create({
|
|
'name': 'Office furnitures',
|
|
'parent_id': product_category_base.id
|
|
})
|
|
|
|
self.productA = self.env['product.product'].create(
|
|
{
|
|
'name': 'Product A',
|
|
'is_storable': True,
|
|
'list_price': 15,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'categ_id': product_category_base.id
|
|
}
|
|
)
|
|
|
|
self.productB = self.env['product.product'].create(
|
|
{
|
|
'name': 'Product B',
|
|
'is_storable': True,
|
|
'list_price': 50,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'categ_id': product_category_1.id
|
|
}
|
|
)
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Discount on Specific Products',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'order',
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 1,
|
|
'discount': 50,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
'discount_product_category_id': product_category_1.id,
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltySpecificDiscountCategoryTour")
|
|
|
|
def test_promo_with_different_taxes(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.tax01 = self.env["account.tax"].create({
|
|
"name": "C01 Tax",
|
|
"amount": "10.00",
|
|
})
|
|
self.product_a = self.env["product.product"].create(
|
|
{
|
|
"name": "Product A",
|
|
"is_storable": True,
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
"taxes_id": [(6, 0, self.tax01.ids)],
|
|
}
|
|
)
|
|
self.product_b = self.env["product.product"].create(
|
|
{
|
|
"name": "Product B",
|
|
"is_storable": True,
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
}
|
|
)
|
|
self.free_product = self.env['loyalty.program'].create({
|
|
'name': 'Free Product A',
|
|
'program_type': 'loyalty',
|
|
'trigger': 'auto',
|
|
'applies_on': 'both',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'money',
|
|
'reward_point_amount': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'required_points': 5,
|
|
'discount_mode': 'per_order',
|
|
'discount': 5,
|
|
})],
|
|
})
|
|
self.env['res.partner'].create({'name': 'AAA Partner'})
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltyTour9")
|
|
|
|
def test_ewallet_expiration_date(self):
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
# Deactivate all other programs to avoid interference
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
# But activate the ewallet_product_50 because it's shared among new ewallet programs.
|
|
self.env.ref('loyalty.ewallet_product_50').write({'active': True})
|
|
# Create ewallet program
|
|
ewallet_program = self.create_programs([('arbitrary_name', 'ewallet')])['arbitrary_name']
|
|
# Create test partners
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAA'})
|
|
#Create an eWallet for partner_aaa
|
|
self.env['loyalty.card'].create({
|
|
'partner_id': partner_aaa.id,
|
|
'program_id': ewallet_program.id,
|
|
'points': 50,
|
|
'expiration_date': date(2020, 1, 1),
|
|
})
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("ExpiredEWalletProgramTour")
|
|
|
|
def test_loyalty_program_with_tagged_free_product(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
free_product_tag = self.env['product.tag'].create({'name': 'Free Product'})
|
|
|
|
self.env['product.product'].create([
|
|
{
|
|
'name': 'Free Product A',
|
|
'is_storable': True,
|
|
'list_price': 1,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'product_tag_ids': [(4, free_product_tag.id)],
|
|
},
|
|
{
|
|
'name': 'Free Product B',
|
|
'is_storable': True,
|
|
'list_price': 1,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'product_tag_ids': [(4, free_product_tag.id)],
|
|
},
|
|
{
|
|
'name': 'Product Test',
|
|
'is_storable': True,
|
|
'list_price': 1,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
}
|
|
])
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Free Product with Tag',
|
|
'program_type': 'loyalty',
|
|
'applies_on': 'both',
|
|
'trigger': 'auto',
|
|
'portal_visible': True,
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 1,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_tag_id': free_product_tag.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 1,
|
|
})],
|
|
})
|
|
|
|
self.env['res.partner'].create({'name': 'AAA Partner'})
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltyTour10")
|
|
|
|
def test_loyalty_program_with_next_order_coupon_free_product(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
free_product = self.env['product.product'].create({
|
|
'name': 'Free Product',
|
|
'is_storable': True,
|
|
'list_price': 1,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.env['product.product'].create({
|
|
'name': 'Product Test',
|
|
'is_storable': True,
|
|
'list_price': 50,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Next Order Coupon Program',
|
|
'program_type': 'next_order_coupons',
|
|
'applies_on': 'future',
|
|
'trigger': 'auto',
|
|
'portal_visible': True,
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'unit',
|
|
'minimum_amount': 100,
|
|
'minimum_qty': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_id': free_product.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 1,
|
|
})],
|
|
})
|
|
|
|
self.env['res.partner'].create({'name': 'AAA Partner'})
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltyTour11.1")
|
|
|
|
coupon = loyalty_program.coupon_ids
|
|
self.assertEqual(len(coupon), 1, "Coupon not generated")
|
|
self.assertEqual(coupon.points, 3, "Coupon not generated with correct points")
|
|
coupon.write({"code": "123456"})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_pos_tour("PosLoyaltyTour11.2")
|
|
self.assertEqual(coupon.points, 0, "Coupon not used")
|
|
|
|
def test_loyalty_program_with_tagged_buy_x_get_y(self):
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
free_product_tag = self.env['product.tag'].create({'name': 'Free Product'})
|
|
|
|
self.env['product.product'].create([
|
|
{
|
|
'name': 'Free Product A',
|
|
'list_price': 1,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'product_tag_ids': [(4, free_product_tag.id)],
|
|
},
|
|
{
|
|
'name': 'Free Product B',
|
|
'list_price': 5,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'product_tag_ids': [(4, free_product_tag.id)],
|
|
},
|
|
])
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Buy X get Y with Tag',
|
|
'program_type': 'buy_x_get_y',
|
|
'applies_on': 'current',
|
|
'trigger': 'auto',
|
|
'portal_visible': True,
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 1,
|
|
'product_tag_id': free_product_tag.id,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_tag_id': free_product_tag.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 2,
|
|
})],
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyTour12",
|
|
login="pos_user",
|
|
)
|
|
|
|
def test_promotion_with_min_amount_and_specific_product_rule(self):
|
|
"""
|
|
Test that the discount is applied iff the min amount is reached for the specified product.
|
|
"""
|
|
self.env['loyalty.program'].search([]).action_archive()
|
|
self.product_a = self.env['product.product'].create({
|
|
'name': "Product A",
|
|
'is_storable': True,
|
|
'list_price': 20,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.env['product.product'].create({
|
|
'name': "Product B",
|
|
'is_storable': True,
|
|
'list_price': 30,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.env['loyalty.program'].create({
|
|
'name': "Discount on specific products",
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [Command.create({
|
|
'minimum_amount': 40,
|
|
'product_ids': [Command.set(self.product_a.ids)],
|
|
})],
|
|
'reward_ids': [Command.create({
|
|
'reward_type': 'discount',
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
'discount_product_ids': [Command.set(self.product_a.ids)],
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
'/pos/web?config_id=%d' % self.main_pos_config.id,
|
|
'PosLoyaltyMinAmountAndSpecificProductTour',
|
|
login='pos_user',
|
|
)
|
|
|
|
def test_gift_card_price_no_tax(self):
|
|
"""
|
|
Test that the gift card has the right price (especially does not include taxes)
|
|
"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
# Deactivate all other programs to avoid interference
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
# But activate the gift_card_product_50 because it's shared among new gift card programs.
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
|
|
# Create gift card program
|
|
gift_card_program = self.create_programs([('arbitrary_name', 'gift_card')])['arbitrary_name']
|
|
|
|
# Set a tax which should not be applied
|
|
gift_card_program.payment_program_discount_product_id.taxes_id = self.env['account.tax'].create({
|
|
'name': "Test Tax",
|
|
"amount_type": "percent",
|
|
'amount': 15,
|
|
})
|
|
|
|
# Generate 1$ gift card.
|
|
self.env["loyalty.generate.wizard"].with_context(
|
|
{"active_id": gift_card_program.id}
|
|
).create({"coupon_qty": 1, 'points_granted': 1}).generate_coupons()
|
|
# Change the code of the gift card.
|
|
gift_card_program.coupon_ids.code = '043123456'
|
|
|
|
# Run the tour. It will use the gift card.
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"GiftCardProgramPriceNoTaxTour",
|
|
login="pos_user"
|
|
)
|
|
|
|
def test_physical_gift_card_sale(self):
|
|
"""
|
|
Test that the manual gift card sold has been correctly generated.
|
|
"""
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
# Deactivate all other programs to avoid interference and activate the gift_card_product_50
|
|
LoyaltyProgram.search([]).write({'pos_ok': False})
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
|
|
# Create gift card program
|
|
gift_card_program = self.create_programs([('arbitrary_name', 'gift_card')])['arbitrary_name']
|
|
|
|
# Run the tour
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PhysicalGiftCardProgramSaleTour",
|
|
login="pos_user"
|
|
)
|
|
|
|
expected_coupons = {
|
|
"test-card-0000": 125,
|
|
"new-card-0001": 250,
|
|
}
|
|
|
|
# Check if the expected coupon codes are present
|
|
coupon_codes = {coupon.code for coupon in gift_card_program.coupon_ids}
|
|
for expected_code in expected_coupons:
|
|
self.assertIn(expected_code, coupon_codes, f"Expected coupon code '{expected_code}' not found")
|
|
|
|
# Check if the expected number of coupons are generated
|
|
self.assertEqual(len(gift_card_program.coupon_ids), 3, "Three coupons should be generated")
|
|
|
|
# Check if the coupon codes and points match the expected values
|
|
for coupon in gift_card_program.coupon_ids:
|
|
if coupon.code in expected_coupons:
|
|
self.assertEqual(coupon.points, expected_coupons[coupon.code], f"Coupon points for '{coupon.code}' should be {expected_coupons[coupon.code]}")
|
|
else:
|
|
# This is the auto-generated coupon with 50 points
|
|
self.assertEqual(coupon.points, 100, "Auto-generated coupon should have 100 points")
|
|
|
|
# Check if the total points of all coupons match the expected value
|
|
total_points = sum(coupon.points for coupon in gift_card_program.coupon_ids)
|
|
self.assertEqual(total_points, 475, "Total points should be 425")
|
|
|
|
def test_dont_grant_points_reward_order_lines(self):
|
|
"""
|
|
Make sure that points granted per unit are only given
|
|
for the product -non reward- lines!
|
|
"""
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
loyalty_program = self.env['loyalty.program'].create({
|
|
'name': 'Loyalty Program',
|
|
'program_type': 'loyalty',
|
|
'applies_on': 'both',
|
|
'trigger': 'auto',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_amount': 1,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 2,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 100,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'cheapest',
|
|
'required_points': 2,
|
|
})],
|
|
})
|
|
|
|
partner = self.env['res.partner'].create({'name': 'Test Partner'})
|
|
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyDontGrantPointsForRewardOrderLines",
|
|
login="pos_user",
|
|
)
|
|
|
|
loyalty_card = loyalty_program.coupon_ids.filtered(lambda coupon: coupon.partner_id.id == partner.id)
|
|
|
|
self.assertTrue(loyalty_card)
|
|
self.assertFalse(loyalty_card.points)
|
|
|
|
def test_points_awarded_global_discount_code_no_domain_program(self):
|
|
"""
|
|
Check the calculation for points awarded when there is a global discount applied and the
|
|
loyalty program applies on all product (no domain).
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.product_a.write({
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
self.auto_promo_program_next.applies_on = 'current'
|
|
self.auto_promo_program_next.active = True
|
|
|
|
loyalty_program = self.create_programs([('Loyalty P', 'loyalty')])['Loyalty P']
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAA'})
|
|
loyalty_card = self.env['loyalty.card'].create({
|
|
'program_id': loyalty_program.id,
|
|
'partner_id': partner_aaa.id,
|
|
'points': 0,
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyPointsGlobalDiscountProgramNoDomain",
|
|
login="pos_user",
|
|
)
|
|
self.assertEqual(loyalty_card.points, 90)
|
|
|
|
def test_points_awarded_discount_code_no_domain_program(self):
|
|
"""
|
|
Check the calculation for points awarded when there is a discount coupon applied and the
|
|
loyalty program applies on all product (no domain).
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.product_a.write({
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
self.product_b.write({
|
|
'list_price': 50,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
loyalty_program = self.create_programs([('Loyalty P', 'loyalty')])['Loyalty P']
|
|
loyalty_program.pos_config_ids = [Command.link(self.main_pos_config.id)]
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAA'})
|
|
loyalty_card = self.env['loyalty.card'].create({
|
|
'program_id': loyalty_program.id,
|
|
'partner_id': partner_aaa.id,
|
|
'points': 0,
|
|
})
|
|
|
|
self.code_promo_program.active = True
|
|
self.code_promo_program.reward_ids.write(
|
|
{
|
|
'description': '10% on your order',
|
|
'discount': 10,
|
|
'discount_applicability': 'order',
|
|
'discount_product_ids': None
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyPointsDiscountNoDomainProgramNoDomain",
|
|
login="pos_user",
|
|
)
|
|
self.assertEqual(loyalty_card.points, 135)
|
|
|
|
def test_points_awarded_general_discount_code_specific_domain_program(self):
|
|
"""
|
|
Check the calculation for points awarded when there is a discount coupon applied and the
|
|
loyalty program applies on a sepcific domain. The discount code has no domain. The product
|
|
related to that discount is not in the domain of the loyalty program.
|
|
Expected behavior: The discount is not included in the computation of points
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
product_category_base = self.env.ref('product.product_category_1')
|
|
product_category_food = self.env['product.category'].create({
|
|
'name': 'Food',
|
|
'parent_id': product_category_base.id
|
|
})
|
|
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
self.product_a.write({
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'categ_id': product_category_food.id,
|
|
})
|
|
self.product_b.write({
|
|
'list_price': 50,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
loyalty_program = self.create_programs([('Loyalty P', 'loyalty')])['Loyalty P']
|
|
loyalty_program.rule_ids.product_category_id = product_category_food.id
|
|
loyalty_program.pos_config_ids = [Command.link(self.main_pos_config.id)]
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAA'})
|
|
loyalty_card = self.env['loyalty.card'].create({
|
|
'program_id': loyalty_program.id,
|
|
'partner_id': partner_aaa.id,
|
|
'points': 0,
|
|
})
|
|
|
|
self.code_promo_program.active = True
|
|
self.code_promo_program.reward_ids.write(
|
|
{
|
|
'description': '10% on your order',
|
|
'discount': 10,
|
|
'discount_applicability': 'order',
|
|
'discount_product_ids': None
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyPointsDiscountNoDomainProgramDomain",
|
|
login="pos_user",
|
|
)
|
|
self.assertEqual(loyalty_card.points, 100)
|
|
|
|
def test_points_awarded_specific_discount_code_specific_domain_program(self):
|
|
"""
|
|
Check the calculation for points awarded when there is a discount coupon applied and the
|
|
loyalty program applies on a sepcific domain. The discount code has the same domain as the
|
|
loyalty program. The product related to that discount code is set up to be included in the
|
|
domain of the loyalty program.
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
product_category_base = self.env.ref('product.product_category_1')
|
|
product_category_food = self.env['product.category'].create({
|
|
'name': 'Food',
|
|
'parent_id': product_category_base.id
|
|
})
|
|
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
self.product_a.write({
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'categ_id': product_category_food.id,
|
|
})
|
|
self.product_b.write({
|
|
'list_price': 50,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
loyalty_program = self.create_programs([('Loyalty P', 'loyalty')])['Loyalty P']
|
|
loyalty_program.rule_ids.product_category_id = product_category_food.id
|
|
loyalty_program.pos_config_ids = [Command.link(self.main_pos_config.id)]
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAA'})
|
|
loyalty_card = self.env['loyalty.card'].create({
|
|
'program_id': loyalty_program.id,
|
|
'partner_id': partner_aaa.id,
|
|
'points': 0,
|
|
})
|
|
|
|
self.code_promo_program.active = True
|
|
self.code_promo_program.reward_ids.write(
|
|
{
|
|
'description': '10% on your order',
|
|
'discount': 10,
|
|
'discount_product_ids': None,
|
|
'discount_product_category_id': product_category_food.id,
|
|
})
|
|
|
|
discount_product = self.env['product.product'].search([('id', '=', self.code_promo_program.reward_ids.discount_line_product_id.id)])
|
|
discount_product.categ_id = product_category_food.id
|
|
discount_product.name = "10% on food"
|
|
discount_product.available_in_pos = True
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyPointsDiscountWithDomainProgramDomain",
|
|
login="pos_user",
|
|
)
|
|
self.assertEqual(loyalty_card.points, 90)
|
|
|
|
def test_points_awarded_ewallet(self):
|
|
"""
|
|
Check the calculation for point awarded when using ewallet
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.product_a.write({
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
loyalty_program = self.create_programs([('Loyalty P', 'loyalty')])['Loyalty P']
|
|
loyalty_program.pos_config_ids = [Command.link(self.main_pos_config.id)]
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAA'})
|
|
loyalty_card = self.env['loyalty.card'].create({
|
|
'program_id': loyalty_program.id,
|
|
'partner_id': partner_aaa.id,
|
|
'points': 0,
|
|
})
|
|
|
|
ewallet_program = self.env['loyalty.program'].create({
|
|
'name': 'eWallet Program',
|
|
'program_type': 'ewallet',
|
|
'trigger': 'auto',
|
|
'applies_on': 'future',
|
|
'reward_ids': [Command.create({
|
|
'reward_type': 'discount',
|
|
'discount_mode': 'per_point',
|
|
'discount': 1,
|
|
})],
|
|
'rule_ids': [Command.create({
|
|
'reward_point_amount': '1',
|
|
'reward_point_mode': 'money',
|
|
'product_ids': self.env.ref('loyalty.ewallet_product_50'),
|
|
})],
|
|
'trigger_product_ids': self.env.ref('loyalty.ewallet_product_50'),
|
|
})
|
|
|
|
self.env['loyalty.card'].create({
|
|
'program_id': ewallet_program.id,
|
|
'partner_id': partner_aaa.id,
|
|
'points': 10,
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/ui?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyPointsEwallet",
|
|
login="pos_user",
|
|
)
|
|
self.assertEqual(loyalty_card.points, 100)
|
|
|
|
def test_points_awarded_giftcard(self):
|
|
"""
|
|
Check the calculation for point awarded when using a gift card
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
# Create gift card program
|
|
gift_card_program = self.create_programs([('arbitrary_name', 'gift_card')])['arbitrary_name']
|
|
|
|
self.product_a.write({
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
loyalty_program = self.create_programs([('Loyalty P', 'loyalty')])['Loyalty P']
|
|
loyalty_program.pos_config_ids = [Command.link(self.main_pos_config.id)]
|
|
partner_aaa = self.env['res.partner'].create({'name': 'AAAA'})
|
|
loyalty_card = self.env['loyalty.card'].create({
|
|
'program_id': loyalty_program.id,
|
|
'partner_id': partner_aaa.id,
|
|
'points': 0,
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyPointsGiftcard",
|
|
login="pos_user",
|
|
)
|
|
self.assertEqual(loyalty_card.points, 100)
|
|
|
|
def test_archived_reward_products(self):
|
|
"""
|
|
Check that a loyalty_reward with no active reward product is not loaded.
|
|
In the case where the reward is based on reward_product_tag_id we also check
|
|
the case where at least one reward is active.
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
free_product_tag = self.env['product.tag'].create({'name': 'Free Product'})
|
|
self.env['res.partner'].create({'name': 'AAAA'})
|
|
|
|
self.product_a.write({
|
|
'name': 'Test Product A',
|
|
'is_storable': True,
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
self.product_b.write({'product_tag_ids': [(4, free_product_tag.id)]})
|
|
product_c = self.env['product.product'].create(
|
|
{
|
|
'name': 'Free Product C',
|
|
'list_price': 1,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
'product_tag_ids': [(4, free_product_tag.id)],
|
|
}
|
|
)
|
|
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
loyalty_program = LoyaltyProgram.create(LoyaltyProgram._get_template_values()['loyalty'])
|
|
loyalty_program_tag = LoyaltyProgram.create(LoyaltyProgram._get_template_values()['loyalty'])
|
|
|
|
loyalty_program.reward_ids.write({
|
|
'reward_type': 'product',
|
|
'required_points': 1,
|
|
'reward_product_id': self.product_b,
|
|
})
|
|
|
|
loyalty_program_tag.reward_ids.write({
|
|
'reward_type': 'product',
|
|
'required_points': 1,
|
|
'reward_product_tag_id': free_product_tag.id,
|
|
})
|
|
|
|
self.product_b.active = False
|
|
product_c.active = False
|
|
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyArchivedRewardProductsInactive",
|
|
login="pos_user",
|
|
)
|
|
|
|
product_c.active = True
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyArchivedRewardProductsActive",
|
|
login="pos_user"
|
|
)
|
|
|
|
def test_change_reward_value_with_language(self):
|
|
"""
|
|
Verify that the displayed language is not en_US.
|
|
When a user has another language than en_US set,
|
|
he shouldn't have the en_US message displayed but the message of the active language.
|
|
For this test, we shouldn't have the description displayed for selecting the reward in en_US but in en_GB.
|
|
Description in en_US (unexpected): 'A en_US name which should not be displayed'
|
|
Description in en_GB (expected): '$ 2 on your order'
|
|
"""
|
|
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env['res.lang']._activate_lang('en_GB')
|
|
env_gb = self.env(context={'lang': 'en_GB'})
|
|
self.pos_user.write({'lang': 'en_GB'})
|
|
|
|
loyalty_program = env_gb['loyalty.program'].create({
|
|
'name': 'Loyalty Program',
|
|
'program_type': 'loyalty',
|
|
'applies_on': 'both',
|
|
'trigger': 'auto',
|
|
'rule_ids': [(0, 0, {
|
|
'reward_point_amount': 1,
|
|
'reward_point_mode': 'money',
|
|
'minimum_qty': 0,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 2,
|
|
'discount_mode': 'per_order',
|
|
'discount_applicability': 'order',
|
|
'required_points': 1,
|
|
})],
|
|
})
|
|
|
|
loyalty_program.reward_ids.update_field_translations('description', {'en_US': 'A en_US name which should not be displayed'})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"ChangeRewardValueWithLanguage",
|
|
login="pos_user",
|
|
)
|
|
|
|
def test_loyalty_reward_product_tag(self):
|
|
"""
|
|
We test that a program using product tag to define reward products will
|
|
correctly compute the reward lines.
|
|
"""
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
free_product_tag = self.env['product.tag'].create({'name': 'Free Product Tag'})
|
|
self.product_a.write({'product_tag_ids': [(4, free_product_tag.id)], 'lst_price': 2, 'taxes_id': None, 'name': 'Product A'})
|
|
self.product_b.write({'product_tag_ids': [(4, free_product_tag.id)], 'lst_price': 5, 'taxes_id': None, 'name': 'Product B'})
|
|
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Buy 2 Take 1 Free Product',
|
|
'program_type': 'buy_x_get_y',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [(0, 0, {
|
|
'product_ids': self.desk_organizer,
|
|
'reward_point_mode': 'unit',
|
|
'minimum_qty': 2,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'product',
|
|
'reward_product_tag_id': free_product_tag.id,
|
|
'reward_product_qty': 1,
|
|
'required_points': 2,
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyRewardProductTag",
|
|
login="pos_user",
|
|
)
|
|
|
|
def test_gift_card_rewards_using_taxes(self):
|
|
"""
|
|
Check the gift card value when the reward has taxes
|
|
"""
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
|
|
gift_card_program = self.create_programs([('arbitrary_name', 'gift_card')])['arbitrary_name']
|
|
self.product_a = self.env["product.product"].create({
|
|
"name": "Test Product A",
|
|
"list_price": 100,
|
|
"available_in_pos": True,
|
|
"taxes_id": False,
|
|
})
|
|
|
|
self.tax01 = self.env["account.tax"].create({
|
|
"name": "C01 Tax",
|
|
"amount": "15.00",
|
|
})
|
|
gift_card_program.payment_program_discount_product_id.taxes_id = self.tax01
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosLoyaltyGiftCardTaxes",
|
|
login="accountman",
|
|
)
|
|
self.main_pos_config.current_session_id.close_session_from_ui()
|
|
|
|
def test_customer_loyalty_points_displayed(self):
|
|
"""
|
|
Verify that the loyalty points of a customer are well displayed.
|
|
This test will only work on big screens because the balance column is not shown when 'ui.isSmall == True'.
|
|
"""
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
|
|
john_doe = self.env['res.partner'].create({'name': 'John Doe'})
|
|
|
|
loyalty_program = self.create_programs([('Loyalty P', 'loyalty')])['Loyalty P']
|
|
self.env['loyalty.card'].create({
|
|
'partner_id': john_doe.id,
|
|
'program_id': loyalty_program.id,
|
|
'points': 0
|
|
})
|
|
|
|
self.product_a.write({
|
|
'list_price': 100,
|
|
'available_in_pos': True,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
self.main_pos_config.open_ui()
|
|
self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, "CustomerLoyaltyPointsDisplayed", login="pos_user")
|
|
|
|
def test_cheapest_product_reward_pos_combo(self):
|
|
self.env['product.product'].create({
|
|
"name": "Expensive product",
|
|
"lst_price": 1000,
|
|
"available_in_pos": True,
|
|
})
|
|
self.env['product.product'].create({
|
|
"name": "Cheap product",
|
|
"lst_price": 1,
|
|
"available_in_pos": True,
|
|
})
|
|
setup_product_combo_items(self)
|
|
self.office_combo.write({'lst_price': 50})
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Auto Promo Program - Cheapest Product',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'rule_ids': [(0, 0, {
|
|
'minimum_qty': 2,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'cheapest',
|
|
})]
|
|
})
|
|
|
|
self.main_pos_config.with_user(self.pos_user).open_ui()
|
|
self.start_tour(f"/pos/ui?config_id={self.main_pos_config.id}", 'PosComboCheapestRewardProgram', login="pos_user")
|
|
|
|
def test_specific_product_reward_pos_combo(self):
|
|
setup_product_combo_items(self)
|
|
self.office_combo.write({'lst_price': 200})
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Combo Product Promotion',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'rule_ids': [(0, 0, {
|
|
'minimum_qty': 1,
|
|
'product_ids': self.office_combo.ids,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'specific',
|
|
'discount_product_ids': self.office_combo.ids,
|
|
})]
|
|
})
|
|
|
|
self.main_pos_config.with_user(self.pos_user).open_ui()
|
|
self.start_tour(f"/pos/ui?config_id={self.main_pos_config.id}", 'PosComboSpecificProductProgram', login="pos_user")
|
|
|
|
def test_apply_reward_on_product_scan(self):
|
|
"""
|
|
Test that the rewards are correctly applied if the
|
|
product is scanned rather than added by hand.
|
|
"""
|
|
product = self.product_a
|
|
product.write({
|
|
'available_in_pos': True,
|
|
'barcode': '95412427100283',
|
|
})
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env['loyalty.program'].create({
|
|
'name': 'My super program',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [Command.create({
|
|
'product_ids': [Command.set(product.ids)],
|
|
'reward_point_mode': 'order',
|
|
})],
|
|
'reward_ids': [Command.create({
|
|
'reward_type': 'discount',
|
|
'discount': 50,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
self.main_pos_config.with_user(self.pos_admin).open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosRewardProductScan",
|
|
login="pos_admin",
|
|
)
|
|
# check the same flow with gs1 nomenclature
|
|
self.env.company.nomenclature_id = self.env.ref('barcodes_gs1_nomenclature.default_gs1_nomenclature')
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"PosRewardProductScanGS1",
|
|
login="pos_admin",
|
|
)
|
|
|
|
def test_coupon_pricelist(self):
|
|
self.env["product.product"].create(
|
|
{
|
|
"name": "Test Product 1",
|
|
"is_storable": True,
|
|
"list_price": 25,
|
|
"available_in_pos": True,
|
|
}
|
|
)
|
|
|
|
alt_pos_config = self.main_pos_config.copy()
|
|
pricelist_1 = self.env['product.pricelist'].create(
|
|
{
|
|
"name": "test pricelist 1",
|
|
"currency_id": self.env.ref("base.USD").id,
|
|
}
|
|
)
|
|
alt_pos_config.write({
|
|
'use_pricelist': True,
|
|
'available_pricelist_ids': [(4, pricelist_1.id)],
|
|
'pricelist_id': pricelist_1.id,
|
|
})
|
|
|
|
self.env["loyalty.program"].create(
|
|
{
|
|
"name": "Test Loyalty Program",
|
|
"program_type": "promotion",
|
|
"trigger": "with_code",
|
|
'pos_ok': True,
|
|
"pricelist_ids": [(4, pricelist_1.id)],
|
|
"rule_ids": [
|
|
Command.create({"mode": "with_code", "code": "hellopromo", "minimum_amount": 10}),
|
|
],
|
|
"reward_ids": [
|
|
Command.create({
|
|
"reward_type": "discount",
|
|
"discount": 10,
|
|
"discount_mode": "percent",
|
|
"discount_applicability": "order",
|
|
"required_points": 1,
|
|
}),
|
|
],
|
|
'pos_config_ids': [Command.link(alt_pos_config.id)],
|
|
|
|
}
|
|
)
|
|
|
|
alt_pos_config.with_user(self.pos_admin).open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % alt_pos_config.id,
|
|
"PosLoyaltyPromocodePricelist",
|
|
login="pos_user",
|
|
)
|
|
|
|
def test_gift_card_program_create_with_invoice(self):
|
|
"""
|
|
Test for gift card program when pos.config.gift_card_settings == 'create_set'.
|
|
"""
|
|
self.pos_user.write({
|
|
'groups_id': [
|
|
(4, self.env.ref('stock.group_stock_user').id),
|
|
]
|
|
})
|
|
LoyaltyProgram = self.env['loyalty.program']
|
|
(LoyaltyProgram.search([])).write({'pos_ok': False})
|
|
self.env.ref('loyalty.gift_card_product_50').write({'active': True})
|
|
|
|
gift_card_program = self.create_programs([('arbitrary_name', 'gift_card')])['arbitrary_name']
|
|
self.env['res.partner'].create({'name': 'Test Partner'})
|
|
|
|
self.main_pos_config.with_user(self.pos_user).open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"GiftCardProgramInvoice",
|
|
login="pos_user",
|
|
)
|
|
self.assertEqual(len(gift_card_program.coupon_ids), 1)
|
|
|
|
def test_refund_product_part_of_rules(self):
|
|
|
|
self.product_a.available_in_pos = True
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env['loyalty.program'].create({
|
|
'name': 'My super program',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'applies_on': 'current',
|
|
'rule_ids': [Command.create({
|
|
'product_ids': [Command.set(self.product_a.ids)],
|
|
'reward_point_mode': 'order',
|
|
})],
|
|
'reward_ids': [Command.create({
|
|
'reward_type': 'discount',
|
|
'discount': 50,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'order',
|
|
})],
|
|
'pos_config_ids': [Command.link(self.main_pos_config.id)],
|
|
})
|
|
|
|
self.main_pos_config.with_user(self.pos_user).open_ui()
|
|
self.start_tour(
|
|
"/pos/web?config_id=%d" % self.main_pos_config.id,
|
|
"RefundRulesProduct",
|
|
login="pos_user",
|
|
)
|
|
|
|
def test_cheapest_product_tax_included(self):
|
|
tax_01 = self.env['account.tax'].create({
|
|
"name": "Tax 1",
|
|
"amount": 10,
|
|
"price_include_override": "tax_included",
|
|
})
|
|
|
|
self.env['product.product'].create({
|
|
"name": "Product",
|
|
"lst_price": 1,
|
|
"available_in_pos": True,
|
|
"taxes_id": [(6, 0, [tax_01.id])]
|
|
})
|
|
|
|
self.env['loyalty.program'].search([]).write({'active': False})
|
|
self.env['loyalty.program'].create({
|
|
'name': 'Auto Promo Program - Cheapest Product',
|
|
'program_type': 'promotion',
|
|
'trigger': 'auto',
|
|
'rule_ids': [(0, 0, {
|
|
'minimum_qty': 2,
|
|
})],
|
|
'reward_ids': [(0, 0, {
|
|
'reward_type': 'discount',
|
|
'discount': 10,
|
|
'discount_mode': 'percent',
|
|
'discount_applicability': 'cheapest',
|
|
})]
|
|
})
|
|
|
|
self.main_pos_config.with_user(self.pos_user).open_ui()
|
|
self.start_tour(f"/pos/ui?config_id={self.main_pos_config.id}", 'PosCheapestProductTaxInclude', login="pos_user")
|