[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:
@@ -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):
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user