From 1e48a1a7a5fb8a17920d2fb380cece6f009633b2 Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Thu, 9 Mar 2023 14:10:18 +0000 Subject: [PATCH] [FIX] website_sale: do not use cached pricelist on partner update If the SO partner changes, we shouldn't use the pricelist id stored on the session, only the new partner pricelist. opw-3138262 closes odoo/odoo#116434 X-original-commit: 16ba84c25c107996fd0c57f4ffbeb63737601406 Signed-off-by: Victor Feyens (vfe) --- addons/website_sale/controllers/main.py | 2 +- addons/website_sale/models/website.py | 3 +++ .../website_sale/tests/test_sale_process.py | 25 +++++++++++++++++++ .../tests/test_apply_pending_coupon.py | 25 +++++++++++++++++-- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index bce302b00cd..439e2c112f7 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -718,10 +718,10 @@ class WebsiteSale(http.Controller): # empty promo code is used to reset/remove pricelist (see `sale_get_order()`) if promo: pricelist_sudo = request.env['product.pricelist'].sudo().search([('code', '=', promo)], limit=1) - request.session['website_sale_current_pl'] = pricelist_sudo.id if not (pricelist_sudo and request.website.is_pricelist_available(pricelist_sudo.id)): return request.redirect("%s?code_not_available=1" % redirect) + request.session['website_sale_current_pl'] = pricelist_sudo.id # TODO find the best way to create the order with the correct pricelist directly ? # not really necessary, but could avoid one write on SO record order_sudo = request.website.sale_get_order(force_create=True) diff --git a/addons/website_sale/models/website.py b/addons/website_sale/models/website.py index 8b4096a5b7d..284fb57849d 100644 --- a/addons/website_sale/models/website.py +++ b/addons/website_sale/models/website.py @@ -377,7 +377,10 @@ class Website(models.Model): previous_fiscal_position = sale_order_sudo.fiscal_position_id previous_pricelist = sale_order_sudo.pricelist_id + # Reset the session pricelist according to logged partner pl + request.session.pop('website_sale_current_pl', None) pricelist_id = self._get_current_pricelist_id(partner_sudo) + request.session['website_sale_current_pl'] = pricelist_id # change the partner, and trigger the computes (fpos) sale_order_sudo.write({ diff --git a/addons/website_sale/tests/test_sale_process.py b/addons/website_sale/tests/test_sale_process.py index fc9eb6bc4be..a0fa32f7b35 100644 --- a/addons/website_sale/tests/test_sale_process.py +++ b/addons/website_sale/tests/test_sale_process.py @@ -273,6 +273,31 @@ class TestWebsiteSaleCheckoutAddress(TransactionCaseWithUserDemo): self.WebsiteSaleController.pricelist('') self.assertNotEqual(so.pricelist_id, eur_pl, "Pricelist should be removed when sending an empty pl code") + def test_04_pl_reset_on_login(self): + """Check that after login, the SO pricelist is correctly recomputed.""" + test_user = self.env['res.users'].create({ + 'name': 'Toto', + 'login': 'long_enough_password', + 'password': 'long_enough_password', + }) + eur_pl = self.env['product.pricelist'].create({ + 'name': 'EUR_test', + 'website_id': self.website.id, + 'code': 'EUR_test', + }) + test_user.partner_id.property_product_pricelist = eur_pl + + public_user_env = self.env(user=self.website.user_id) + so = self._create_so(public_user_env.user.partner_id.id) + + with MockRequest(self.env, website=self.website, sale_order_id=so.id, website_sale_current_pl=so.pricelist_id.id): + order = self.website.sale_get_order() + pl = order.pricelist_id + self.assertNotEqual(pl, eur_pl) + order_b = self.website.with_user(test_user).sale_get_order() + self.assertEqual(order, order_b) + self.assertEqual(order_b.pricelist_id, eur_pl) + # TEST WEBSITE & MULTI COMPANY def test_05_create_so_with_website_and_multi_company(self): diff --git a/addons/website_sale_loyalty/tests/test_apply_pending_coupon.py b/addons/website_sale_loyalty/tests/test_apply_pending_coupon.py index 6f1544f2662..b4b56d56224 100644 --- a/addons/website_sale_loyalty/tests/test_apply_pending_coupon.py +++ b/addons/website_sale_loyalty/tests/test_apply_pending_coupon.py @@ -1,10 +1,11 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo import http +from odoo.tests import tagged, HttpCase + from odoo.addons.sale_loyalty.tests.common import TestSaleCouponNumbersCommon from odoo.addons.website.tools import MockRequest from odoo.addons.website_sale_loyalty.controllers.main import WebsiteSale -from odoo.tests import tagged -from odoo.tests.common import HttpCase @tagged('-at_install', 'post_install') @@ -33,9 +34,15 @@ class TestSaleCouponApplyPending(HttpCase, TestSaleCouponNumbersCommon): 'points_granted': 1, }).generate_coupons() self.coupon = self.coupon_program.coupon_ids[0] + installed_modules = set(self.env['ir.module.module'].search([ + ('state', '=', 'installed'), + ]).mapped('name')) + for _ in http._generate_routing_rules(installed_modules, nodb_only=False): + pass def test_01_activate_coupon_with_existing_program(self): order = self.empty_order + self.env['product.pricelist.item'].search([]).unlink() with MockRequest(self.env, website=self.website, sale_order_id=order.id, website_sale_current_pl=1) as request: self.WebsiteSaleController.cart_update_json(self.largeCabinet.id, set_qty=2) @@ -51,18 +58,32 @@ class TestSaleCouponApplyPending(HttpCase, TestSaleCouponNumbersCommon): def test_02_pending_coupon_with_existing_program(self): order = self.empty_order + self.env['product.pricelist.item'].search([]).unlink() with MockRequest(self.env, website=self.website, sale_order_id=order.id, website_sale_current_pl=1) as request: self.WebsiteSaleController.cart_update_json(self.largeCabinet.id, set_qty=1) self.WebsiteSaleController.pricelist(self.global_program.rule_ids.code) + self.assertEqual(self.largeCabinet.lst_price, 320) + cabinet_sol = order.order_line.filtered(lambda sol: sol.product_id == self.largeCabinet) + promo_sol = (order.order_line - cabinet_sol) + self.assertTrue(cabinet_sol) + self.assertEqual(cabinet_sol.price_unit, 320) + self.assertEqual(cabinet_sol.price_total, 320) + self.assertEqual(promo_sol.price_total, -32) + self.assertEqual(order.amount_tax, 0) + self.assertEqual(order.cart_quantity, 1) self.assertEqual(order.amount_total, 288, "The order total should equal 288: 320 - 10%") self.WebsiteSaleController.activate_coupon(self.coupon.code) promo_code = request.session.get('pending_coupon_code') + self.assertEqual(order.amount_tax, 0) + self.assertEqual(order.cart_quantity, 1) self.assertEqual(order.amount_total, 288, "The order total should still equal 288 as the coupon for free product can't be applied since it requires 2 min qty") self.assertEqual(promo_code, self.coupon.code, "The promo code should be set in the pending coupon dict as it couldn't be applied, we save it for later reuse") self.WebsiteSaleController.cart_update_json(self.largeCabinet.id, add_qty=1) promo_code = request.session.get('pending_coupon_code') self.assertFalse(promo_code, "The promo code should be removed from the pending coupon dict as it should have been applied") + self.assertEqual(order.amount_tax, 0) + self.assertEqual(order.cart_quantity, 2) self.assertEqual(order.amount_total, 576, "The order total should equal 576: 2*320 - 0 (free product) - 10%")