diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 68b7f445da5ad08aa8385791036600721ce2b185..59ab41d1e0114a8e37466642b096a551372f579b 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -411,6 +411,8 @@ class WebsiteSale(http.Controller): products_prices = lazy(lambda: products._get_sales_prices(pricelist)) + fiscal_position_id = website._get_current_fiscal_position_id(request.env.user.partner_id) + values = { 'search': fuzzy_search_term or search, 'original_search': fuzzy_search_term and search, @@ -435,6 +437,7 @@ class WebsiteSale(http.Controller): 'products_prices': products_prices, 'get_product_prices': lambda product: lazy(lambda: products_prices[product.id]), 'float_round': tools.float_round, + 'fiscal_position_id': fiscal_position_id, } if filter_by_price_enabled: values['min_price'] = min_price or available_min_price diff --git a/addons/website_sale/static/tests/tours/website_sale_fiscal_position_tour.js b/addons/website_sale/static/tests/tours/website_sale_fiscal_position_tour.js new file mode 100644 index 0000000000000000000000000000000000000000..cfd31d7b72856aaa16d7630d1e798ea859ddbc9d --- /dev/null +++ b/addons/website_sale/static/tests/tours/website_sale_fiscal_position_tour.js @@ -0,0 +1,37 @@ +odoo.define('website_sale_tour.website_sale_fiscal_position_tour', function (require) { + 'use strict'; + + var tour = require("web_tour.tour"); + + tour.register('website_sale_fiscal_position_portal_tour', { + test: true, + url: '/shop?search=Super%20Product' + }, [ + { + content: "Check price", + trigger: ".oe_product:contains('Super product') .product_price:contains('80.00')", + run: function() {} // Check + }, + ]); + + tour.register('website_sale_fiscal_position_public_tour', { + test: true, + url: '/shop?search=Super%20Product' + }, [ + { + content: "Toggle Pricelist", + trigger: ".o_pricelist_dropdown > .dropdown-toggle", + run: 'click', + }, + { + content: "Change Pricelist", + trigger: ".dropdown-item:contains('EUROPE EUR')", + run: 'click', + }, + { + content: "Check price", + trigger: ".oe_product:contains('Super product') .product_price:contains('92.00')", + run: function() {} // Check + }, + ]); +}); diff --git a/addons/website_sale/tests/__init__.py b/addons/website_sale/tests/__init__.py index 7294c8d003643d9ccb0f58ada49c5eac6f31f246..a14df15f8e1027a0a582a33fed86e3117fbbd130 100644 --- a/addons/website_sale/tests/__init__.py +++ b/addons/website_sale/tests/__init__.py @@ -22,3 +22,4 @@ from . import test_website_sale_product from . import test_website_editor from . import test_website_sale_reorder_from_portal from . import test_website_sale_snippets +from . import test_website_sale_fiscal_position diff --git a/addons/website_sale/tests/test_website_sale_fiscal_position.py b/addons/website_sale/tests/test_website_sale_fiscal_position.py new file mode 100644 index 0000000000000000000000000000000000000000..a088910c5db995159da1230cae425c78fd3eb139 --- /dev/null +++ b/addons/website_sale/tests/test_website_sale_fiscal_position.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.addons.base.tests.common import HttpCaseWithUserPortal +from odoo.addons.product.tests.common import ProductCommon +from odoo.tests import tagged + +from odoo import Command + +@tagged('post_install', '-at_install') +class TestWebsiteSaleFiscalPosition(ProductCommon, HttpCaseWithUserPortal): + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._use_currency('USD') + + def test_shop_fiscal_position_products_template(self): + """ + The `website_sale.products` template is computationally intensive + and therefore uses the cache. + The goal of this test is to check that this template + is up to date with the fiscal position detected. + """ + website_id = self.env.ref('website.default_website').id + belgium_id = self.env.ref('base.be').id + # Set setting to display tax included on the website + config = self.env['res.config.settings'].create({}) + config.show_line_subtotals_tax_selection = "tax_included" + config.execute() + # Create a fiscal position with a mapping of taxes + tax_15_excl = self.env['account.tax'].create({ + 'name': '15% excl', + 'type_tax_use': 'sale', + 'amount_type': 'percent', + 'amount': 15, + 'price_include': False, + 'include_base_amount': False, + }) + tax_0 = self.env['account.tax'].create({ + 'name': '0%', + 'type_tax_use': 'sale', + 'amount_type': 'percent', + 'amount': 0, + }) + self.env['account.fiscal.position'].create({ + 'name': 'fiscal_pos_belgium', + 'auto_apply': True, + 'country_id': belgium_id, + 'tax_ids': [Command.create({ + 'tax_src_id': tax_15_excl.id, + 'tax_dest_id': tax_0.id, + })] + }) + # Create a pricelist which will be automatically detected + self.env['product.pricelist'].create({ + 'name': 'EUROPE EUR', + 'selectable': True, + 'website_id': website_id, + 'country_group_ids': [Command.link(self.env.ref('base.europe').id)], + 'sequence': 1, + 'currency_id': self.env.ref('base.EUR').id, + }) + # Create the product to be used for analysis + self.env["product.product"].create({ + 'name': "Super product", + 'list_price': 40.00, + 'taxes_id': [tax_15_excl.id], + 'website_published': True, + }) + # Create a conversion rate (1 USD <=> 2 EUR) + self.env['res.currency.rate'].search([]).unlink() + self.env['res.currency.rate'].create({ + 'company_id': self.env.company.id, + 'currency_id': self.env.ref('base.EUR').id, + 'company_rate': 2, + 'name': '2023-01-01', + }) + + self.partner_portal.country_id = belgium_id + + # [1] By going to the shop page with the portal user, + # a t-cache key `pricelist,products` + `fiscal_position_id` is generated + self.start_tour("/shop", 'website_sale_fiscal_position_portal_tour', login="portal") + # [2] If we return to the page with a public user + # and take the portal user's pricelist, + # the prices must not be those previously calculated for the portal user. + # Because the fiscal position differs from that of the public user. + self.start_tour("/shop", 'website_sale_fiscal_position_public_tour', login="") diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index 4cd92e2f5c5d07c48db5ebd68faa9aeb9ab6e432..93eba39de47b5e240557d8498406dc964c098a12 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -408,6 +408,13 @@ </t> </template> + <!-- Add the fiscal position in the t-cache key after all overrides --> + <template id="products_fiscal_position" inherit_id="website_sale.products" priority="99"> + <xpath expr="//div[starts-with(@t-cache, 'pricelist,products')]" position="attributes"> + <attribute name="t-cache" add="fiscal_position_id" separator=","/> + </xpath> + </template> + <!-- (Option) Products: Enable "Card" or "Thumbnails" designs --> <template id="products_design_card" name="Card Design" inherit_id="website_sale.products" active="False"> <xpath expr="//table" position="attributes">