diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py index 74a9ae99a4c..4080e62f002 100644 --- a/addons/email_template/email_template.py +++ b/addons/email_template/email_template.py @@ -99,7 +99,7 @@ class email_template(osv.osv): mod_name = False if model_id: mod_name = self.pool.get('ir.model').browse(cr, uid, model_id, context).model - return {'value':{'model': mod_name}} + return {'value': {'model': mod_name}} _columns = { 'name': fields.char('Name'), @@ -320,7 +320,7 @@ class email_template(osv.osv): # Add template attachments for attach in template.attachment_ids: - attachments.append(attach.datas_fname, attach.datas) + attachments.append((attach.datas_fname, attach.datas)) values['attachments'] = attachments return values diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py index 05f8f81d76d..85ab3afc902 100644 --- a/addons/email_template/tests/test_mail.py +++ b/addons/email_template/tests/test_mail.py @@ -19,8 +19,8 @@ # ############################################################################## +import base64 from openerp.tests import common -import tools class test_message_compose(common.TransactionCase): @@ -44,10 +44,12 @@ class test_message_compose(common.TransactionCase): self.build_email_real = self.registry('ir.mail_server').build_email self.registry('ir.mail_server').build_email = self._mock_build_email self.registry('ir.mail_server').send_email = self._mock_smtp_gateway - - # create a 'pigs' group that will be used through the various tests + + # create a 'pigs' and 'bird' groups that will be used through the various tests self.group_pigs_id = self.mail_group.create(self.cr, self.uid, {'name': 'Pigs', 'description': 'Fans of Pigs, unite !'}) + self.group_bird_id = self.mail_group.create(self.cr, self.uid, + {'name': 'Bird', 'description': 'I am angry !'}) def test_00_message_compose_wizard(self): """ Tests designed for the mail.compose.message wizard updated by email_template. """ @@ -55,74 +57,116 @@ class test_message_compose(common.TransactionCase): mail_compose = self.registry('mail.compose.message') self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a.a'}) user_admin = self.res_users.browse(cr, uid, uid) + p_a_id = user_admin.partner_id.id group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) - group_bird_id = self.mail_group.create(cr, uid, {'name': 'Bird', 'description': 'I am angry !'}) - group_bird = self.mail_group.browse(cr, uid, group_bird_id) + group_bird = self.mail_group.browse(cr, uid, self.group_bird_id) - # Create template on mail.group + # Mail data + _subject1 = 'Pigs' + _subject2 = 'Bird' + _body_html1 = 'Fans of Pigs, unite !\n
Admin
\n' + _body_html2 = 'I am angry !\n
Admin
\n' + _attachments = [ + {'name': 'First', 'datas_fname': 'first.txt', 'datas': base64.b64encode('My first attachment')}, + {'name': 'Second', 'datas_fname': 'second.txt', 'datas': base64.b64encode('My second attachment')} + ] + _attachments_test = [('first.txt', 'My first attachment'), ('second.txt', 'My second attachment')] + + # Create template on mail.group, with attachments group_model_id = self.registry('ir.model').search(cr, uid, [('model', '=', 'mail.group')])[0] email_template = self.registry('email.template') email_template_id = email_template.create(cr, uid, {'model_id': group_model_id, 'name': 'Pigs Template', 'subject': '${object.name}', 'body_html': '${object.description}', 'user_signature': True, + 'attachment_ids': [(0, 0, _attachments[0]), (0, 0, _attachments[1])], 'email_to': 'b@b.b c@c.c', 'email_cc': 'd@d.d'}) - # Mail data - _subject1 = 'Pigs' - _subject2 = 'Bird' - _body_text1 = 'Pigs rules' - _body_text_html1 = 'Fans of Pigs, unite !\n
Admin
\n' - _body_text2 = 'I am angry !' - _body_text_html2 = 'I am angry !
Admin
' + # ---------------------------------------- + # CASE1: comment and save as template + # ---------------------------------------- - # CASE1: create in comment + # 1. Comment on pigs + compose_id = mail_compose.create(cr, uid, + {'subject': 'Forget me subject', 'body': '

Dummy body

'}, + {'default_composition_mode': 'comment', 'default_model': 'mail.group', + 'default_res_id': self.group_pigs_id, + 'default_template_id': email_template_id, + 'active_ids': [self.group_pigs_id, self.group_bird_id]}) + compose = mail_compose.browse(cr, uid, compose_id) + + # 2. Save current composition form as a template + mail_compose.save_as_template(cr, uid, [compose_id], context={'default_model': 'mail.group'}) + # Test: email_template subject, body_html, model + last_template_id = email_template.search(cr, uid, [('model', '=', 'mail.group'), ('subject', '=', 'Forget me subject')], limit=1)[0] + self.assertTrue(last_template_id, 'email_template not found for model mail.group, subject Forget me subject') + last_template = email_template.browse(cr, uid, last_template_id) + self.assertEqual(last_template.body_html, '

Dummy body

', 'email_template incorrect body_html') + + # ---------------------------------------- + # CASE2: comment with template, save as template + # ---------------------------------------- + + # 1. Comment on pigs compose_id = mail_compose.create(cr, uid, {'subject': 'Forget me subject', 'body': 'Dummy body'}, {'default_composition_mode': 'comment', 'default_model': 'mail.group', - 'default_res_id': self.group_pigs_id, 'default_use_template': True, - 'active_ids': [self.group_pigs_id, group_bird_id] }) + 'default_res_id': self.group_pigs_id, + 'default_template_id': email_template_id, + 'active_ids': [self.group_pigs_id, self.group_bird_id]}) compose = mail_compose.browse(cr, uid, compose_id) - # Perform 'onchange_template_id' with 'use_template' set - values = mail_compose.onchange_template_id(cr, uid, [], compose.use_template, email_template_id, compose.composition_mode, compose.model, compose.res_id) - compose.write(values.get('value', {}), {'default_composition_mode': 'comment', 'default_model': 'mail.group'}) + # 2. Perform 'toggle_template', to set use_template and use template_id + mail_compose.toggle_template(cr, uid, [compose_id], {'default_composition_mode': 'comment', 'default_model': 'mail.group'}) compose.refresh() message_pids = [partner.id for partner in compose.partner_ids] partner_ids = self.res_partner.search(cr, uid, [('email', 'in', ['b@b.b', 'c@c.c', 'd@d.d'])]) - partners = self.res_partner.browse(cr, uid, partner_ids) - # Test: subject, body, partner_ids + # Test: mail.compose.message: subject, body, content_subtype, partner_ids self.assertEqual(compose.subject, _subject1, 'mail.compose.message subject incorrect') - self.assertEqual(compose.body, _body_text_html1, 'mail.compose.message body incorrect') + self.assertEqual(compose.body, _body_html1, 'mail.compose.message body incorrect') + self.assertEqual(compose.content_subtype, 'html', 'mail.compose.message content_subtype incorrect') self.assertEqual(set(message_pids), set(partner_ids), 'mail.compose.message partner_ids incorrect') + # Test: mail.compose.message: attachments + # Test: mail.message: attachments + for attach in compose.attachment_ids: + self.assertEqual(attach.res_model, 'mail.group', 'mail.message attachment res_model incorrect') + self.assertEqual(attach.res_id, self.group_pigs_id, 'mail.message attachment res_id incorrect') + self.assertIn((attach.name, base64.b64decode(attach.datas)), _attachments_test, + 'mail.message attachment name / data incorrect') - # Perform 'onchange_use_template': use_template is not set anymore - values = mail_compose.onchange_use_template(cr, uid, [], not compose.use_template, compose.template_id, compose.composition_mode, compose.model, compose.res_id) - compose.write(values.get('value', {}), {'default_composition_mode': 'comment', 'default_model': 'mail.group'}) + # 3. Perform 'toggle_template': template is not set anymore + mail_compose.toggle_template(cr, uid, [compose_id], {'default_composition_mode': 'comment', 'default_model': 'mail.group'}) compose.refresh() # Test: subject, body, partner_ids self.assertEqual(compose.subject, False, 'mail.compose.message subject incorrect') self.assertEqual(compose.body, '', 'mail.compose.message body incorrect') - # CASE12 create in mass_mail composition + # ---------------------------------------- + # CASE3: mass_mail with template + # ---------------------------------------- + + # 1. Mass_mail on pigs and bird, with a default_partner_ids set to check he is correctly added compose_id = mail_compose.create(cr, uid, {'subject': 'Forget me subject', 'body': 'Dummy body'}, {'default_composition_mode': 'mass_mail', 'default_model': 'mail.group', - 'default_res_id': -1, 'default_use_template': True, - 'active_ids': [self.group_pigs_id, group_bird_id] }) + 'default_res_id': self.group_pigs_id, + 'default_template_id': email_template_id, + 'default_partner_ids': [p_a_id], + 'active_ids': [self.group_pigs_id, self.group_bird_id]}) compose = mail_compose.browse(cr, uid, compose_id) - # Test 'onchange_template_id' with 'use_template' set - values = mail_compose.onchange_template_id(cr, uid, [], compose.use_template, email_template_id, compose.composition_mode, compose.model, compose.res_id) - print values - # self.assertEqual() - # compose.write(values['value']) - values = mail_compose.onchange_use_template(cr, uid, [], not compose.use_template, compose.template_id, compose.composition_mode, compose.model, compose.res_id) - print values - + # 2. Perform 'toggle_template', to set use_template and use template_id + mail_compose.toggle_template(cr, uid, [compose_id], {'default_composition_mode': 'comment', 'default_model': 'mail.group'}) compose.refresh() + message_pids = [partner.id for partner in compose.partner_ids] + partner_ids = [p_a_id] + # Test: mail.compose.message: subject, body, content_subtype, partner_ids + self.assertEqual(compose.subject, '${object.name}', 'mail.compose.message subject incorrect') + self.assertEqual(compose.body, '${object.description}', 'mail.compose.message body incorrect') + self.assertEqual(compose.content_subtype, 'html', 'mail.compose.message content_subtype incorrect') + self.assertEqual(set(message_pids), set(partner_ids), 'mail.compose.message partner_ids incorrect') - # Post the comment, get created message - mail_compose.send_mail(cr, uid, [compose_id], {'default_res_id': -1, 'active_ids': [self.group_pigs_id, group_bird_id]}) + # 3. Post the comment, get created message + mail_compose.send_mail(cr, uid, [compose_id], {'default_res_id': -1, 'active_ids': [self.group_pigs_id, self.group_bird_id]}) group_pigs.refresh() group_bird.refresh() message_pigs = group_pigs.message_ids[0] @@ -130,9 +174,13 @@ class test_message_compose(common.TransactionCase): # Test: subject, body self.assertEqual(message_pigs.subject, _subject1, 'mail.message subject on Pigs incorrect') self.assertEqual(message_bird.subject, _subject2, 'mail.message subject on Bird incorrect') - self.assertEqual(message_pigs.body, _body_text_html1, 'mail.message body on Pigs incorrect') - self.assertEqual(message_bird.body, _body_text_html2, 'mail.message body on Bird incorrect') - # Test: partner_ids - print message_pigs.partner_ids - print message_pigs.partner_ids - self.assertEqual(len(message_pigs.partner_ids), 6, 'mail.message partner_ids incorrect') \ No newline at end of file + self.assertEqual(message_pigs.body, _body_html1, 'mail.message body on Pigs incorrect') + self.assertEqual(message_bird.body, _body_html2, 'mail.message body on Bird incorrect') + # Test: partner_ids: p_a_id (default) + 3 newly created partners + message_pigs_pids = [partner.id for partner in message_pigs.partner_ids] + message_bird_pids = [partner.id for partner in message_bird.partner_ids] + partner_ids = self.res_partner.search(cr, uid, [('email', 'in', ['b@b.b', 'c@c.c', 'd@d.d'])]) + [p_a_id] + self.assertEqual(len(message_pigs_pids), len(partner_ids), 'mail.message on pigs incorrect number of partner_ids') + self.assertEqual(len(message_bird_pids), len(partner_ids), 'mail.message on bird partner_ids incorrect') + self.assertEqual(set(message_pigs_pids), set(partner_ids), 'mail.message on pigs incorrect number of partner_ids') + self.assertEqual(set(message_bird_pids), set(partner_ids), 'mail.message on bird partner_ids incorrect') diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index 85dfe8bc843..2baef6e6c90 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -19,22 +19,19 @@ # ############################################################################## -import base64 import tools from osv import osv from osv import fields -from tools.translate import _ class mail_compose_message(osv.osv_memory): _inherit = 'mail.compose.message' - _compose_fields = ['body', 'body_html', 'subject', 'partner_ids', 'attachment_ids'] def _get_templates(self, cr, uid, context=None): if context is None: context = {} model = False - email_template_obj= self.pool.get('email.template') + email_template_obj = self.pool.get('email.template') message_id = context.get('default_parent_id', context.get('message_id', context.get('active_id'))) if context.get('default_composition_mode') == 'reply' and message_id: @@ -54,6 +51,9 @@ class mail_compose_message(osv.osv_memory): context = {} result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context) result['template_id'] = context.get('default_template_id', context.get('mail.compose.template_id', False)) + # force html when using templates + if result.get('use_template'): + result['content_subtype'] = 'html' return result _columns = { @@ -67,34 +67,50 @@ class mail_compose_message(osv.osv_memory): - use_template set in mass_mailing: we cannot render, so return the template values - use_template set: return rendered values """ if use_template and template_id and composition_mode == 'mass_mail': - values = self.pool.get('email.template').read(cr, uid, template_id, self._compose_fields, context) + values = self.pool.get('email.template').read(cr, uid, template_id, ['subject', 'body_html'], context) + values.pop('id') elif use_template and template_id: values = self.generate_email_for_composer(cr, uid, template_id, res_id, context=context) + # transform attachments into attachment_ids + values['attachment_ids'] = [] + ir_attach_obj = self.pool.get('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': model, + 'res_id': res_id, + } + values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context)) else: - values = self.default_get(cr, uid, self._compose_fields, context=context) + values = self.default_get(cr, uid, ['body', 'body_html', 'subject', 'partner_ids', 'attachment_ids'], context=context) if values.get('body_html'): values['body'] = values.pop('body_html') values.update(use_template=use_template, template_id=template_id) - return {'value': values} def toggle_template(self, cr, uid, ids, context=None): - """ hit toggle template mode button: calls onchange_use_template to - emulate an on_change, then writes the value to update the form. """ + """ hit toggle template mode button: calls onchange_use_template to + emulate an on_change, then writes the values to update the form. """ for record in self.browse(cr, uid, ids, context=context): onchange_res = self.onchange_use_template(cr, uid, ids, not record.use_template, - record.template_id, record.composition_mode, record.model, record.res_id, context=context)['value'] - record.write(onchange_res.get('value', {})) + record.template_id, record.composition_mode, record.model, record.res_id, context=context).get('value', {}) + # update partner_ids and attachment_ids + onchange_res['partner_ids'] = [(4, partner_id) for partner_id in onchange_res.pop('partner_ids', [])] + onchange_res['attachment_ids'] = [(4, attachment_id) for attachment_id in onchange_res.pop('attachment_ids', [])] + record.write(onchange_res) return True def onchange_use_template(self, cr, uid, ids, use_template, template_id, composition_mode, model, res_id, context=None): """ onchange_use_template (values: True or False). If use_template is - False, we do like an onchange with template_id False for values """ + False, we do as an onchange with template_id False for values """ values = self.onchange_template_id(cr, uid, ids, use_template, template_id, composition_mode, model, res_id, context=context) + # force html when using templates if use_template: - values['content_subtype'] = 'html' + values['value']['content_subtype'] = 'html' return values def save_as_template(self, cr, uid, ids, context=None): @@ -112,7 +128,7 @@ class mail_compose_message(osv.osv_memory): values = { 'name': template_name, 'subject': record.subject or False, - 'body': record.body or False, + 'body_html': record.body or False, 'model_id': model_id or False, 'attachment_ids': [(6, 0, [att.id for att in record.attachment_ids])] } @@ -127,61 +143,29 @@ class mail_compose_message(osv.osv_memory): def generate_email_for_composer(self, cr, uid, template_id, res_id, context=None): """ Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids """ - fields = ['body', 'body_html', 'subject', 'email_to', 'email_cc', 'attachment_ids'] template_values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context) - values = {field: template_values[field] for field in fields if template_values.get(field)} - + # filter template values + fields = ['body', 'body_html', 'subject', 'email_to', 'email_cc', 'attachments'] + values = dict((field, template_values[field]) for field in fields if template_values.get(field)) + values['body'] = values.pop('body_html', '') # transform email_to, email_cc into partner_ids values['partner_ids'] = [] mails = tools.email_split(values.pop('email_to', '') + ' ' + values.pop('email_cc', '')) for mail in mails: - partner_search_ids = self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', mail)], context=context) - if partner_search_ids: - values['partner_ids'].append((4, partner_search_ids[0])) - else: - partner_id = self.pool.get('res.partner').name_create(cr, uid, mail, context=context)[0] - partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context) - values['partner_ids'].append((4, partner_id)) - - # transform attachments into attachment_ids - values['attachment_ids'] = [] - for attach_fname, attach_datas in template_values.get('attachments', []): - data_attach = { - 'name': attach_fname, - 'datas': attach_datas, - 'datas_fname': attach_fname, - 'res_model': model, - 'res_id': res_id, - } - values['attachment_ids'].append((0, 0, data_attach)) - + partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context) + values['partner_ids'].append(partner_id) return values - def render_message(self, cr, uid, wizard, model, res_id, context=None): + def render_message(self, cr, uid, wizard, res_id, context=None): """ Generate an email from the template for given (model, res_id) pair. This method is meant to be inherited by email_template that will produce a more complete dictionary, with email_to, ... """ - # render the template to get the email - fields = ['body', 'body_html', 'subject', 'email_to', 'email_cc', 'partner_ids', 'attachment_ids'] - template_values = self.pool.get('email.template').generate_email(cr, uid, wizard.template_id, res_id, context=context) - template_values = {field: template_values[field] for field in fields if template_values.get(field)} - - # transform email_to, email_cc into partner_ids - partner_ids = [] - mails = tools.email_split(template_values.pop('email_to', '') + ' ' + template_values.pop('email_cc', '')) - for mail in mails: - partner_search_ids = self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', mail)], context=context) - if partner_search_ids: - partner_ids.append((4, partner_search_ids[0])) - else: - partner_id = self.pool.get('res.partner').name_create(cr, uid, mail, context=context)[0] - partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context) - partner_ids.append((4, partner_id)) - + # generate the composer email + values = self.generate_email_for_composer(cr, uid, wizard.template_id, res_id, context=context) # get values to return - email_dict = super(mail_compose_message, self).render_message(cr, uid, wizard, model, res_id, context) - email_dict.update(template_values, partner_ids=partner_ids) + email_dict = super(mail_compose_message, self).render_message(cr, uid, wizard, res_id, context) + email_dict.update(values) return email_dict def render_template(self, cr, uid, template, model, res_id, context=None): diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml index 228dcc2745a..96aaa1cfaae 100644 --- a/addons/email_template/wizard/mail_compose_message_view.xml +++ b/addons/email_template/wizard/mail_compose_message_view.xml @@ -42,10 +42,12 @@