From 088dc6a3d3327b1f79904d0091ed28d8b5dcc849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 30 Aug 2012 17:51:54 +0200 Subject: [PATCH] [WIP] email_template: WIP on mail.compose.message in email_template. Cleaned a bit the code, the view. Added base for testing mail composer in tests. TODO: handle partners, email_cc, email_to, attachments, ... almost everything. bzr revid: tde@openerp.com-20120830155154-419yn1aj0u6vq8yb --- addons/email_template/tests/__init__.py | 27 ++++ addons/email_template/tests/test_mail.py | 103 ++++++++++++++ .../wizard/mail_compose_message.py | 134 ++++++++---------- .../wizard/mail_compose_message_view.xml | 11 +- 4 files changed, 199 insertions(+), 76 deletions(-) create mode 100644 addons/email_template/tests/__init__.py create mode 100644 addons/email_template/tests/test_mail.py diff --git a/addons/email_template/tests/__init__.py b/addons/email_template/tests/__init__.py new file mode 100644 index 00000000000..d63c5634cc3 --- /dev/null +++ b/addons/email_template/tests/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +from . import test_mail + +checks = [ + test_mail, +] + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py new file mode 100644 index 00000000000..db2168a75d5 --- /dev/null +++ b/addons/email_template/tests/test_mail.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.tests import common +import tools + +class test_message_compose(common.TransactionCase): + + def _mock_smtp_gateway(self, *args, **kwargs): + return True + + def _mock_build_email(self, *args, **kwargs): + self._build_email_args = args + self._build_email_kwargs = kwargs + return self.build_email_real(*args, **kwargs) + + def setUp(self): + super(test_message_compose, self).setUp() + self.mail_group = self.registry('mail.group') + self.mail_mail = self.registry('mail.mail') + self.mail_message = self.registry('mail.message') + self.res_users = self.registry('res.users') + self.res_partner = self.registry('res.partner') + + # Install mock SMTP gateway + 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 + self.group_pigs_id = self.mail_group.create(self.cr, self.uid, + {'name': 'Pigs', 'description': 'Fans of Pigs, unite !'}) + + def test_00_message_compose_wizard(self): + """ Tests designed for the mail.compose.message wizard updated by email_template. """ + cr, uid = self.cr, self.uid + mail_compose = self.registry('mail.compose.message') + self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a'}) + user_admin = self.res_users.browse(cr, uid, uid) + group_model_id = self.registry('ir.model').search(cr, uid, [('model', '=', 'mail.group')])[0] + group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) + + # Create template on mail.group + email_template = self.registry('email.template') + email_template_id = email_template.create(cr, uid, {'model_id': group_model_id, + 'name': 'Pigs Template', 'subject': '${record.name}', + 'body_html': '${object.description}', 'user_signature': True, + 'email_to': 'b@b c@c', 'email_cc': 'd@d'}) + # import pdb + # pdb.set_trace() + + # Mail data + _subject = 'Pigs' + _body_text = 'Pigs rules' + + # 3 - Create in mass_mail composition mode that should work with or without email_template installed + compose_id = mail_compose.create(cr, uid, + {'subject': _subject, 'body': _body_text}, + {'default_composition_mode': 'mass_mail', 'default_model': 'mail.group', + 'default_res_id': -1, 'default_use_template': True, + 'active_ids': [self.group_pigs_id], 'default_template_id': email_template_id}) + compose = mail_compose.browse(cr, uid, compose_id) + # print compose.subject + + + # Try the 'onchange_template_id' + values = mail_compose.onchange_template_id(cr, uid, [], compose.use_template, compose.template_id, compose.composition_mode, compose.res_id) + # print values + values = mail_compose.onchange_use_template(cr, uid, [], not compose.use_template, compose.template_id, compose.composition_mode, compose.res_id) + # print values + + compose.refresh() + + + # # 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_pigs.refresh() + # msg = group_pigs.message_ids[0] + + # # Test: last message on Pigs = last created message + # test_msg = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [], limit=1))[0] + # self.assertEqual(msg.id, test_msg.id, 'Pigs did not receive its mass mailing message') + # # Test: mail.message: subject, body + # self.assertEqual(msg.subject, _subject, 'mail.message subject is incorrect') + # self.assertEqual(msg.body, group_pigs.description, 'mail.message body is incorrect') \ No newline at end of file diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index a05aa232453..7dbb47e8380 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -20,62 +20,62 @@ ############################################################################## import base64 +import tools from osv import osv from osv import fields from tools.translate import _ -import tools - class mail_compose_message(osv.osv_memory): + """ Inherit mail_compose_message to add email template feature in the + message composer. """ + _inherit = 'mail.compose.message' def _get_templates(self, cr, uid, context=None): - """ - Return Email Template of particular Model. - """ + """ Return Email Template of particular Model. """ if context is None: context = {} - record_ids = [] - email_template= self.pool.get('email.template') model = False - if context.get('message_id'): - mail_message = self.pool.get('mail.message') - message_data = mail_message.browse(cr, uid, int(context.get('message_id')), context) - model = message_data.model - elif context.get('mail.compose.target.model') or context.get('active_model'): - model = context.get('mail.compose.target.model', context.get('active_model')) + email_template_obj= self.pool.get('email.template') + + if context.get('default_composition_mode') == 'reply' and context.get('active_id'): + message_data = self.pool.get('mail.message').browse(cr, uid, int(context.get('active_id')), context) + if message_data: + model = message_data.model + else: + model = context.get('default_model', context.get('active_model')) + if model: - record_ids = email_template.search(cr, uid, [('model', '=', model)]) - return email_template.name_get(cr, uid, record_ids, context) + [(False,'')] + record_ids = email_template_obj.search(cr, uid, [('model', '=', model)], context=context) + return email_template_obj.name_get(cr, uid, record_ids, context) + [(False, '')] return [] + def default_get(self, cr, uid, fields, context=None): + """ Override to handle templates. """ + if context is None: + 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)) + return result + _columns = { 'use_template': fields.boolean('Use Template'), - 'template_id': fields.selection(_get_templates, 'Template', - size=-1 # means we want an int db column - ), - } - - _defaults = { - 'template_id' : lambda self, cr, uid, context={} : context.get('mail.compose.template_id', False) + # incredible hack of the day: size=-1 means we want an int db column instead of an str one + 'template_id': fields.selection(_get_templates, 'Template', size=-1), } - def on_change_template(self, cr, uid, ids, use_template, template_id, email_from=None, email_to=None, context=None): - if context is None: - context = {} - values = {} - if template_id: - res_id = context.get('active_id', False) - if context.get('mail.compose.message.mode') == 'mass_mail': - # use the original template values - to be rendered when actually sent - # by super.send_mail() - values = self.pool.get('email.template').read(cr, uid, template_id, self.fields_get_keys(cr, uid), context) + def onchange_template_id(self, cr, uid, ids, use_template, template_id, composition_mode, res_id, context=None): + """ onchange_template_id: read or render the template if set, get back + to default values if not. """ + fields = ['body', 'body_html', 'subject', 'partner_ids', 'email_to', 'email_cc'] + if use_template and template_id: + # use the original template values, to be rendered when actually sent + if composition_mode == 'mass_mail': + values = self.pool.get('email.template').read(cr, uid, template_id, fields, context) + # render the mail as one-shot else: - # render the mail as one-shot values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context) - # get partner_ids back - values['dest_partner_ids'] = values['partner_ids'] # retrofit generated attachments in the expected field format if values['attachments']: attachment = values.pop('attachments') @@ -92,65 +92,57 @@ class mail_compose_message(osv.osv_memory): } att_ids.append(attachment_obj.create(cr, uid, data_attach)) values['attachment_ids'] = att_ids - else: - # restore defaults - values = self.default_get(cr, uid, self.fields_get_keys(cr, uid), context) - values.update(use_template=use_template, template_id=template_id) + else: # restore defaults + values = self.default_get(cr, uid, fields, context=context) + + if values.get('body_html') is not None: + values['body'] = values.get('body_html') + values.update(use_template=use_template, template_id=template_id) return {'value': values} - def template_toggle(self, cr, uid, ids, context=None): + 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. """ for record in self.browse(cr, uid, ids, context=context): - values = {} - use_template = record.use_template - # simulate an on_change on use_template - values.update(self.onchange_use_template(cr, uid, ids, not use_template, context=context)['value']) - record.write(values) - return False + onchange_res = self.onchange_use_template(cr, uid, ids, not record.use_template, context=context)['value'] + record.write(onchange_res) + return True - def onchange_use_template(self, cr, uid, ids, use_template, context=None): - values = {'use_template': use_template} - for record in self.browse(cr, uid, ids, context=context): - if not use_template: - # equivalent to choosing an empty template - onchange_template_values = self.on_change_template(cr, uid, record.id, use_template, - False, email_from=record.email_from, email_to=record.email_to, context=context) - values.update(onchange_template_values['value']) - return {'value': values} + def onchange_use_template(self, cr, uid, ids, use_template, template_id, composition_mode, 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 """ + onchange_template_values = self.onchange_template_id(cr, uid, ids, use_template, + template_id, composition_mode, res_id, context=context) + return onchange_template_values def save_as_template(self, cr, uid, ids, context=None): - if context is None: - context = {} + """ hit save as template button: current form value will be a new + template attached to the current document. """ email_template = self.pool.get('email.template') - model_pool = self.pool.get('ir.model') + ir_model_pool = self.pool.get('ir.model') for record in self.browse(cr, uid, ids, context=context): - model = record.model or context.get('active_model') - model_ids = model_pool.search(cr, uid, [('model', '=', model)]) + model = record.model + model_ids = ir_model_pool.search(cr, uid, [('model', '=', model)]) model_id = model_ids and model_ids[0] or False model_name = '' if model_id: - model_name = model_pool.browse(cr, uid, model_id, context=context).name + model_name = ir_model_pool.browse(cr, uid, model_id, context=context).name template_name = "%s: %s" % (model_name, tools.ustr(record.subject)) values = { 'name': template_name, - 'email_from': record.email_from or False, 'subject': record.subject or False, 'body': record.body or False, - 'email_to': record.email_to or False, - 'email_cc': record.email_cc or False, - 'reply_to': record.reply_to or False, 'model_id': model_id or False, 'attachment_ids': [(6, 0, [att.id for att in record.attachment_ids])] } template_id = email_template.create(cr, uid, values, context=context) - record.write({'template_id': template_id, - 'use_template': True}) + record.write({'template_id': template_id, 'use_template': True}) + return True - # _reopen same wizard screen with new template preselected - return False - - # override the basic implementation def render_template(self, cr, uid, template, model, res_id, context=None): + """ Override of mail.compose.message behavior: use the power of + templates ! """ return self.pool.get('email.template').render_template(cr, uid, template, model, res_id, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml index dff6f4a3ad4..f54ee0d3723 100644 --- a/addons/email_template/wizard/mail_compose_message_view.xml +++ b/addons/email_template/wizard/mail_compose_message_view.xml @@ -10,15 +10,16 @@ -