[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.
This commit is contained in:
Sébastien Theys
2019-02-15 08:52:26 +00:00
parent 6c9c871d08
commit f2d4b118d0
9 changed files with 154 additions and 21 deletions
+8 -3
View File
@@ -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)
+4 -2
View File
@@ -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
@@ -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)",
@@ -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)",
@@ -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 () {},
},
]
);
});
@@ -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",
+12 -3
View File
@@ -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")
+8 -5
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tour_shop_zoom.js"></script>
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tour_shop_dynamic_variants.js"></script>
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tour_shop_deleted_archived_variants.js"></script>
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tour_shop_list_view_b2c.js"></script>
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tour_shop_no_variant_attribute.js"></script>
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_options.js"></script>
</xpath>
@@ -663,12 +664,14 @@
<input type="hidden" t-if="len(filtered_sorted_variants) == 1" class="product_id" name="product_id" t-att-value="filtered_sorted_variants[0].id"/>
<t t-if="len(filtered_sorted_variants) &gt; 1">
<div t-foreach="filtered_sorted_variants" t-as="variant_id" class="custom-control custom-radio">
<input type="radio" name="product_id" class="custom-control-input product_id js_product_change" t-att-checked="'checked' if variant_id_index == 0 else None" t-attf-id="radio_variant_#{variant_id.id}" t-att-value="variant_id.id" t-att-data-lst_price="compute_currency(variant_id.lst_price)" t-att-data-price="variant_id.price" t-att-data-combination="variant_id.product_template_attribute_value_ids.ids"/>
<t t-set="template_combination_info" t-value="product._get_combination_info(only_template=True, add_qty=add_qty, pricelist=pricelist)"/>
<t t-set="combination_info" t-value="variant_id._get_combination_info_variant(add_qty=add_qty, pricelist=pricelist)"/>
<input type="radio" name="product_id" class="custom-control-input product_id js_product_change" t-att-checked="'checked' if variant_id_index == 0 else None" t-attf-id="radio_variant_#{variant_id.id}" t-att-value="variant_id.id" t-att-data-lst_price="combination_info['list_price']" t-att-data-price="combination_info['price']" t-att-data-combination="variant_id.product_template_attribute_value_ids.ids"/>
<label t-attf-for="radio_variant_#{variant_id.id}" label-default="label-default" class="custom-control-label">
<span t-esc="variant_id.name_get()[0][1]"/>
<t t-set="diff_price" t-value="website.currency_id.compare_amounts(variant_id.price, variant_id.product_tmpl_id.price)"/>
<span class="badge badge-pill" t-if="diff_price != 0">
<t t-esc="diff_price > 0 and '+' or '-'"/><span t-esc="abs(variant_id.price - variant_id.product_tmpl_id.price)" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
<span t-esc="combination_info['display_name']"/>
<t t-set="diff_price" t-value="website.currency_id.compare_amounts(combination_info['price'], template_combination_info['price'])"/>
<span class="badge badge-pill badge-secondary" t-if="diff_price != 0">
<t t-esc="diff_price > 0 and '+' or '-'"/><span t-esc="abs(combination_info['price'] - template_combination_info['price'])" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
</span>
</label>
</div>
@@ -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'])