[FIX] website_sale: harmonize tax computation

Standard `sale` tax flows rely on `_get_tax_included_price_unit`,
whereas part of `website_sale` flows do, while another part relies
on `_fix_tax_included_price_company`, which doesn't handle some
advanced cases (fiscal position mapping of price_included taxes).

This commit drops the use of `_fix_tax_included_price_company` in
website_sale, to only use the newest API of `_get_tax_included_price_unit`,
supposed to handle more cases.

Also makes all taxes computation go through a single entry point,
`_apply_taxes_to_price`, already used for `combination_info` logic (/shop/product),
but not in `_get_sales_prices` (/shop page).

opw-3700803

original commit : 662ea281515156a781ab68079d0123ea45ebf40f

closes odoo/odoo#160198

Signed-off-by: Laurent Smet (las) <las@odoo.com>
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
This commit is contained in:
Victor Feyens
2024-04-02 18:17:59 +00:00
parent b6688b1a47
commit 9338ac0174
3 changed files with 29 additions and 38 deletions
+9 -20
View File
@@ -103,24 +103,13 @@ 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()
fiscal_position_sudo = website.sudo().fiscal_position_id
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
return self.env['product.template']._apply_taxes_to_price(
self._get_contextual_price(),
website.currency_id,
product_taxes,
fiscal_position_sudo.map_tax(product_taxes),
self,
)
+13 -18
View File
@@ -254,7 +254,6 @@ class ProductTemplate(models.Model):
return {}
pricelist and pricelist.ensure_one()
partner_sudo = self.env.user.partner_id
pricelist = pricelist or self.env['product.pricelist']
currency = pricelist.currency_id or self.env.company.currency_id
date = fields.Date.context_today(self)
@@ -264,11 +263,6 @@ class ProductTemplate(models.Model):
show_strike_price = self.env.user.has_group('website_sale.group_product_price_comparison')
base_sales_prices = self._price_compute('list_price', currency=currency)
website = self.env['website'].get_current_website()
if website.show_line_subtotals_tax_selection == 'tax_excluded':
tax_display = 'total_excluded'
else:
tax_display = 'total_included'
res = {}
for template in self:
@@ -286,10 +280,10 @@ class ProductTemplate(models.Model):
if not price_list_contains_template:
price_reduce = base_sales_prices[template.id]
if template.currency_id != pricelist.currency_id:
if template.currency_id != currency:
base_price = template.currency_id._convert(
base_price,
pricelist.currency_id,
currency,
self.env.company,
date,
round=False
@@ -299,13 +293,13 @@ class ProductTemplate(models.Model):
base_price = base_sales_prices[template.id]
# Compare_list_price are never tax included
base_price = self.env['account.tax']._fix_tax_included_price_company(
base_price, product_taxes, taxes, self.env.company)
base_price = taxes.compute_all(base_price, pricelist.currency_id, 1, template, partner_sudo)[tax_display]
base_price = self._apply_taxes_to_price(
base_price, currency, product_taxes, taxes, self,
)
price_reduce = self.env['account.tax']._fix_tax_included_price_company(
price_reduce, product_taxes, taxes, self.env.company)
price_reduce = taxes.compute_all(price_reduce, pricelist.currency_id, 1, template, partner_sudo)[tax_display]
price_reduce = self._apply_taxes_to_price(
price_reduce, currency, product_taxes, taxes, self,
)
template_price_vals = {
'price_reduce': price_reduce,
@@ -560,11 +554,12 @@ class ProductTemplate(models.Model):
def _apply_taxes_to_price(
self, price, currency, product_taxes, taxes, product_or_template,
):
# Ideally, we should use _get_tax_included_unit_price
# but it doesn't allow to request tax-excluded amount.
website = self.env['website'].get_current_website()
price = self.env['account.tax']._fix_tax_included_price_company(
price, product_taxes, taxes, self.env.company,
price = self.env['product.product']._get_tax_included_unit_price_from_price(
price,
currency,
product_taxes,
product_taxes_after_fp=taxes,
)
show_tax = website.show_line_subtotals_tax_selection
tax_display = 'total_excluded' if show_tax == 'tax_excluded' else 'total_included'
@@ -170,6 +170,13 @@ class TestWebsiteSaleProductAttributeValueConfig(TestSaleProductAttributeValueCo
self.assertEqual(round(combination_info['list_price'], 2), 434.78, "434.78$ + 0% tax (mapped from fp 15% -> 0%)")
self.assertEqual(combination_info['price_extra'], 173.91, "173.91$ + 0% tax (mapped from fp 15% -> 0%)")
# Try same flow with tax included for apply tax
tax0.write({'name': "Test tax 5", 'amount': 5, 'price_include': True})
combination_info = product._get_combination_info()
self.assertEqual(round(combination_info['price'], 2), 456.52, "434.78$ + 5% tax (mapped from fp 15% -> 5% for BE)")
self.assertEqual(round(combination_info['list_price'], 2), 456.52, "434.78$ + 5% tax (mapped from fp 15% -> 5% for BE)")
self.assertEqual(combination_info['price_extra'], 182.61, "173.91$ + 5% tax (mapped from fp 15% -> 5% for BE)")
@tagged('post_install', '-at_install', 'product_pricelist')
class TestWebsiteSaleProductPricelist(TestSaleProductAttributeValueCommon):