Skip to content
Snippets Groups Projects
Commit 1e30bab3 authored by Yolann Sabaux's avatar Yolann Sabaux
Browse files

[FIX] website_sale: display correct price according in carousel

Steps to reproduce:
1) Create product P for $1000, with 15% Tax, publish to website.
1-bis) make sure the 15% tax is "included"
2) Settings -> search 'price' -> Tax Excluded.
3) Go to website /shop page, and edit to place the Products block, and search for

Issue:
The price displayed on the product in "86.96" (correct) but the price on the product in the carousel displays "100.00"

Cause:
The price for the carousel is not fetched the same way
https://github.com/odoo/odoo/blob/e829b345f0f5e5346be416b8354c29fa9acb74a7/addons/website_sale/data/product_snippet_template_data.xml#L388



And the method does not take into account this fourth scenario. That is:
- a tax with price_include set to True
- a show_line_subtotals_tax_selection config parameter set to "tax_excluded"

Note:
There is an issue with the case of a mapping from a tax included to a tax included:
```
param_main_product_tax_included = True
param_fpos = 'to_tax_included' # mapping from 15% to 10%
```
As if the product price is 100, the tax set on the product is 15%.
```
>>> self.env['account.tax']._fix_tax_included_price_company( price, product_taxes, taxes, self.env.company.id)
86.96
```
The price would be 100/1.15 = 86.96

And when calling `taxes.compute_all(price, product=self, partner=self.env['res.partner'])` it would return
```
included = 86.96 ; excluded = 79.05
```
The base is computed by taking the initial base such as
```
100/1.15/1.1 = 79.05
```
Instead of keeping the initial base and applying the new tax percentage to compute the total included
```
base = 100/1.15 = 86.96
total_included = 86.96 * 1.10 = 95.656
amount_tax = 8.696
```
After some discussion, it turns out this problem is a known issue. To make the mapping from 'tax_included' to 'tax_included' more sensible, we'd need to make some additional changes beyond what we're addressing in this fix.

opw-3370999

closes odoo/odoo#133501

