Add optional subject to notifications
issue9321 review290011002
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
* Add optional subject to notifications
|
||||
|
||||
Version 5.6.0 - 2020-05-04
|
||||
* Bug fixes (see mercurial logs for details)
|
||||
* Add commission agent as a recipient
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.model.exceptions import ValidationError
|
||||
|
||||
|
||||
class TemplateError(ValidationError):
|
||||
pass
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data grouped="1">
|
||||
<record model="ir.message" id="msg_notification_invalid_subject">
|
||||
<field name="text">Invalid e-mail subject in notification "%(notification)s" with exception "%(exception)s".</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
+34
-1
@@ -8,13 +8,17 @@ from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.nonmultipart import MIMENonMultipart
|
||||
from email.utils import formataddr, getaddresses
|
||||
|
||||
from genshi.template import TextTemplate
|
||||
|
||||
from trytond.config import config
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.report import get_email
|
||||
from trytond.sendmail import sendmail_transactional, SMTPDataManager
|
||||
from trytond.transaction import Transaction
|
||||
from .exceptions import TemplateError
|
||||
|
||||
_EMAIL_MODELS = [
|
||||
'res.user',
|
||||
@@ -37,6 +41,11 @@ class Email(ModelSQL, ModelView):
|
||||
from_ = fields.Char(
|
||||
"From",
|
||||
help="Leave empty for the value defined in the configuration file.")
|
||||
subject = fields.Char(
|
||||
"Subject", translate=True,
|
||||
help="The Genshi syntax can be used "
|
||||
"with 'record' in the evaluation context.\n"
|
||||
"If empty the report name will be used.")
|
||||
recipients = fields.Many2One(
|
||||
'ir.model.field', "Recipients",
|
||||
domain=[
|
||||
@@ -240,11 +249,17 @@ class Email(ModelSQL, ModelView):
|
||||
|
||||
# TODO order languages to get default as last one for title
|
||||
content, title = get_email(self.content, record, languages)
|
||||
language = list(languages)[-1]
|
||||
if self.subject:
|
||||
with Transaction().set_context(language=language.code):
|
||||
notification = self.__class__(self.id)
|
||||
title = (TextTemplate(notification.subject)
|
||||
.generate(record=record)
|
||||
.render())
|
||||
|
||||
if self.attachments:
|
||||
msg = MIMEMultipart('mixed')
|
||||
msg.attach(content)
|
||||
language = list(languages)[-1]
|
||||
for report in self.attachments:
|
||||
msg.attach(Attachment.get_mime(report, record, language.code))
|
||||
else:
|
||||
@@ -329,6 +344,24 @@ class Email(ModelSQL, ModelView):
|
||||
if logs:
|
||||
Log.create(logs)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, notifications):
|
||||
super().validate(notifications)
|
||||
for notification in notifications:
|
||||
notification.check_subject()
|
||||
|
||||
def check_subject(self):
|
||||
if not self.subject:
|
||||
return
|
||||
try:
|
||||
TextTemplate(self.subject)
|
||||
except Exception as exception:
|
||||
raise TemplateError(
|
||||
gettext('notification_email.'
|
||||
'msg_notification_invalid_subject',
|
||||
notification=self.rec_name,
|
||||
exception=exception)) from exception
|
||||
|
||||
|
||||
class EmailAttachment(ModelSQL):
|
||||
"Email Notification Attachment"
|
||||
|
||||
@@ -51,7 +51,7 @@ for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER', 'CI_JOB_ID']:
|
||||
if local_version:
|
||||
version += '+' + '.'.join(local_version)
|
||||
|
||||
requires = []
|
||||
requires = ['Genshi']
|
||||
for dep in info.get('depends', []):
|
||||
if not re.match(r'(ir|res)(\W|$)', dep):
|
||||
requires.append(get_require_version('trytond_%s' % dep))
|
||||
|
||||
@@ -168,6 +168,68 @@ class NotificationEmailTestCase(ModuleTestCase):
|
||||
attachment.get_content_type(), 'text/plain')
|
||||
self.assertEqual(attachment.get_filename(), "Attachment.txt")
|
||||
|
||||
@with_transaction()
|
||||
def test_notification_email_subject(self):
|
||||
"Test email notificiation with subject"
|
||||
pool = Pool()
|
||||
Model = pool.get('ir.model')
|
||||
User = pool.get('res.user')
|
||||
NotificationEmail = pool.get('notification.email')
|
||||
Language = pool.get('ir.lang')
|
||||
|
||||
self._setup_notification()
|
||||
model, = Model.search([
|
||||
('model', '=', User.__name__),
|
||||
])
|
||||
en, = Language.search([('code', '=', 'en')])
|
||||
|
||||
notification_email, = NotificationEmail.search([])
|
||||
notification_email.subject = 'Notification for ${record.name}'
|
||||
notification_email.save()
|
||||
|
||||
user, = User.create([{'name': "Michael Scott", 'login': "msc"}])
|
||||
|
||||
msg = notification_email.get_email(
|
||||
user, FROM, ['Administrator <user@example.com>'], [], [], [en])
|
||||
|
||||
self.assertEqual(msg['Subject'], 'Notification for Michael Scott')
|
||||
|
||||
@with_transaction()
|
||||
def test_notification_email_translated_subject(self):
|
||||
"Test email notificiation with translated subject"
|
||||
pool = Pool()
|
||||
Model = pool.get('ir.model')
|
||||
User = pool.get('res.user')
|
||||
NotificationEmail = pool.get('notification.email')
|
||||
Language = pool.get('ir.lang')
|
||||
|
||||
self._setup_notification()
|
||||
model, = Model.search([
|
||||
('model', '=', User.__name__),
|
||||
])
|
||||
es, = Language.search([('code', '=', 'es')])
|
||||
Language.load_translations([es])
|
||||
|
||||
notification_email, = NotificationEmail.search([])
|
||||
notification_email.subject = 'Notification for ${record.name}'
|
||||
notification_email.save()
|
||||
|
||||
with Transaction().set_context(lang='es'):
|
||||
notification_email, = NotificationEmail.search([])
|
||||
notification_email.subject = 'Notificación para ${record.name}'
|
||||
notification_email.save()
|
||||
|
||||
user, = User.create([{
|
||||
'name': "Michael Scott",
|
||||
'login': "msc",
|
||||
'language': es.id,
|
||||
}])
|
||||
|
||||
msg = notification_email.get_email(
|
||||
user, FROM, ['Administrator <user@example.com>'], [], [], [es])
|
||||
|
||||
self.assertEqual(msg['Subject'], 'Notificación para Michael Scott')
|
||||
|
||||
@unittest.skipIf(
|
||||
(3, 5, 0) <= sys.version_info < (3, 5, 2), "python bug #25195")
|
||||
@with_transaction()
|
||||
|
||||
@@ -11,3 +11,4 @@ extras_depend:
|
||||
xml:
|
||||
notification.xml
|
||||
ir.xml
|
||||
message.xml
|
||||
|
||||
@@ -6,6 +6,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="from_"/>
|
||||
<label name="content"/>
|
||||
<field name="content"/>
|
||||
<label name="subject"/>
|
||||
<field name="subject" colspan="3"/>
|
||||
<label name="recipients"/>
|
||||
<field name="recipients"/>
|
||||
<label name="fallback_recipients"/>
|
||||
|
||||
Reference in New Issue
Block a user