[IMP] mail.compose.message: added basic mass_mail support back. Moved generation into a dedicated method, to be inherited in email_template. Added somes tests in mail to test mass_mailing without email_template.

bzr revid: tde@openerp.com-20120830143549-33sgtd30asvztg2c
This commit is contained in:
Thibault Delavallée
2012-08-30 16:35:49 +02:00
parent 1dce0b1dc4
commit 00fc7d1e88
3 changed files with 104 additions and 63 deletions
+22 -1
View File
@@ -97,7 +97,8 @@ class test_mail(common.TransactionCase):
'alias_model_id': self.mail_group_model_id})
# 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'})
self.group_pigs_id = self.mail_group.create(self.cr, self.uid,
{'name': 'Pigs', 'description': 'Fans of Pigs, unite !'})
def test_00_message_process(self):
cr, uid = self.cr, self.uid
@@ -375,6 +376,26 @@ class test_mail(common.TransactionCase):
self.assertEqual(compose.parent_id.id, msg.id,
'Wizard parent_id is %d; should be %d' % (compose.parent_id.id, msg.id))
# 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': '${object.description}'},
{'default_composition_mode': 'mass_mail', 'default_model': 'mail.group', 'default_res_id': -1,
'active_ids': [self.group_pigs_id]})
compose = mail_compose.browse(cr, uid, compose_id)
# 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')
def test_30_message_read(self):
""" Tests designed for message_read. """
def _simplify_struct(read_dict):
+76 -58
View File
@@ -68,7 +68,7 @@ class mail_compose_message(osv.TransientModel):
result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context)
# get some important values from context
composition_mode = context.get('mail.compose.message.mode')
composition_mode = context.get('default_composition_mode', context.get('mail.compose.message.mode'))
model = context.get('default_model', context.get('active_model'))
res_id = context.get('default_res_id', context.get('active_id'))
active_id = context.get('active_id')
@@ -77,8 +77,10 @@ class mail_compose_message(osv.TransientModel):
# get default values according to the composition mode
if composition_mode in ['reply']:
vals = self.get_message_data(cr, uid, active_id, context=context)
elif composition_mode in ['comment', 'mass_mail'] and model and res_id:
elif composition_mode in ['comment'] and model and res_id:
vals = self.get_record_data(cr, uid, model, res_id, context=context)
elif composition_mode in ['mass_mail'] and model and active_ids:
vals = {'model': model, 'res_id': res_id, 'content_subtype': 'html'}
else:
vals = {'model': model, 'res_id': res_id}
if composition_mode:
@@ -189,91 +191,107 @@ class mail_compose_message(osv.TransientModel):
""" onchange_content_subtype (values: 'plain' or 'html'). This onchange
on the subtype allows to have some specific behavior when switching
between text or html mode.
Basically, subject is reset when going out of html mode.
This method can be overridden for models that want to have their
specific behavior.
"""
specific behavior. """
return {'value': {'content_subtype': value}}
def _verify_partner_email(self, cr, uid, partner_ids, context=None):
""" Verify that selected partner_ids have an email_address defined.
Otherwise throw a warning. """
partner_wo_email_lst = []
for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
if not partner.email:
partner_wo_email_lst.append(partner)
if not partner_wo_email_lst:
return {}
warning_msg = _('The following partners chosen as recipients for the email have no email address linked :')
for partner in partner_wo_email_lst:
warning_msg += '\n- %s' % (partner.name)
return {'warning': {
'title': _('Partners email addresses not found'),
'message': warning_msg }
}
def onchange_partner_ids(self, cr, uid, ids, value, context=None):
""" onchange_partner_ids (value format: [[6, False, [3, 4]]]). The
basic purpose of this method is to check that destination partners
effectively have email addresses. Otherwise a warning is thrown.
"""
partner_ids = value[0][2]
partner_wo_email_lst = []
for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
if not partner.email:
partner_wo_email_lst.append(partner)
if not partner_wo_email_lst:
return {'value': {}}
warning_msg = _('The following partners chosen as recipients for the email have no email address linked :')
for partner in partner_wo_email_lst:
warning_msg += '\n- %s' % (partner.name)
warning = {
'title': _('Partners email addresses not found'),
'message': warning_msg,
}
return {'warning': warning, 'value': {}}
res = {'value': {}}
if not value or not value[0] or not value[0][0] == 6:
return
res.update(self._verify_partner_email(cr, uid, value[0][2], context=context))
return res
def send_mail(self, cr, uid, ids, context=None):
""" Process the wizard content and proceed with sending the related
email(s), rendering any template patterns on the fly if needed. """
if context is None:
context = {}
active_ids = context.get('active_ids')
for wizard in self.browse(cr, uid, ids, context=context):
mass_mail_mode = wizard.composition_mode == 'mass_mail'
attachment = {}
for attach in wizard.attachment_ids:
attachment[attach.datas_fname] = attach.datas and attach.datas or False
# default values, according to the wizard options
subject = wizard.subject if wizard.content_subtype == 'html' else False
partner_ids = [(4, partner.id) for partner in wizard.partner_ids]
body = wizard.body if wizard.content_subtype == 'html' else '<pre>%s</pre>' % tools.ustr(wizard.body_text)
active_model_pool = self.pool.get(wizard.model if wizard.model else 'mail.thread')
#TODO: TDE: WIP: have to check for mass mail and templates - no time anymore today
if context.get('mail.compose.message.mode') == 'mass_mail' and context.get('default_model', False) and context.get('default_res_id', False):
active_model = context.get('default_model', False)
active_model_pool = self.pool.get(active_model)
subject = self.render_template(cr, uid, subject, active_model, active_id)
body = self.render_template(cr, uid, wizard.body, active_model, active_id)
# TODO TDE: find partner_ids
# if email_to: find or create a partner
if values['email_to']:
partner_id = self.pool.get('mail.thread').message_partner_by_email(cr, uid, values['email_to'], context=context)['partner_id']
if not partner_id:
partner_id = self.pool.get('res.partner').name_create(cr, uid, values['email_to'], context=context)
values['partner_ids'] = [partner_id]
# determine the ids we are commenting
if mass_mail_mode:
res_ids = context.get('active_ids', [])
else:
res_ids = [wizard.res_id]
active_model_pool.message_post(cr, uid, res_ids, body=body, subject=subject, msg_type='comment',
attachments=attachment, context=context, partner_ids=partner_ids)
# wizard works in batch mode: [res_id] or active_ids
res_ids = active_ids if mass_mail_mode and wizard.model and active_ids else [wizard.res_id]
for res_id in res_ids:
# default values, according to the wizard options
post_values = {
'subject': wizard.subject if wizard.content_subtype == 'html' else False,
'body': wizard.body if wizard.content_subtype == 'html' else '<pre>%s</pre>' % tools.ustr(wizard.body_text),
'partner_ids': [(4, partner.id) for partner in wizard.partner_ids],
'attachments': [(attach.datas_fname, attach.datas) for attach in wizard.attachment_ids],
}
# mass mailing: render and override default values
if mass_mail_mode and wizard.model:
email_dict = self.render_message(cr, uid, wizard, wizard.model, res_id, context=context)
post_values['subject'] = email_dict.get('subject', False)
post_values['body'] = email_dict.get('body', '')
if email_dict.get('partner_ids'):
post_values['partner_ids'] += [(4, id) for id in email_dict.get('partner_ids')]
if email_dict.get('attachments'):
post_values['attachments'] += [(attach.datas_fname, attach.datas) for attach in email_dict.get('attachments')]
# post the message
active_model_pool.message_post(cr, uid, res_ids, msg_type='comment', context=context, **post_values)
return {'type': 'ir.actions.act_window_close'}
def render_message(self, cr, uid, wizard, model, 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, ...
"""
# TDE: TODO: to move into mail.compose.message in email template
# mails = tools.email_split(email_dict.get('email_to', '')) + tools.email_split(email_dict.get('email_cc', ''))
# for mail in mails:
# partner_search_ids = self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], context=context)
# if partner_search_ids:
# partner_ids.append((4, 0, partner_search_ids[0]))
# else:
# partner_id = self.pool.get('res.partner').name_create(cr, uid, values['email_to'], context=context)
# partner_ids.append((4, 0, partner_id))
return {
'subject': self.render_template(cr, uid, wizard.subject, model, res_id, context),
'body': self.render_template(cr, uid, wizard.body, model, res_id, context),
'partner_ids': [],
'attachment_ids': [],
}
def render_template(self, cr, uid, template, model, res_id, context=None):
"""Render the given template text, replace mako-like expressions ``${expr}``
with the result of evaluating these expressions with an evaluation context
containing:
""" Render the given template text, replace mako-like expressions ``${expr}``
with the result of evaluating these expressions with an evaluation context
containing:
* ``user``: browse_record of the current user
* ``object``: browse_record of the document record this mail is
related to
* ``context``: the context passed to the mail composition wizard
:param str template: the template text to render
:param str model: model name of the document record this mail is related to.
:param int res_id: id of the document record this mail is related to.
:param str template: the template text to render
:param str model: model name of the document record this mail is related to.
:param int res_id: id of the document record this mail is related to.
"""
if context is None:
context = {}
@@ -7,6 +7,7 @@
<field name="arch" type="xml">
<form string="Compose Email" version="7.0">
<group>
<field name="composition_mode" invisible="1"/>
<field name="model" invisible="1"/>
<field name="res_id" invisible="1"/>
<field name="author_id"/>
@@ -38,11 +39,11 @@
<field name="arch" type="xml">
<form string="Compose Email" version="7.0" >
<group>
<!-- truly invisible fields for control and options -->
<field name="composition_mode" colspan="2" nolabel="1" invisible="1"/>
<field name="model" colspan="2" nolabel="1" invisible="1"/>
<field name="res_id" colspan="2" nolabel="1" invisible="1"/>
<field name="parent_id" colspan="2" nolabel="1" invisible="1"/>
<!-- truly invisible fields for control and options -->
<field name="content_subtype" colspan="2" nolabel="1" invisible="1"/>
<!-- visible wizard -->
<field name="subject" colspan="2" nolabel="1" placeholder="Subject..."
@@ -63,14 +64,15 @@
class="oe_mail_compose_message_attachment_ids"/>
<!-- void div to display attachments, Chatter-controlled -->
<div colspan="2" class="oe_mail_compose_message_attachments"/>
<!-- buttons, mostly Chatter-controlled -->
<!-- buttons, with as few Chatter logic as possible -->
<div>
<button name="send_mail" string="Post" type="object"
class="oe_mail_compose_message_button_send"/>
</div>
<div class='oe_mail_compose_message_icons'>
<button icon="/mail/static/src/img/attachment.png" name="dummy"
<button icon="/mail/static/src/img/attachment.png"
class="oe_mail_compose_message_attachment" string=""
name="dummy"
help="Add an attachment"/>
<button icon="/mail/static/src/img/formatting.png"
class="oe_mail_compose_message_formatting" string=""
@@ -100,6 +102,6 @@
target="new"
key2="client_action_multi"
id="base.action_partner_mass_mail"
context="{'mail.compose.message.mode':'mass_mail'}"/>
context="{'default_composition_mode': 'mass_mail'}"/>
</data>
</openerp>