Signed-off-by: default avatarYolann Sabaux (yosa) <yosa@odoo.com>
parent 05ea6bf3
No related branches found
No related tags found
No related merge requests found
......@@ -100,7 +100,14 @@ class Product(models.Model):
self.ensure_one()
price = self._get_contextual_price()
line_tax_type = self.env['ir.config_parameter'].sudo().get_param('account.show_line_subtotals_tax_selection')
company_taxes = self.taxes_id.filtered(lambda tax: tax.company_id == self.env.company)
if line_tax_type == "tax_included" and company_taxes:
price = company_taxes.compute_all(price, product=self, partner=self.env['res.partner'])['total_included']
fpos_id = self.env['website'].sudo()._get_current_fiscal_position_id(self.env.user.partner_id)
fiscal_position = self.env['account.fiscal.position'].sudo().browse(fpos_id)
product_taxes = self.sudo().taxes_id.filtered(lambda x: x.company_id == self.env.company)
if product_taxes:
taxes = fiscal_position.map_tax(product_taxes)
price = self.env['account.tax']._fix_tax_included_price_company(
price, product_taxes, taxes, self.env.company,
)
tax_display = "total_included" if line_tax_type == "tax_included" else "total_excluded"
price = taxes.compute_all(price, product=self, partner=self.env['res.partner'])[tax_display]
return price
# coding: utf-8
import itertools
from odoo.tests import tagged
from odoo.addons.website.tools import MockRequest
from odoo.addons.sale.tests.test_sale_product_attribute_value_config import TestSaleProductAttributeValueCommon
from odoo.addons.website_sale.controllers.main import WebsiteSale
@tagged('post_install', '-at_install')
class WebsiteSaleProductTests(TestSaleProductAttributeValueCommon):
def setUp(self):
super().setUp()
self.website = self.env.ref('website.default_website')
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.WebsiteSaleController = WebsiteSale()
cls.website = cls.env.ref('website.default_website')
cls.tax_5 = cls.env['account.tax'].create({
'name': '5% Tax',
'amount_type': 'percent',
'amount': 5,
'price_include': False,
'include_base_amount': False,
'type_tax_use': 'sale',
})
cls.tax_10 = cls.env['account.tax'].create({
'name': '10% Tax',
'amount_type': 'percent',
'amount': 10,
'price_include': False,
'include_base_amount': False,
'type_tax_use': 'sale',
})
cls.tax_15 = cls.env['account.tax'].create({
'name': '15% Tax',
'amount_type': 'percent',
'amount': 15,
'price_include': False,
'include_base_amount': False,
'type_tax_use': 'sale',
})
cls.fiscal_country = cls.env['res.country'].create({
'name': "Super Fiscal Position",
'code': 'SFP',
})
cls.product = cls.env['product.product'].create({
'name': 'Super Product',
'list_price': 100.0,
})
def test_website_sale_contextual_price(self):
contextual_price = self.computer._get_contextual_price()
......@@ -32,3 +71,73 @@ class WebsiteSaleProductTests(TestSaleProductAttributeValueCommon):
2000.0 * currency_ratio * discount_rate, contextual_price,
"With a website pricelist context, the contextual price should be the one defined for the website's pricelist."
)
def test_get_contextual_price_tax_selection(self):
"""
`_get_contextual_price_tax_selection` is used to display the price on the website (e.g. in the carousel).
We test that the contextual price is correctly computed. That is, it is coherent with the price displayed on the product when in the cart.
"""
param_main_product_tax_included = [True, False]
param_show_line_subtotals_tax_selection = ['tax_included', 'tax_excluded']
param_extra_tax = [False, 'included', 'excluded']
param_fpos = [False, 'to_tax_excluded']
parameters = itertools.product(param_main_product_tax_included, param_show_line_subtotals_tax_selection, param_extra_tax, param_fpos)
for main_product_tax_included, show_line_subtotals_tax_selection, extra_tax, fpos in parameters:
with self.subTest(main_product_tax_included=main_product_tax_included, show_line_subtotals_tax_selection=show_line_subtotals_tax_selection, extra_tax=extra_tax, fpos=fpos):
# set "show_line_subtotals_tax_selection" parameter
config = self.env['res.config.settings'].create({})
config.show_line_subtotals_tax_selection = show_line_subtotals_tax_selection
config.execute()
# set "main_product_tax_included" parameter
if main_product_tax_included:
self.tax_15.price_include = True
self.tax_15.include_base_amount = True
self.product.taxes_id = self.tax_15
tax_ids = [self.tax_15.id]
# set "extra_tax" parameter
if extra_tax:
if extra_tax == 'included':
self.tax_5.price_include = True
self.tax_5.include_base_amount = True
tax_ids.append(self.tax_5.id)
# set "fpos" parameter
if fpos:
if fpos == 'to_tax_included':
self.tax_10.price_include = True
self.tax_10.include_base_amount = True
fiscal_position = self.env['account.fiscal.position'].create({
'name': 'Super Fiscal Position',
'auto_apply': True,
'country_id': self.fiscal_country.id,
})
self.env['account.fiscal.position.tax'].create({
'position_id': fiscal_position.id,
'tax_src_id': self.tax_15.id,
'tax_dest_id': self.tax_10.id,
})
self.env.user.partner_id.country_id = self.fiscal_country
# define the website pricelist
current_website = self.env['website'].get_current_website()
pricelist = current_website.get_current_pricelist()
pricelist.currency_id = self.product.currency_id
self.env['product.pricelist.item'].create({
'price_discount': 0,
'compute_price': 'formula',
'pricelist_id': pricelist.id,
})
with MockRequest(self.env, website=self.website, website_sale_current_pl=pricelist.id):
contextual_price = self.product._get_contextual_price_tax_selection()
self.WebsiteSaleController.cart_update_json(product_id=self.product.id, add_qty=1)
sale_order = self.website.sale_get_order()
if show_line_subtotals_tax_selection == 'tax_included':
self.assertAlmostEqual(sale_order.amount_total, contextual_price)
else:
self.assertAlmostEqual(sale_order.amount_untaxed, contextual_price)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment