[ADD] Mass mailing + Mass forward
[odoo/odoo.git] / addons / crm_partner_assign / wizard / crm_forward_to_partner.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU Affero General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU Affero General Public License for more details.
17 #
18 #    You should have received a copy of the GNU Affero General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22
23 import base64
24 import time
25 import re
26 from osv import osv, fields
27 import tools
28 from tools.translate import _
29
30 class crm_lead_forward_to_partner(osv.osv_memory):
31     """Forwards lead history"""
32     _name = 'crm.lead.forward.to.partner'
33     _inherit = "crm.send.mail"
34
35     _columns = {
36         'name': fields.selection([('user', 'User'), ('partner', 'Partner'), \
37                          ('email', 'Email Address')], 'Send to', required=True),
38         'user_id': fields.many2one('res.users', "User"),
39         'partner_id' : fields.many2one('res.partner', 'Partner'),
40         'address_id' : fields.many2one('res.partner.address', 'Address'),
41         'history': fields.selection([('info', 'Case Information'), ('latest', 'Latest email'), ('whole', 'Whole Story')], 'Send history', required=True),
42     }
43
44     _defaults = {
45         'name' : 'email',
46         'history': 'latest',
47         'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid],
48     }
49
50
51     def get_whole_history(self, cr, uid, ids, context=None):
52         """This function gets whole communication history and returns as top posting style
53         @param self: The object pointer
54         @param cr: the current row, from the database cursor,
55         @param uid: the current user’s ID for security checks,
56         @param ids: List of history IDs
57         @param context: A standard dictionary for contextual values
58         """
59         whole = []
60         for hist_id in ids:
61             whole.append(self.get_latest_history(cr, uid, hist_id, context=context))
62         whole = '\n\n'.join(whole)
63         return whole or ''
64
65     def get_latest_history(self, cr, uid, hist_id, context=None):
66         """This function gets latest communication and returns as top posting style
67         @param self: The object pointer
68         @param cr: the current row, from the database cursor,
69         @param uid: the current user’s ID for security checks,
70         @param hist_id: Id of latest history
71         @param context: A standard dictionary for contextual values
72         """
73         log_pool = self.pool.get('mailgate.message')
74         hist = log_pool.browse(cr, uid, hist_id, context=context)
75         header = '-------- Original Message --------'
76         sender = 'From: %s' %(hist.email_from or '')
77         to = 'To: %s' % (hist.email_to or '')
78         sentdate = 'Date: %s' % (hist.date or '')
79         desc = '\n%s'%(hist.description)
80         original = [header, sender, to, sentdate, desc]
81         original = '\n'.join(original)
82         return original
83
84     def on_change_email(self, cr, uid, ids, user):
85         """This function fills email information based on user selected
86         @param self: The object pointer
87         @param cr: the current row, from the database cursor,
88         @param uid: the current user’s ID for security checks,
89         @param ids: List of Mail’s IDs
90         @param user: Changed User id
91         @param partner: Changed Partner id
92         """
93         if not user:
94             return {'value': {'email_to': False}}
95         email = self.pool.get('res.users')._get_email_from(cr, uid, [user])[user]
96         return {'value': {'email_to': email}}
97
98     def on_change_history(self, cr, uid, ids, history_type, context=None):
99         """Gives message body according to type of history selected
100             * info: Forward the case information
101             * whole: Send the whole history
102             * latest: Send the latest histoy
103         @param self: The object pointer
104         @param cr: the current row, from the database cursor,
105         @param uid: the current user’s ID for security checks,
106         @param ids: List of history IDs
107         @param context: A standard dictionary for contextual values
108         """
109         #TODO: ids and context are not comming
110         res = False
111         res_id = context.get('active_id')
112         msg_val = self._get_case_history(cr, uid, history_type, res_id, context=context)
113         if msg_val:
114             res = {'value': {'body' : '\n\n' + msg_val}}
115         return res
116
117     def _get_case_history(self, cr, uid, history_type, res_id, context=None):
118         if not res_id:
119             return
120
121         msg_val = ''
122         case_info = self.get_lead_details(cr, uid, res_id, context=context)
123         model_pool = self.pool.get('crm.lead')
124
125         if history_type == 'info':
126             msg_val = case_info
127
128         elif history_type == 'whole':
129             log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
130             log_ids = map(lambda x: x.id, filter(lambda x: x.history, log_ids))
131             msg_val = case_info + '\n\n' + self.get_whole_history(cr, uid, log_ids, context=context)
132
133         elif history_type == 'latest':
134             log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
135             log_ids = filter(lambda x: x.history and x.id, log_ids)
136             if not log_ids:
137                 msg_val = case_info
138             else:
139                 msg_val = case_info + '\n\n' + self.get_latest_history(cr, uid, log_ids[0].id, context=context)
140
141         return msg_val
142
143     def on_change_partner(self, cr, uid, ids, partner_id):
144         """This function fills address information based on partner/user selected
145         @param self: The object pointer
146         @param cr: the current row, from the database cursor,
147         @param uid: the current user’s ID for security checks,
148         @param ids: List of Mail’s IDs
149         @param user: Changed User id
150         @param partner: Changed Partner id
151         """
152         if not partner_id:
153             return {'value' : {'email_to' : False, 'address_id': False}}
154
155         partner_obj = self.pool.get('res.partner')
156         addr = partner_obj.address_get(cr, uid, [partner_id], ['contact'])
157         data = {'address_id': addr['contact']}
158         data.update(self.on_change_address(cr, uid, ids, addr['contact'])['value'])
159
160         partner = partner_obj.browse(cr, uid, [partner_id])
161         user_id = partner and partner[0].user_id or False
162         email = user_id and user_id.user_email or ''
163         data.update({'email_cc' : email})
164         return {
165             'value' : data,
166             'domain' : {'address_id' : partner_id and "[('partner_id', '=', partner_id)]" or "[]"}
167             }
168
169     def on_change_address(self, cr, uid, ids, address_id):
170         email = ''
171         if address_id:
172             email = self.pool.get('res.partner.address').browse(cr, uid, address_id).email
173         return {'value': {'email_to' : email}}
174
175     def action_forward(self, cr, uid, ids, context=None):
176         """
177         Forward the lead to a partner
178         """
179         if context is None:
180             context = {}
181         this = self.browse(cr, uid, ids[0], context=context)
182         case_pool = self.pool.get(context.get('active_model'))
183         res_id = context and context.get('active_id', False) or False
184         case = case_pool.browse(cr, uid, res_id, context=context)
185
186         context.update({'mail': 'forward'})
187         super(crm_lead_forward_to_partner, self).action_send(cr, uid, ids, context=context)
188
189         to_write = {'date_assign': time.strftime('%Y-%m-%d')}
190         if (this.name == 'partner' and this.partner_id):
191             to_write['partner_assigned_id'] = this.partner_id.id
192
193         if this.name == 'user':
194             to_write.update({'user_id' : this.user_id.id})
195         email_re = r'([^ ,<@]+@[^> ,]+)'
196         email_cc = re.findall(email_re, case.email_cc or '')
197         new_cc = []
198         if case.email_cc:
199             new_cc.append(case.email_cc)
200         for to in this.email_to.split(','):
201             email_to = re.findall(email_re, to)
202             email_to = email_to and email_to[0] or ''
203             if email_to not in email_cc:
204                 new_cc.append(to)
205         to_write.update({'email_cc' : ', '.join(new_cc) })
206         case_pool.write(cr, uid, case.id, to_write, context=context)
207
208         return {'type': 'ir.actions.act_window_close'}
209
210     def get_lead_details(self, cr, uid, lead_id, context=None):
211         template = ["""Dear,
212
213 Below is possibly an interesting lead for you.
214
215 OpenERP Leads are now forwarded to our trusted partners, through our OpenERP CRM.
216 We hope that this one will provide you an interesting project, as they've recently contacted us showing interest in our software.
217
218 Please keep your account manager informed about the advancements of this lead or if you are not able to answer to its requests by replying to this email. This way, we can keep track of closed leads or forward them to other partners.
219
220 Please don't forget to propose our OpenERP Publisher's Warranty at the beginning of your implementation projects, together with your services quotation. The Warranty will provide unlimited bugfixing that will avoid you waste time on bugs detected during the implementation. It also provides free migration services for the current stable version at the time of signature; otherwise if we released a new version during your implementation, the customer would not always be able to easily migrate to newer versions. Please find all related information via http://www.openerp.com/services/pricing
221
222 Kind regards, OpenERP Team
223
224             """, "\n\n"]
225         lead_proxy = self.pool.get('crm.lead')
226         lead = lead_proxy.browse(cr, uid, lead_id, context=context)
227         if not lead.type or lead.type == 'lead' or not lead.partner_address_id:
228                 field_names = [
229                     'partner_name', 'title', 'function', 'street', 'street2',
230                     'zip', 'city', 'country_id', 'state_id', 'email_from',
231                     'phone', 'fax', 'mobile', 'categ_id', 'description',
232                 ]
233
234                 for field_name in field_names:
235                     field_definition = lead_proxy._columns[field_name]
236                     value = None
237
238                     if field_definition._type == 'selection':
239                         if hasattr(field_definition.selection, '__call__'):
240                             key = field_definition.selection(lead_proxy, cr, uid, context=context)
241                         else:
242                             key = field_definition.selection
243                         value = dict(key).get(lead[field_name], lead[field_name])
244                     elif field_definition._type == 'many2one':
245                         if lead[field_name]:
246                             value = lead[field_name].name_get()[0][1]
247                     else:
248                         value = lead[field_name]
249
250                     body.append("%s: %s" % (field_definition.string, value or ''))
251         elif lead.type == 'opportunity':
252             pa = lead.partner_address_id
253             body = [
254                 "Partner: %s" % (lead.partner_id and lead.partner_id.name_get()[0][1]),
255                 "Contact: %s" % (pa.name or ''),
256                 "Title: %s" % (pa.title or ''),
257                 "Function: %s" % (pa.function or ''),
258                 "Street: %s" % (pa.street or ''),
259                 "Street2: %s" % (pa.street2 or ''),
260                 "Zip: %s" % (pa.zip or ''),
261                 "City: %s" % (pa.city or ''),
262                 "Country: %s" % (pa.country_id and pa.country_id.name_get()[0][1] or ''),
263                 "State: %s" % (pa.state_id and pa.state_id.name_get()[0][1] or ''),
264                 "Email: %s" % (pa.email or ''),
265                 "Phone: %s" % (pa.phone or ''),
266                 "Fax: %s" % (pa.fax or ''),
267                 "Mobile: %s" % (pa.mobile or ''),
268                 "Lead Category: %s" % (lead.categ_id and lead.categ_id.name or ''),
269                 "Details: %s" % (lead.description or ''),
270             ]
271         return "\n".join(template + body + ['---'])
272
273     def default_get(self, cr, uid, fields, context=None):
274         """
275         This function gets default values
276         """
277
278         if context is None:
279             context = {}
280
281         defaults = super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
282         active_id = context.get('active_id')
283         if not active_id:
284             return defaults
285
286         lead_proxy = self.pool.get('crm.lead')
287         partner_obj = self.pool.get('res.partner')
288         lead = lead_proxy.browse(cr, uid, active_id, context=context)
289
290         email_cc = ''
291         email = ''
292         if lead.partner_assigned_id:
293             partner = partner_obj.browse(cr, uid, [lead.partner_assigned_id.id])
294             user_id = partner and partner[0].user_id or False
295             email_cc = user_id and user_id.user_email or ''
296
297             addr = partner_obj.address_get(cr, uid, [partner[0].id], ['contact'])
298             email = self.pool.get('res.partner.address').browse(cr, uid, addr['contact']).email
299
300
301
302         body = self._get_case_history(cr, uid, defaults.get('history', 'latest'), lead.id, context=context)
303         defaults.update({
304             'subject' : '%s: %s - %s' % (_('Fwd'), 'Openerp lead forward', lead.name),
305             'body' : body,
306             'email_cc' : email_cc,
307             'email_to' : email,
308         })
309         return defaults
310
311 crm_lead_forward_to_partner()
312
313 class crm_lead_mass_forward_to_partner(osv.osv_memory):
314     _name = 'crm.lead.mass.forward.to.partner'
315     _inherit = 'crm.lead.forward.to.partner'
316
317     def action_mass_forward(self, cr, uid, ids, context=None):
318         if not context:
319             context = {}
320
321         active_ids = context.get('active_ids')
322         case_obj = self.pool.get('crm.lead')
323         for case in case_obj.browse(cr, uid, active_ids, context=context):
324             if case.type != "opportunity":
325                 continue
326
327             if not case.partner_assigned_id:
328                 case_obj.assign_partner(cr,uid, [case.id], context=context)
329                 case = case_obj.browse(cr, uid, case.id, context=context)
330
331             if not case.partner_assigned_id:
332                 continue
333
334             context.update({'active_id' : case.id})
335             value = self.default_get(cr, uid, ['body', 'email_to', 'email_cc', 'subject', 'history'], context=context)
336             self.write(cr, uid, ids, value, context=context)
337             self.action_forward(cr,uid, ids, context=context)
338
339         return {'type': 'ir.actions.act_window_close'}
340
341
342 crm_lead_mass_forward_to_partner()
343
344 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: