[FIX] Improved language in notification for partner creation.
[odoo/odoo.git] / addons / crm / crm_phonecall.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (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 Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 from crm import crm_base
23 from osv import fields, osv
24 from tools.translate import _
25 import crm
26 import time
27 from datetime import datetime
28
29 class crm_phonecall(crm_base, osv.osv):
30     """ Phonecall Cases """
31
32     _name = "crm.phonecall"
33     _description = "Phonecall"
34     _order = "id desc"
35     _inherit = ['mail.thread']
36     _columns = {
37         # From crm.case
38         'id': fields.integer('ID', readonly=True),
39         'name': fields.char('Call Summary', size=64, required=True),
40         'active': fields.boolean('Active', required=False),
41         'date_action_last': fields.datetime('Last Action', readonly=1),
42         'date_action_next': fields.datetime('Next Action', readonly=1),
43         'create_date': fields.datetime('Creation Date' , readonly=True),
44         'section_id': fields.many2one('crm.case.section', 'Sales Team', \
45                         select=True, help='Sales team to which Case belongs to.'),
46         'user_id': fields.many2one('res.users', 'Responsible'),
47         'partner_id': fields.many2one('res.partner', 'Partner'),
48         'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
49                                  domain="[('partner_id','=',partner_id)]"),
50         'company_id': fields.many2one('res.company', 'Company'),
51         'description': fields.text('Description'),
52         'state': fields.selection([
53                                     ('draft', 'Draft'),
54                                     ('open', 'Todo'),
55                                     ('cancel', 'Cancelled'),
56                                     ('done', 'Held'),
57                                     ('pending', 'Not Held'),
58                                 ], 'State', size=16, readonly=True,
59                                   help='The state is set to \'Todo\', when a case is created.\
60                                   \nIf the case is in progress the state is set to \'Open\'.\
61                                   \nWhen the call is over, the state is set to \'Held\'.\
62                                   \nIf the call needs to be done then the state is set to \'Not Held\'.'),
63         'email_from': fields.char('Email', size=128, help="These people will receive email."),
64         'date_open': fields.datetime('Opened', readonly=True),
65         # phonecall fields
66         'duration': fields.float('Duration', help="Duration in Minutes"),
67         'categ_id': fields.many2one('crm.case.categ', 'Category', \
68                         domain="['|',('section_id','=',section_id),('section_id','=',False),\
69                         ('object_id.model', '=', 'crm.phonecall')]"),
70         'partner_phone': fields.char('Phone', size=32),
71         'partner_contact': fields.related('partner_address_id', 'name', \
72                                  type="char", string="Contact", size=128),
73         'partner_mobile': fields.char('Mobile', size=32),
74         'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
75         'date_closed': fields.datetime('Closed', readonly=True),
76         'date': fields.datetime('Date'),
77         'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
78         'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
79     }
80
81     def _get_default_state(self, cr, uid, context=None):
82         if context and context.get('default_state', False):
83             return context.get('default_state')
84         return 'open'
85
86     _defaults = {
87         'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
88         'priority': crm.AVAILABLE_PRIORITIES[2][0],
89         'state':  _get_default_state,
90         'user_id': lambda self,cr,uid,ctx: uid,
91         'active': 1,
92     }
93
94     def get_needaction_user_id(self, cr, uid, ids, name, arg, context=None):
95         result = {}
96         for obj in self.browse(cr, uid, ids, context=context):
97             result[obj.id] = False
98             if (obj.state == 'draft' and obj.user_id):
99                 result[obj.id] = obj.user_id.id
100         return result
101
102     def _case_cancel_notification(self, cr, uid, ids, context=None):
103         for phonecall in self.browse(cr, uid, ids, context=context):
104             message = _("Phonecall has been <b>cancelled</b>.")
105             phonecall.message_append_note( _('System notification'),
106                         message, type='notification', context=context)
107         return True
108
109     def _case_pending_notification(self, cr, uid, ids, context=None):
110         for phonecall in self.browse(cr, uid, ids, context=context):
111             message = _("Phonecall is <b>pending</b>.")
112             phonecall.message_append_note('' ,message)
113         return True
114
115     def done_notification(self, cr, uid, ids, context=None):
116         for phonecall in self.browse(cr, uid, ids, context=context):
117             message = _("Phonecall has been <b>done</b>.")
118             phonecall.message_append_note('', message)
119         return True
120
121     def _case_open_notification(self, cr, uid, ids, context=None):
122         for phonecall in self.browse(cr, uid, ids, context=context):
123             phonecall.message_subscribe([phonecall.user_id.id], context=context)
124             message = _("Phonecall has been <b>opened</b>.")
125             phonecall.message_append_note('' ,message)
126         return True
127
128     def _case_partner_notification(self, cr, uid, ids, context=None):
129         for phonecall in self.browse(cr, uid, ids, context=context):
130             message = _("Partner has been <b>created</b>")
131             phonecall.message_append_note('' ,message)
132         return True
133
134     # From crm.case
135     def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
136         res = super(crm_phonecall, self).onchange_partner_address_id(cr, uid, ids, add, email)
137         res.setdefault('value', {})
138         if add:
139             address = self.pool.get('res.partner.address').browse(cr, uid, add)
140             res['value']['partner_phone'] = address.phone
141             res['value']['partner_mobile'] = address.mobile
142         return res
143
144     def case_close(self, cr, uid, ids, context=None):
145         """Overrides close for crm_case for setting close date
146         """
147         res = True
148         for phone in self.browse(cr, uid, ids):
149             phone_id = phone.id
150             data = {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}
151             if phone.duration <=0:
152                 duration = datetime.now() - datetime.strptime(phone.date, '%Y-%m-%d %H:%M:%S')
153                 data.update({'duration': duration.seconds/float(60)})
154             res = super(crm_phonecall, self).case_close(cr, uid, [phone_id], context)
155             self.write(cr, uid, [phone_id], data)
156             self.done_notification(cr, uid, [phone_id], context);
157         return res
158
159     def case_reset(self, cr, uid, ids, context=None):
160         """Resets case as Todo
161         """
162         res = super(crm_phonecall, self).case_reset(cr, uid, ids, context)
163         self.write(cr, uid, ids, {'duration': 0.0, 'state':'open'})
164         self._case_open_notification(cr, uid, ids, context=context)
165         return res
166
167
168     def case_open(self, cr, uid, ids, context=None):
169         """Overrides cancel for crm_case for setting Open Date
170         """
171         res = super(crm_phonecall, self).case_open(cr, uid, ids, context)
172         self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')})
173         return res
174
175     def schedule_another_phonecall(self, cr, uid, ids, schedule_time, call_summary, \
176                     user_id=False, section_id=False, categ_id=False, action='schedule', context=None):
177         """
178         action :('schedule','Schedule a call'), ('log','Log a call')
179         """
180         model_data = self.pool.get('ir.model.data')
181         phonecall_dict = {}
182         if not categ_id:
183             res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
184             if res_id:
185                 categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
186         for call in self.browse(cr, uid, ids, context=context):
187             if not section_id:
188                 section_id = call.section_id and call.section_id.id or False
189             if not user_id:
190                 user_id = call.user_id and call.user_id.id or False
191             vals = {
192                     'name' : call_summary,
193                     'user_id' : user_id or False,
194                     'categ_id' : categ_id or False,
195                     'description' : call.description or False,
196                     'date' : schedule_time,
197                     'section_id' : section_id or False,
198                     'partner_id': call.partner_id and call.partner_id.id or False,
199                     'partner_address_id': call.partner_address_id and call.partner_address_id.id or False,
200                     'partner_phone' : call.partner_phone,
201                     'partner_mobile' : call.partner_mobile,
202                     'priority': call.priority,
203             }
204             new_id = self.create(cr, uid, vals, context=context)
205             self.case_open(cr, uid, [new_id])
206             if action == 'log':
207                 self.case_close(cr, uid, [new_id])
208             phonecall_dict[call.id] = new_id
209         return phonecall_dict
210
211     def _call_create_partner(self, cr, uid, phonecall, context=None):
212         partner = self.pool.get('res.partner')
213         partner_id = partner.create(cr, uid, {
214                     'name': phonecall.name,
215                     'user_id': phonecall.user_id.id,
216                     'comment': phonecall.description,
217                     'address': []
218         })
219         return partner_id
220
221     def _call_set_partner(self, cr, uid, ids, partner_id, context=None):
222         self.write(cr, uid, ids, {'partner_id' : partner_id}, context=context)
223         self._case_partner_notification(cr, uid, ids, context)
224
225     def _call_create_partner_address(self, cr, uid, phonecall, partner_id, context=None):
226         address = self.pool.get('res.partner.address')
227         return address.create(cr, uid, {
228                     'partner_id': partner_id,
229                     'name': phonecall.name,
230                     'phone': phonecall.partner_phone,
231         })
232
233     def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
234         """
235         This function convert partner based on action.
236         if action is 'create', create new partner with contact and assign lead to new partner_id.
237         otherwise assign lead to specified partner_id
238         """
239         if context is None:
240             context = {}
241         partner_ids = {}
242         for call in self.browse(cr, uid, ids, context=context):
243             if action == 'create':
244                if not partner_id:
245                    partner_id = self._call_create_partner(cr, uid, call, context=context)
246                self._call_create_partner_address(cr, uid, call, partner_id, context=context)
247             self._call_set_partner(cr, uid, [call.id], partner_id, context=context)
248             partner_ids[call.id] = partner_id
249         return partner_ids
250
251
252     def redirect_phonecall_view(self, cr, uid, phonecall_id, context=None):
253         model_data = self.pool.get('ir.model.data')
254         # Select the view
255         tree_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_tree_view')
256         form_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_form_view')
257         search_view = model_data.get_object_reference(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
258         value = {
259                 'name': _('Phone Call'),
260                 'view_type': 'form',
261                 'view_mode': 'tree,form',
262                 'res_model': 'crm.phonecall',
263                 'res_id' : int(phonecall_id),
264                 'views': [(form_view and form_view[1] or False, 'form'), (tree_view and tree_view[1] or False, 'tree'), (False, 'calendar')],
265                 'type': 'ir.actions.act_window',
266                 'search_view_id': search_view and search_view[1] or False,
267         }
268         return value
269
270
271     def convert_opportunity(self, cr, uid, ids, opportunity_summary=False, partner_id=False, planned_revenue=0.0, probability=0.0, context=None):
272         partner = self.pool.get('res.partner')
273         address = self.pool.get('res.partner.address')
274         opportunity = self.pool.get('crm.lead')
275         opportunity_dict = {}
276         default_contact = False
277         for call in self.browse(cr, uid, ids, context=context):
278             if not partner_id:
279                 partner_id = call.partner_id and call.partner_id.id or False
280             if partner_id:
281                 address_id = partner.address_get(cr, uid, [partner_id])['default']
282                 if address_id:
283                     default_contact = address.browse(cr, uid, address_id, context=context)
284             opportunity_id = opportunity.create(cr, uid, {
285                             'name': opportunity_summary or call.name,
286                             'planned_revenue': planned_revenue,
287                             'probability': probability,
288                             'partner_id': partner_id or False,
289                             'partner_address_id': default_contact and default_contact.id,
290                             'phone': default_contact and default_contact.phone,
291                             'mobile': default_contact and default_contact.mobile,
292                             'section_id': call.section_id and call.section_id.id or False,
293                             'description': call.description or False,
294                             'priority': call.priority,
295                             'type': 'opportunity',
296                             'phone': call.partner_phone or False,
297                             'email_from': default_contact and default_contact.email,
298                         })
299             vals = {
300                     'partner_id': partner_id,
301                     'opportunity_id' : opportunity_id,
302             }
303             self.write(cr, uid, [call.id], vals)
304             self.case_close(cr, uid, [call.id])
305             opportunity.case_open(cr, uid, [opportunity_id])
306             opportunity_dict[call.id] = opportunity_id
307         return opportunity_dict
308
309     def action_make_meeting(self, cr, uid, ids, context=None):
310         """
311         This opens Meeting's calendar view to schedule meeting on current Phonecall
312         @return : Dictionary value for created Meeting view
313         """
314         value = {}
315         for phonecall in self.browse(cr, uid, ids, context=context):
316             data_obj = self.pool.get('ir.model.data')
317
318             # Get meeting views
319             result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter')
320             res = data_obj.read(cr, uid, result, ['res_id'])
321             id1 = data_obj._get_id(cr, uid, 'crm', 'crm_case_calendar_view_meet')
322             id2 = data_obj._get_id(cr, uid, 'crm', 'crm_case_form_view_meet')
323             id3 = data_obj._get_id(cr, uid, 'crm', 'crm_case_tree_view_meet')
324             if id1:
325                 id1 = data_obj.browse(cr, uid, id1, context=context).res_id
326             if id2:
327                 id2 = data_obj.browse(cr, uid, id2, context=context).res_id
328             if id3:
329                 id3 = data_obj.browse(cr, uid, id3, context=context).res_id
330
331             context = {
332                         'default_phonecall_id': phonecall.id,
333                         'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
334                         'default_email': phonecall.email_from ,
335                         'default_name': phonecall.name
336                     }
337
338             value = {
339                 'name': _('Meetings'),
340                 'domain' : "[('user_id','=',%s)]" % (uid),
341                 'context': context,
342                 'view_type': 'form',
343                 'view_mode': 'calendar,form,tree',
344                 'res_model': 'crm.meeting',
345                 'view_id': False,
346                 'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
347                 'type': 'ir.actions.act_window',
348                 'search_view_id': res['res_id'],
349                 'nodestroy': True
350                 }
351
352         return value
353
354 crm_phonecall()
355
356
357 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: