[REF] survey: refactor template use on invite wizard

Purpose of this merge is to remove the ugly __URL__ hack of survey templates.
It is solved by making template rendered on user_input model. This means each
invitation recipient will received its own rendered mail. Small jinja code
allows therefore to include the url in a clean odoo-style way.

Subject and body in survey invite wizard are not rendered anymore. It means
jinja could be displayed. This is necessary as this wizard will work in batch
mode, rendering the body on each recipient.

This commit is linked to task ID 1911586 and PR #28986.
This commit is contained in:
Thibault Delavallée
2019-01-14 15:22:18 +00:00
parent 6fa4688693
commit 7d110c20c5
3 changed files with 34 additions and 59 deletions
+8 -7
View File
@@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="email_template_survey" model="mail.template">
<record id="mail_template_user_input_invite" model="mail.template">
<field name="name">Survey: Send by email</field>
<field name="model_id" ref="model_survey_survey" />
<field name="subject">${object.title}: Survey</field>
<field name="model_id" ref="model_survey_user_input" />
<field name="subject">Participate to ${object.survey_id.title} survey</field>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px; font-size: 13px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Hello<br /><br />
We are conducting a survey, and your response would be appreciated.
Dear ${object.partner_id.name or 'participant'}<br/><br/>
We are conducting a survey and your response would be appreciated.
<div style="margin: 16px 0px 16px 0px;">
<a href="__URL__"
<a href="${('%s?token=%s' % (object.survey_id.public_url, object.token)) | safe}"
style="background-color: #875A7B; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
Start Survey
</a>
</div>
Thanks for your participation!
Please answer the appraisal for ${format_date(object.deadline)}.<br/><br/>
Thank you for your participation.
</p>
</div>
</field>
+1 -1
View File
@@ -341,7 +341,7 @@ class Survey(models.Model):
if self.stage_id.closed:
raise UserError(_("You cannot send invitations for closed surveys."))
template = self.env.ref('survey.email_template_survey', raise_if_not_found=False)
template = self.env.ref('survey.mail_template_user_input_invite', raise_if_not_found=False)
local_context = dict(
self.env.context,
+25 -51
View File
@@ -36,7 +36,7 @@ class SurveyInvite(models.TransientModel):
string='Attachments')
template_id = fields.Many2one(
'mail.template', 'Use template', index=True,
domain="[('model', '=', 'survey.survey')]")
domain="[('model', '=', 'survey.user_input')]")
# origin
email_from = fields.Char('From', default=_get_default_from, help="Email address of the sender.")
author_id = fields.Many2one(
@@ -108,48 +108,22 @@ class SurveyInvite(models.TransientModel):
_('The following recipients have no user account: %s. You should create user accounts for them or allow external signup in configuration.' %
(','.join(invalid_partners.mapped('name')))))
@api.onchange('template_id', 'survey_id')
@api.onchange('template_id')
def _onchange_template_id(self):
""" UPDATE ME """
to_render_fields = [
'subject', 'body_html',
'email_from', 'reply_to',
'partner_to', 'email_to', 'email_cc',
'attachment_ids',
'mail_server_id'
]
returned_fields = to_render_fields + ['partner_ids', 'attachments']
for wizard in self:
if wizard.template_id:
values = {}
if self.template_id:
self.subject = self.template_id.subject
self.body = self.template_id.body_html
template_values = wizard.template_id.generate_email([wizard.survey_id.id], fields=to_render_fields)[wizard.survey_id.id]
values = dict((field, template_values[field]) for field in returned_fields if template_values.get(field))
values['body'] = values.pop('body_html', '')
# transform attachments into attachment_ids; not attached to the document because this will
# be done further in the posting process, allowing to clean database if email not send
Attachment = self.env['ir.attachment']
for attach_fname, attach_datas in values.pop('attachments', []):
data_attach = {
'name': attach_fname,
'datas': attach_datas,
'datas_fname': attach_fname,
'res_model': 'mail.compose.message', # TDE CHECKME
'res_id': 0,
'type': 'binary', # override default_type from context, possibly meant for another model!
}
values.setdefault('attachment_ids', list()).append(Attachment.create(data_attach).id)
else:
default_values = self.default_get(returned_fields)
values = dict((key, default_values[key]) for key in returned_fields if key in default_values)
# This onchange should return command instead of ids for x2many field.
# ORM handle the assignation of command list on new onchange (api.v8),
# this force the complete replacement of x2many field with
# command and is compatible with onchange api.v7
values = self._convert_to_write(values)
wizard.update(values)
@api.model
def create(self, values):
if values.get('template_id') and not (values.get('body') or values.get('subject')):
template = self.env['mail.template'].browse(values['template_id'])
if not values.get('subject'):
values['subject'] = template.subject
if not values.get('body'):
values['body'] = template.body_html
return super(SurveyInvite, self).create(values)
#------------------------------------------------------
# Wizard validation and send
@@ -182,24 +156,29 @@ class SurveyInvite(models.TransientModel):
answers |= existing_answers
for new_partner in partners - partners_done:
answers |= self.survey_id._create_answer(partner=new_partner, deadline=self.deadline)
answers |= self.survey_id._create_answer(partner=new_partner, **self._get_answers_values())
for new_email in [email for email in emails if email not in emails_done]:
answers |= self.survey_id._create_answer(email=new_email, deadline=self.deadline)
answers |= self.survey_id._create_answer(email=new_email, **self._get_answers_values())
return answers
def _get_answers_values(self):
return {
'deadline': self.deadline,
}
def _send_mail(self, answer):
""" Create mail specific for recipient containing notably its access token """
url = '%s?token=%s' % (self.survey_id.public_url, answer.token)
subject = self.env['mail.template']._render_template(self.subject, 'survey.user_input', answer.id, post_process=True)
body = self.env['mail.template']._render_template(self.body, 'survey.user_input', answer.id, post_process=True)
# post the message
mail_values = {
'email_from': self.email_from,
'author_id': self.author_id.id,
'model': None,
'res_id': None,
'subject': self.subject,
'body_html': self.body.replace("__URL__", url),
'subject': subject,
'body_html': body,
'attachment_ids': [(4, att.id) for att in self.attachment_ids],
'auto_delete': True,
}
@@ -233,11 +212,6 @@ class SurveyInvite(models.TransientModel):
self.ensure_one()
Partner = self.env['res.partner']
# check if __URL__ is in the text
if self.body.find("__URL__") < 0:
raise UserError(_("The content of the text don't contain '__URL__'. \
__URL__ is automaticaly converted into the special url of the survey."))
# compute partners and emails, try to find partners for given emails
valid_partners = self.partner_ids
valid_emails = []