[FIX] sale_coupon, sale_coupon_delivery: Wrong discount on promotion program

Let's consider a product P with a unit price = 100€
When a price list PL with a discount of 20% was applied, and
a coupon program CP with a discount of 10% was also applied,
system still calculated the rate based on unit price of the product
and not on the discounted price.

So in this example, the amount of the CP discount was 10€ instead of
8€ because the CP discount was computed on the unit price 100€
instead of the discounted price 80€ (with 20% discount of PL)

opw:2006829

X-port/Cherry-pick of odoo/enterprise@23739e8a71
This commit is contained in:
Goffin Simon
2019-06-27 19:14:28 +02:00
committed by Christophe Simonis
parent 6c5783bd5a
commit 0247d2f35f
4 changed files with 63 additions and 5 deletions
+4 -4
View File
@@ -79,7 +79,7 @@ class SaleOrder(models.Model):
return applied_programs.filtered(lambda program: program._is_global_discount_program())
def _get_reward_values_product(self, program):
price_unit = self.order_line.filtered(lambda line: program.reward_product_id == line.product_id)[0].price_unit
price_unit = self.order_line.filtered(lambda line: program.reward_product_id == line.product_id)[0].price_reduce
order_lines = (self.order_line - self._get_reward_lines()).filtered(lambda x: program._is_valid_product(x.product_id))
max_product_qty = sum(order_lines.mapped('product_uom_qty')) or 1
@@ -120,10 +120,10 @@ class SaleOrder(models.Model):
def _get_cheapest_line(self):
# Unit prices tax included
return min(self.order_line.filtered(lambda x: not x.is_reward_line and x.price_unit > 0), key=lambda x: x['price_unit'])
return min(self.order_line.filtered(lambda x: not x.is_reward_line and x.price_reduce > 0), key=lambda x: x['price_reduce'])
def _get_reward_values_discount_percentage_per_line(self, program, line):
discount_amount = line.product_uom_qty * line.price_unit * (program.discount_percentage / 100)
discount_amount = line.product_uom_qty * line.price_reduce * (program.discount_percentage / 100)
return discount_amount
def _get_reward_values_discount(self, program):
@@ -142,7 +142,7 @@ class SaleOrder(models.Model):
if program.discount_apply_on == 'cheapest_product':
line = self._get_cheapest_line()
if line:
discount_line_amount = line.price_unit * (program.discount_percentage / 100)
discount_line_amount = line.price_reduce * (program.discount_percentage / 100)
if discount_line_amount:
taxes = line.tax_id
if self.fiscal_position_id:
+19
View File
@@ -60,6 +60,14 @@ class TestSaleCouponCommon(TestSaleProductAttributeValueSetup):
'taxes_id': [(6, 0, [self.tax_15pc_excl.id])],
})
self.product_C = self.env['product.product'].create({
'name': 'Product C',
'list_price': 100,
'sale_ok': True,
'taxes_id': [(6, 0, [])],
})
# Immediate Program By A + B: get B free
# No Conditions
self.immediate_promotion_program = self.env['sale.coupon.program'].create({
@@ -79,3 +87,14 @@ class TestSaleCouponCommon(TestSaleProductAttributeValueSetup):
'rule_products_domain': "[('id', 'in', [%s])]" % (self.product_A.id),
'active': True,
})
self.code_promotion_program_with_discount = self.env['sale.coupon.program'].create({
'name': 'Buy 1 C + Enter code, 10 percent discount on C',
'promo_code_usage': 'code_needed',
'reward_type': 'discount',
'discount_type': 'percentage',
'discount_percentage': 10,
'rule_products_domain': "[('id', 'in', [%s])]" % (self.product_C.id),
'active': True,
'discount_apply_on': 'on_order',
})
@@ -66,6 +66,45 @@ class TestProgramWithCodeOperations(TestSaleCouponCommon):
self.assertEqual(len(order.order_line.ids), 0)
self.assertEqual(coupon.state, 'new')
def test_coupon_code_with_pricelist(self):
# Test case: Generate a coupon (10% discount) and apply it on an order with a specific pricelist (10% discount)
self.env['sale.coupon.generate'].with_context(active_id=self.code_promotion_program_with_discount.id).create({
'generation_type': 'nbr_coupon',
'nbr_coupons': 1,
}).generate_coupon()
coupon = self.code_promotion_program_with_discount.coupon_ids
first_pricelist = self.env['product.pricelist'].create({
'name': 'First pricelist',
'discount_policy': 'with_discount',
'item_ids': [(0, 0, {
'compute_price': 'percentage',
'base': 'list_price',
'percent_price': 10,
'applied_on': '3_global',
'name': 'First discount'
})]
})
order = self.empty_order
order.pricelist_id = first_pricelist
order.write({'order_line': [
(0, False, {
'product_id': self.product_C.id,
'name': '1 Product C',
'product_uom': self.uom_unit.id,
'product_uom_qty': 1.0,
})
]})
self.env['sale.coupon.apply.code'].with_context(active_id=order.id).create({
'coupon_code': coupon.code
}).process_coupon()
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 2)
self.assertEqual(coupon.state, 'used')
self.assertEqual(order.amount_total, 81, "SO total should be 81: (10% of 100 with pricelist) + 10% of 90 with coupon code")
def test_on_next_order_reward_promotion_program(self):
# The flow:
# 1. Create a program `A` that gives a free `Product B` on next order if you buy a an `product A`
@@ -42,7 +42,7 @@ class SaleOrder(models.Model):
def _get_cheapest_line(self):
# Unit prices tax included
return min(self.order_line.filtered(lambda x: not x.is_reward_line and not x.is_delivery and x.price_unit > 0), key=lambda x: x['price_unit'])
return min(self.order_line.filtered(lambda x: not x.is_reward_line and not x.is_delivery and x.price_reduce > 0), key=lambda x: x['price_reduce'])
class SalesOrderLine(models.Model):
_inherit = "sale.order.line"