[FIX] sale_loyalty: add ewallet and coupons to cart
Steps to reproduce: - go to e-commerce; - add two products (A and B) to the cart; - apply an eWallet; - apply a coupons which allows a 100% discount on product A. Issue: A traceback appears (Internal Server Error). Cause: We are trying to access a dictionary value a key which does not exist. Solution: Correct the distribution of the amount of payment programs. opw-3115066 closes odoo/odoo#110036 X-original-commit: 0654d87211d9d9319e94b87a8bc6469778633f02 Signed-off-by: William Braeckman (wbr) <wbr@odoo.com> Signed-off-by: Lefebvre Thomas (thle) <thle@odoo.com>
This commit is contained in:
@@ -229,6 +229,7 @@ class SaleOrder(models.Model):
|
||||
continue
|
||||
discount_lines[line.reward_identifier_code] |= line
|
||||
|
||||
order_lines -= self.order_line.filtered("reward_id")
|
||||
cheapest_line = False
|
||||
for lines in discount_lines.values():
|
||||
line_reward = lines.reward_id
|
||||
@@ -252,12 +253,19 @@ class SaleOrder(models.Model):
|
||||
# Fixed prices are per tax
|
||||
discounted_amounts = {line.tax_id: abs(line.price_total) for line in lines}
|
||||
for line in itertools.chain(non_common_lines, common_lines):
|
||||
discounted_amount = discounted_amounts[line.tax_id]
|
||||
# For gift card and eWallet programs we have no tax but we can consume the amount completely
|
||||
if lines.reward_id.program_id.is_payment_program:
|
||||
discounted_amount = discounted_amounts[lines.tax_id]
|
||||
else:
|
||||
discounted_amount = discounted_amounts[line.tax_id]
|
||||
if discounted_amount == 0:
|
||||
continue
|
||||
remaining = remaining_amount_per_line[line]
|
||||
consumed = min(remaining, discounted_amount)
|
||||
discounted_amounts[line.tax_id] -= consumed
|
||||
if lines.reward_id.program_id.is_payment_program:
|
||||
discounted_amounts[lines.tax_id] -= consumed
|
||||
else:
|
||||
discounted_amounts[line.tax_id] -= consumed
|
||||
remaining_amount_per_line[line] -= consumed
|
||||
|
||||
discountable = 0
|
||||
@@ -310,7 +318,7 @@ class SaleOrder(models.Model):
|
||||
converted_discount = self.currency_id._convert(min(max_discount, discountable), reward.currency_id, self.company_id, fields.Date.today())
|
||||
point_cost = converted_discount / reward.discount
|
||||
# Gift cards and eWallets are considered gift cards and should not have any taxes
|
||||
if reward.program_id.program_type in ('ewallet', 'gift_card'):
|
||||
if reward.program_id.is_payment_program:
|
||||
return [{
|
||||
'name': reward.description,
|
||||
'product_id': reward.discount_line_product_id.id,
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import TransactionCase, tagged, new_test_user
|
||||
from odoo.tests import tagged, new_test_user
|
||||
from odoo.addons.sale_loyalty.tests.common import TestSaleCouponCommon
|
||||
from odoo import Command
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestLoyalty(TransactionCase):
|
||||
class TestLoyalty(TestSaleCouponCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -117,3 +119,104 @@ class TestLoyalty(TransactionCase):
|
||||
# This last one will try to find related POS lines while user have not access to POS.
|
||||
order._action_cancel()
|
||||
self.assertFalse(order.coupon_point_ids)
|
||||
|
||||
def test_distribution_amount_payment_programs(self):
|
||||
"""
|
||||
Check how the amount of a payment reward is distributed.
|
||||
An ewallet should not be used to refund taxes.
|
||||
Its amount must be distributed between the products.
|
||||
"""
|
||||
|
||||
# Create two products
|
||||
product_a, product_b = self.env['product.product'].create([
|
||||
{
|
||||
'name': 'Product A',
|
||||
'list_price': 100,
|
||||
'sale_ok': True,
|
||||
'taxes_id': [Command.set(self.tax_15pc_excl.ids)],
|
||||
},
|
||||
{
|
||||
'name': 'Product B',
|
||||
'list_price': 100,
|
||||
'sale_ok': True,
|
||||
'taxes_id': [Command.set(self.tax_15pc_excl.ids)],
|
||||
},
|
||||
])
|
||||
|
||||
# Create a coupon and a ewallet
|
||||
coupon_program, ewallet_program = self.env['loyalty.program'].create([
|
||||
{
|
||||
'name': 'Coupon Program',
|
||||
'program_type': 'coupons',
|
||||
'trigger': 'with_code',
|
||||
'applies_on': 'both',
|
||||
'reward_ids': [Command.create({
|
||||
'reward_type': 'discount',
|
||||
'discount': 100.0,
|
||||
'discount_applicability': 'specific',
|
||||
'discount_product_domain': '[("name", "=", "Product A")]',
|
||||
})],
|
||||
},
|
||||
{
|
||||
'name': 'eWallet Program',
|
||||
'program_type': 'ewallet',
|
||||
'applies_on': 'future',
|
||||
'trigger': 'auto',
|
||||
'rule_ids': [Command.create({
|
||||
'reward_point_mode': 'money',
|
||||
})],
|
||||
'reward_ids': [Command.create({
|
||||
'discount_mode': 'per_point',
|
||||
'discount': 1,
|
||||
'discount_applicability': 'order',
|
||||
})],
|
||||
}
|
||||
])
|
||||
|
||||
coupon_partner, _ = self.env['loyalty.card'].create([
|
||||
{
|
||||
'program_id': coupon_program.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'points': 1,
|
||||
'code': '5555',
|
||||
},
|
||||
{
|
||||
'program_id': ewallet_program.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'points': 115,
|
||||
},
|
||||
])
|
||||
|
||||
# Create the order
|
||||
order = self.env['sale.order'].with_user(self.user_salemanager).create({
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
Command.create({
|
||||
'product_id': product_a.id,
|
||||
}),
|
||||
Command.create({
|
||||
'product_id': product_b.id,
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
||||
self.assertEqual(order.amount_total, 230.0)
|
||||
self.assertEqual(order.amount_untaxed, 200.0)
|
||||
self.assertEqual(order.amount_tax, 30.0)
|
||||
|
||||
# Apply the eWallet
|
||||
order._update_programs_and_rewards()
|
||||
self._claim_reward(order, ewallet_program)
|
||||
|
||||
self.assertEqual(order.amount_total, 115.0)
|
||||
self.assertEqual(order.amount_untaxed, 85.0)
|
||||
self.assertEqual(order.amount_tax, 30.0)
|
||||
self.assertEqual(order.reward_amount, -115.0)
|
||||
|
||||
# Apply the coupon
|
||||
self._apply_promo_code(order, coupon_partner.code)
|
||||
|
||||
self.assertEqual(order.amount_total, 0.0)
|
||||
self.assertEqual(order.amount_untaxed, -15.0)
|
||||
self.assertEqual(order.amount_tax, 15.0)
|
||||
self.assertEqual(order.reward_amount, -215.0)
|
||||
|
||||
Reference in New Issue
Block a user