From 67954c080ecac6d76fcb2d76d14f34adc3f9c4c2 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Tue, 29 Aug 2023 15:14:44 +0000 Subject: [PATCH] [FIX] sale: apply record rules on order cancellation subject and body When rendering the sale order cancellation message, the rendering should apply the current user record rules, for instance the count of the partner sale orders should match the count of what the salesman can see in his ui. Otherwise he doesn't understand why he has a different count in the UI and in the cancellation message. In case you want the behavior of seeing all records and not just the current salesman records only, then you apply within the template itself the `sudo()`. Applying the `sudo` where you actually need it in the template, and not computing the full subject/body as sudo, offers more granularity. closes odoo/odoo#135233 X-original-commit: 5d49a08f60b1f299784e2e983e87cdec178642c1 Signed-off-by: Denis Ledoux (dle) --- addons/mail/models/mail_composer_mixin.py | 4 +- addons/sale/tests/__init__.py | 1 + addons/sale/tests/test_sale_order_cancel.py | 46 +++++++++++++++++++++ addons/sale/wizard/sale_order_cancel.py | 4 +- 4 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 addons/sale/tests/test_sale_order_cancel.py diff --git a/addons/mail/models/mail_composer_mixin.py b/addons/mail/models/mail_composer_mixin.py index 55813c51ba2..91375fb1271 100644 --- a/addons/mail/models/mail_composer_mixin.py +++ b/addons/mail/models/mail_composer_mixin.py @@ -21,9 +21,9 @@ class MailComposerMixin(models.AbstractModel): _description = 'Mail Composer Mixin' # Content - subject = fields.Char('Subject', compute='_compute_subject', readonly=False, store=True) + subject = fields.Char('Subject', compute='_compute_subject', readonly=False, store=True, compute_sudo=False) body = fields.Html( - 'Contents', compute='_compute_body', readonly=False, store=True, + 'Contents', compute='_compute_body', readonly=False, store=True, compute_sudo=False, render_engine='qweb', render_options={'post_process': True}, sanitize=False) body_has_template_value = fields.Boolean( 'Body content is the same as the template', diff --git a/addons/sale/tests/__init__.py b/addons/sale/tests/__init__.py index c74eb1449a6..91de5b7b2eb 100644 --- a/addons/sale/tests/__init__.py +++ b/addons/sale/tests/__init__.py @@ -13,6 +13,7 @@ from . import test_reinvoice from . import test_sale_flow from . import test_sale_onboarding from . import test_sale_order +from . import test_sale_order_cancel from . import test_sale_prices from . import test_sale_product_attribute_value_config from . import test_sale_refund diff --git a/addons/sale/tests/test_sale_order_cancel.py b/addons/sale/tests/test_sale_order_cancel.py new file mode 100644 index 00000000000..34db1380d75 --- /dev/null +++ b/addons/sale/tests/test_sale_order_cancel.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.tests.common import users + +from odoo.addons.sale.tests.common import SaleCommon +from odoo.addons.sales_team.tests.common import TestSalesCommon + + +class TestSaleOrderCancel(SaleCommon, TestSalesCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.template = cls.env.ref('sale.mail_template_sale_cancellation') + cls.template.write({ + 'subject': 'I can see {{ len(object.partner_id.sale_order_ids) }} order(s)', + 'body_html': 'I can see order(s)', + }) + + cls.partner = cls.env['res.partner'].create({'name': 'foo'}) + + cls.manager_order, cls.salesman_order = cls.env['sale.order'].create([ + {'partner_id': cls.partner.id, 'user_id': cls.user_sales_manager.id}, + {'partner_id': cls.partner.id, 'user_id': cls.user_sales_salesman.id} + ]) + # Invalidate the cache, e.g. to clear the computation of partner.sale_order_ids + cls.env.invalidate_all() + + @users('user_sales_salesman') + def test_salesman_record_rules(self): + cancel = self.env['sale.order.cancel'].create({ + 'template_id': self.template.id, + 'order_id': self.salesman_order.id, + }) + + self.assertEqual(cancel.subject, 'I can see 1 order(s)') + self.assertEqual(cancel.body, 'I can see 1 order(s)') + + @users('user_sales_manager') + def test_manager_record_rules(self): + cancel = self.env['sale.order.cancel'].create({ + 'template_id': self.template.id, + 'order_id': self.manager_order.id, + }) + + self.assertEqual(cancel.subject, 'I can see 2 order(s)') + self.assertEqual(cancel.body, 'I can see 2 order(s)') diff --git a/addons/sale/wizard/sale_order_cancel.py b/addons/sale/wizard/sale_order_cancel.py index 82bc4f61381..9c2c102ac73 100644 --- a/addons/sale/wizard/sale_order_cancel.py +++ b/addons/sale/wizard/sale_order_cancel.py @@ -52,7 +52,7 @@ class SaleOrderCancel(models.TransientModel): @api.depends('order_id') def _compute_subject(self): - for wizard_su in self.filtered('template_id').sudo(): + for wizard_su in self.filtered('template_id'): wizard_su.subject = wizard_su.template_id._render_field( 'subject', [wizard_su.order_id.id], @@ -62,7 +62,7 @@ class SaleOrderCancel(models.TransientModel): @api.depends('order_id') def _compute_body(self): - for wizard_su in self.filtered('template_id').sudo(): + for wizard_su in self.filtered('template_id'): wizard_su.body = wizard_su.template_id._render_field( 'body_html', [wizard_su.order_id.id],