diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index f75cda8cdde..9d656c7607d 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -1293,17 +1293,17 @@ class account_voucher(osv.osv):
def create_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
message = "%s created." % self._document_type[obj.type or False]
- self.message_post(cr, uid, [obj.id], body=message, context=context)
+ self.message_post(cr, uid, [obj.id], body=message, subtype="new", context=context)
def post_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
message = "%s '%s' is posted." % (self._document_type[obj.type or False], obj.move_id.name)
- self.message_post(cr, uid, [obj.id], body=message, context=context)
+ self.message_post(cr, uid, [obj.id], body=message, subtype="post", context=context)
def reconcile_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
message = "%s reconciled." % self._document_type[obj.type or False]
- self.message_post(cr, uid, [obj.id], body=message, context=context)
+ self.message_post(cr, uid, [obj.id], body=message, subtype="reconcile", context=context)
account_voucher()
diff --git a/addons/account_voucher/account_voucher_data.xml b/addons/account_voucher/account_voucher_data.xml
index 656d2c2cd91..a99a8735842 100644
--- a/addons/account_voucher/account_voucher_data.xml
+++ b/addons/account_voucher/account_voucher_data.xml
@@ -2,16 +2,38 @@
-
- mail.group
-
- notification
- eInvoicing & Payments application installed!
- OpenERP's electronic invoicing accelerates the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system.
+
+
+
+ OpenERP's electronic invoicing allows to ease and fasten the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system.
-You can track customer payments easily and automate follow-ups. You get an overview of the discussion with your customers on each invoice for easier traceability.
+You can track customer payments easily and automate the reminders. You get an overview of the discussion with your customers on each invoice to ensure a full traceability.
-For advanced accounting features, you should install the "Accounting and Finance" module.
+If you want to use advanced accounting features, you should install the "Accounting and Finance" module.
+ Module eInvoicing & Payments has been installed.
+
+
+
+
+
+
+ post
+
+
+
+
+ reconcile
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py
index d90e2006a71..2e6e5089c88 100644
--- a/addons/analytic/analytic.py
+++ b/addons/analytic/analytic.py
@@ -297,7 +297,7 @@ class account_analytic_account(osv.osv):
def create_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
- self.message_post(cr, uid, [obj.id], body=_("Contract for %s has been created.") % (obj.partner_id.name), context=context)
+ self.message_post(cr, uid, [obj.id], body=_("Contract for %s has been created.") % (obj.partner_id.name), subtype="new", context=context)
account_analytic_account()
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index b725a4ad988..801895885b2 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -595,18 +595,9 @@ class crm_lead(base_stage, osv.osv):
for lead in self.browse(cr, uid, ids, context=context):
if lead.state in ('done', 'cancel'):
continue
-
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
self.write(cr, uid, [lead.id], vals, context=context)
-
self.convert_opportunity_send_note(cr, uid, lead, context=context)
- #TOCHECK: why need to change partner details in all messages of lead ?
- # TDE FIXME: I propose to delete this, makes no sense to update partner of an already-send email ...
- # if lead.partner_id:
- # msg_ids = [x.id for x in lead.message_ids]
- # mail_message.write(cr, uid, msg_ids, {
- # 'partner_id': lead.partner_id.id
- # }, context=context)
if user_ids or section_id:
self.allocate_salesman(cr, uid, ids, user_ids, section_id, context=context)
diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py
index d540971c3b4..73dc5ed2754 100644
--- a/addons/email_template/email_template.py
+++ b/addons/email_template/email_template.py
@@ -29,7 +29,7 @@ from osv import fields
import tools
from tools.translate import _
from tools.html_sanitize import html_sanitize
-from tools import html2plaintext
+from tools import append_content_to_html
from urllib import quote as quote
_logger = logging.getLogger(__name__)
@@ -40,10 +40,8 @@ except ImportError:
class email_template(osv.osv):
"Templates for sending email"
- _inherit = 'mail.mail'
_name = "email.template"
_description = 'Email Templates'
- _rec_name = 'name' # override mail.message's behavior
def render_template(self, cr, uid, template, model, res_id, context=None):
"""Render the given template text, replace mako expressions ``${expr}``
@@ -103,57 +101,44 @@ class email_template(osv.osv):
mod_name = self.pool.get('ir.model').browse(cr, uid, model_id, context).model
return {'value':{'model': mod_name}}
- def name_get(self, cr, uid, ids, context=None):
- """ Override name_get of mail.message: return directly the template
- name, and not the generated name from mail.message.common."""
- return [(record.id, record.name) for record in self.browse(cr, uid, ids, context=context)]
-
_columns = {
- 'name': fields.char('Name', size=250),
- 'model_id': fields.many2one('ir.model', 'Related document model'),
- 'lang': fields.char('Language Selection', size=250,
+ 'name': fields.char('Name'),
+ 'model_id': fields.many2one('ir.model', 'Applies to', help="The kind of document with with this template can be used"),
+ 'model': fields.related('model_id', 'model', type='char', string='Related Document Model',
+ size=128, select=True, store=True, readonly=True),
+ 'lang': fields.char('Language',
help="Optional translation language (ISO code) 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}."),
+ "${object.partner_id.lang.code}.",
+ placeholder="${object.partner_id.lang.code}"),
'user_signature': fields.boolean('Add 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"),
- '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', 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)"),
- 'reply_to': fields.char('Reply-To', size=250, help="Preferred response address (placeholders may be used here)"),
+ 'email_from': fields.char('From', help="Sender address (placeholders may be used here)"),
+ 'email_to': fields.char('To', help="Comma-separated recipient addresses (placeholders may be used here)"),
+ 'email_cc': fields.char('Cc', help="Carbon copy recipients (placeholders may be used here)"),
+ 'reply_to': fields.char('Reply-To', help="Preferred response address (placeholders may be used here)"),
'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing Mail Server', readonly=False,
help="Optional preferred server for outgoing mails. If not set, the highest "
"priority one will be used."),
- 'body_html': fields.text('Rich-text Contents', translate=True, help="Rich-text/HTML version of the message (placeholders may be used here)"),
+ 'body_html': fields.text('Body', translate=True, help="Rich-text/HTML version of the message (placeholders may be used here)"),
+ 'report_name': fields.char('Report Filename', 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"),
+ 'attachment_ids': fields.many2many('ir.attachment', 'email_template_attachment_rel', 'email_template_id',
+ 'attachment_id', 'Attachments',
+ help="You may attach files to this template, to be added to all "
+ "emails created from this template"),
+ 'auto_delete': fields.boolean('Auto Delete', help="Permanently delete this email after sending it, to save space"),
# Fake fields used to implement the placeholder assistant
'model_object_field': fields.many2one('ir.model.fields', string="Field",
@@ -167,12 +152,8 @@ class email_template(osv.osv):
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."),
- }
-
- _defaults = {
- 'track_campaign_item': True
+ 'null_value': fields.char('Default Value', help="Optional value to use if the target field is empty"),
+ 'copyvalue': fields.char('Placeholder Expression', help="Final placeholder expression, to be copy-pasted in the desired template field."),
}
def create_action(self, cr, uid, ids, context=None):
@@ -217,7 +198,7 @@ class email_template(osv.osv):
if template.ref_ir_value:
ir_values_obj = self.pool.get('ir.values')
ir_values_obj.unlink(cr, uid, template.ref_ir_value.id, context)
- except:
+ except Exception:
raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
return True
@@ -289,32 +270,14 @@ class email_template(osv.osv):
: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
+ mail.mail entry, with one extra key ``attachments``, in the
+ format expected by :py:meth:`mail_thread.message_post`.
"""
if context is None:
context = {}
- values = {
- 'subject': False,
- 'body_html': False,
- 'email_from': False,
- 'email_to': False,
- 'email_cc': False,
- 'reply_to': False,
- 'auto_delete': False,
- 'model': False,
- 'res_id': 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, res_id, context)
+ values = {'model': template.model_id.model}
for field in ['subject', 'body_html', 'email_from',
'email_to', 'email_cc', 'reply_to']:
@@ -322,21 +285,20 @@ class email_template(osv.osv):
template.model, res_id, context=context) \
or False
- if values['body_html']:
- values['body'] = html_sanitize(values['body_html'])
- values['body_text'] = html2plaintext(values['body_html'])
-
if template.user_signature:
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
- values['body'] += '\n\n' + signature
+ values['body_html'] = append_content_to_html(values['body_html'], signature)
+
+ if values['body_html']:
+ values['body'] = html_sanitize(values['body_html'])
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)
- attachments = {}
- # Add report as a Document
+ attachments = []
+ # Add report in attachments
if template.report_template:
report_name = self.render_template(cr, uid, template.report_name, template.model, res_id, context=context)
report_service = 'report.' + report_xml_pool.browse(cr, uid, template.report_template.id, context).report_name
@@ -352,12 +314,11 @@ class email_template(osv.osv):
ext = "." + format
if not report_name.endswith(ext):
report_name += ext
- attachments[report_name] = result
+ attachments.append(report_name, result)
- # Add document attachments
+ # Add template attachments
for attach in template.attachment_ids:
- # keep the bytes as fetched from the db, base64 encoded
- attachments[attach.datas_fname] = attach.datas
+ attachments.append(attach.datas_fname, attach.datas)
values['attachments'] = attachments
return values
diff --git a/addons/email_template/email_template_view.xml b/addons/email_template/email_template_view.xml
index cd75a719197..448655a3121 100644
--- a/addons/email_template/email_template_view.xml
+++ b/addons/email_template/email_template_view.xml
@@ -1,95 +1,67 @@
-
email.template.formemail.template
@@ -99,9 +71,9 @@
email.template
-
+
diff --git a/addons/email_template/security/ir.model.access.csv b/addons/email_template/security/ir.model.access.csv
index d2d6adf3bf3..adce0420793 100644
--- a/addons/email_template/security/ir.model.access.csv
+++ b/addons/email_template/security/ir.model.access.csv
@@ -1,5 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_email_template,email.template,model_email_template,,1,0,0,0
+access_email_template,email.template,model_email_template,,1,1,1,0
access_email_template_system,email.template system,model_email_template,base.group_system,1,1,1,1
-access_email_template_manager,email.template,model_email_template,,1,1,1,1
-access_email_template_preview_system,email.template.preview system,model_email_template_preview,base.group_system,1,1,1,1
diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py
index db2168a75d5..5ca608e6b81 100644
--- a/addons/email_template/tests/test_mail.py
+++ b/addons/email_template/tests/test_mail.py
@@ -53,51 +53,59 @@ class test_message_compose(common.TransactionCase):
""" Tests designed for the mail.compose.message wizard updated by email_template. """
cr, uid = self.cr, self.uid
mail_compose = self.registry('mail.compose.message')
- self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a'})
+ self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a.a'})
user_admin = self.res_users.browse(cr, uid, uid)
- group_model_id = self.registry('ir.model').search(cr, uid, [('model', '=', 'mail.group')])[0]
group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
+ group_bird_id = self.mail_group.create(cr, uid, {'name': 'Bird', 'description': 'I am angry !'})
+ group_bird = self.mail_group.browse(cr, uid, group_bird_id)
# Create template on mail.group
+ group_model_id = self.registry('ir.model').search(cr, uid, [('model', '=', 'mail.group')])[0]
email_template = self.registry('email.template')
email_template_id = email_template.create(cr, uid, {'model_id': group_model_id,
- 'name': 'Pigs Template', 'subject': '${record.name}',
+ 'name': 'Pigs Template', 'subject': '${object.name}',
'body_html': '${object.description}', 'user_signature': True,
- 'email_to': 'b@b c@c', 'email_cc': 'd@d'})
- # import pdb
- # pdb.set_trace()
+ 'email_to': 'b@b.b c@c.c', 'email_cc': 'd@d.d'})
# Mail data
- _subject = 'Pigs'
- _body_text = 'Pigs rules'
+ _subject1 = 'Pigs'
+ _subject2 = 'Bird'
+ _body_text1 = 'Pigs rules'
+ _body_text_html1 = 'Pigs rules
Admin
'
+ _body_text2 = 'I am angry !'
+ _body_text_html2 = 'I am angry !
Admin
'
- # 3 - Create in mass_mail composition mode that should work with or without email_template installed
+ # CASE1: create in mass_mail composition mode that should work with email_template installed
compose_id = mail_compose.create(cr, uid,
- {'subject': _subject, 'body': _body_text},
+ {'subject': 'Forget me subject', 'body': 'Dummy body'},
{'default_composition_mode': 'mass_mail', 'default_model': 'mail.group',
'default_res_id': -1, 'default_use_template': True,
- 'active_ids': [self.group_pigs_id], 'default_template_id': email_template_id})
+ 'active_ids': [self.group_pigs_id, group_bird_id], 'default_template_id': email_template_id})
compose = mail_compose.browse(cr, uid, compose_id)
# print compose.subject
# Try the 'onchange_template_id'
- values = mail_compose.onchange_template_id(cr, uid, [], compose.use_template, compose.template_id, compose.composition_mode, compose.res_id)
- # print values
- values = mail_compose.onchange_use_template(cr, uid, [], not compose.use_template, compose.template_id, compose.composition_mode, compose.res_id)
- # print values
+ values = mail_compose.onchange_template_id(cr, uid, [], compose.use_template, compose.template_id, compose.composition_mode, compose.model, compose.res_id)
+ print values
+ # compose.write(values['value'])
+ values = mail_compose.onchange_use_template(cr, uid, [], not compose.use_template, compose.template_id, compose.composition_mode, compose.model, compose.res_id)
+ print values
compose.refresh()
-
- # # 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')
\ No newline at end of file
+ # 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_bird_id]})
+ group_pigs.refresh()
+ group_bird.refresh()
+ message_pigs = group_pigs.message_ids[0]
+ message_bird = group_bird.message_ids[0]
+ # Test: subject, body
+ self.assertEqual(message_pigs.subject, _subject1, 'mail.message subject on Pigs incorrect')
+ self.assertEqual(message_bird.subject, _subject2, 'mail.message subject on Bird incorrect')
+ self.assertEqual(message_pigs.body, _body_text_html1, 'mail.message body on Pigs incorrect')
+ self.assertEqual(message_bird.body, _body_text_html2, 'mail.message body on Bird incorrect')
+ # Test: partner_ids
+ print message_pigs.partner_ids
+ print message_pigs.partner_ids
+ self.assertEqual(len(message_pigs.partner_ids), 6, 'mail.message partner_ids incorrect')
\ No newline at end of file
diff --git a/addons/email_template/wizard/email_template_preview.py b/addons/email_template/wizard/email_template_preview.py
index 2c1866a53c4..862c34cc426 100644
--- a/addons/email_template/wizard/email_template_preview.py
+++ b/addons/email_template/wizard/email_template_preview.py
@@ -65,29 +65,19 @@ class email_template_preview(osv.osv_memory):
return result
_columns = {
- 'res_id':fields.selection(_get_records, 'Sample Document'),
+ 'res_id': fields.selection(_get_records, 'Sample Document'),
}
def on_change_res_id(self, cr, uid, ids, res_id, context=None):
- if not res_id:
- return {}
+ if not res_id: return {}
vals = {}
email_template = self.pool.get('email.template')
template_id = context and context.get('template_id')
- template = email_template.get_email_template(cr, uid, template_id=template_id, record_id=res_id, context=context)
- model = template.model
- 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['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
- if template.body_html:
- vals['body_html'] = self.render_template(cr, uid, template.body_html, model, res_id, context) or ''
- vals['report_name'] = self.render_template(cr, uid, template.report_name, model, res_id, context)
+ template = email_template.browse(cr, uid, template_id, context=context)
+ vals['name'] = template.name
+ mail_values = email_template.generate_email(cr, uid, template_id, res_id, context=context)
+ for k in ('email_from','email_to','email_cc','reply_to','subject','body_html'):
+ vals[k] = mail_values[k]
return {'value': vals}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/email_template/wizard/email_template_preview_view.xml b/addons/email_template/wizard/email_template_preview_view.xml
index 708ca2b0406..f4f75567a42 100644
--- a/addons/email_template/wizard/email_template_preview_view.xml
+++ b/addons/email_template/wizard/email_template_preview_view.xml
@@ -6,26 +6,22 @@
email_template.preview.formemail_template.preview
-
diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py
index 11e726c537b..71586649f37 100644
--- a/addons/email_template/wizard/mail_compose_message.py
+++ b/addons/email_template/wizard/mail_compose_message.py
@@ -27,13 +27,9 @@ from osv import fields
from tools.translate import _
class mail_compose_message(osv.osv_memory):
- """ Inherit mail_compose_message to add email template feature in the
- message composer. """
-
_inherit = 'mail.compose.message'
def _get_templates(self, cr, uid, context=None):
- """ Return Email Template of particular Model. """
if context is None:
context = {}
model = False
@@ -52,7 +48,6 @@ class mail_compose_message(osv.osv_memory):
return []
def default_get(self, cr, uid, fields, context=None):
- """ Override to handle templates. """
if context is None:
context = {}
result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context)
@@ -65,43 +60,36 @@ class mail_compose_message(osv.osv_memory):
'template_id': fields.selection(_get_templates, 'Template', size=-1),
}
- def onchange_template_id(self, cr, uid, ids, use_template, template_id, composition_mode, res_id, context=None):
- """ onchange_template_id: read or render the template if set, get back
- to default values if not. """
+ def onchange_template_id(self, cr, uid, ids, use_template, template_id, composition_mode, model, res_id, context=None):
+ """ - use_template not set: return default_get
+ - use_template set:
+ - mass_mailing: we cannot render, so return the template values
+ - else: return rendered values """
fields = ['body', 'body_html', 'subject', 'partner_ids', 'email_to', 'email_cc']
- if use_template and template_id:
- # use the original template values, to be rendered when actually sent
- if composition_mode == 'mass_mail':
- values = self.pool.get('email.template').read(cr, uid, template_id, fields, context)
- # render the mail as one-shot
- else:
- values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context)
- # retrofit generated attachments in the expected field format
- if values['attachments']:
- attachment = values.pop('attachments')
- attachment_obj = self.pool.get('ir.attachment')
- att_ids = []
- for fname, fcontent in attachment.iteritems():
- data_attach = {
- 'name': fname,
- 'datas': fcontent,
- 'datas_fname': fname,
- 'description': fname,
- 'res_model' : self._name,
- 'res_id' : ids[0] if ids else False
- }
- att_ids.append(attachment_obj.create(cr, uid, data_attach))
- values['attachment_ids'] = att_ids
- else: # restore defaults
+ if use_template and template_id and composition_mode == 'mass_mail':
+ values = self.pool.get('email.template').read(cr, uid, template_id, fields, context)
+ elif use_template and template_id:
+ values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context)
+
+ values['attachment_ids'] = []
+ attachment_obj = self.pool.get('ir.attachment')
+ for attach_fname, attach_datas in values.get('attachments', []):
+ data_attach = {
+ 'name': attach_fname,
+ 'datas': attach_datas,
+ 'datas_fname': attach_fname,
+ 'description': fname,
+ 'res_model': model,
+ 'res_id': res_id,
+ }
+ values['attachment_ids'].append(attachment_obj.create(cr, uid, data_attach), context=context)
+ else:
values = self.default_get(cr, uid, fields, context=context)
if values.get('body_html') and not values.get('body'):
values['body'] = values.get('body_html')
-
values.update(use_template=use_template, template_id=template_id)
- print 'returning ', values
-
return {'value': values}
def toggle_template(self, cr, uid, ids, context=None):
@@ -109,16 +97,15 @@ class mail_compose_message(osv.osv_memory):
emulate an on_change, then writes the value to update the form. """
for record in self.browse(cr, uid, ids, context=context):
onchange_res = self.onchange_use_template(cr, uid, ids, not record.use_template,
- record.template_id, record.composition_mode, record.res_id, context=context)['value']
+ record.template_id, record.composition_mode, record.model, record.res_id, context=context)['value']
record.write(onchange_res)
return True
- def onchange_use_template(self, cr, uid, ids, use_template, template_id, composition_mode, res_id, context=None):
+ def onchange_use_template(self, cr, uid, ids, use_template, template_id, composition_mode, model, res_id, context=None):
""" onchange_use_template (values: True or False). If use_template is
False, we do like an onchange with template_id False for values """
- onchange_template_values = self.onchange_template_id(cr, uid, ids, use_template,
- template_id, composition_mode, res_id, context=context)
- return onchange_template_values
+ return self.onchange_template_id(cr, uid, ids, use_template,
+ template_id, composition_mode, model, res_id, context=context)
def save_as_template(self, cr, uid, ids, context=None):
""" hit save as template button: current form value will be a new
@@ -144,9 +131,36 @@ class mail_compose_message(osv.osv_memory):
record.write({'template_id': template_id, 'use_template': True})
return True
+ #------------------------------------------------------
+ # Wizard validation and send
+ #------------------------------------------------------
+
+ 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, ...
+ """
+ # render the template to get the email
+ template_values = self.pool.get('email.template').generate_email(cr, uid, wizard.template_id, res_id, context=context)
+ # TDE TODO: handle fields to update / not to update (mail_server_id, auto_delete, ...)
+ # transform email_to, email_cc into partner_ids
+ partner_ids = []
+ mails = tools.email_split(template_values.pop('email_to', '') + ' ' + template_values.pop('email_cc', ''))
+ for mail in mails:
+ partner_search_ids = self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', mail)], context=context)
+ if partner_search_ids:
+ partner_ids.append((4, partner_search_ids[0]))
+ else:
+ partner_id = self.pool.get('res.partner').name_create(cr, uid, mail, context=context)[0]
+ partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
+ partner_ids.append((4, partner_id))
+ # get values to return
+ email_dict = super(mail_compose_message, self).render_message(cr, uid, wizard, model, res_id, context)
+ email_dict.update(template_values)
+ email_dict.update(partner_ids=partner_ids, attachments=template_values.get('attachments'))
+ return email_dict
+
def render_template(self, cr, uid, template, model, res_id, context=None):
- """ Override of mail.compose.message behavior: use the power of
- templates ! """
return self.pool.get('email.template').render_template(cr, uid, template, model, res_id, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml
index f54ee0d3723..228dcc2745a 100644
--- a/addons/email_template/wizard/mail_compose_message_view.xml
+++ b/addons/email_template/wizard/mail_compose_message_view.xml
@@ -19,7 +19,7 @@
+ on_change="onchange_template_id(use_template, template_id, composition_mode, model, res_id, context)"/>
@@ -34,10 +34,10 @@
+ on_change="onchange_use_template(use_template, template_id, composition_mode, model, res_id, context)"/>
+ on_change="onchange_template_id(use_template, template_id, composition_mode, model, res_id, context)"/>
diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml
index b06ae9f0b6f..b131d9c9c52 100644
--- a/addons/event/event_view.xml
+++ b/addons/event/event_view.xml
@@ -101,7 +101,7 @@
-
+
diff --git a/addons/idea/idea.py b/addons/idea/idea.py
index e2e5ec50ddf..e33c9b99014 100644
--- a/addons/idea/idea.py
+++ b/addons/idea/idea.py
@@ -67,21 +67,21 @@ class idea_idea(osv.osv):
def idea_cancel(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state': 'cancel' })
- self.message_post(cr, uid, ids, body=_('Idea canceled.'), context=context)
+ self.message_post(cr, uid, ids, body=_('Idea cancelled.'), subtype="cancelled", context=context)
return True
def idea_open(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state': 'open'})
- self.message_post(cr, uid, ids, body=_('Idea accepted.'), context=context)
+ self.message_post(cr, uid, ids, body=_('Idea accepted.'), subtype="open", context=context)
return True
def idea_close(self, cr, uid, ids, context={}):
- self.message_post(cr, uid, ids, body=_('Idea done.'), context=context)
+ self.message_post(cr, uid, ids, body=_('Idea closed.'), subtype="closed", context=context)
self.write(cr, uid, ids, { 'state': 'close' })
return True
def idea_draft(self, cr, uid, ids, context={}):
- self.message_post(cr, uid, ids, body=_('Idea reset to draft.'), context=context)
+ self.message_post(cr, uid, ids, body=_('Idea reset to draft.'), subtype="new", context=context)
self.write(cr, uid, ids, { 'state': 'draft' })
return True
idea_idea()
diff --git a/addons/idea/idea_data.xml b/addons/idea/idea_data.xml
index d63eb907ef8..36ccf2e992e 100644
--- a/addons/idea/idea_data.xml
+++ b/addons/idea/idea_data.xml
@@ -15,6 +15,35 @@
+
+
+
+ new
+
+
+
+
+ open
+
+
+
+ cancelled
+
+
+
+
+ closed
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py
index 531fdd46f1f..c813eaa5dc0 100644
--- a/addons/mail/mail_followers.py
+++ b/addons/mail/mail_followers.py
@@ -61,14 +61,21 @@ class mail_notification(osv.Model):
_columns = {
'partner_id': fields.many2one('res.partner', string='Contact',
- ondelete='cascade', required=True, select=1),
+ ondelete='cascade', required=True),
'read': fields.boolean('Read'),
+ 'message_id': fields.many2one('mail.message', string='Message',
+ ondelete='cascade', required=True),
}
_defaults = {
'read': False,
}
+ def init(self, cr):
+ cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_notification_partner_id_read_message_id',))
+ if not cr.fetchone():
+ cr.execute('CREATE INDEX mail_notification_partner_id_read_message_id ON mail_notification (partner_id, read, message_id)')
+
def create(self, cr, uid, vals, context=None):
""" Override of create to check that we can not create a notification
for a message the user can not read. """
@@ -76,6 +83,11 @@ class mail_notification(osv.Model):
return super(mail_notification, self).create(cr, uid, vals, context=context)
return False
+ def set_message_read(self, cr, uid, msg_id, context=None):
+ partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
+ notif_ids = self.search(cr, uid, [('partner_id', '=', partner_id), ('message_id', '=', msg_id)], context=context)
+ return self.write(cr, uid, notif_ids, {'read': True}, context=context)
+
def notify(self, cr, uid, partner_ids, msg_id, context=None):
""" Send by email the notification depending on the user preferences """
context = context or {}
@@ -90,12 +102,7 @@ class mail_notification(osv.Model):
body_html = msg.body
signature = msg.author_id and msg.author_id.user_ids[0].signature or ''
if signature:
- signature_block = u'\n