From 1d85cabb50cba5e330707c4041e03eaa7f27bbe4 Mon Sep 17 00:00:00 2001 From: Thibault Libioulle Date: Fri, 4 Feb 2022 09:38:29 +0000 Subject: [PATCH] [FIX] product,website_sale: fix contextual price on eCommerce Prior to this commit the price in the product dynamic filter was not correctly computed since the pricelist was not available in the context. This commit provides a fallback on request website pricelist in order to display a non-zero price if it exists. task-2765828 closes odoo/odoo#85507 X-original-commit: 88bfd8a60cefac45e73cd032204c9b90a862ee6c Signed-off-by: Yannick Tivisse (yti) --- addons/product/models/product_product.py | 4 +-- addons/product/models/product_template.py | 13 +++++-- .../website_sale/models/product_template.py | 12 +++++++ addons/website_sale/tests/__init__.py | 1 + .../tests/test_website_sale_product.py | 34 +++++++++++++++++++ 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 addons/website_sale/tests/test_website_sale_product.py diff --git a/addons/product/models/product_product.py b/addons/product/models/product_product.py index c908686539c..bf8d027ce60 100644 --- a/addons/product/models/product_product.py +++ b/addons/product/models/product_product.py @@ -678,9 +678,9 @@ class ProductProduct(models.Model): def _get_contextual_price(self): self.ensure_one() # YTI TODO: During website_sale cleaning, we should get rid of those crappy context thing - if not self._context.get('pricelist'): + pricelist = self.product_tmpl_id._get_contextual_pricelist() + if not pricelist: return 0.0 - pricelist = self.env['product.pricelist'].browse(self._context.get('pricelist')) quantity = self.env.context.get('quantity', 1.0) uom = self.env['uom.uom'].browse(self.env.context.get('uom')) diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index 76d4094493a..e2160394de3 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -1273,11 +1273,20 @@ class ProductTemplate(models.Model): def _get_contextual_price(self): self.ensure_one() # YTI TODO: During website_sale cleaning, we should get rid of those crappy context thing - if not self._context.get('pricelist'): + pricelist = self._get_contextual_pricelist() + if not pricelist: return 0.0 - pricelist = self.env['product.pricelist'].browse(self._context.get('pricelist')) quantity = self.env.context.get('quantity', 1.0) uom = self.env['uom.uom'].browse(self.env.context.get('uom')) date = self.env.context.get('date') return pricelist._get_product_price(self, quantity, uom=uom, date=date) + + def _get_contextual_pricelist(self): + """ Get the contextual pricelist + + This method is meant to be overriden in other standard modules. + """ + if self._context.get('pricelist'): + return self.env['product.pricelist'].browse(self._context.get('pricelist')) + return self.env['product.pricelist'] diff --git a/addons/website_sale/models/product_template.py b/addons/website_sale/models/product_template.py index ea723e10713..6747b885dde 100644 --- a/addons/website_sale/models/product_template.py +++ b/addons/website_sale/models/product_template.py @@ -3,6 +3,7 @@ from odoo import api, fields, models, _ from odoo.addons.http_routing.models.ir_http import slug, unslug +from odoo.addons.website.models import ir_http from odoo.tools.translate import html_translate from odoo.osv import expression @@ -474,3 +475,14 @@ class ProductTemplate(models.Model): 'currency': product.currency_id.name, 'price': combination['list_price'], } + + def _get_contextual_pricelist(self): + """ Override to fallback on website current pricelist + """ + pricelist = super()._get_contextual_pricelist() + if pricelist: + return pricelist + website = ir_http.get_request_website() + if website: + return website.get_current_pricelist() + return pricelist diff --git a/addons/website_sale/tests/__init__.py b/addons/website_sale/tests/__init__.py index fdc363141e7..0dfc8b8900e 100644 --- a/addons/website_sale/tests/__init__.py +++ b/addons/website_sale/tests/__init__.py @@ -12,3 +12,4 @@ from . import test_website_sale_product_attribute_value_config from . import test_website_sale_image from . import test_website_sequence from . import test_website_sale_visitor +from . import test_website_sale_product diff --git a/addons/website_sale/tests/test_website_sale_product.py b/addons/website_sale/tests/test_website_sale_product.py new file mode 100644 index 00000000000..99537dca91e --- /dev/null +++ b/addons/website_sale/tests/test_website_sale_product.py @@ -0,0 +1,34 @@ +# coding: utf-8 +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 + +@tagged('post_install', '-at_install') +class WebsiteSaleProductTests(TestSaleProductAttributeValueCommon): + + def setUp(self): + super().setUp() + self.website = self.env.ref('website.default_website') + + def test_website_sale_contextual_price(self): + contextual_price = self.computer._get_contextual_price() + self.assertEqual(0.0, contextual_price, "With no pricelist context, the contextual price should be 0.") + + current_website = self.env['website'].get_current_website() + pricelist = current_website.get_current_pricelist() + + # make sure the pricelist has a 10% discount + self.env['product.pricelist.item'].create({ + 'price_discount': 10, + 'compute_price': 'formula', + 'pricelist_id': pricelist.id, + }) + discount_rate = 0.9 + currency_ratio = 2 + pricelist.currency_id = self._setup_currency(currency_ratio) + with MockRequest(self.env, website=self.website): + contextual_price = self.computer._get_contextual_price() + self.assertEqual( + 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." + )