From f2d4b118d039d746a76a36986ad8fbcb12599677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Wed, 13 Feb 2019 16:25:56 +0000 Subject: [PATCH] [FIX] sale,website_sale: fix list view of variants price compute Before this commit, the list view of variant didn't use `_get_combination_info` so the displayed price was not taking into account important settings such as B2B/B2C and currency convert. --- addons/sale/models/product_template.py | 11 ++- addons/website_sale/models/product.py | 6 +- .../js/website_sale_tour_shop_customize.js | 10 ++ ...ale_tour_shop_deleted_archived_variants.js | 10 +- .../website_sale_tour_shop_list_view_b2c.js | 98 +++++++++++++++++++ ...ite_sale_tour_shop_no_variant_attribute.js | 6 +- addons/website_sale/tests/test_customize.py | 15 ++- addons/website_sale/views/templates.xml | 13 ++- .../models/product_template.py | 6 +- 9 files changed, 154 insertions(+), 21 deletions(-) create mode 100644 addons/website_sale/static/src/js/website_sale_tour_shop_list_view_b2c.js diff --git a/addons/sale/models/product_template.py b/addons/sale/models/product_template.py index b0cd6345784..b6f94c129fc 100644 --- a/addons/sale/models/product_template.py +++ b/addons/sale/models/product_template.py @@ -166,7 +166,7 @@ class ProductTemplate(models.Model): return res @api.multi - def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, parent_combination=False): + def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, parent_combination=False, only_template=False): """ Return info about a given combination. Note: this method does not take into account whether the combination is @@ -191,6 +191,9 @@ class ProductTemplate(models.Model): given, it will try to find the first possible combination, taking into account parent_combination (if set) for the exclusion rules. + :param only_template: boolean, if set to True, get the info for the + template only: ignore combination and don't try to find variant + :return: dict with product/combination info: - product_id: the variant id matching the combination (if it exists) @@ -219,10 +222,12 @@ class ProductTemplate(models.Model): combination = combination or product_template.env['product.template.attribute.value'] - if not product_id and not combination: + if not product_id and not combination and not only_template: combination = product_template._get_first_possible_combination(parent_combination) - if product_id and not combination: + if only_template: + product = product_template.env['product.product'] + elif product_id and not combination: product = product_template.env['product.product'].browse(product_id) else: product = product_template._get_variant_for_combination(combination) diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py index db0ac30f060..15b0bc793b9 100644 --- a/addons/website_sale/models/product.py +++ b/addons/website_sale/models/product.py @@ -229,7 +229,7 @@ class ProductTemplate(models.Model): return self._get_possible_variants(parent_combination).sorted(_sort_key_variant) @api.multi - def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, parent_combination=False): + def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, parent_combination=False, only_template=False): """Override for website, where we want to: - take the website pricelist if no pricelist is set - apply the b2b/b2c setting to the result @@ -246,7 +246,9 @@ class ProductTemplate(models.Model): if not pricelist: pricelist = current_website.get_current_pricelist() - combination_info = super(ProductTemplate, self)._get_combination_info(combination, product_id, add_qty, pricelist, parent_combination) + combination_info = super(ProductTemplate, self)._get_combination_info( + combination=combination, product_id=product_id, add_qty=add_qty, pricelist=pricelist, + parent_combination=parent_combination, only_template=only_template) if self.env.context.get('website_id'): partner = self.env.user.partner_id diff --git a/addons/website_sale/static/src/js/website_sale_tour_shop_customize.js b/addons/website_sale/static/src/js/website_sale_tour_shop_customize.js index 009eb44b436..fc1d6b12e50 100644 --- a/addons/website_sale/static/src/js/website_sale_tour_shop_customize.js +++ b/addons/website_sale/static/src/js/website_sale_tour_shop_customize.js @@ -69,6 +69,11 @@ odoo.define('website_sale.tour_shop_customize', function (require) { trigger: '#customize-menu a:contains(List View of Variants)', run: function () {}, // it's a check }, + { + content: "check list view of variants is disabled initially", + trigger: 'body:not(:has(.js_product_change))', + run: function () {}, + }, { content: "click on 'List View of Variants'", trigger: "#customize-menu a:contains(List View of Variants)", @@ -78,6 +83,11 @@ odoo.define('website_sale.tour_shop_customize', function (require) { trigger: '.js_product_change', run: function () {}, // it's a check }, + { + context: "check variant price", + trigger: '.custom-radio:contains("Aluminium") .badge:contains("+") .oe_currency_value:contains("50.4")', + run: function () {}, + }, { content: "check price is 750", trigger: ".product_price .oe_price .oe_currency_value:containsExact(750.00)", diff --git a/addons/website_sale/static/src/js/website_sale_tour_shop_deleted_archived_variants.js b/addons/website_sale/static/src/js/website_sale_tour_shop_deleted_archived_variants.js index c83b45434c9..0b9d4208ff1 100644 --- a/addons/website_sale/static/src/js/website_sale_tour_shop_deleted_archived_variants.js +++ b/addons/website_sale/static/src/js/website_sale_tour_shop_deleted_archived_variants.js @@ -7,13 +7,17 @@ var base = require('web_editor.base'); // This tour relies on a data created from the python test. tour.register('tour_shop_deleted_archived_variants', { test: true, - url: '/shop?search=Test Product', + url: '/shop?search=Test Product 2', wait_for: base.ready(), }, [ { - content: "select Test Product", - trigger: '.oe_product_cart a:containsExact("Test Product")', + content: "check price on /shop (3rd variant)", + trigger: '.oe_product_cart .oe_currency_value:contains("31.00")', + }, + { + content: "select Test Product 2", + trigger: '.oe_product_cart a:containsExact("Test Product 2")', }, { content: "check price (3rd variant)", diff --git a/addons/website_sale/static/src/js/website_sale_tour_shop_list_view_b2c.js b/addons/website_sale/static/src/js/website_sale_tour_shop_list_view_b2c.js new file mode 100644 index 00000000000..33c6a7ff2cd --- /dev/null +++ b/addons/website_sale/static/src/js/website_sale_tour_shop_list_view_b2c.js @@ -0,0 +1,98 @@ +odoo.define('website_sale.tour_shop_list_view_b2c', function (require) { +'use strict'; + +var base = require('web_editor.base'); +var rpc = require('web.rpc'); +var tour = require('web_tour.tour'); + +tour.register('shop_list_view_b2c', { + test: true, + url: '/shop?search=Test Product', + wait_for: base.ready() +}, + [ + { + content: "activate b2c", + trigger: 'body', + run: function () { + return rpc.query({ + model: 'res.config.settings', + method: 'create', + args: [{ + 'auth_signup_uninvited': 'b2c', + 'show_line_subtotals_tax_selection': 'tax_included', + 'group_show_line_subtotals_tax_excluded': false, + 'group_show_line_subtotals_tax_included': true, + }], + }).then(function (resId) { + return rpc.query({ + model: 'res.config.settings', + method: 'execute', + args: [[resId]], + }).then(function () { + window.location.reload(); + }); + }); + }, + }, + { + content: "check price on /shop", + trigger: '.oe_product_cart .oe_currency_value:contains("825.00")', + run: function () {}, + }, + { + content: "select product", + trigger: '.oe_product_cart a:contains("Test Product")', + }, + { + content: "check list view of variants is disabled initially (when on /product page)", + trigger: 'body:not(:has(.js_product_change))', + extra_trigger: '#product_details', + run: function () {}, + }, + { + content: "open customize menu", + trigger: '#customize-menu > a', + extra_trigger: 'body:not(.notReady)', + }, + { + content: "click on 'List View of Variants'", + trigger: '#customize-menu a:contains(List View of Variants)', + }, + { + content: "check page loaded after list of variant customization enabled", + trigger: '.js_product_change', + run: function () {}, + }, + { + context: "check variant price", + trigger: '.custom-radio:contains("Aluminium") .badge:contains("+") .oe_currency_value:contains("55.44")', + run: function () {}, + }, + { + content: "check price is 825", + trigger: '.product_price .oe_price .oe_currency_value:containsExact("825.00")', + run: function () {}, + }, + { + content: "switch to another variant", + trigger: '.js_product label:contains("Aluminium")', + }, + { + content: "verify that price has changed when changing variant", + trigger: '.product_price .oe_price .oe_currency_value:containsExact("880.44")', + run: function () {}, + }, + { + content: "click on 'Add to Cart' button", + trigger: 'a:contains(Add to Cart)', + }, + { + content: "check price on /cart", + trigger: '#cart_products .oe_currency_value:containsExact("880.44")', + run: function () {}, + }, + ] +); + +}); diff --git a/addons/website_sale/static/src/js/website_sale_tour_shop_no_variant_attribute.js b/addons/website_sale/static/src/js/website_sale_tour_shop_no_variant_attribute.js index 765fc540ccd..76f179c4578 100644 --- a/addons/website_sale/static/src/js/website_sale_tour_shop_no_variant_attribute.js +++ b/addons/website_sale/static/src/js/website_sale_tour_shop_no_variant_attribute.js @@ -7,13 +7,13 @@ var base = require('web_editor.base'); // This tour relies on a data created from the python test. tour.register('tour_shop_no_variant_attribute', { test: true, - url: '/shop?search=Test Product', + url: '/shop?search=Test Product 3', wait_for: base.ready(), }, [ { - content: "select Test Product", - trigger: '.oe_product_cart a:containsExact("Test Product")', + content: "select Test Product 3", + trigger: '.oe_product_cart a:containsExact("Test Product 3")', }, { content: "check price", diff --git a/addons/website_sale/tests/test_customize.py b/addons/website_sale/tests/test_customize.py index 11f10c4c5e0..5e0ab59370e 100644 --- a/addons/website_sale/tests/test_customize.py +++ b/addons/website_sale/tests/test_customize.py @@ -6,13 +6,18 @@ import odoo.tests @odoo.tests.common.tagged('post_install', '-at_install') class TestUi(odoo.tests.HttpCase): - def test_01_admin_shop_customize_tour(self): + def setUp(self): + super(TestUi, self).setUp() # create a template product_template = self.env['product.template'].create({ 'name': 'Test Product', 'website_published': True, 'list_price': 750, }) + + tax = self.env['account.tax'].create({'name': "Test tax", 'amount': 10}) + product_template.taxes_id = tax + product_attribute = self.env.ref('product.product_attribute_1') product_attribute_value_1 = self.env.ref('product.product_attribute_value_1') product_attribute_value_2 = self.env.ref('product.product_attribute_value_2') @@ -36,6 +41,7 @@ class TestUi(odoo.tests.HttpCase): product_template.create_variant_ids() + def test_01_admin_shop_customize_tour(self): self.phantom_js("/", "odoo.__DEBUG__.services['web_tour.tour'].run('shop_customize')", "odoo.__DEBUG__.services['web_tour.tour'].tours.shop_customize.ready", login="admin") def test_02_admin_shop_custom_attribute_value_tour(self): @@ -140,7 +146,7 @@ class TestUi(odoo.tests.HttpCase): # create the template product_template = self.env['product.template'].create({ - 'name': 'Test Product', + 'name': 'Test Product 2', 'website_published': True, }) @@ -188,7 +194,7 @@ class TestUi(odoo.tests.HttpCase): # create the template product_template = self.env['product.template'].create({ - 'name': 'Test Product', + 'name': 'Test Product 3', 'website_published': True, }) @@ -205,3 +211,6 @@ class TestUi(odoo.tests.HttpCase): product_template.create_variant_ids() self.phantom_js("/", "odoo.__DEBUG__.services['web_tour.tour'].run('tour_shop_no_variant_attribute')", "odoo.__DEBUG__.services['web_tour.tour'].tours.tour_shop_no_variant_attribute.ready", login="demo") + + def test_06_admin_list_view_b2c(self): + self.browser_js("/", "odoo.__DEBUG__.services['web_tour.tour'].run('shop_list_view_b2c')", "odoo.__DEBUG__.services['web_tour.tour'].tours.shop_list_view_b2c.ready", login="admin") diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index ca37cf67128..ec5ea685097 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -32,6 +32,7 @@ + @@ -663,12 +664,14 @@
- + + +
diff --git a/addons/website_sale_stock/models/product_template.py b/addons/website_sale_stock/models/product_template.py index d2d5f9e5759..31229c46637 100644 --- a/addons/website_sale_stock/models/product_template.py +++ b/addons/website_sale_stock/models/product_template.py @@ -17,8 +17,10 @@ class ProductTemplate(models.Model): custom_message = fields.Text(string='Custom Message', default='') @api.multi - def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, reference_product=False): - combination_info = super(ProductTemplate, self)._get_combination_info(combination, product_id, add_qty, pricelist, reference_product) + def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, reference_product=False, only_template=False): + combination_info = super(ProductTemplate, self)._get_combination_info( + combination=combination, product_id=product_id, add_qty=add_qty, pricelist=pricelist, + parent_combination=reference_product, only_template=only_template) if combination_info['product_id']: product = self.env['product.product'].sudo().browse(combination_info['product_id'])