2011-07-22 16:34:57 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
##############################################################################
|
|
|
|
#
|
|
|
|
# OpenERP, Open Source Management Solution
|
|
|
|
# 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/>
|
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
2012-01-18 11:18:55 +00:00
|
|
|
import ast
|
2011-07-22 16:34:57 +00:00
|
|
|
import re
|
|
|
|
|
|
|
|
import tools
|
|
|
|
from osv import osv
|
|
|
|
from osv import fields
|
|
|
|
from tools.safe_eval import safe_eval as eval
|
|
|
|
from tools.translate import _
|
|
|
|
|
2012-01-09 13:12:05 +00:00
|
|
|
from ..mail_message import to_email
|
|
|
|
|
2011-07-22 16:34:57 +00:00
|
|
|
# main mako-like expression pattern
|
|
|
|
EXPRESSION_PATTERN = re.compile('(\$\{.+?\})')
|
|
|
|
|
2012-07-06 07:38:52 +00:00
|
|
|
class mail_compose_message(osv.TransientModel):
|
2012-06-25 13:42:53 +00:00
|
|
|
"""Generic Email composition wizard. This wizard is meant to be inherited
|
2011-07-22 16:34:57 +00:00
|
|
|
at model and view level to provide specific wizard features.
|
|
|
|
|
|
|
|
The behavior of the wizard can be modified through the use of context
|
|
|
|
parameters, among which are:
|
|
|
|
|
2011-09-06 09:32:28 +00:00
|
|
|
* mail.compose.message.mode: if set to 'reply', the wizard is in
|
2012-07-06 10:11:30 +00:00
|
|
|
reply to a previous message mode and pre-populated with the original
|
|
|
|
quote. If set to 'comment', it means you are writing a new message to
|
|
|
|
be attached to a document. If set to 'mass_mail', the wizard is in
|
|
|
|
mass mailing where the mail details can contain template placeholders
|
|
|
|
that will be merged with actual data before being sent to each
|
|
|
|
recipient.
|
2011-07-22 16:34:57 +00:00
|
|
|
* active_model: model name of the document to which the mail being
|
|
|
|
composed is related
|
|
|
|
* active_id: id of the document to which the mail being composed is
|
|
|
|
related, or id of the message to which user is replying,
|
2011-09-06 09:32:28 +00:00
|
|
|
in case ``mail.compose.message.mode == 'reply'``
|
2011-07-22 16:34:57 +00:00
|
|
|
* active_ids: ids of the documents to which the mail being composed is
|
2011-09-06 09:32:28 +00:00
|
|
|
related, in case ``mail.compose.message.mode == 'mass_mail'``.
|
2011-07-22 16:34:57 +00:00
|
|
|
"""
|
|
|
|
_name = 'mail.compose.message'
|
|
|
|
_inherit = 'mail.message.common'
|
2012-06-25 13:42:53 +00:00
|
|
|
_description = 'Email composition wizard'
|
2011-07-22 16:34:57 +00:00
|
|
|
|
|
|
|
def default_get(self, cr, uid, fields, context=None):
|
2012-07-10 13:06:31 +00:00
|
|
|
""" Overridden to provide specific defaults depending on the context
|
|
|
|
parameters.
|
|
|
|
|
|
|
|
Composition mode
|
|
|
|
- comment: default mode; active_model, active_id = model and ID of a
|
|
|
|
document we are commenting,
|
|
|
|
- reply: active_id = ID of a mail.message to which we are replying.
|
|
|
|
From this message we can find the related model and res_id,
|
|
|
|
- mass_mailing mode: active_model, active_id = model and ID of a
|
|
|
|
document we are commenting,
|
2011-07-22 16:34:57 +00:00
|
|
|
|
|
|
|
:param dict context: several context values will modify the behavior
|
|
|
|
of the wizard, cfr. the class description.
|
|
|
|
"""
|
|
|
|
if context is None:
|
|
|
|
context = {}
|
2012-07-06 10:11:30 +00:00
|
|
|
compose_mode = context.get('mail.compose.message.mode', 'comment')
|
|
|
|
active_model = context.get('active_model')
|
|
|
|
active_id = context.get('active_id')
|
2012-07-10 13:06:31 +00:00
|
|
|
result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context)
|
|
|
|
|
|
|
|
# get default values according to the composition mode
|
|
|
|
vals = {}
|
2012-07-06 10:11:30 +00:00
|
|
|
if compose_mode in ['reply']:
|
|
|
|
vals = self.get_message_data(cr, uid, int(context['active_id']), context=context)
|
|
|
|
elif compose_mode in ['comment', 'mass_mail'] and active_model and active_id:
|
|
|
|
vals = self.get_value(cr, uid, active_model, active_id, context)
|
2011-09-25 01:47:59 +00:00
|
|
|
for field in vals:
|
|
|
|
if field in fields:
|
2012-07-06 07:38:52 +00:00
|
|
|
result[field] = vals[field]
|
2011-09-09 15:55:17 +00:00
|
|
|
|
|
|
|
# link to model and record if not done yet
|
2012-07-06 10:11:30 +00:00
|
|
|
if not result.get('model') and active_model:
|
|
|
|
result['model'] = active_model
|
|
|
|
if not result.get('res_id') and active_id:
|
|
|
|
result['res_id'] = active_id
|
|
|
|
# if result['model'] == 'mail.message' and not result.get('parent_id'):
|
|
|
|
# result['parent_id'] = context.get('active_id')
|
2011-09-09 15:55:17 +00:00
|
|
|
|
2011-09-06 08:00:14 +00:00
|
|
|
# Try to provide default email_from if not specified yet
|
|
|
|
if not result.get('email_from'):
|
2012-07-06 10:11:30 +00:00
|
|
|
current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
2011-09-06 08:00:14 +00:00
|
|
|
result['email_from'] = current_user.user_email or False
|
2012-07-06 07:38:52 +00:00
|
|
|
|
2011-07-22 16:34:57 +00:00
|
|
|
return result
|
|
|
|
|
|
|
|
_columns = {
|
2012-07-06 10:11:30 +00:00
|
|
|
'dest_partner_ids': fields.many2many('res.partner',
|
2012-07-06 07:38:52 +00:00
|
|
|
'email_message_send_partner_rel',
|
2012-07-06 10:11:30 +00:00
|
|
|
'wizard_id', 'partner_id', 'Destination partners',
|
|
|
|
help="When sending emails through the social network composition wizard"\
|
|
|
|
"you may choose to send a copy of the mail to partners."),
|
2011-07-22 16:34:57 +00:00
|
|
|
'attachment_ids': fields.many2many('ir.attachment','email_message_send_attachment_rel', 'wizard_id', 'attachment_id', 'Attachments'),
|
|
|
|
'auto_delete': fields.boolean('Auto Delete', help="Permanently delete emails after sending"),
|
|
|
|
'filter_id': fields.many2one('ir.filters', 'Filters'),
|
|
|
|
}
|
|
|
|
|
|
|
|
def get_value(self, cr, uid, model, res_id, context=None):
|
2012-07-10 15:33:16 +00:00
|
|
|
""" Returns a defaults-like dict with initial values for the composition
|
|
|
|
wizard when sending an email related to the document record
|
|
|
|
identified by ``model`` and ``res_id``.
|
|
|
|
|
|
|
|
The default implementation returns an empty dictionary, and is meant
|
|
|
|
to be overridden by subclasses.
|
|
|
|
|
|
|
|
: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 dict context: several context values will modify the behavior
|
|
|
|
of the wizard, cfr. the class description.
|
2011-07-22 16:34:57 +00:00
|
|
|
"""
|
2012-07-10 15:33:16 +00:00
|
|
|
result = {}
|
|
|
|
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
|
|
|
result.update({
|
|
|
|
'model': model,
|
|
|
|
'res_id': res_id,
|
|
|
|
'email_from': user.user_email or tools.config.get('email_from', False),
|
|
|
|
'body_html': '<br />---<br />' + tools.ustr(user.signature or ''),
|
|
|
|
})
|
|
|
|
return result
|
2011-07-22 16:34:57 +00:00
|
|
|
|
2012-07-13 14:23:33 +00:00
|
|
|
def onchange_email_mode(self, cr, uid, ids, value, model, res_id, context=None):
|
|
|
|
""" email_mode (values: True or False). This onchange on the email mode
|
|
|
|
allows to have some specific behavior when going in email mode, or
|
|
|
|
when going out of email mode.
|
|
|
|
Basically, dest_partner_ids is reset when going out of email
|
|
|
|
mode.
|
|
|
|
This method can be overridden for models that want to have their
|
|
|
|
specific behavior.
|
|
|
|
Note that currently, this onchange is used in mail.js and called
|
|
|
|
manually on the form instantiated in the Chatter.
|
|
|
|
"""
|
|
|
|
if not value:
|
|
|
|
return {'value': {'dest_partner_ids': []}}
|
|
|
|
return {'value': {}}
|
|
|
|
|
|
|
|
def onchange_formatting(self, cr, uid, ids, value, model, res_id, context=None):
|
|
|
|
""" onchange_formatting (values: True or False). This onchange on the
|
|
|
|
formatting allows to have some specific behavior when going in
|
|
|
|
formatting mode, or when going out of formatting.
|
|
|
|
Basically, subject is reset when going out of formatting mode.
|
|
|
|
This method can be overridden for models that want to have their
|
|
|
|
specific behavior.
|
|
|
|
Note that currently, this onchange is used in mail.js and called
|
|
|
|
manually on the form instantiated in the Chatter.
|
|
|
|
"""
|
|
|
|
if not value:
|
|
|
|
return {'value': {'subject': False}}
|
|
|
|
return {'value': {}}
|
|
|
|
|
2011-07-22 16:34:57 +00:00
|
|
|
def get_message_data(self, cr, uid, message_id, context=None):
|
2012-07-10 15:33:16 +00:00
|
|
|
""" Returns a defaults-like dict with initial values for the composition
|
|
|
|
wizard when replying to the given message (e.g. including the quote
|
|
|
|
of the initial message, and the correct recipient). It should not be
|
|
|
|
called unless ``context['mail.compose.message.mode'] == 'reply'``.
|
|
|
|
|
|
|
|
:param int message_id: id of the mail.message to which the user
|
|
|
|
is replying.
|
|
|
|
:param dict context: several context values will modify the behavior
|
|
|
|
of the wizard, cfr. the class description.
|
2011-07-22 16:34:57 +00:00
|
|
|
"""
|
|
|
|
if context is None:
|
|
|
|
context = {}
|
|
|
|
result = {}
|
2012-07-10 15:33:16 +00:00
|
|
|
if not message_id:
|
|
|
|
return result
|
|
|
|
|
|
|
|
current_user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
|
|
|
message_data = self.pool.get('mail.message').browse(cr, uid, message_id, context)
|
|
|
|
# Form the subject
|
|
|
|
re_prefix = _("Re:")
|
|
|
|
reply_subject = tools.ustr(message_data.subject or '')
|
|
|
|
if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)):
|
|
|
|
reply_subject = "%s %s" % (re_prefix, reply_subject)
|
|
|
|
# Form the bodies (text and html). We use the plain text version of the
|
|
|
|
# original mail, by default, as it is easier to quote than the HTML
|
|
|
|
# version. TODO: make it possible to switch to HTML on the fly
|
|
|
|
sent_date = _('On %(date)s, ') % {'date': message_data.date} if message_data.date else ''
|
|
|
|
sender = _('%(sender_name)s wrote:') % {'sender_name': tools.ustr(message_data.email_from or _('You'))}
|
|
|
|
body_text = message_data.body_text or ''
|
|
|
|
quoted_body_text = '> %s' % tools.ustr(body_text.replace('\n', "\n> ") or '')
|
|
|
|
quoted_body_html = '> %s' % tools.ustr(body_text.replace('\n', "<br />> ") or '')
|
|
|
|
reply_body_text = '\n%s%s\n%s\n%s' % (sent_date, sender, quoted_body_text, current_user.signature)
|
|
|
|
reply_body_html = '\n%s%s\n%s\n%s' % (sent_date, sender, quoted_body_html, current_user.signature)
|
2012-07-12 15:42:59 +00:00
|
|
|
# form dest_partner_ids
|
|
|
|
dest_partner_ids = [partner.id for partner in message_data.partner_ids]
|
2012-07-10 15:33:16 +00:00
|
|
|
# Update header and references
|
|
|
|
reply_headers = {}
|
|
|
|
reply_references = message_data.references and tools.ustr(message_data.references) or False
|
|
|
|
reply_message_id = message_data.message_id or False
|
|
|
|
if reply_message_id:
|
|
|
|
reply_references = (reply_references or '') + " " + mail_wiz.message_id
|
|
|
|
reply_headers['In-Reply-To'] = mail_wiz.message_id
|
|
|
|
# update the result
|
|
|
|
result.update({
|
|
|
|
'body_text': reply_body_text,
|
|
|
|
'body_html': quoted_body_html,
|
|
|
|
'subject': reply_subject,
|
|
|
|
'attachment_ids': [],
|
2012-07-12 15:42:59 +00:00
|
|
|
'dest_partner_ids': dest_partner_ids,
|
2012-07-10 15:33:16 +00:00
|
|
|
'model': message_data.model or False,
|
|
|
|
'res_id': message_data.res_id or False,
|
|
|
|
'email_from': current_user.user_email or message_data.email_to or False,
|
|
|
|
'email_to': message_data.reply_to or message_data.email_from or False,
|
|
|
|
'email_cc': message_data.email_cc or False,
|
|
|
|
'user_id': uid,
|
|
|
|
# pass msg-id and references of mail we're replying to, to construct the
|
|
|
|
# new ones later when sending
|
|
|
|
'message_id': reply_message_id,
|
|
|
|
'references': reply_references,
|
|
|
|
'headers': reply_headers,
|
|
|
|
})
|
2011-07-22 16:34:57 +00:00
|
|
|
return result
|
|
|
|
|
2012-07-10 15:33:16 +00:00
|
|
|
def send_mail(self, cr, uid, ids, context=None):
|
2012-07-06 15:51:41 +00:00
|
|
|
'''Process the wizard contents and proceed with sending the corresponding
|
|
|
|
email(s), rendering any template patterns on the fly if needed.
|
|
|
|
If the wizard is in mass-mail mode (context['mail.compose.message.mode'] is
|
|
|
|
set to ``'mass_mail'``), the resulting email(s) are scheduled for being
|
|
|
|
sent the next time the mail.message scheduler runs, or the next time
|
|
|
|
``mail.message.process_email_queue`` is called.
|
|
|
|
Otherwise the new message is sent immediately.
|
|
|
|
|
|
|
|
:param dict context: several context values will modify the behavior
|
|
|
|
of the wizard, cfr. the class description.
|
|
|
|
'''
|
|
|
|
if context is None:
|
|
|
|
context = {}
|
2012-07-12 15:42:59 +00:00
|
|
|
# composition wizard options
|
|
|
|
email_mode = context.get('email_mode')
|
|
|
|
formatting = context.get('formatting')
|
|
|
|
mass_mail_mode = context.get('mail.compose.message.mode') == 'mass_mail'
|
|
|
|
|
|
|
|
mail_message_obj = self.pool.get('mail.message')
|
2012-07-06 15:51:41 +00:00
|
|
|
for mail_wiz in self.browse(cr, uid, ids, context=context):
|
|
|
|
# attachments
|
|
|
|
attachment = {}
|
|
|
|
for attach in mail_wiz.attachment_ids:
|
|
|
|
attachment[attach.datas_fname] = attach.datas and attach.datas.decode('base64')
|
|
|
|
|
2012-07-12 15:42:59 +00:00
|
|
|
# default values, according to the wizard options
|
|
|
|
subject = mail_wiz.subject if formatting else False
|
|
|
|
content_subtype = 'html' if formatting else 'plain'
|
|
|
|
type = 'email' if email_mode else 'comment'
|
|
|
|
partner_ids = [partner.id for partner in mail_wiz.dest_partner_ids]
|
2012-07-06 15:51:41 +00:00
|
|
|
references = None
|
|
|
|
headers = {}
|
2012-07-12 15:42:59 +00:00
|
|
|
body = mail_wiz.body_html if content_subtype == 'html' else mail_wiz.body_text
|
2012-07-06 15:51:41 +00:00
|
|
|
|
2012-07-12 15:42:59 +00:00
|
|
|
# get model, active_ids, and check if model is openchatter-enabled
|
|
|
|
if mass_mail_mode and context.get('active_ids') and context.get('active_model'):
|
|
|
|
active_ids = context['active_ids']
|
|
|
|
active_model = context['active_model']
|
|
|
|
elif mass_mail_mode:
|
|
|
|
active_model = mail_wiz.model
|
|
|
|
active_model_pool = self.pool.get(active_model)
|
|
|
|
active_ids = active_model_pool.search(cr, uid, ast.literal_eval(mail_wiz.filter_id.domain), context=ast.literal_eval(mail_wiz.filter_id.context))
|
2012-07-06 15:51:41 +00:00
|
|
|
else:
|
|
|
|
active_model = mail_wiz.model
|
2012-07-12 15:42:59 +00:00
|
|
|
active_ids = [mail_wiz.res_id]
|
2012-07-06 15:51:41 +00:00
|
|
|
active_model_pool = self.pool.get(active_model)
|
2012-07-12 15:42:59 +00:00
|
|
|
mail_thread_enabled = hasattr(active_model_pool, 'message_append')
|
2012-07-06 15:51:41 +00:00
|
|
|
|
|
|
|
if context.get('mail.compose.message.mode') == 'mass_mail':
|
|
|
|
# Mass mailing: must render the template patterns
|
|
|
|
for active_id in active_ids:
|
2012-07-11 14:32:45 +00:00
|
|
|
rendered_subject = self.render_template(cr, uid, subject, active_model, active_id)
|
2012-07-12 15:42:59 +00:00
|
|
|
rendered_body_html = self.render_template(cr, uid, mail_wiz.body_html, active_model, active_id)
|
|
|
|
rendered_body_text = self.render_template(cr, uid, mail_wiz.body_text, active_model, active_id)
|
2012-07-06 15:51:41 +00:00
|
|
|
email_from = self.render_template(cr, uid, mail_wiz.email_from, active_model, active_id)
|
|
|
|
email_to = self.render_template(cr, uid, mail_wiz.email_to, active_model, active_id)
|
|
|
|
email_cc = self.render_template(cr, uid, mail_wiz.email_cc, active_model, active_id)
|
|
|
|
email_bcc = self.render_template(cr, uid, mail_wiz.email_bcc, active_model, active_id)
|
|
|
|
reply_to = self.render_template(cr, uid, mail_wiz.reply_to, active_model, active_id)
|
2012-07-12 15:42:59 +00:00
|
|
|
|
2012-07-06 15:51:41 +00:00
|
|
|
# in mass-mailing mode we only schedule the mail for sending, it will be
|
|
|
|
# processed as soon as the mail scheduler runs.
|
|
|
|
if mail_thread_enabled:
|
2012-07-12 15:42:59 +00:00
|
|
|
active_model_pool.message_append(cr, uid, [active_id], rendered_subject, rendered_body_text, rendered_body_html,
|
|
|
|
type=type, content_subtype=content_subtype, state='outgoing', partner_ids=partner_ids,
|
|
|
|
email_from=email_from, email_to=email_to, email_cc=email_cc, email_bcc=email_bcc,
|
2012-07-06 15:51:41 +00:00
|
|
|
reply_to=reply_to, references=references, attachments=attachment, headers=headers, context=context)
|
|
|
|
else:
|
2012-07-12 15:42:59 +00:00
|
|
|
mail_message_obj.schedule_with_attach(cr, uid, email_from, to_email(email_to), subject, rendered_body_text,
|
2012-07-06 15:51:41 +00:00
|
|
|
model=mail_wiz.model, email_cc=to_email(email_cc), email_bcc=to_email(email_bcc), reply_to=reply_to,
|
2012-07-12 15:42:59 +00:00
|
|
|
attachments=attachment, references=references, res_id=active_id, partner_ids=partner_ids,
|
2012-07-06 15:51:41 +00:00
|
|
|
content_subtype=mail_wiz.content_subtype, headers=headers, context=context)
|
|
|
|
else:
|
|
|
|
# normal mode - no mass-mailing
|
|
|
|
if mail_thread_enabled:
|
2012-07-12 15:42:59 +00:00
|
|
|
msg_ids = active_model_pool.message_append(cr, uid, active_ids, subject, mail_wiz.body_text, mail_wiz.body_html,
|
|
|
|
type=type, content_subtype=content_subtype, state='outgoing', partner_ids=partner_ids,
|
|
|
|
email_from=mail_wiz.email_from, email_to=mail_wiz.email_to, email_cc=mail_wiz.email_cc, email_bcc=mail_wiz.email_bcc,
|
|
|
|
reply_to=mail_wiz.reply_to, references=references, attachments=attachment, headers=headers, context=context)
|
2012-07-06 15:51:41 +00:00
|
|
|
else:
|
2012-07-12 15:42:59 +00:00
|
|
|
msg_ids = [mail_message_obj.schedule_with_attach(cr, uid, mail_wiz.email_from, to_email(mail_wiz.email_to), subject, mail_wiz.body_text,
|
2012-07-06 15:51:41 +00:00
|
|
|
model=mail_wiz.model, email_cc=to_email(mail_wiz.email_cc), email_bcc=to_email(mail_wiz.email_bcc), reply_to=mail_wiz.reply_to,
|
2012-07-12 15:42:59 +00:00
|
|
|
attachments=attachment, references=references, res_id=int(mail_wiz.res_id), partner_ids=partner_ids,
|
2012-07-06 15:51:41 +00:00
|
|
|
content_subtype=mail_wiz.content_subtype, headers=headers, context=context)]
|
|
|
|
# in normal mode, we send the email immediately, as the user expects us to (delay should be sufficiently small)
|
2012-07-12 15:42:59 +00:00
|
|
|
mail_message_obj.send(cr, uid, msg_ids, context=context)
|
2012-07-06 15:51:41 +00:00
|
|
|
|
|
|
|
return {'type': 'ir.actions.act_window_close'}
|
|
|
|
|
2011-07-22 16:34:57 +00:00
|
|
|
def render_template(self, cr, uid, template, model, res_id, context=None):
|
|
|
|
"""Render the given template text, replace mako-like expressions ``${expr}``
|
2011-08-22 17:16:59 +00:00
|
|
|
with the result of evaluating these expressions with an evaluation context
|
|
|
|
containing:
|
2011-07-22 16:34:57 +00:00
|
|
|
|
|
|
|
* ``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 context is None:
|
|
|
|
context = {}
|
|
|
|
def merge(match):
|
|
|
|
exp = str(match.group()[2:-1]).strip()
|
|
|
|
result = eval(exp,
|
|
|
|
{
|
|
|
|
'user' : self.pool.get('res.users').browse(cr, uid, uid, context=context),
|
|
|
|
'object' : self.pool.get(model).browse(cr, uid, res_id, context=context),
|
|
|
|
'context': dict(context), # copy context to prevent side-effects of eval
|
|
|
|
})
|
|
|
|
if result in (None, False):
|
|
|
|
return ""
|
|
|
|
return tools.ustr(result)
|
|
|
|
return template and EXPRESSION_PATTERN.sub(merge, template)
|
|
|
|
|
2012-07-03 13:14:53 +00:00
|
|
|
|
2012-07-10 13:06:31 +00:00
|
|
|
class mail_compose_message_extended(osv.TransientModel):
|
2012-07-03 13:14:53 +00:00
|
|
|
""" Extension of 'mail.compose.message' to support default field values related
|
|
|
|
to CRM-like models that follow the following conventions:
|
|
|
|
|
|
|
|
1. The model object must have an attribute '_mail_compose_message' equal to True.
|
|
|
|
|
|
|
|
2. The model should define the following fields:
|
|
|
|
- 'name' as subject of the message (required);
|
|
|
|
- 'email_from' as destination email address (required);
|
|
|
|
- 'email_cc' as cc email addresses (required);
|
|
|
|
- 'section_id.reply_to' as reply-to address (optional).
|
|
|
|
"""
|
|
|
|
_inherit = 'mail.compose.message'
|
|
|
|
|
|
|
|
def get_value(self, cr, uid, model, res_id, context=None):
|
2012-07-10 15:33:16 +00:00
|
|
|
""" Overrides the default implementation to provide more default field values
|
|
|
|
related to the corresponding CRM case.
|
2012-07-03 13:14:53 +00:00
|
|
|
"""
|
2012-07-13 14:23:33 +00:00
|
|
|
result = super(mail_compose_message_extended, self).get_value(cr, uid, model, res_id, context=context)
|
2012-07-03 13:14:53 +00:00
|
|
|
model_obj = self.pool.get(model)
|
|
|
|
if getattr(model_obj, '_mail_compose_message', False) and res_id:
|
|
|
|
data = model_obj.browse(cr, uid , res_id, context)
|
|
|
|
result.update({
|
|
|
|
'email_to': data.email_from or False,
|
|
|
|
'email_cc': tools.ustr(data.email_cc or ''),
|
|
|
|
'subject': data.name or False,
|
|
|
|
})
|
|
|
|
if hasattr(data, 'section_id'):
|
|
|
|
result['reply_to'] = data.section_id and data.section_id.reply_to or False
|
|
|
|
return result
|
|
|
|
|
2012-07-13 14:23:33 +00:00
|
|
|
def onchange_email_mode(self, cr, uid, ids, value, model, res_id, context=None):
|
|
|
|
""" Overrides the default implementation to provide default values for
|
|
|
|
dest_partner_ids. This method checks that a partner maching the
|
|
|
|
``email_from`` of the record exists. It it does not exist, it
|
|
|
|
creates a new partner. The found or created partner is then added
|
|
|
|
in dest_partner_ids.
|
|
|
|
Partner check/creation valid inly if the value is True, and if
|
|
|
|
the model has the ``_mail_compose_message`` attribute.
|
|
|
|
"""
|
|
|
|
result = super(mail_compose_message_extended, self).onchange_email_mode(cr, uid, ids, value, model, res_id, context=context)
|
|
|
|
model_obj = self.pool.get(model)
|
|
|
|
if not value or not (getattr(model_obj, '_mail_compose_message', False) and res_id):
|
|
|
|
return result
|
|
|
|
data = model_obj.browse(cr, uid , res_id, context=context)
|
|
|
|
partner_obj = self.pool.get('res.partner')
|
|
|
|
partner_ids = partner_obj.search(cr, uid, [('email', '=', data.email_from)], context=context)
|
|
|
|
if partner_ids:
|
|
|
|
partner_id = partner_ids[0]
|
|
|
|
else:
|
|
|
|
partner_id = partner_obj.name_create(cr, uid, data.email_from, context=context)[0]
|
|
|
|
result['value'].update({
|
|
|
|
'dest_partner_ids': [partner_id],
|
|
|
|
'email_cc': tools.ustr(data.email_cc or ''),
|
|
|
|
})
|
|
|
|
if hasattr(data, 'section_id'):
|
|
|
|
result['value']['reply_to'] = data.section_id and data.section_id.reply_to or False
|
|
|
|
return result
|
|
|
|
|
|
|
|
def onchange_formatting(self, cr, uid, ids, value, model, res_id, context=None):
|
|
|
|
""" Overrides the default implementation to provide default values for
|
|
|
|
the subject.
|
|
|
|
Subject re-creation valid only if the value is True, and if the
|
|
|
|
model has the ``_mail_compose_message`` attribute.
|
|
|
|
"""
|
|
|
|
result = super(mail_compose_message_extended, self).onchange_formatting(cr, uid, ids, value, model, res_id, context=context)
|
|
|
|
model_obj = self.pool.get(model)
|
|
|
|
if not value or not (getattr(model_obj, '_mail_compose_message', False) and res_id):
|
|
|
|
return result
|
|
|
|
data = model_obj.browse(cr, uid , res_id, context=context)
|
|
|
|
result['value'].update({
|
|
|
|
'subject': data.name or False,
|
|
|
|
})
|
|
|
|
return result
|
|
|
|
|
2011-07-22 16:34:57 +00:00
|
|
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|