[FIX] sale_coupon: no fixed tax discount

Have a product with percent tax and fixed tax
Have a promo program applying 50% on the order
Create a sale order
- Add the product
- Add the promo

Issue: The fixed tax is discounted
We should ignore fixed taxes when applying promotions.

opw-3580170

closes odoo/odoo#149165

X-original-commit: 2acce1c84586a0f91ac3a83570d574d0ec96f1f6
Signed-off-by: Andrea Grazioso (agr) <agr@odoo.com>
This commit is contained in:
Andrea Grazioso (agr-odoo)
2024-01-17 09:15:29 +00:00
parent 5e9918f845
commit e00c7a4359
2 changed files with 113 additions and 10 deletions
+18 -10
View File
@@ -171,9 +171,15 @@ class SaleOrder(models.Model):
# Ignore lines from this reward
if not line.product_uom_qty or not line.price_unit:
continue
line_discountable = line.price_unit * line.product_uom_qty * (1 - (line.discount or 0.0) / 100.0)
discountable += line.price_total
discountable_per_tax[line.tax_id] += line_discountable
tax_data = line._convert_to_tax_base_line_dict()
# To compute the discountable amount we get the fixed tax amount and
# subtract it from the order total. This way fixed taxes will not be discounted
tax_data['taxes'] = tax_data['taxes'].filtered(lambda t: t.amount_type == 'fixed')
tax_results = self.env['account.tax']._compute_taxes([tax_data])
totals = list(tax_results['totals'].values())[0]
discountable += line.price_total - totals['amount_tax']
taxes = line.tax_id.filtered(lambda t: t.amount_type != 'fixed')
discountable_per_tax[taxes] += totals['amount_untaxed']
return discountable, discountable_per_tax
def _cheapest_line(self):
@@ -195,7 +201,8 @@ class SaleOrder(models.Model):
cheapest_line = self._cheapest_line()
discountable = cheapest_line.price_unit * (1 - (cheapest_line.discount or 0) / 100)
return discountable, {cheapest_line.tax_id: discountable}
taxes = cheapest_line.tax_id.filtered(lambda t: t.amount_type != 'fixed')
return discountable, {taxes: discountable}
def _get_specific_discountable_lines(self, reward):
"""
@@ -258,21 +265,21 @@ class SaleOrder(models.Model):
else:
non_common_lines = discounted_lines - lines_to_discount
# Fixed prices are per tax
discounted_amounts = {line.tax_id: abs(line.price_total) for line in lines}
discounted_amounts = {line.tax_id.filtered(lambda t: t.amount_type != 'fixed'): abs(line.price_total) for line in lines}
for line in itertools.chain(non_common_lines, common_lines):
# 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]
discounted_amount = discounted_amounts[lines.tax_id.filtered(lambda t: t.amount_type != 'fixed')]
else:
discounted_amount = discounted_amounts[line.tax_id]
discounted_amount = discounted_amounts[line.tax_id.filtered(lambda t: t.amount_type != 'fixed')]
if discounted_amount == 0:
continue
remaining = remaining_amount_per_line[line]
consumed = min(remaining, discounted_amount)
if lines.reward_id.program_id.is_payment_program:
discounted_amounts[lines.tax_id] -= consumed
discounted_amounts[lines.tax_id.filtered(lambda t: t.amount_type != 'fixed')] -= consumed
else:
discounted_amounts[line.tax_id] -= consumed
discounted_amounts[line.tax_id.filtered(lambda t: t.amount_type != 'fixed')] -= consumed
remaining_amount_per_line[line] -= consumed
discountable = 0
@@ -283,7 +290,8 @@ class SaleOrder(models.Model):
# line_discountable is the same as in a 'order' discount
# but first multiplied by a factor for the taxes to apply
# and then multiplied by another factor coming from the discountable
discountable_per_tax[line.tax_id] += line_discountable *\
taxes = line.tax_id.filtered(lambda t: t.amount_type != 'fixed')
discountable_per_tax[taxes] += line_discountable *\
(remaining_amount_per_line[line] / line.price_total)
return discountable, discountable_per_tax
@@ -1657,3 +1657,98 @@ class TestSaleCouponProgramNumbers(TestSaleCouponNumbersCommon):
self.assertEqual(len(order.order_line), 2, 'Promotion should add 1 line')
self.assertEqual(order.amount_total, 5, '10$ - 5$(discount) = 5$(total) ')
def test_fixed_tax_not_affected(self):
program = self.env['loyalty.program'].create({
'name': '50% discount',
'program_type': 'promotion',
'trigger': 'auto',
'applies_on': 'current',
'rule_ids': [(0, 0, {
})],
'reward_ids': [(0, 0, {
'reward_type': 'discount',
'discount_mode': 'percent',
'discount': 50,
'discount_applicability': 'order',
'required_points': 1,
})],
})
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_10_fixed = self.env['account.tax'].create({
'name': "10$ Fixed tax",
'amount_type': 'fixed',
'amount': 10,
})
# Set tax and prices on products as neeed for the test
self.product_A.write({'list_price': 100})
self.product_A.taxes_id = (self.tax_15pc_excl + self.tax_10_fixed)
# Add products in order
self.env['sale.order.line'].create({
'product_id': self.product_A.id,
'name': 'product A',
'product_uom_qty': 1.0,
'order_id': order.id,
})
self._auto_rewards(order, program)
self.assertEqual(len(order.order_line), 2, 'Promotion should add 1 line')
self.assertEqual(order.amount_total, 67.5, '100$ + 15% tax + 10$ tax - 50%(discount) = 67.5$(total) ')
self.assertEqual(order.amount_tax, 17.5, '15% tax + 10$ tax$ - 50%$(discount) = 17.5$(total) ')
def test_fixed_tax_not_affected_2(self):
program = self.env['loyalty.program'].create({
'name': '50$ discount',
'program_type': 'promotion',
'trigger': 'auto',
'applies_on': 'current',
'rule_ids': [(0, 0, {
})],
'reward_ids': [(0, 0, {
'reward_type': 'discount',
'discount_mode': 'per_order',
'discount': 50,
'discount_applicability': 'order',
'required_points': 1,
})],
})
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_10_fixed = self.env['account.tax'].create({
'name': "10$ Fixed tax",
'amount_type': 'fixed',
'amount': 10,
})
# Set tax and prices on products as neeed for the test
self.product_A.write({'list_price': 100})
self.product_A.taxes_id = (self.tax_15pc_excl + self.tax_10_fixed)
# Add products in order
self.env['sale.order.line'].create({
'product_id': self.product_A.id,
'name': 'product A',
'product_uom_qty': 1.0,
'order_id': order.id,
})
self._auto_rewards(order, program)
self.assertEqual(len(order.order_line), 2, 'Promotion should add 1 line')
self.assertEqual(order.amount_total, 75, '100$ + 15% tax + 10$ tax - 50$(discount) = 75$(total) ')