[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:
committed by
Christophe Simonis
parent
6c5783bd5a
commit
0247d2f35f
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user