diff --git a/addons/survey/__manifest__.py b/addons/survey/__manifest__.py index 2c2e45bf93d..042076f1f2e 100644 --- a/addons/survey/__manifest__.py +++ b/addons/survey/__manifest__.py @@ -31,7 +31,7 @@ sent mails with personal token for the invitation of the survey. 'views/survey_question_views.xml', 'views/survey_page_views.xml', 'views/survey_templates.xml', - 'wizard/survey_mail_compose_message_views.xml', + 'wizard/survey_invite_views.xml', ], 'demo': [ 'data/survey_demo_user.xml', diff --git a/addons/survey/models/survey_survey.py b/addons/survey/models/survey_survey.py index 65955df273e..b78f947aeef 100644 --- a/addons/survey/models/survey_survey.py +++ b/addons/survey/models/survey_survey.py @@ -302,7 +302,7 @@ class Survey(models.Model): 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', - 'res_model': 'survey.mail.compose.message', + 'res_model': 'survey.invite', 'target': 'new', 'context': local_context, } diff --git a/addons/survey/tests/test_survey.py b/addons/survey/tests/test_survey.py index 2b6d46b14ff..312a566e56a 100644 --- a/addons/survey/tests/test_survey.py +++ b/addons/survey/tests/test_survey.py @@ -132,7 +132,7 @@ class TestSurvey(TransactionCase): 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', - 'res_model': 'survey.mail.compose.message', + 'res_model': 'survey.invite', 'target': 'new', 'context': ctx, }) @@ -150,15 +150,15 @@ class TestSurvey(TransactionCase): def test_07_survey_email_message(self): # Case-1: Executing send_mail with correct data. partner = self.env['res.partner'].create({'name': 'Marie De Cock', 'email': 'marie.de.cock@gmail.com'}) - survey_mail_message = self.env['survey.mail.compose.message'].sudo(self.survey_manager).create({ + survey_mail_message = self.env['survey.invite'].sudo(self.survey_manager).create({ 'survey_id': self.survey1.id, 'public': 'email_public_link', 'body': '__URL__', 'partner_ids': [(4, partner.id)]}) survey_mail_message.send_mail() # Case-2: Executing send_mail with incorrect data. mail_messages = [ - self.env['survey.mail.compose.message'].sudo(self.survey_manager).create({ # Mail Message without __URL__ in body. + self.env['survey.invite'].sudo(self.survey_manager).create({ # Mail Message without __URL__ in body. 'survey_id': self.survey1.id, 'public': 'email_public_link'}), - self.env['survey.mail.compose.message'].sudo(self.survey_manager).create({ # Mail Message without recipents. + self.env['survey.invite'].sudo(self.survey_manager).create({ # Mail Message without recipents. 'survey_id': self.survey1.id, 'public': 'email_public_link', 'body': "__URL__"})] for message in mail_messages: self.assertRaises(UserError, message.send_mail) diff --git a/addons/survey/wizard/__init__.py b/addons/survey/wizard/__init__.py index 09c05c0941a..df860ddab0d 100644 --- a/addons/survey/wizard/__init__.py +++ b/addons/survey/wizard/__init__.py @@ -1,4 +1,4 @@ # -*- encoding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import survey_mail_compose_message +from . import survey_invite diff --git a/addons/survey/wizard/survey_mail_compose_message.py b/addons/survey/wizard/survey_invite.py similarity index 70% rename from addons/survey/wizard/survey_mail_compose_message.py rename to addons/survey/wizard/survey_invite.py index 1f1ab22a77e..4f8f57276cb 100644 --- a/addons/survey/wizard/survey_mail_compose_message.py +++ b/addons/survey/wizard/survey_invite.py @@ -5,6 +5,7 @@ import logging import re import uuid +from email.utils import formataddr from werkzeug import urls from odoo import api, fields, models, _ @@ -17,16 +18,47 @@ emails_split = re.compile(r"[;,\n\r]+") email_validator = re.compile(r"[^@]+@[^@]+\.[^@]+") -class SurveyMailComposeMessage(models.TransientModel): - _name = 'survey.mail.compose.message' - _inherit = 'mail.compose.message' - _description = 'Email composition wizard for Survey' +class SurveyInvite(models.TransientModel): + _name = 'survey.invite' + _description = 'Survey Invitation Wizard' def default_survey_id(self): context = self.env.context if context.get('model') == 'survey.survey': return context.get('res_id') + @api.model + def _get_default_from(self): + if self.env.user.email: + return formataddr((self.env.user.name, self.env.user.email)) + raise UserError(_("Unable to post message, please configure the sender's email address.")) + + @api.model + def _get_default_author(self): + return self.env.user.partner_id + + # composer content + subject = fields.Char('Subject') + body = fields.Html('Contents', default='', sanitize_style=True) + attachment_ids = fields.Many2many( + 'ir.attachment', 'survey_mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', + string='Attachments') + template_id = fields.Many2one( + 'mail.template', 'Use template', index=True, + domain="[('model', '=', 'survey.survey')]") + # origin + email_from = fields.Char('From', default=_get_default_from, help="Email address of the sender.") + author_id = fields.Many2one( + 'res.partner', 'Author', index=True, + ondelete='set null', default=_get_default_author, + help="Author of the message.") + # recipients + partner_ids = fields.Many2many('res.partner', 'survey_mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', string='Existing contacts') + multi_email = fields.Text(string='List of emails', help="This list of emails of recipients will not be converted in contacts.\ + Emails must be separated by commas, semicolons or newline.") + # technical info + mail_server_id = fields.Many2one('ir.mail_server', 'Outgoing mail server') + # survey survey_id = fields.Many2one('survey.survey', string='Survey', default=default_survey_id, required=True) public = fields.Selection([('public_link', 'Share the public web link to your audience.'), ('email_public_link', 'Send by email the public web link to your audience.'), @@ -34,10 +66,6 @@ class SurveyMailComposeMessage(models.TransientModel): string='Share options', default='public_link', required=True) public_url = fields.Char(compute="_compute_survey_url", string="Public url") public_url_html = fields.Char(compute="_compute_survey_url", string="Public HTML web link") - partner_ids = fields.Many2many('res.partner', 'survey_mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', string='Existing contacts') - attachment_ids = fields.Many2many('ir.attachment', 'survey_mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', string='Attachments') - multi_email = fields.Text(string='List of emails', help="This list of emails of recipients will not be converted in contacts.\ - Emails must be separated by commas, semicolons or newline.") date_deadline = fields.Date(string="Deadline to which the invitation to respond is valid", help="Deadline to which the invitation to respond for this survey is valid. If the field is empty,\ the invitation is still valid.") @@ -50,7 +78,7 @@ class SurveyMailComposeMessage(models.TransientModel): @api.model def default_get(self, fields): - res = super(SurveyMailComposeMessage, self).default_get(fields) + res = super(SurveyInvite, self).default_get(fields) context = self.env.context if context.get('active_model') == 'res.partner' and context.get('active_ids'): res.update({'partner_ids': context['active_ids']}) @@ -74,6 +102,49 @@ class SurveyMailComposeMessage(models.TransientModel): emails_checked.sort() self.multi_email = '\n'.join(emails_checked) + @api.onchange('template_id', 'survey_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 = {} + + 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) + #------------------------------------------------------ # Wizard validation and send #------------------------------------------------------ @@ -183,8 +254,6 @@ class SurveyMailComposeMessage(models.TransientModel): partner_list.append({'id': partner.id, 'email': partner.email}) if not len(emails_list) and not len(partner_list): - if wizard.model == 'res.partner' and wizard.res_id: - return False raise UserError(_("Please enter at least one valid recipient.")) for email in emails_list: diff --git a/addons/survey/wizard/survey_mail_compose_message_views.xml b/addons/survey/wizard/survey_invite_views.xml similarity index 88% rename from addons/survey/wizard/survey_mail_compose_message_views.xml rename to addons/survey/wizard/survey_invite_views.xml index 167464896ba..942714e0f43 100644 --- a/addons/survey/wizard/survey_mail_compose_message_views.xml +++ b/addons/survey/wizard/survey_invite_views.xml @@ -1,19 +1,12 @@ - - - - - survey.mail.compose.message.form - survey.mail.compose.message + + survey.invite.view.form + survey.invite
- - - -