[IMP] email_template: added an option to automatically generate
recipients instead of using template-based values. This should be the default way of using templates actually, to avoid confusion with mako, ill-defined templates, ... email_template code has been updated to handle recipient_ids when creating an email, depending on its generated template values or default recipients. mail_compose_message has also been updated, delegating the calculation of recipient when having a template to the template itself, using some context keys to force the use of partners instead of email_to and email_cc. Also updated email_template form view to be a bit less confusing. bzr revid: tde@openerp.com-20140325140324-bljvybigk3zv5ugm
This commit is contained in:
parent
73bebb6563
commit
97d49659d0
|
@ -231,6 +231,11 @@ class email_template(osv.osv):
|
|||
'email_from': fields.char('From',
|
||||
help="Sender address (placeholders may be used here). If not set, the default "
|
||||
"value will be the author's email alias if configured, or email address."),
|
||||
'use_default_to': fields.boolean(
|
||||
'Default recipients',
|
||||
help="Default recipients of the record:\n"
|
||||
"- partner (using id on a partner or the partner_id field) OR\n"
|
||||
"- email (using email_from or email field)"),
|
||||
'email_to': fields.char('To (Emails)', help="Comma-separated recipient addresses (placeholders may be used here)"),
|
||||
'partner_to': fields.char('To (Partners)',
|
||||
help="Comma-separated ids of recipient partners (placeholders may be used here)",
|
||||
|
@ -386,6 +391,42 @@ class email_template(osv.osv):
|
|||
})
|
||||
return {'value': result}
|
||||
|
||||
def generate_recipients_batch(self, cr, uid, results, template_id, res_ids, context=None):
|
||||
"""Generates the recipients of the template. Default values can ben generated
|
||||
instead of the template values if requested by template or context.
|
||||
Emails (email_to, email_cc) can be transformed into partners if requested
|
||||
in the context. """
|
||||
if context is None:
|
||||
context = {}
|
||||
template = self.browse(cr, uid, template_id, context=context)
|
||||
|
||||
if template.use_default_to or context.get('tpl_force_default_to'):
|
||||
if template.model and hasattr(self.pool[template.model], 'message_get_default_recipients'):
|
||||
default_recipients = self.pool[template.model].message_get_default_recipients(cr, uid, res_ids, context=context)
|
||||
elif template.model:
|
||||
ctx = dict(context, thread_model=template.model)
|
||||
default_recipients = self.pool['mail.thread'].message_get_default_recipients(cr, uid, res_ids, context=ctx)
|
||||
else:
|
||||
default_recipients = {}
|
||||
for res_id, recipients in default_recipients:
|
||||
results[res_id].pop('partner_to')
|
||||
results[res_id].update(default_recipients)
|
||||
|
||||
for res_id, values in results.iteritems():
|
||||
partner_ids = values.get('partner_ids', list())
|
||||
if context and context.get('tpl_partners_only'):
|
||||
mails = tools.email_split(values.pop('email_to', '')) + tools.email_split(values.pop('email_cc', ''))
|
||||
for mail in mails:
|
||||
partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context)
|
||||
partner_ids.append(partner_id)
|
||||
partner_to = values.pop('partner_to', '')
|
||||
if partner_to:
|
||||
# placeholders could generate '', 3, 2 due to some empty field values
|
||||
tpl_partner_ids = [pid for pid in partner_to.split(',') if pid]
|
||||
partner_ids += self.pool['res.partner'].exists(cr, SUPERUSER_ID, tpl_partner_ids, context=context)
|
||||
results[res_id]['partner_ids'] = partner_ids
|
||||
return results
|
||||
|
||||
def generate_email_batch(self, cr, uid, template_id, res_ids, context=None, fields=None):
|
||||
"""Generates an email from the template for given the given model based on
|
||||
records given by res_ids.
|
||||
|
@ -420,14 +461,18 @@ class email_template(osv.osv):
|
|||
context=context)
|
||||
for res_id, field_value in generated_field_values.iteritems():
|
||||
results.setdefault(res_id, dict())[field] = field_value
|
||||
# compute recipients
|
||||
results = self.generate_recipients_batch(cr, uid, results, template.id, template_res_ids, context=context)
|
||||
# update values for all res_ids
|
||||
for res_id in template_res_ids:
|
||||
values = results[res_id]
|
||||
# body: add user signature, sanitize
|
||||
if 'body_html' in fields and template.user_signature:
|
||||
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
|
||||
values['body_html'] = tools.append_content_to_html(values['body_html'], signature)
|
||||
if values.get('body_html'):
|
||||
values['body'] = tools.html_sanitize(values['body_html'])
|
||||
# technical settings
|
||||
values.update(
|
||||
mail_server_id=template.mail_server_id.id or False,
|
||||
auto_delete=template.auto_delete,
|
||||
|
@ -485,16 +530,7 @@ class email_template(osv.osv):
|
|||
values = self.generate_email(cr, uid, template_id, res_id, context=context)
|
||||
if not values.get('email_from'):
|
||||
raise osv.except_osv(_('Warning!'), _("Sender email is missing or empty after template rendering. Specify one to deliver your message"))
|
||||
# process partner_to field that is a comma separated list of partner_ids -> recipient_ids
|
||||
# NOTE: only usable if force_send is True, because otherwise the value is
|
||||
# not stored on the mail_mail, and therefore lost -> fixed in v8
|
||||
values['recipient_ids'] = []
|
||||
partner_to = values.pop('partner_to', '')
|
||||
if partner_to:
|
||||
# placeholders could generate '', 3, 2 due to some empty field values
|
||||
tpl_partner_ids = [pid for pid in partner_to.split(',') if pid]
|
||||
values['recipient_ids'] += [(4, pid) for pid in self.pool['res.partner'].exists(cr, SUPERUSER_ID, tpl_partner_ids, context=context)]
|
||||
|
||||
values['recipient_ids'] = [(4, pid) for pid in values.get('partner_ids', list())]
|
||||
attachment_ids = values.pop('attachment_ids', [])
|
||||
attachments = values.pop('attachments', [])
|
||||
msg_id = mail_mail.create(cr, uid, values, context=context)
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/><h1><field name="name" required="1"/></h1>
|
||||
<label for="model_id"/><field name="model_id" required="1" on_change="onchange_model_id(model_id)" class="oe_inline"/>
|
||||
<group>
|
||||
<field name="model_id" required="1" on_change="onchange_model_id(model_id)"/>
|
||||
<field name="model" invisible="1"/>
|
||||
</group>
|
||||
</div>
|
||||
<div class="oe_right oe_button_box" name="buttons">
|
||||
<field name="ref_ir_act_window" invisible="1"/>
|
||||
|
@ -25,25 +27,40 @@
|
|||
context="{'template_id':active_id}"/>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Mailing Template">
|
||||
<group>
|
||||
<page string="Content">
|
||||
<label for="subject"/>
|
||||
<h2 style="display: inline-block;"><field name="subject" placeholder="Subject (placeholders may be used here)"/></h2>
|
||||
<field name="body_html"/>
|
||||
<field name="attachment_ids" widget="many2many_binary"/>
|
||||
</page>
|
||||
<page string="Email Configuration">
|
||||
<group>
|
||||
<field name="email_from"
|
||||
placeholder="Override author's email"/>
|
||||
<field name="email_to"
|
||||
<field name="use_default_to"/>
|
||||
<field name="email_to" attrs="{'invisible': [('use_default_to', '=', True)]}"
|
||||
placeholder="Comma-separated recipient addresses"/>
|
||||
<field name="partner_to"
|
||||
<field name="partner_to" attrs="{'invisible': [('use_default_to', '=', True)]}"
|
||||
placeholder="Comma-separated ids of recipient partners"/>
|
||||
<field name="email_cc"
|
||||
<field name="email_cc" attrs="{'invisible': [('use_default_to', '=', True)]}"
|
||||
placeholder="Comma-separated carbon copy recipients addresses"/>
|
||||
<field name="reply_to"
|
||||
placeholder="Preferred reply address"/>
|
||||
<field name="subject"
|
||||
placeholder="Subject (placeholders may be used here)"/>
|
||||
<field name="user_signature" string="Author Signature (mass mail only)"/>
|
||||
</group>
|
||||
<group class="oe_edit_only">
|
||||
<h3 colspan="2">Dynamic placeholder generator</h3>
|
||||
</page>
|
||||
<page string="Advanced Settings">
|
||||
<group>
|
||||
<field name="lang"/>
|
||||
<field name="mail_server_id"/>
|
||||
<field name="auto_delete"/>
|
||||
<field name="report_template" domain="[('model','=',model)]"/>
|
||||
<field name="report_name" class="oe_inline"
|
||||
attrs="{'invisible':[('report_template','=',False)]}"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Dynamic Placeholder Generator">
|
||||
<group>
|
||||
<field name="model_object_field"
|
||||
domain="[('model_id','=',model_id),('ttype','!=','one2many'),('ttype','!=','many2many')]"
|
||||
on_change="onchange_sub_model_object_value_field(model_object_field)"/>
|
||||
|
@ -56,21 +73,6 @@
|
|||
on_change="onchange_sub_model_object_value_field(model_object_field,sub_model_object_field,null_value)"/>
|
||||
<field name="copyvalue"/>
|
||||
</group>
|
||||
</group>
|
||||
<h3>Body</h3>
|
||||
<field name="body_html" width="250" height="450"
|
||||
placeholder="Rich-text/HTML content of the message (placeholders may be used here)"/>
|
||||
<field name="attachment_ids" widget="many2many_binary"/>
|
||||
</page>
|
||||
<page string="Advanced Settings">
|
||||
<group>
|
||||
<field name="lang"/>
|
||||
<field name="mail_server_id"/>
|
||||
<field name="auto_delete"/>
|
||||
<field name="report_template" domain="[('model','=',model)]"/>
|
||||
<field name="report_name" class="oe_inline"
|
||||
attrs="{'invisible':[('report_template','=',False)]}"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
|
@ -85,17 +87,20 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Templates" version="7.0">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name"/><field name="name" required="1" class="oe_inline"/><br />
|
||||
<label for="model_id"/><field name="model_id" required="1" class="oe_inline"
|
||||
options="{'no_open': True, 'no_create': True}"
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" required="True"/>
|
||||
<field name="model_id" required="1" options="{'no_open': True, 'no_create': True}"
|
||||
on_change="onchange_model_id(model_id)"/>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<div class="oe_right oe_button_box" name="buttons">
|
||||
<button name="%(wizard_email_template_preview)d" string="Preview"
|
||||
type="action" target="new"
|
||||
context="{'template_id':active_id}"/>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Body">
|
||||
<field name="body_html" nolabel="1"/>
|
||||
|
|
|
@ -30,10 +30,11 @@
|
|||
<record id="wizard_email_template_preview" model="ir.actions.act_window">
|
||||
<field name="name">Template Preview</field>
|
||||
<field name="res_model">email_template.preview</field>
|
||||
<field name="src_model">email_template.preview</field>
|
||||
<field name="src_model">email.template</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="email_template_preview_form"/>
|
||||
<field name="auto_refresh" eval="1" />
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'template_id':active_id}</field>
|
||||
|
|
|
@ -157,47 +157,29 @@ class mail_compose_message(osv.TransientModel):
|
|||
# Wizard validation and send
|
||||
#------------------------------------------------------
|
||||
|
||||
def _get_or_create_partners_from_values(self, cr, uid, rendered_values, context=None):
|
||||
""" Check for email_to, email_cc, partner_to """
|
||||
partner_ids = []
|
||||
mails = tools.email_split(rendered_values.pop('email_to', '')) + tools.email_split(rendered_values.pop('email_cc', ''))
|
||||
for mail in mails:
|
||||
partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context)
|
||||
partner_ids.append(partner_id)
|
||||
partner_to = rendered_values.pop('partner_to', '')
|
||||
if partner_to:
|
||||
# placeholders could generate '', 3, 2 due to some empty field values
|
||||
tpl_partner_ids = [pid for pid in partner_to.split(',') if pid]
|
||||
partner_ids += self.pool['res.partner'].exists(cr, SUPERUSER_ID, tpl_partner_ids, context=context)
|
||||
return partner_ids
|
||||
|
||||
def generate_email_for_composer_batch(self, cr, uid, template_id, res_ids, context=None, fields=None):
|
||||
""" Call email_template.generate_email(), get fields relevant for
|
||||
mail.compose.message, transform email_cc and email_to into partner_ids """
|
||||
# filter template values
|
||||
if context is None:
|
||||
context = {}
|
||||
if fields is None:
|
||||
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'mail_server_id']
|
||||
returned_fields = fields + ['attachments']
|
||||
returned_fields = fields + ['partner_ids', 'attachments']
|
||||
values = dict.fromkeys(res_ids, False)
|
||||
|
||||
template_values = self.pool.get('email.template').generate_email_batch(cr, uid, template_id, res_ids, fields=fields, context=context)
|
||||
ctx = dict(context, tpl_partners_only=True)
|
||||
template_values = self.pool.get('email.template').generate_email_batch(cr, uid, template_id, res_ids, fields=fields, context=ctx)
|
||||
for res_id in res_ids:
|
||||
res_id_values = dict((field, template_values[res_id][field]) for field in returned_fields if template_values[res_id].get(field))
|
||||
res_id_values['body'] = res_id_values.pop('body_html', '')
|
||||
|
||||
# transform email_to, email_cc into partner_ids
|
||||
ctx = dict((k, v) for k, v in (context or {}).items() if not k.startswith('default_'))
|
||||
partner_ids = self._get_or_create_partners_from_values(cr, uid, res_id_values, context=ctx)
|
||||
# legacy template behavior: void values do not erase existing values and the
|
||||
# related key is removed from the values dict
|
||||
if partner_ids:
|
||||
res_id_values['partner_ids'] = list(partner_ids)
|
||||
|
||||
values[res_id] = res_id_values
|
||||
return values
|
||||
|
||||
def render_message_batch(self, cr, uid, wizard, res_ids, context=None):
|
||||
""" Override to handle templates. """
|
||||
# generate composer values
|
||||
composer_values = super(mail_compose_message, self).render_message_batch(cr, uid, wizard, res_ids, context)
|
||||
|
||||
# generate template-based values
|
||||
if wizard.template_id:
|
||||
template_values = self.generate_email_for_composer_batch(
|
||||
|
@ -206,10 +188,13 @@ class mail_compose_message(osv.TransientModel):
|
|||
context=context)
|
||||
else:
|
||||
template_values = dict.fromkeys(res_ids, dict())
|
||||
# generate composer values
|
||||
composer_values = super(mail_compose_message, self).render_message_batch(cr, uid, wizard, res_ids, context)
|
||||
|
||||
for res_id in res_ids:
|
||||
if wizard.template_id:
|
||||
# recipients are managed by the template
|
||||
composer_values[res_id].pop('partner_ids')
|
||||
composer_values[res_id].pop('email_to')
|
||||
composer_values[res_id].pop('email_cc')
|
||||
# remove attachments from template values as they should not be rendered
|
||||
template_values[res_id].pop('attachment_ids', None)
|
||||
# update template values by composer values
|
||||
|
|
Loading…
Reference in New Issue