[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:
committed by
Thibault Delavallée
co-authored by
Thibault Delavallée
parent
2d6df1fe7a
commit
b19fe6dea5
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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)
|
||||
Reference in New Issue
Block a user