[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:
@@ -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) ')
|
||||
|
||||
Reference in New Issue
Block a user