[IMP] mail: introduce a composer mixin for invite / send email wizards

This commits introduces a new mixin ``mail.composer.mixin`` used when sending
emails or notifications based on a mail template.

Main current purpose is to hide details related to subject and body computation
and rendering based on a mail.template. It also give the base tools to control
who is allowed to edit body, notably when dealing with templating language
like jinja or qweb.

It is meant to evolve in a near future with upcoming support of qweb and fine
grain control of rendering access.

Task ID-2534550 (Template usage improvement)
Task ID-2477164 (Composer mixin)
COM PR odoo/odoo#70889
ENT PR odoo/enterprise#18352

Co-Authored-By: Stéphane Debauche <std@odoo.com>
Co-Authored-By: Thibault Delavallée <tde@odoo.com>
This commit is contained in:
Stéphane Debauche
2021-06-01 09:06:07 +00:00
committed by Thibault Delavallée
co-authored by Thibault Delavallée
parent 2d6df1fe7a
commit b19fe6dea5
6 changed files with 117 additions and 1 deletions
+3 -1
View File
@@ -1,13 +1,15 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import mail_render_mixin
from . import mail_composer_mixin
from . import mail_message_subtype
from . import mail_tracking_value
from . import mail_alias
from . import mail_alias_mixin
from . import mail_followers
from . import mail_notification
from . import mail_render_mixin
from . import mail_message
from . import mail_activity
from . import mail_mail
+49
View File
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class MailComposerMixin(models.AbstractModel):
""" Mixin used to edit and render some fields used when sending emails or
notifications based on a mail template.
Main current purpose is to hide details related to subject and body computation
and rendering based on a mail.template. It also give the base tools to control
who is allowed to edit body, notably when dealing with templating language
like jinja or qweb.
It is meant to evolve in a near future with upcoming support of qweb and fine
grain control of rendering access.
"""
_name = 'mail.composer.mixin'
_inherit = 'mail.render.mixin'
_description = 'Mail Composer Mixin'
# Content
subject = fields.Char('Subject', compute='_compute_subject', readonly=False, store=True)
body = fields.Html('Contents', sanitize_style=True, compute='_compute_body', store=True, readonly=False)
template_id = fields.Many2one('mail.template', 'Mail Template', domain="[('model', '=', render_model)]")
# Access
can_edit_body = fields.Boolean('Can Edit Body', compute='_compute_can_edit_body')
@api.depends('template_id')
def _compute_subject(self):
for composer_mixin in self:
if composer_mixin.template_id:
composer_mixin.subject = composer_mixin.template_id.subject
elif not composer_mixin.subject:
composer_mixin.subject = False
@api.depends('template_id')
def _compute_body(self):
for composer_mixin in self:
if composer_mixin.template_id:
composer_mixin.body = composer_mixin.template_id.body_html
elif not composer_mixin.body:
composer_mixin.body = False
@api.depends('template_id')
@api.depends_context('uid')
def _compute_can_edit_body(self):
self.can_edit_body = True
@@ -122,3 +122,16 @@ class MailTestContainer(models.Model):
values['alias_force_thread_id'] = self.id
values['alias_parent_thread_id'] = self.id
return values
class MailTestComposerMixin(models.Model):
""" A simple invite-like wizard using the composer mixin, rendering on
itself. """
_description = 'Invite-like Wizard'
_name = 'mail.test.composer.mixin'
_inherit = ['mail.composer.mixin']
name = fields.Char('Name')
author_id = fields.Many2one('res.partner')
def _compute_render_model(self):
self.render_model = self._name
@@ -11,6 +11,8 @@ access_mail_test_activity_portal,mail.test.activity.portal,model_mail_test_activ
access_mail_test_activity_user,mail.test.activity.user,model_mail_test_activity,base.group_user,1,1,1,1
access_mail_test_ticket_portal,mail.test.ticket.portal,model_mail_test_ticket,base.group_portal,0,0,0,0
access_mail_test_ticket_user,mail.test.ticket.user,model_mail_test_ticket,base.group_user,1,1,1,1
access_mail_test_composer_mixin_all,mail.test.composer.mixin.all,model_mail_test_composer_mixin,,0,0,0,0
access_mail_test_composer_mixin_user,mail.test.composer.mixin.user,model_mail_test_composer_mixin,base.group_user,1,1,1,1
access_mail_test_container_portal,mail.test.container_portal,model_mail_test_container,base.group_portal,1,1,0,0
access_mail_test_container_user,mail.test.container.user,model_mail_test_container,base.group_user,1,1,1,1
access_mail_test_cc_portal,mail.test.cc.portal,model_mail_test_cc,base.group_portal,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
11 access_mail_test_activity_user mail.test.activity.user model_mail_test_activity base.group_user 1 1 1 1
12 access_mail_test_ticket_portal mail.test.ticket.portal model_mail_test_ticket base.group_portal 0 0 0 0
13 access_mail_test_ticket_user mail.test.ticket.user model_mail_test_ticket base.group_user 1 1 1 1
14 access_mail_test_composer_mixin_all mail.test.composer.mixin.all model_mail_test_composer_mixin 0 0 0 0
15 access_mail_test_composer_mixin_user mail.test.composer.mixin.user model_mail_test_composer_mixin base.group_user 1 1 1 1
16 access_mail_test_container_portal mail.test.container_portal model_mail_test_container base.group_portal 1 1 0 0
17 access_mail_test_container_user mail.test.container.user model_mail_test_container base.group_user 1 1 1 1
18 access_mail_test_cc_portal mail.test.cc.portal model_mail_test_cc base.group_portal 1 0 0 0
+1
View File
@@ -4,6 +4,7 @@ from . import test_invite
from . import test_ir_actions
from . import test_mail_activity
from . import test_mail_composer
from . import test_mail_composer_mixin
from . import test_mail_followers
from . import test_mail_message
from . import test_mail_mail
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail.tests.common import TestMailCommon, TestRecipients
from odoo.tests import tagged
from odoo.tests.common import users
@tagged('mail_composer_mixin')
class TestMailComposerMixin(TestMailCommon, TestRecipients):
@classmethod
def setUpClass(cls):
super(TestMailComposerMixin, cls).setUpClass()
cls._init_mail_gateway()
cls.mail_template = cls.env['mail.template'].create({
'subject': 'Subject for ${object.name}',
'body_html': '<p>Body for ${object.name}</p>',
})
@users("employee")
def test_content_sync(self):
record = self.env['mail.test.composer.mixin'].create({
'name': 'Invite',
'template_id': self.mail_template.id,
})
self.assertEqual(record.subject, self.mail_template.subject)
self.assertEqual(record.body, self.mail_template.body_html)
subject = record._render_field('subject', record.ids)[record.id]
self.assertEqual(subject, 'Subject for %s' % record.name)
body = record._render_field('body', record.ids)[record.id]
self.assertEqual(body, '<p>Body for %s</p>' % record.name)
@users("employee")
def test_rendering(self):
record = self.env['mail.test.composer.mixin'].create({
'name': 'Invite',
'subject': 'Subject for ${object.name}',
'body': '<p>Content from ${user.name}</p>',
})
self.assertEqual(record.subject, 'Subject for ${object.name}')
self.assertEqual(record.body, '<p>Content from ${user.name}</p>')
subject = record._render_field('subject', record.ids)[record.id]
self.assertEqual(subject, 'Subject for %s' % record.name)
body = record._render_field('body', record.ids)[record.id]
self.assertEqual(body, '<p>Content from %s</p>' % self.env.user.name)