[FIX] product,sale,website_sale: fix currency conversion of product
In commit f8dad1bb4b, we tried to fix the currency
conversion of products by always using the currency of the product as the base.
This is still correct.
However, the conversion method also needs to know the company (to find the
correct currency rate), and it was assumed the company was also always set on
the product. This is of course not correct when using multi-company.
In this commit we fix that issue by falling back if no company is set on the
product. The order of the fallback is: product website company, given website
company, given pricelist company, current user company.
closes #29905
closes #29946
closes #30046
Co-authored-by: Sébastien Theys <seb@odoo.com>
Co-authored-by: Wolfgang Taferner <wolfgang.taferner@wt-io-it.at>
This commit is contained in:
co-authored by
Wolfgang Taferner
parent
d73c4e583a
commit
e8a01ddc88
@@ -909,6 +909,36 @@ class ProductTemplate(models.Model):
|
||||
return result
|
||||
combination = combination[:-1]
|
||||
|
||||
@api.multi
|
||||
def _get_current_company(self, **kwargs):
|
||||
"""Get the most appropriate company for this product.
|
||||
|
||||
If the company is set on the product, directly return it. Otherwise,
|
||||
fallback to a contextual company.
|
||||
|
||||
:param kwargs: kwargs forwarded to the fallback method.
|
||||
|
||||
:return: the most appropriate company for this product
|
||||
:rtype: recordset of one `res.company`
|
||||
"""
|
||||
self.ensure_one()
|
||||
return self.company_id or self._get_current_company_fallback(**kwargs)
|
||||
|
||||
@api.multi
|
||||
def _get_current_company_fallback(self, **kwargs):
|
||||
"""Fallback to get the most appropriate company for this product.
|
||||
|
||||
This should only be called from `_get_current_company` but is defined
|
||||
separately to allow override.
|
||||
|
||||
The final fallback will be the current user's company.
|
||||
|
||||
:return: the fallback company for this product
|
||||
:rtype: recordset of one `res.company`
|
||||
"""
|
||||
self.ensure_one()
|
||||
return self.env.user.company_id
|
||||
|
||||
@api.model
|
||||
def get_empty_list_help(self, help):
|
||||
self = self.with_context(
|
||||
|
||||
@@ -258,7 +258,7 @@ class ProductTemplate(models.Model):
|
||||
|
||||
if pricelist and pricelist.currency_id != product_template.currency_id:
|
||||
list_price = product_template.currency_id._convert(
|
||||
list_price, pricelist.currency_id, product_template.company_id,
|
||||
list_price, pricelist.currency_id, product_template._get_current_company(pricelist=pricelist),
|
||||
fields.Date.today()
|
||||
)
|
||||
|
||||
@@ -293,3 +293,11 @@ class ProductTemplate(models.Model):
|
||||
return False
|
||||
combination = self._get_first_possible_combination(parent_combination)
|
||||
return True if combination else self._is_combination_possible(combination, parent_combination)
|
||||
|
||||
@api.multi
|
||||
def _get_current_company_fallback(self, **kwargs):
|
||||
"""Override: if a pricelist is given, fallback to the company of the
|
||||
pricelist if it is set, otherwise use the one from parent method."""
|
||||
res = super(ProductTemplate, self)._get_current_company_fallback(**kwargs)
|
||||
pricelist = kwargs.get('pricelist')
|
||||
return pricelist and pricelist.company_id or res
|
||||
|
||||
@@ -185,6 +185,11 @@ class TestSaleProductAttributeValueConfig(TestSaleProductAttributeValueSetup):
|
||||
do_test(self)
|
||||
|
||||
def test_02_get_combination_info(self):
|
||||
# If using multi-company, company_id will be False, and this code should
|
||||
# still work.
|
||||
# The case with a company_id will be implicitly tested on website_sale.
|
||||
self.computer.company_id = False
|
||||
|
||||
computer_ssd_256 = self._get_product_template_attribute_value(self.ssd_256)
|
||||
computer_ram_8 = self._get_product_template_attribute_value(self.ram_8)
|
||||
computer_hdd_1 = self._get_product_template_attribute_value(self.hdd_1)
|
||||
|
||||
@@ -150,9 +150,10 @@ class WebsiteSale(ProductConfiguratorController):
|
||||
return pricelist_context, pricelist
|
||||
|
||||
def _get_compute_currency(self, pricelist, product=None):
|
||||
from_currency = (product or request.env.user.company_id).currency_id
|
||||
company = product and product._get_current_company(pricelist=pricelist, website=request.website) or pricelist.company_id or request.website.company_id
|
||||
from_currency = (product or company).currency_id
|
||||
to_currency = pricelist.currency_id
|
||||
return lambda price: from_currency._convert(price, to_currency, (product or request.env.user).company_id, fields.Date.today())
|
||||
return lambda price: from_currency._convert(price, to_currency, company, fields.Date.today())
|
||||
|
||||
def _get_search_order(self, post):
|
||||
# OrderBy will be parsed in orm and so no direct sql injection
|
||||
@@ -312,7 +313,7 @@ class WebsiteSale(ProductConfiguratorController):
|
||||
pricelist = request.website.get_current_pricelist()
|
||||
|
||||
def compute_currency(price):
|
||||
return product.currency_id._convert(price, pricelist.currency_id, product.company_id, fields.Date.today())
|
||||
return product.currency_id._convert(price, pricelist.currency_id, product._get_current_company(pricelist=pricelist, website=request.website), fields.Date.today())
|
||||
|
||||
if not product_context.get('pricelist'):
|
||||
product_context['pricelist'] = pricelist.id
|
||||
|
||||
@@ -286,6 +286,14 @@ class ProductTemplate(models.Model):
|
||||
"""
|
||||
return self._create_product_variant(self._get_first_possible_combination(), log_warning)
|
||||
|
||||
@api.multi
|
||||
def _get_current_company_fallback(self, **kwargs):
|
||||
"""Override: if a website is set on the product or given, fallback to
|
||||
the company of the website. Otherwise use the one from parent method."""
|
||||
res = super(ProductTemplate, self)._get_current_company_fallback(**kwargs)
|
||||
website = self.website_id or kwargs.get('website')
|
||||
return website and website.company_id or res
|
||||
|
||||
def _default_website_sequence(self):
|
||||
self._cr.execute("SELECT MIN(website_sequence) FROM %s" % self._table)
|
||||
min_sequence = self._cr.fetchone()[0]
|
||||
|
||||
Reference in New Issue
Block a user