[FIX] website_sale_coupon: merge 'sibling' discount lines in cart

A discount on products with different taxes will result in as many discount
lines as there is different taxes.

This commit will merge all these lines in a single one on the front-end (cart)
to not change the behavior/display for the end user. This will be purely visual
as it does not affect SO lines.

task-1866977
Related to #2224
This commit is contained in:
Romain Derie
2018-09-13 15:16:57 +02:00
parent f71c33230a
commit 269f8c5601
2 changed files with 96 additions and 11 deletions
+38
View File
@@ -6,6 +6,44 @@ from odoo.http import request
class SaleOrder(models.Model):
_inherit = "sale.order"
@api.one
def _compute_website_order_line(self):
""" This method will merge multiple discount lines generated by a same program
into a single one (temporary line with `new()`).
This case will only occur when the program is a discount applied on multiple
products with different taxes.
In this case, each taxes will have their own discount line. This is required
to have correct amount of taxes according to the discount.
But we wan't these lines to be `visually` merged into a single one in the
e-commerce since the end user should only see one discount line.
This is only possible since we don't show taxes in cart.
eg:
line 1: 10% discount on product with tax `A` - $15
line 2: 10% discount on product with tax `B` - $11.5
line 3: 10% discount on product with tax `C` - $10
would be `hidden` and `replaced` by
line 1: 10% discount - $36.5
Note: The line will be created without tax(es) and the amount will be computed
depending if B2B or B2C is enabled.
"""
super(SaleOrder, self)._compute_website_order_line()
for program in self._get_applied_programs_with_rewards_on_current_order():
program_lines = self.order_line.filtered(lambda line: line.product_id == program.discount_line_product_id)
if len(program_lines) > 1:
price_unit = sum(l.price_subtotal if self.env.user.has_group('sale.group_show_price_subtotal') else l.price_total for l in program_lines)
self.website_order_line += self.env['sale.order.line'].new({
'product_id': program_lines[0].product_id.id,
'price_unit': price_unit,
'name': program_lines[0].name,
'product_uom_qty': 1,
'product_uom': program_lines[0].product_uom.id,
'order_id': self.id,
'is_reward_line': True,
})
self.website_order_line -= program_lines
def _compute_cart_info(self):
super(SaleOrder, self)._compute_cart_info()
for order in self:
+58 -11
View File
@@ -36,9 +36,9 @@ tour.register('shop_sale_coupon', {
trigger: '.oe_product_cart a:contains("iPad Mini")',
},
{
content: "add 3 iPad Mini into cart",
content: "add 2 iPad Mini into cart",
trigger: '#product_details input[name="add_qty"]',
run: "text 3",
run: "text 2",
},
{
content: "click on 'Add to Cart' button",
@@ -68,31 +68,79 @@ tour.register('shop_sale_coupon', {
trigger: '.reward_product:contains("10.0 % discount on total amount")',
run: function () {}, // it's a check
},
/* 2. Add some iPad to get a free one, play with quantity */
/* 2. Add an Ice Cream in the cart (which has different tax than iPad) and ensure only one discount line is shown */
{
content: "go to shop",
trigger: '.reward_product:contains("10.0 % discount on total amount")',
run: function () {
location.href = '/shop'
},
},
{
content: "type Ice Cream in search",
trigger: 'form input[name="search"]',
run: "text Ice Cream",
},
{
content: "start search",
trigger: 'form:has(input[name="search"]) .oe_search_button',
},
{
content: "select Ice Cream",
extra_trigger: '.oe_search_found', // Wait to be on search results or it sometimes throws concurent error (sent search form + click on product on /shop)
trigger: '.oe_product_cart a:containsExact("Ice Cream")',
},
{
content: "click on 'Add to Cart' button",
trigger: "a:contains(Add to Cart)",
},
{
content: "check reduction amount got recomputed and merged both discount lines into one only",
extra_trigger: '.oe_currency_value:contains("‑74.00")',
trigger: '.oe_website_sale .oe_cart',
run: function () {}, // it's a check
},
/* 3. Add some iPad to get a free one, play with quantity */
{
content: "add one iPad",
trigger: '#cart_products input.js_quantity',
run: "text 3",
},
{
content: "check reduction amount got recomputed when changing qty",
trigger: '.oe_currency_value:contains("‑106.00")',
run: function () {}, // it's a check
},
{
content: "add more iPad Mini into cart",
trigger: '#cart_products input.js_quantity',
run: "text 4",
},
{
content: "check reduction amount got recomputed",
extra_trigger: '.oe_currency_value:contains("96.00")', // For some reason, "-96.00" won't work
trigger: '.reward_product:contains("Free Product - iPad Mini")',
content: "check free product is added",
trigger: '#wrap:has(.reward_product:contains("Free Product - iPad Mini"))',
run: function () {}, // it's a check
},
{
content: "remove one iPad from cart",
trigger: '#cart_products a.js_add_cart_json:first',
trigger: '#cart_products input.js_quantity[value="4"]',
run: "text 3",
},
{
content: "check free product is removed",
trigger: '#wrap:not(:has(.reward_product:contains("Free Product - iPad Mini")))',
run: function () {}, // it's a check
},
/* 3. Empty cart and disable coupon */
/* 4. Empty cart and disable coupon */
{
content: "remove iPad Mini from cart",
trigger: '#cart_products input.js_quantity:first',
trigger: '#cart_products input.js_quantity[value="3"]',
run: "text 0",
},
{
content: "remove Ice Cream from cart",
extra_trigger: '#wrap:not(:has(.td-product_name:contains("iPad Mini")))', // wait iPad got removed
trigger: '#cart_products input.js_quantity[value="1"]',
run: "text 0",
},
{
@@ -100,7 +148,7 @@ tour.register('shop_sale_coupon', {
trigger: '#wrap:not(:has(#cart_products))',
run: function () {}, // it's a check
},
/* 4. Disabled customize options coupon box & 'Show # found'*/
/* 5. Disabled customize options coupon box & 'Show # found'*/
{
content: "open customize menu",
extra_trigger: '.oe_website_sale .oe_cart',
@@ -135,7 +183,6 @@ if ('website_sale_options.website_sale' in odoo.__DEBUG__.services) {
content: "click in modal on 'Proceed to checkout' button",
trigger: 'a:contains("Proceed to checkout")',
});
break;
}
}
}