[FIX] website_event, website_hr_recruitment: depends website_partner
[odoo/odoo.git] / addons / email_template / wizard / mail_compose_message.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU General Public License as published by
9 #    the Free Software Foundation, either version 3 of the License, or
10 #    (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #    You should have received a copy of the GNU General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>
19 #
20 ##############################################################################
21
22 from openerp import tools
23 from openerp.osv import osv, fields
24
25
26 def _reopen(self, res_id, model):
27     return {'type': 'ir.actions.act_window',
28             'view_mode': 'form',
29             'view_type': 'form',
30             'res_id': res_id,
31             'res_model': self._name,
32             'target': 'new',
33             # save original model in context, because selecting the list of available
34             # templates requires a model in context
35             'context': {
36                 'default_model': model,
37             },
38             }
39
40
41 class mail_compose_message(osv.TransientModel):
42     _inherit = 'mail.compose.message'
43
44     _columns = {
45         'template_id': fields.many2one('email.template', 'Use template', select=True),
46         'partner_to': fields.char('To (Partner IDs)',
47             help="Comma-separated list of recipient partners ids (placeholders may be used here)"),
48         'email_to': fields.char('To (Emails)',
49             help="Comma-separated recipient addresses (placeholders may be used here)",),
50         'email_cc': fields.char('Cc (Emails)',
51             help="Carbon copy recipients (placeholders may be used here)"),
52     }
53
54     def send_mail(self, cr, uid, ids, context=None):
55         """ Override of send_mail to duplicate attachments linked to the email.template.
56             Indeed, basic mail.compose.message wizard duplicates attachments in mass
57             mailing mode. But in 'single post' mode, attachments of an email template
58             also have to be duplicated to avoid changing their ownership. """
59         if context is None:
60             context = {}
61         wizard_context = dict(context)
62         for wizard in self.browse(cr, uid, ids, context=context):
63             if wizard.template_id:
64                 wizard_context['mail_notify_user_signature'] = False  # template user_signature is added when generating body_html
65                 wizard_context['mail_auto_delete'] = wizard.template_id.auto_delete  # mass mailing: use template auto_delete value -> note, for emails mass mailing only
66             if not wizard.attachment_ids or wizard.composition_mode == 'mass_mail' or not wizard.template_id:
67                 continue
68             new_attachment_ids = []
69             for attachment in wizard.attachment_ids:
70                 if attachment in wizard.template_id.attachment_ids:
71                     new_attachment_ids.append(self.pool.get('ir.attachment').copy(cr, uid, attachment.id, {'res_model': 'mail.compose.message', 'res_id': wizard.id}, context=context))
72                 else:
73                     new_attachment_ids.append(attachment.id)
74                 self.write(cr, uid, wizard.id, {'attachment_ids': [(6, 0, new_attachment_ids)]}, context=context)
75         return super(mail_compose_message, self).send_mail(cr, uid, ids, context=wizard_context)
76
77     def onchange_template_id(self, cr, uid, ids, template_id, composition_mode, model, res_id, context=None):
78         """ - mass_mailing: we cannot render, so return the template values
79             - normal mode: return rendered values """
80         if template_id and composition_mode == 'mass_mail':
81             fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'mail_server_id']
82             template_values = self.pool.get('email.template').read(cr, uid, template_id, fields, context)
83             values = dict((field, template_values[field]) for field in fields if template_values.get(field))
84         elif template_id:
85             values = self.generate_email_for_composer_batch(cr, uid, template_id, [res_id], context=context)[res_id]
86             # transform attachments into attachment_ids; not attached to the document because this will
87             # be done further in the posting process, allowing to clean database if email not send
88             values['attachment_ids'] = values.pop('attachment_ids', [])
89             ir_attach_obj = self.pool.get('ir.attachment')
90             for attach_fname, attach_datas in values.pop('attachments', []):
91                 data_attach = {
92                     'name': attach_fname,
93                     'datas': attach_datas,
94                     'datas_fname': attach_fname,
95                     'res_model': 'mail.compose.message',
96                     'res_id': 0,
97                     'type': 'binary',  # override default_type from context, possibly meant for another model!
98                 }
99                 values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context))
100         else:
101             values = self.default_get(cr, uid, ['subject', 'body', 'email_from', 'email_to', 'email_cc', 'partner_to', 'reply_to', 'attachment_ids', 'mail_server_id'], context=context)
102
103         if values.get('body_html'):
104             values['body'] = values.pop('body_html')
105         return {'value': values}
106
107     def save_as_template(self, cr, uid, ids, context=None):
108         """ hit save as template button: current form value will be a new
109             template attached to the current document. """
110         email_template = self.pool.get('email.template')
111         ir_model_pool = self.pool.get('ir.model')
112         for record in self.browse(cr, uid, ids, context=context):
113             model_ids = ir_model_pool.search(cr, uid, [('model', '=', record.model)], context=context)
114             model_id = model_ids and model_ids[0] or False
115             model_name = ''
116             if model_id:
117                 model_name = ir_model_pool.browse(cr, uid, model_id, context=context).name
118             template_name = "%s: %s" % (model_name, tools.ustr(record.subject))
119             values = {
120                 'name': template_name,
121                 'subject': record.subject or False,
122                 'body_html': record.body or False,
123                 'model_id': model_id or False,
124                 'attachment_ids': [(6, 0, [att.id for att in record.attachment_ids])],
125             }
126             template_id = email_template.create(cr, uid, values, context=context)
127             # generate the saved template
128             template_values = record.onchange_template_id(template_id, record.composition_mode, record.model, record.res_id)['value']
129             template_values['template_id'] = template_id
130             record.write(template_values)
131             return _reopen(self, record.id, record.model)
132
133     #------------------------------------------------------
134     # Wizard validation and send
135     #------------------------------------------------------
136
137     def _get_or_create_partners_from_values(self, cr, uid, rendered_values, context=None):
138         """ Check for email_to, email_cc, partner_to """
139         partner_ids = []
140         mails = tools.email_split(rendered_values.pop('email_to', '') + ' ' + rendered_values.pop('email_cc', ''))
141         for mail in mails:
142             partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context)
143             partner_ids.append(partner_id)
144         partner_to = rendered_values.pop('partner_to', '')
145         if partner_to:
146             for partner_id in partner_to.split(','):
147                 if partner_id:  # placeholders could generate '', 3, 2 due to some empty field values
148                     partner_ids.append(int(partner_id))
149         return partner_ids
150
151     def generate_email_for_composer_batch(self, cr, uid, template_id, res_ids, context=None):
152         """ Call email_template.generate_email(), get fields relevant for
153             mail.compose.message, transform email_cc and email_to into partner_ids """
154         # filter template values
155         fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc',  'reply_to', 'attachment_ids', 'attachments', 'mail_server_id']
156         values = dict.fromkeys(res_ids, False)
157
158         template_values = self.pool.get('email.template').generate_email_batch(cr, uid, template_id, res_ids, context=context)
159         for res_id in res_ids:
160             res_id_values = dict((field, template_values[res_id][field]) for field in fields if template_values[res_id].get(field))
161             res_id_values['body'] = res_id_values.pop('body_html', '')
162
163             # transform email_to, email_cc into partner_ids
164             ctx = dict((k, v) for k, v in (context or {}).items() if not k.startswith('default_'))
165             partner_ids = self._get_or_create_partners_from_values(cr, uid, res_id_values, context=ctx)
166             # legacy template behavior: void values do not erase existing values and the
167             # related key is removed from the values dict
168             if partner_ids:
169                 res_id_values['partner_ids'] = list(partner_ids)
170
171             values[res_id] = res_id_values
172         return values
173
174     def render_message_batch(self, cr, uid, wizard, res_ids, context=None):
175         """ Override to handle templates. """
176         # generate template-based values
177         if wizard.template_id:
178             template_values = self.generate_email_for_composer_batch(cr, uid, wizard.template_id.id, res_ids, context=context)
179         else:
180             template_values = dict.fromkeys(res_ids, dict())
181         # generate composer values
182         composer_values = super(mail_compose_message, self).render_message_batch(cr, uid, wizard, res_ids, context)
183
184         for res_id in res_ids:
185             # remove attachments from template values as they should not be rendered
186             template_values[res_id].pop('attachment_ids', None)
187             # remove some keys from composer that are readonly
188             composer_values[res_id].pop('email_to', None)
189             composer_values[res_id].pop('email_cc', None)
190             composer_values[res_id].pop('partner_to', None)
191             # update template values by composer values
192             template_values[res_id].update(composer_values[res_id])
193         return template_values
194
195     def render_template_batch(self, cr, uid, template, model, res_ids, context=None):
196         return self.pool.get('email.template').render_template_batch(cr, uid, template, model, res_ids, context=context)
197
198     # Compatibility methods
199     def generate_email_for_composer(self, cr, uid, template_id, res_id, context=None):
200         return self.generate_email_for_composer_batch(cr, uid, template_id, [res_id], context)[res_id]
201
202 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: