[IMP] email_template: another pass of cleanup (wip)

bzr revid: odo@openerp.com-20110825122725-mc1zx2f3ck9xr6g9
This commit is contained in:
Olivier Dony 2011-08-25 14:27:25 +02:00
parent b0bed63351
commit 0b0aa95cfe
8 changed files with 268 additions and 345 deletions

View File

@ -19,7 +19,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
import mako_template
import email_template
import wizard

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-2010 OpenERP SA (<http://www.openerp.com>)
# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -21,26 +21,44 @@
##############################################################################
{
"name" : "Email Template for OpenERP",
"version" : "0.7 RC",
"name" : "Email Templates",
"version" : "1.1",
"author" : "Openlabs",
"website" : "http://openerp.com",
"category" : "Tools",
'complexity': "expert",
"depends" : ['mail'],
"description": """
Email Template is extraction of Power Email basically just to send emails.
==========================================================================
Email Templating (simplified version of the original Power Email by Openlabs)
=============================================================================
You can define email accounts(server, port, mail format - HTML/Text/Both)
and email templates (resource, recipient, subject, body, attachments).
Lets you design complete email templates related to any OpenERP document (Sale
Orders, Invoices and so on), including sender, recipient, subject, body (HTML and
Text). You may also automatically attach files to your templates, or print and
attach a report.
For advanced use, the templates may include dynamic attributes of the document
they are related to. For example, you may use the name of a Partner's country
when writing to them, also providing a safe default in case the attribute is
not defined. Each template contains a built-in assistant to help with the
inclusion of these dynamic values.
If you enable the option, a composition assistant will also appear in the sidebar
of the OpenERP documents to which the template applies (e.g. Invoices).
This serves as a quick way to send a new email based on the template, after
reviewing and adapting the contents, if needed.
This composition assistant will also turn into a mass mailing system when called
for multiple documents at once.
These email templates are also at the heart of the marketing campaign system
(see the ``marketing_campaign`` application), if you need to automate larger
campaigns on any OpenERP document.
Technical note: only the templating system of the original Power Email by
Openlabs was kept
For each email template, you can have OpenERP generate a Wizard Action / Button
that will be related to the object. So if you choose to do marketing campaigns
for leads, the action will be added to the right side panel of the Lead form.
""",
"init_xml": [],
"update_xml": [
"data": [
'wizard/email_template_preview_view.xml',
'email_template_view.xml',
'wizard/email_compose_message_view.xml',

View File

@ -20,136 +20,146 @@
#
##############################################################################
import base64
import mako_template
import netsvc
from osv import osv
from osv import fields
import base64
import netsvc
from tools.translate import _
class email_template(osv.osv):
"Templates for sending Email"
_inherit = 'email.message.common'
_name = "email.template"
_description = 'Email Templates for Models'
try:
from mako.template import Template as MakoTemplate
except ImportError:
logging.getLogger('init').warning("email_template: mako templates not available, templating features will not work!")
def get_template_value(self, cr, uid, message=None, model=None, record_id=None, context=None):
import mako_template
return mako_template.get_value(cr, uid, message=message, model=model, record_id=record_id, context=context)
class email_template(osv.osv):
"Templates for sending email"
_inherit = 'mail.message'
_name = "email.template"
_description = 'Email Templates'
def render_template(self, cr, uid, template, model, res_id, context=None):
"""Render the given template text, replace mako 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.
"""
if not template: return u""
try:
template = tools.ustr(template)
record = self.pool.get(model).browse(cr, uid, res_id, context=context)
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
result = MakoTemplate(template).render_unicode(object=record,
user=user,
context=context,
format_exceptions=True)
if result == u'False':
result = u''
return result
except Exception:
logging.exception("failed to render mako template value %r", template)
return u""
def get_email_template(self, cr, uid, template_id=False, record_id=None, context=None):
"Return Template Object"
if context is None:
context = {}
if not template_id:
return False
template = self.browse(cr, uid, int(template_id), context)
lang = self.get_template_value(cr, uid, template.lang, template.model, record_id, context)
lang = self.render_template(cr, uid, template.lang, template.model, record_id, context)
if lang:
# Use translated template if necessary
ctx = context.copy()
ctx['lang'] = lang
template = self.browse(cr, uid, template.id, ctx)
else:
template = self.browse(cr, uid, int(template_id), context)
return template
def onchange_model_id(self, cr, uid, ids, model_id, context=None):
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}}
def _lang_get(self, cr, uid, context={}):
obj = self.pool.get('res.lang')
ids = obj.search(cr, uid, [], context=context)
res = obj.read(cr, uid, ids, ['code', 'name'], context)
return [(r['code'], r['name']) for r in res] + [('','')]
return {'value':{'model': mod_name}}
_columns = {
'name': fields.char('Name', size=250),
'model_id':fields.many2one('ir.model', 'Resource'),
'model': fields.related('model_id', 'model', string='Model', type="char", size=128, store=True, readonly=True),
'lang': fields.selection(_lang_get, 'Language', size=5, help="The default language for the email."
" Placeholders can be used here. "
"eg. ${object.partner_id.lang}"),
'subject':fields.char(
'Subject',
size=200,
help="The subject of email."
" Placeholders can be used here.",
translate=True),
'user_signature':fields.boolean(
'Signature',
help="the signature from the User details"
" will be appended to the mail"),
'report_name':fields.char(
'Report Filename',
size=200,
help="Name of the generated report file. Placeholders can be used in the filename. eg: 2009_SO003.pdf",
translate=True),
'report_template':fields.many2one(
'ir.actions.report.xml',
'Report to send'),
'attachment_ids': fields.many2many(
'ir.attachment',
'email_template_attachment_rel',
'email_template_id',
'attachment_id',
'Attached Files',
help="You may attach existing files to this template, "
"so they will be added in all emails created from this template"),
'ref_ir_act_window':fields.many2one(
'ir.actions.act_window',
'Window Action',
help="Action that will open this email template on Resource records",
readonly=True),
'ref_ir_value':fields.many2one(
'ir.values',
'Wizard Button',
help="Button in the side bar of the form view of this Resource that will invoke the Window Action",
readonly=True),
'model_object_field':fields.many2one(
'ir.model.fields',
string="Field",
help="Select the field from the model you want to use."
"\nIf it is a relationship field you will be able to "
"choose the nested values in the box below\n(Note:If "
"there are no values make sure you have selected the"
" correct model)"),
'sub_object':fields.many2one(
'ir.model',
'Sub-model',
help='When a relation field is used this field'
' will show you the type of field you have selected'),
'sub_model_object_field':fields.many2one(
'ir.model.fields',
'Sub Field',
help="When you choose relationship fields "
"this field will specify the sub value you can use."),
'null_value':fields.char(
'Null Value',
help="This Value is used if the field is empty",
size=50),
'copyvalue':fields.char(
'Expression',
size=100,
help="Copy and paste the value in the "
"location you want to use a system value."),
'model_id': fields.many2one('ir.model', 'Related document model'),
'lang': fields.char('Language code', size=250,
help="Optional translation language to select when sending out an email. "
"If not set, the english version will be used. "
"This should usually be a placeholder expression "
"that provides the appropriate language code, e.g. "
"${object.partner_id.lang.code}."),
'user_signature': fields.boolean('Signature',
help="If checked, the user's signature will be appended to the text version "
"of the message"),
'report_name': fields.char('Report Filename', size=200, translate=True,
help="Name to use for the generated report file (may contain placeholders)\n"
"The extension can be omitted and will then come from the report type."),
'report_template':fields.many2one('ir.actions.report.xml', 'Optional report to print and attach'),
'ref_ir_act_window':fields.many2one('ir.actions.act_window', 'Sidebar action', readonly=True,
help="Sidebar action to make this template available on records "
"of the related document model"),
'ref_ir_value':fields.many2one('ir.values', 'Sidebar button', readonly=True,
help="Sidebar button to open the sidebar action"),
'auto_delete': fields.boolean('Auto Delete', help="Permanently delete emails after sending"),
'model': fields.related('model_id','model', type='char', size=128, string='Object', help="Placeholders can be used here."),
'email_from': fields.char('From', size=128, help="Email From. Placeholders can be used here."),
'email_to': fields.char('To', size=256, help="Email Recipients. Placeholders can be used here."),
'email_cc': fields.char('Cc', size=256, help="Carbon Copy Email Recipients. Placeholders can be used here."),
'email_bcc': fields.char('Bcc', size=256, help="Blind Carbon Copy Email Recipients. Placeholders can be used here."),
'reply_to':fields.char('Reply-To', size=250, help="Placeholders can be used here."),
'body': fields.text('Description', translate=True, help="Placeholders can be used here."),
'body_html': fields.text('HTML', help="Contains HTML version of email. Placeholders can be used here."),
'track_campaign_item': fields.boolean('Resource Tracking',
help="Enable this is you wish to include a special tracking marker "
"in outgoing emails so you can identify replies and link "
"them back to the corresponding resource record. "
"This is useful for CRM leads for example"),
# Overridden mail.message.common fields for technical reasons:
'model': fields.related('model_id','model', type='char', string='Related Document model',
size=128, select=True, store=True, readonly=True),
# we need a separate m2m table to avoid ID collisions with the original mail.message entries
'attachment_ids': fields.many2many('ir.attachment', 'email_template_attachment_rel', 'email_template_id',
'attachment_id', 'Files to attach',
help="You may attach files to this template, to be added to all "
"emails created from this template"),
# Overridden mail.message.common fields to make tooltips more appropriate:
'subject':fields.char('Subject', size=512, translate=True, help="Subject (placeholders may be used here)",),
'email_from': fields.char('From', size=128, help="Sender address (placeholders may be used here)"),
'email_to': fields.char('To', size=256, help="Comma-separated recipient addresses (placeholders may be used here)"),
'email_cc': fields.char('Cc', size=256, help="Carbon copy recipients (placeholders may be used here)"),
'email_bcc': fields.char('Bcc', size=256, help="Blind carbon copy recipients (placeholders may be used here)"),
'reply_to': fields.char('Reply-To', size=250, help="Preferred response address (placeholders may be used here)"),
'body_text': fields.text('Text contents', translate=True, help="Plaintext version of the message (placeholders may be used here)"),
'body_html': fields.text('Rich-text contents', help="Rich-text/HTML version of the message (placeholders may be used here)"),
'message_id': fields.char('Message-Id', size=256, help="Message-ID SMTP header to use in outgoing messages based on this template. "
"Please note that this overrides the 'Resource Tracking' option, "
"so if you simply need to track replies to outgoing emails, enable "
"that option instead.\n"
"Placeholders must be used here, as this value always needs to be unique!"),
# Fake fields used to implement the placeholder assistant
'model_object_field': fields.many2one('ir.model.fields', string="Field",
help="Select target field from the related document model.\n"
"If it is a relationship field you will be able to select "
"a target field at the destination of the relationship."),
'sub_object': fields.many2one('ir.model', 'Sub-model', readonly=True,
help="When a relationship field is selected as first field, "
"this field shows the document model the relationship goes to."),
'sub_model_object_field': fields.many2one('ir.model.fields', 'Sub-field',
help="When a relationship field is selected as first field, "
"this field lets you select the target field within the "
"destination document model (sub-model)."),
'null_value': fields.char('Null value', help="Optional value to use if the target field is empty", size=128),
'copyvalue': fields.char('Expression', size=256, help="Final placeholder expression, to be copy-pasted in the desired template field."),
}
def create_action(self, cr, uid, ids, context=None):
vals = {}
if context is None:
context = {}
action_obj = self.pool.get('ir.actions.act_window')
data_obj = self.pool.get('ir.model.data')
for template in self.browse(cr, uid, ids, context=context):
@ -159,7 +169,7 @@ class email_template(osv.osv):
vals['ref_ir_act_window'] = action_obj.create(cr, uid, {
'name': template.name,
'type': 'ir.actions.act_window',
'res_model': 'email.compose.message',
'res_model': 'mail.compose.message',
'src_model': src_obj,
'view_type': 'form',
'context': "{'mass_mail':True}",
@ -201,16 +211,17 @@ class email_template(osv.osv):
if default is None:
default = {}
default = default.copy()
default['name'] = template.name or '' + '(copy)'
default['name'] = template.name + _('(copy)')
return super(email_template, self).copy(cr, uid, id, default, context)
def build_expression(self, field_name, sub_field_name, null_value):
"""
Returns a template expression based on data provided
@param field_name: field name
@param sub_field_name: sub field name (M2O)
@param null_value: default value if the target value is empty
@return: computed expression
"""Returns a placeholder expression for use in a template field,
based on the values provided in the placeholder assistant.
:param field_name: main field name
:param sub_field_name: sub field name (M2O)
:param null_value: default value if the target value is empty
:return: final placeholder expression
"""
expression = ''
if field_name:
@ -221,78 +232,6 @@ class email_template(osv.osv):
expression += " or '''%s'''" % null_value
expression += "}"
return expression
#
# def onchange_model_object_field(self, cr, uid, ids, model_object_field, context=None):
# if not model_object_field:
# return {}
# result = {}
# field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
# #Check if field is relational
# if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
# res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
# if res_ids:
# result['sub_object'] = res_ids[0]
# result['copyvalue'] = self.build_expression(False, False, False)
# result['sub_model_object_field'] = False
# result['null_value'] = False
# else:
# #Its a simple field... just compute placeholder
# result['sub_object'] = False
# result['copyvalue'] = self.build_expression(field_obj.name, False, False)
# result['sub_model_object_field'] = False
# result['null_value'] = False
# return {'value':result}
#
# def onchange_sub_model_object_field(self, cr, uid, ids, model_object_field, sub_model_object_field, context=None):
# if not model_object_field or not sub_model_object_field:
# return {}
# result = {}
# field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
# if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
# res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
# sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context)
# if res_ids:
# result['sub_object'] = res_ids[0]
# result['copyvalue'] = self.build_expression(field_obj.name, sub_field_obj.name, False)
# result['sub_model_object_field'] = sub_model_object_field
# result['null_value'] = False
# else:
# #Its a simple field... just compute placeholder
# result['sub_object'] = False
# result['copyvalue'] = self.build_expression(field_obj.name, False, False)
# result['sub_model_object_field'] = False
# result['null_value'] = False
# return {'value':result}
#
#
# def onchange_null_value(self, cr, uid, ids, model_object_field, sub_model_object_field, null_value, template_language, context=None):
# if not model_object_field and not null_value:
# return {}
# result = {}
# field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
# if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
# res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
# sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context)
# if res_ids:
# result['sub_object'] = res_ids[0]
# result['copyvalue'] = self.build_expression(field_obj.name,
# sub_field_obj.name,
# null_value,
# template_language
# )
# result['sub_model_object_field'] = sub_model_object_field
# result['null_value'] = null_value
# else:
# #Its a simple field... just compute placeholder
# result['sub_object'] = False
# result['copyvalue'] = self.build_expression(field_obj.name,
# False,
# null_value,
# template_language
# )
# result['sub_model_object_field'] = False
# result['null_value'] = null_value
# return {'value':result}
def onchange_sub_model_object_value_field(self, cr, uid, ids, model_object_field, sub_model_object_field=False, null_value=None, context=None):
result = {
@ -324,16 +263,23 @@ class email_template(osv.osv):
return {'value':result}
def generate_email(self, cr, uid, template_id, record_id, context=None):
"""
Generates an email from the template for
record record_id of target object
def generate_email(self, cr, uid, template_id, res_id, context=None):
"""Generates an email from the template for given (model, res_id) pair.
:param template_id: id of the template to render.
:param res_id: id of the record to use for rendering the template (model
is taken from template definition)
:returns: a dict containing all relevant fields for creating a new
mail.message entry, with the addition one additional
special key ``attachments`` containing a list of
"""
if context is None:
context = {}
values = {
'subject': False,
'body': False,
'body_text': False,
'body_html': False,
'email_from': False,
'email_to': False,
'email_cc': False,
'email_bcc': False,
@ -341,70 +287,87 @@ class email_template(osv.osv):
'auto_delete': False,
'model': False,
'res_id': False,
'smtp_server_id': False,
'attachment': False,
'mail_server_id': False,
'attachments': False,
'attachment_ids': False,
'message_id': False,
'state': 'outgoing',
}
if not template_id:
return values
report_xml_pool = self.pool.get('ir.actions.report.xml')
template = self.get_email_template(cr, uid, template_id, record_id, context)
def _get_template_value(field):
if context.get('mass_mail', False): # Mass Mail: Gets original template values for multiple email change
return getattr(template, field)
else:
return self.get_template_value(cr, uid, getattr(template, field), template.model, record_id, context=context)
template = self.get_email_template(cr, uid, template_id, res_id, context)
body = _get_template_value('body')
for field in ['subject', 'body_text', 'body_html', 'email_from',
'email_to', 'email_cc', 'email_bcc', 'reply_to',
'message_id']:
values[field] = self.render_template(cr, uid, getattr(template, field),
template.model, res_id, context=context) \
or False
#Use signatures if allowed
if template.user_signature:
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
body += '\n' + signature
values['body_text'] += '\n\n' + signature
values = {
'smtp_server_id' : template.smtp_server_id.id,
'body' : body,
'email_to' : _get_template_value('email_to') or False,
'email_cc' : _get_template_value('email_cc') or False,
'email_bcc' : _get_template_value('email_bcc') or False,
'reply_to' : _get_template_value('reply_to') or False,
'subject' : _get_template_value('subject') or False,
'auto_delete': template.auto_delete,
'model' : template.model or False,
'res_id' : record_id or False,
#'body_html': self.get_template_value(cr, uid, template.body_html, model, record_id, context),
}
values.update(mail_server_id = template.mail_server_id.id or False,
auto_delete = template.auto_delete,
model=template.model,
res_id=res_id or False)
attachment = {}
attachments = {}
# Add report as a Document
if template.report_template:
report_name = template.report_name
reportname = 'report.' + report_xml_pool.browse(cr, uid, template.report_template.id, context).report_name
data = {}
data['model'] = template.model
report_service = 'report.' + report_xml_pool.browse(cr, uid, template.report_template.id, context).report_name
# Ensure report is rendered using template's language
ctx = context.copy()
if template.lang:
ctx['lang'] = self.get_template_value(cr, uid, template.lang, template.model, record_id, context)
service = netsvc.LocalService(reportname)
(result, format) = service.create(cr, uid, [record_id], data, ctx)
ctx['lang'] = self.render_template(cr, uid, template.lang, template.model, res_id, context)
service = netsvc.LocalService(report_service)
(result, format) = service.create(cr, uid, [res_id], {'model': template.model}, ctx)
result = base64.b64encode(result)
if not report_name:
report_name = reportname
report_name = report_name + "." + format
attachment[report_name] = result
report_name = report_service
ext = "." + format
if not report_name.endswith(ext):
report_name += ext
attachments[report_name] = result
# Add document attachments
for attach in template.attachment_ids:
#attach = attahcment_obj.browse(cr, uid, attachment_id, context)
attachment[attach.datas_fname] = base64.decodestring(attach.datas)
values['attachment'] = attachment
# keep the bytes as fetched from the db, base64 encoded
attachments[attach.datas_fname] = attach.datas
values['attachments'] = attachments
return values
email_template()
def send_mail(self, cr, uid, template_id, res_id, context=None):
"""Generates a new mail message for the given template and record,
and schedule it for delivery through the ``mail`` module's scheduler.
:param int template_id: id of the template to render
:param int record_id: id of the record to render the template with
(model is taken from the template)
"""
mail_message = self.pool.get('mail.message')
ir_attachment = self.pool.get('ir.attachment')
template = self.browse(cr, uid, template_id, context)
values = self.generate_email(cr, uid, template_id, res_id, context=context)
attachments = values.pop('attachments')
message_id = mail_message.create(values)
# link attachments
attachment_ids = []
for fname, fcontent in values['attachments'].iteritems():
attachment_data = {
'name': fname,
'datas_fname': fname,
'datas': fcontent,
'res_model': mail_message._name,
'res_id': message_id,
}
if context.has_key('default_type'):
del context['default_type']
attachment_ids.append(ir_attachment.create(cr, uid, attachment_data, context))
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -9,14 +9,13 @@
<field name="arch" type="xml">
<form string="Templates">
<field name="name" required="1"/>
<field name="model_id" required="1"
on_change="onchange_model_id(model_id)"/>
<field name="model_id" required="1" on_change="onchange_model_id(model_id)"/>
<field name="model" invisible="1"/>
<notebook colspan="4">
<page string="Email Details">
<group col="2" colspan="2">
<separator string="Addresses" colspan="2"/>
<field name="smtp_server_id"/>
<field name="email_from" required="1"/>
<field name="email_to" required="1"/>
<field name="email_cc"/>
<field name="email_bcc"/>
@ -26,24 +25,24 @@
<separator string="Options" colspan="2"/>
<field name="lang" colspan="4" />
<field name="user_signature" colspan="4" />
<field name="auto_delete"/>
<field name="track_campaign_item" colspan="4"/>
</group>
<group col="2" colspan="2">
<separator colspan="2" string="Email Content"/>
<field name="subject" colspan="4" required="1"/>
<notebook>
<page string="Body">
<field name="body" colspan="4" nolabel="1"/>
<page string="Body (Text)">
<field name="body_text" colspan="4" nolabel="1"/>
</page>
<!-- <page string="Body (Raw HTML)">
<field name="def_body_html" colspan="4" nolabel="1"/>
<page string="Body (Rich/HTML)">
<field name="body_html" colspan="4" nolabel="1"/>
<label string="Note: This is Raw HTML." colspan="4"/>
</page> -->
</page>
</notebook>
</group>
<group col="4" colspan="2">
<notebook>
<page string="Insert Simple Field">
<page string="Dynamic Values Builder">
<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)"
@ -64,26 +63,38 @@
</group>
</page>
<page string="Advanced">
<field name="mail_server_id"/>
<group colspan="2" col="2">
<group colspan="2" col="2">
<separator string="Actions" colspan="2"/>
<button name="create_action" string="Create Action" type="object" icon="gtk-execute" colspan="2" attrs="{'invisible':[('ref_ir_act_window','!=',False), ('ref_ir_value','!=',False)]}"/>
<field name="ref_ir_act_window"/>
<field name="ref_ir_value"/>
<button name="unlink_action" string="Delete Action" type="object" icon="gtk-delete" colspan="2" attrs="{'invisible':[('ref_ir_act_window','=',False), ('ref_ir_value','=',False)]}"/>
<separator string="Sidebar button" colspan="2"/>
<button name="create_action" string="Add sidebar button" type="object" icon="gtk-execute"
colspan="2" attrs="{'invisible':[('ref_ir_act_window','!=',False), ('ref_ir_value','!=',False)]}"
help="Display a button in the sidebar of related documents to open a composition wizard with this template"
/>
<field name="ref_ir_act_window" attrs="{'invisible':[('ref_ir_act_window','!=',False), ('ref_ir_value','!=',False)]}"/>
<field name="ref_ir_value" attrs="{'invisible':[('ref_ir_act_window','!=',False), ('ref_ir_value','!=',False)]}"/>
<button name="unlink_action" string="Remove sidebar button" type="object" icon="gtk-delete"
colspan="2" attrs="{'invisible':[('ref_ir_act_window','=',False), ('ref_ir_value','=',False)]}"
help="Remove the sidebar button currentlu displayed on related documents"
/>
</group>
<group colspan="2" col="2">
<separator string="Advanced Options" colspan="2"/>
<field name="message_id"/>
<field name="auto_delete"/>
</group>
</group>
<group colspan="2" col="2">
<separator string="Attachments" colspan="2"/>
<notebook>
<page string="Existing files">
<field name="attachment_ids" colspan="4" nolabel="1" height="350"/>
</page>
<page string="Report">
<page string="Attach Report">
<field name="report_template" colspan="4"
domain="[('model','=',model)]"/>
<field name="report_name" colspan="4" />
</page>
<page string="Attach existing files">
<field name="attachment_ids" colspan="4" nolabel="1" height="350"/>
</page>
</notebook>
</group>
</page>

View File

@ -1,60 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
import tools
import pooler
import logging
try:
from mako.template import Template as MakoTemplate
except ImportError:
logging.getLogger('init').warning("module email_template: Mako templates not installed")
def get_value(cr, uid, message=None, model=None, record_id=False, context=None):
"""
returns Messages in Mako Template
"""
pool = pooler.get_pool(cr.dbname)
if message is None:
message = {}
#Returns the computed expression
if message:
try:
message = tools.ustr(message)
record = pool.get(model).browse(cr, uid, record_id, context=context)
env = {
'user': pool.get('res.users').browse(cr, uid, uid, context=context),
'db': cr.dbname
}
templ = MakoTemplate(message, input_encoding='utf-8')
reply = MakoTemplate(message).render_unicode(object=record, peobject=record, env=env, format_exceptions=True)
if reply == 'False':
reply = ''
return reply
except Exception:
logging.exception("can't render %r", message)
return u""
else:
return message
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -22,11 +22,10 @@
from osv import osv
from osv import fields
from tools.translate import _
import binascii
import base64
class email_compose_message(osv.osv_memory):
_name = 'email.compose.message'
_inherit = 'email.compose.message'
class mail_compose_message(osv.osv_memory):
_inherit = 'mail.compose.message'
def _get_templates(self, cr, uid, context=None):
"""
@ -38,8 +37,8 @@ class email_compose_message(osv.osv_memory):
email_temp_pool = self.pool.get('email.template')
model = False
if context.get('message_id'):
message_pool = self.pool.get('email.message')
message_data = message_pool.browse(cr, uid, int(context.get('message_id')), context)
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('active_model', False):
model = context.get('active_model')
@ -52,10 +51,6 @@ class email_compose_message(osv.osv_memory):
'template_id': fields.selection(_get_templates, 'Template'),
}
def get_template_value(self, cr, uid, message, model, resource_id, context=None):
template_pool = self.pool.get('email.template')
return template_pool.get_template_value(cr, uid, message, model, resource_id, context)
def on_change_template(self, cr, uid, ids, template_id, context=None):
if context is None:
context = {}
@ -64,17 +59,17 @@ class email_compose_message(osv.osv_memory):
if template_id:
res_id = context.get('active_id', False)
values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context)
if values['attachment']:
attachment = values['attachment']
if values['attachments']:
attachment = values.pop('attachments')
attachment_obj = self.pool.get('ir.attachment')
for fname, fcontent in attachment.items():
for fname, fcontent in attachment.iteritems():
data_attach = {
'name': fname,
'datas': binascii.b2a_base64(str(fcontent)),
'datas': base64.b64_encode(fcontent),
'datas_fname': fname,
'description': _('Mail attachment'),
'description': fname,
'res_model' : self._name,
'res_id' : ids and ids[0] or False
'res_id' : ids[0] if ids else False
}
att_ids.append(attachment_obj.create(cr, uid, data_attach))
values['attachment_ids'] = att_ids
@ -109,6 +104,5 @@ class email_compose_message(osv.osv_memory):
template_pool.create(cr, uid, values, context=context)
return {'type': 'ir.actions.act_window_close'}
email_compose_message()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -3,8 +3,8 @@
<data>
<record model="ir.ui.view" id="email_compose_message_wizard_inherit_form">
<field name="name">email.compose.message.form</field>
<field name="model">email.compose.message</field>
<field name="name">mail.compose.message.form</field>
<field name="model">mail.compose.message</field>
<field name="type">form</field>
<field name="inherit_id" ref="mail.email_compose_message_wizard_form"/>
<field name="arch" type="xml">

View File

@ -82,19 +82,17 @@ class email_template_preview(osv.osv_memory):
template_id = context.get('template_id', False)
template = template_pool.get_email_template(cr, uid, template_id=template_id, record_id=res_id, context=context)
model = template.model
vals['email_to'] = self.get_template_value(cr, uid, template.email_to, model, res_id, context)
vals['email_cc'] = self.get_template_value(cr, uid, template.email_cc, model, res_id, context)
vals['email_bcc'] = self.get_template_value(cr, uid, template.email_bcc, model, res_id, context)
vals['reply_to'] = self.get_template_value(cr, uid, template.reply_to, model, res_id, context)
vals['subject'] = self.get_template_value(cr, uid, template.subject, model, res_id, context)
description = self.get_template_value(cr, uid, template.body, model, res_id, context) or ''
vals['email_to'] = self.render_template(cr, uid, template.email_to, model, res_id, context)
vals['email_cc'] = self.render_template(cr, uid, template.email_cc, model, res_id, context)
vals['email_bcc'] = self.render_template(cr, uid, template.email_bcc, model, res_id, context)
vals['reply_to'] = self.render_template(cr, uid, template.reply_to, model, res_id, context)
vals['subject'] = self.render_template(cr, uid, template.subject, model, res_id, context)
description = self.render_template(cr, uid, template.body, model, res_id, context) or ''
if template.user_signature:
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
description += '\n' + signature
vals['body'] = description
vals['report_name'] = self.get_template_value(cr, uid, template.report_name, model, res_id, context)
return {'value':vals}
email_template_preview()
vals['report_name'] = self.render_template(cr, uid, template.report_name, model, res_id, context)
return {'value': vals}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: