diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index 7c4bb62ddd3..bf0b9786623 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -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( diff --git a/addons/sale/models/product_template.py b/addons/sale/models/product_template.py index 8daa24e9f37..b0cd6345784 100644 --- a/addons/sale/models/product_template.py +++ b/addons/sale/models/product_template.py @@ -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 diff --git a/addons/sale/tests/test_sale_product_attribute_value_config.py b/addons/sale/tests/test_sale_product_attribute_value_config.py index dd36a916778..95b1814f50e 100644 --- a/addons/sale/tests/test_sale_product_attribute_value_config.py +++ b/addons/sale/tests/test_sale_product_attribute_value_config.py @@ -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) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index aec6d3b17ed..80b50fa61db 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -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 diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py index db7d9d9cd96..db0ac30f060 100644 --- a/addons/website_sale/models/product.py +++ b/addons/website_sale/models/product.py @@ -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]