[FIX] website_sale: consistent tax computation
While fixing a non deterministic test failing on nightly l10n builds, slight incoherences between sale & website_sale tax computation have been noticed in the computation of the contextual price (used in some snippets). This commit fixes the test, making sure it doesn't fail on l10n builds, but also uses the same tax util in website_sale than in sale, to make sure the displayed amounts are coherent (and supposedly correct). runbot error: 52831 (& a bunch of others) closes odoo/odoo#153299 X-original-commit: 91f9057c73810c34a4b0b85a60c84bb1c482efa4 Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
This commit is contained in:
@@ -469,7 +469,8 @@ class SaleOrderLine(models.Model):
|
||||
if not line.product_uom or not line.product_id:
|
||||
line.price_unit = 0.0
|
||||
else:
|
||||
price = line.with_company(line.company_id)._get_display_price()
|
||||
line = line.with_company(line.company_id)
|
||||
price = line._get_display_price()
|
||||
line.price_unit = line.product_id._get_tax_included_unit_price(
|
||||
line.company_id or line.env.company,
|
||||
line.order_id.currency_id,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
@@ -109,9 +108,23 @@ class Product(models.Model):
|
||||
def _get_contextual_price_tax_selection(self):
|
||||
self.ensure_one()
|
||||
price = self._get_contextual_price()
|
||||
website = self.env['website'].get_current_website()
|
||||
line_tax_type = website.show_line_subtotals_tax_selection
|
||||
company_taxes = self.taxes_id.filtered(lambda tax: tax.company_id in self.env.company.parent_ids)
|
||||
if line_tax_type == "tax_included" and company_taxes:
|
||||
price = company_taxes.compute_all(price, product=self, partner=self.env['res.partner'])['total_included']
|
||||
product_taxes = self.sudo().taxes_id.filtered(lambda x: x.company_id in self.env.company.parent_ids)
|
||||
if product_taxes:
|
||||
website = self.env['website'].get_current_website()
|
||||
fiscal_position = website.sudo().fiscal_position_id
|
||||
|
||||
price = self._get_tax_included_unit_price(
|
||||
website.company_id,
|
||||
website.currency_id,
|
||||
fields.Date.context_today(self),
|
||||
'sale',
|
||||
fiscal_position=fiscal_position,
|
||||
product_price_unit=price,
|
||||
product_currency=website.currency_id,
|
||||
)
|
||||
line_tax_type = website.show_line_subtotals_tax_selection
|
||||
tax_display = "total_included" if line_tax_type == "tax_included" else "total_excluded"
|
||||
|
||||
taxes = fiscal_position.map_tax(product_taxes)
|
||||
price = taxes.compute_all(price, product=self, partner=self.env['res.partner'])[tax_display]
|
||||
return price
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
# coding: utf-8
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import itertools
|
||||
|
||||
from odoo.fields import Command
|
||||
from odoo.tests import tagged
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_product_attribute_value_config import (
|
||||
TestSaleProductAttributeValueCommon,
|
||||
)
|
||||
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):
|
||||
@@ -12,6 +21,39 @@ class WebsiteSaleProductTests(TestSaleProductAttributeValueCommon):
|
||||
cls.website = cls.env.ref('website.default_website')
|
||||
cls.website.company_id = cls.env.company
|
||||
|
||||
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()
|
||||
self.assertEqual(
|
||||
@@ -78,3 +120,107 @@ class WebsiteSaleProductTests(TestSaleProductAttributeValueCommon):
|
||||
pricelist.discount_policy = 'without_discount'
|
||||
res = product_tmpl._get_sales_prices(pricelist, self.env['account.fiscal.position'])
|
||||
self.assertEqual(res[product_tmpl.id]['base_price'], 75)
|
||||
|
||||
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', 'to_tax_included']
|
||||
parameters = itertools.product(param_main_product_tax_included, param_show_line_subtotals_tax_selection, param_extra_tax, param_fpos)
|
||||
|
||||
self.product.taxes_id = self.tax_15
|
||||
fiscal_position = self.env['account.fiscal.position'].create({
|
||||
'name': 'Super Fiscal Position',
|
||||
'auto_apply': True,
|
||||
'country_id': self.fiscal_country.id,
|
||||
'tax_ids': [
|
||||
Command.create({
|
||||
'tax_src_id': self.tax_15.id,
|
||||
'tax_dest_id': self.tax_10.id,
|
||||
})
|
||||
]
|
||||
})
|
||||
self.env.user.partner_id.country_id = self.fiscal_country
|
||||
|
||||
self.WebsiteSaleController = WebsiteSale()
|
||||
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
|
||||
self.website.invalidate_recordset(['fiscal_position_id'], flush=False)
|
||||
config = self.env['res.config.settings'].create({})
|
||||
config.show_line_subtotals_tax_selection = show_line_subtotals_tax_selection
|
||||
config.execute()
|
||||
|
||||
self.assertEqual(self.website.show_line_subtotals_tax_selection, show_line_subtotals_tax_selection)
|
||||
|
||||
tax_ids = [self.tax_15.id]
|
||||
# set "main_product_tax_included" parameter
|
||||
if main_product_tax_included:
|
||||
self.tax_15.price_include = True
|
||||
self.tax_15.include_base_amount = True
|
||||
else:
|
||||
self.tax_15.price_include = False
|
||||
self.tax_15.include_base_amount = False
|
||||
|
||||
# set "extra_tax" parameter
|
||||
if extra_tax:
|
||||
if extra_tax == 'included':
|
||||
self.tax_5.price_include = True
|
||||
self.tax_5.include_base_amount = True
|
||||
else:
|
||||
self.tax_5.price_include = False
|
||||
self.tax_5.include_base_amount = False
|
||||
|
||||
tax_ids.append(self.tax_5.id)
|
||||
|
||||
self.product.taxes_id = tax_ids
|
||||
|
||||
# set "fpos" parameter
|
||||
if fpos:
|
||||
if fpos == 'to_tax_included':
|
||||
self.tax_10.price_include = True
|
||||
self.tax_10.include_base_amount = True
|
||||
else:
|
||||
self.tax_10.price_include = False
|
||||
self.tax_10.include_base_amount = False
|
||||
|
||||
fiscal_position.action_unarchive()
|
||||
else:
|
||||
fiscal_position.action_archive()
|
||||
|
||||
with MockRequest(self.env, website=self.website):
|
||||
self.assertEqual(
|
||||
self.website.fiscal_position_id,
|
||||
fpos and fiscal_position or self.env['account.fiscal.position']
|
||||
)
|
||||
contextual_price = self.product.with_context(
|
||||
website_id=self.website.id,
|
||||
)._get_contextual_price_tax_selection()
|
||||
self.WebsiteSaleController.cart_update(product_id=self.product.id, add_qty=1)
|
||||
sale_order = self.website.sale_get_order()
|
||||
|
||||
self.assertEqual(sale_order.website_id, self.website)
|
||||
self.assertEqual(sale_order.company_id, self.website.company_id)
|
||||
self.assertEqual(sale_order.currency_id, self.website.currency_id)
|
||||
self.assertFalse(sale_order.pricelist_id)
|
||||
if fpos:
|
||||
self.assertEqual(sale_order.fiscal_position_id, fiscal_position)
|
||||
else:
|
||||
self.assertFalse(sale_order.fiscal_position_id)
|
||||
|
||||
sol = sale_order.order_line
|
||||
if fpos:
|
||||
self.assertEqual(sol.tax_id, fiscal_position.map_tax(self.product.taxes_id))
|
||||
else:
|
||||
self.assertEqual(sol.tax_id, self.product.taxes_id)
|
||||
|
||||
if show_line_subtotals_tax_selection == 'tax_included':
|
||||
self.assertAlmostEqual(sol.price_reduce_taxinc, contextual_price)
|
||||
self.assertAlmostEqual(sale_order.amount_total, contextual_price)
|
||||
else:
|
||||
self.assertAlmostEqual(sol.price_reduce_taxexcl, contextual_price)
|
||||
self.assertAlmostEqual(sale_order.amount_untaxed, contextual_price)
|
||||
|
||||
Reference in New Issue
Block a user