[FIX] crm_lead: yml test: as crm_add_note has been removed, change a test from add_no...
[odoo/odoo.git] / addons / crm / crm_phonecall.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-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 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 base_status.base_state import base_state
23 import crm
24 from datetime import datetime
25 from osv import fields, osv
26 import time
27 from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP
28 from tools.translate import _
29
30 class crm_phonecall(base_state, osv.osv):
31     """ Model for CRM phonecalls """
32     _name = "crm.phonecall"
33     _description = "Phonecall"
34     _order = "id desc"
35     _inherit = ['ir.needaction_mixin', 'mail.thread']
36     _columns = {
37         # base_state required fields
38         'date_action_last': fields.datetime('Last Action', readonly=1),
39         'date_action_next': fields.datetime('Next Action', readonly=1),
40         'create_date': fields.datetime('Creation Date' , readonly=True),
41         'section_id': fields.many2one('crm.case.section', 'Sales Team', \
42                         select=True, help='Sales team to which Case belongs to.'),
43         'user_id': fields.many2one('res.users', 'Responsible'),
44         'partner_id': fields.many2one('res.partner', 'Partner'),
45         'company_id': fields.many2one('res.company', 'Company'),
46         'description': fields.text('Description'),
47         'state': fields.selection([ ('draft', 'Draft'),
48                                     ('open', 'Confirmed'),
49                                     ('pending', 'Not Held'),
50                                     ('cancel', 'Cancelled'),
51                                     ('done', 'Held'),],
52                         string='Status', size=16, readonly=True,
53                         help='The state is set to \'Todo\', when a case is created.\
54                                 If the case is in progress the state is set to \'Open\'.\
55                                 When the call is over, the state is set to \'Held\'.\
56                                 If the call needs to be done then the state is set to \'Not Held\'.'),
57         'email_from': fields.char('Email', size=128, help="These people will receive email."),
58         'date_open': fields.datetime('Opened', readonly=True),
59         # phonecall fields
60         'name': fields.char('Call Summary', size=64, required=True),
61         'active': fields.boolean('Active', required=False),
62         'duration': fields.float('Duration', help="Duration in Minutes"),
63         'categ_id': fields.many2one('crm.case.categ', 'Category', \
64                         domain="['|',('section_id','=',section_id),('section_id','=',False),\
65                         ('object_id.model', '=', 'crm.phonecall')]"),
66         'partner_phone': fields.char('Phone', size=32),
67         'partner_mobile': fields.char('Mobile', size=32),
68         'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
69         'date_closed': fields.datetime('Closed', readonly=True),
70         'date': fields.datetime('Date'),
71         'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
72     }
73
74     def _get_default_state(self, cr, uid, context=None):
75         if context and context.get('default_state', False):
76             return context.get('default_state')
77         return 'open'
78
79     _defaults = {
80         'date': fields.datetime.now,
81         'priority': crm.AVAILABLE_PRIORITIES[2][0],
82         'state':  _get_default_state,
83         'user_id': lambda self,cr,uid,ctx: uid,
84     }
85
86     def create(self, cr, uid, vals, context=None):
87         obj_id = super(crm_phonecall, self).create(cr, uid, vals, context)
88         for phonecall in self.browse(cr, uid, [obj_id], context=context):
89             if not phonecall.opportunity_id:
90                 self.case_open_send_note(cr, uid, [obj_id], context=context)
91         return obj_id
92
93     def case_close(self, cr, uid, ids, context=None):
94         """ Overrides close for crm_case for setting duration """
95         res = True
96         for phone in self.browse(cr, uid, ids, context=context):
97             phone_id = phone.id
98             data = {}
99             if phone.duration <=0:
100                 duration = datetime.now() - datetime.strptime(phone.date, DEFAULT_SERVER_DATETIME_FORMAT)
101                 data['duration'] = duration.seconds/float(60)
102             res = super(crm_phonecall, self).case_close(cr, uid, [phone_id], context=context)
103             self.write(cr, uid, [phone_id], data, context=context)
104         return res
105
106     def case_reset(self, cr, uid, ids, context=None):
107         """Resets case as Todo
108         """
109         res = super(crm_phonecall, self).case_reset(cr, uid, ids, context)
110         self.write(cr, uid, ids, {'duration': 0.0, 'state':'open'}, context=context)
111         return res
112
113     def schedule_another_phonecall(self, cr, uid, ids, schedule_time, call_summary, \
114                     user_id=False, section_id=False, categ_id=False, action='schedule', context=None):
115         """
116         action :('schedule','Schedule a call'), ('log','Log a call')
117         """
118         model_data = self.pool.get('ir.model.data')
119         phonecall_dict = {}
120         if not categ_id:
121             res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
122             if res_id:
123                 categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
124         for call in self.browse(cr, uid, ids, context=context):
125             if not section_id:
126                 section_id = call.section_id and call.section_id.id or False
127             if not user_id:
128                 user_id = call.user_id and call.user_id.id or False
129             vals = {
130                     'name' : call_summary,
131                     'user_id' : user_id or False,
132                     'categ_id' : categ_id or False,
133                     'description' : call.description or False,
134                     'date' : schedule_time,
135                     'section_id' : section_id or False,
136                     'partner_id': call.partner_id and call.partner_id.id or False,
137                     'partner_phone' : call.partner_phone,
138                     'partner_mobile' : call.partner_mobile,
139                     'priority': call.priority,
140             }
141             new_id = self.create(cr, uid, vals, context=context)
142             if action == 'log':
143                 self.case_close(cr, uid, [new_id])
144             phonecall_dict[call.id] = new_id
145         return phonecall_dict
146
147     def _call_create_partner(self, cr, uid, phonecall, context=None):
148         partner = self.pool.get('res.partner')
149         partner_id = partner.create(cr, uid, {
150                     'name': phonecall.name,
151                     'user_id': phonecall.user_id.id,
152                     'comment': phonecall.description,
153                     'address': []
154         })
155         return partner_id
156
157     def _call_set_partner(self, cr, uid, ids, partner_id, context=None):
158         write_res = self.write(cr, uid, ids, {'partner_id' : partner_id}, context=context)
159         self._call_set_partner_send_note(cr, uid, ids, context)
160         return write_res
161
162     def _call_create_partner_address(self, cr, uid, phonecall, partner_id, context=None):
163         address = self.pool.get('res.partner')
164         return address.create(cr, uid, {
165                     'parent_id': partner_id,
166                     'name': phonecall.name,
167                     'phone': phonecall.partner_phone,
168         })
169
170     def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
171         """
172         This function convert partner based on action.
173         if action is 'create', create new partner with contact and assign lead to new partner_id.
174         otherwise assign lead to specified partner_id
175         """
176         if context is None:
177             context = {}
178         partner_ids = {}
179         for call in self.browse(cr, uid, ids, context=context):
180             if action == 'create':
181                if not partner_id:
182                    partner_id = self._call_create_partner(cr, uid, call, context=context)
183                self._call_create_partner_address(cr, uid, call, partner_id, context=context)
184             self._call_set_partner(cr, uid, [call.id], partner_id, context=context)
185             partner_ids[call.id] = partner_id
186         return partner_ids
187
188
189     def redirect_phonecall_view(self, cr, uid, phonecall_id, context=None):
190         model_data = self.pool.get('ir.model.data')
191         # Select the view
192         tree_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_tree_view')
193         form_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_form_view')
194         search_view = model_data.get_object_reference(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
195         value = {
196                 'name': _('Phone Call'),
197                 'view_type': 'form',
198                 'view_mode': 'tree,form',
199                 'res_model': 'crm.phonecall',
200                 'res_id' : int(phonecall_id),
201                 'views': [(form_view and form_view[1] or False, 'form'), (tree_view and tree_view[1] or False, 'tree'), (False, 'calendar')],
202                 'type': 'ir.actions.act_window',
203                 'search_view_id': search_view and search_view[1] or False,
204         }
205         return value
206
207
208     def convert_opportunity(self, cr, uid, ids, opportunity_summary=False, partner_id=False, planned_revenue=0.0, probability=0.0, context=None):
209         partner = self.pool.get('res.partner')
210         opportunity = self.pool.get('crm.lead')
211         opportunity_dict = {}
212         default_contact = False
213         for call in self.browse(cr, uid, ids, context=context):
214             if not partner_id:
215                 partner_id = call.partner_id and call.partner_id.id or False
216             if partner_id:
217                 address_id = partner.address_get(cr, uid, [partner_id])['default']
218                 if address_id:
219                     default_contact = partner.browse(cr, uid, address_id, context=context)
220             opportunity_id = opportunity.create(cr, uid, {
221                             'name': opportunity_summary or call.name,
222                             'planned_revenue': planned_revenue,
223                             'probability': probability,
224                             'partner_id': partner_id or False,
225                             'mobile': default_contact and default_contact.mobile,
226                             'section_id': call.section_id and call.section_id.id or False,
227                             'description': call.description or False,
228                             'priority': call.priority,
229                             'type': 'opportunity',
230                             'phone': call.partner_phone or False,
231                             'email_from': default_contact and default_contact.email,
232                         })
233             vals = {
234                     'partner_id': partner_id,
235                     'opportunity_id' : opportunity_id,
236             }
237             self.write(cr, uid, [call.id], vals)
238             self.case_close(cr, uid, [call.id])
239             opportunity.case_open(cr, uid, [opportunity_id])
240             opportunity_dict[call.id] = opportunity_id
241         return opportunity_dict
242
243     def action_make_meeting(self, cr, uid, ids, context=None):
244         """ This opens Meeting's calendar view to schedule meeting on current Phonecall
245             @return : Dictionary value for created Meeting view
246         """
247         phonecall = self.browse(cr, uid, ids[0], context)
248         res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'base_calendar', 'action_crm_meeting', context)
249         res['context'] = {
250             'default_phonecall_id': phonecall.id,
251             'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
252             'default_user_id': uid,
253             'default_email_from': phonecall.email_from,
254             'default_state': 'open',
255             'default_name': phonecall.name,
256         }
257         return res
258     
259     # ----------------------------------------
260     # OpenChatter
261     # ----------------------------------------
262
263     def case_get_note_msg_prefix(self, cr, uid, id, context=None):
264         return 'Phonecall'
265     
266     def case_reset_send_note(self, cr, uid, ids, context=None):
267         message = _('Phonecall has been <b>reset and set as open</b>.')
268         return self.message_append_note(cr, uid, ids, body=message, context=context)
269
270     def case_open_send_note(self, cr, uid, ids, context=None):
271         lead_obj = self.pool.get('crm.lead')
272         for phonecall in self.browse(cr, uid, ids, context=context):
273             phonecall.message_subscribe([phonecall.user_id.id], context=context)
274             if phonecall.opportunity_id:
275                 lead = phonecall.opportunity_id
276                 # convert datetime field to a datetime, using server format, then
277                 # convert it to the user TZ and re-render it with %Z to add the timezone
278                 phonecall_datetime = fields.DT.datetime.strptime(phonecall.date, DEFAULT_SERVER_DATETIME_FORMAT)
279                 phonecall_date_str = fields.datetime.context_timestamp(cr, uid, phonecall_datetime, context=context).strftime(DATETIME_FORMATS_MAP['%+'] + " (%Z)")
280                 message = _("Phonecall linked to the opportunity <em>%s</em> has been <b>created</b> and <b>scheduled</b> on <em>%s</em>.") % (lead.name, phonecall_date_str)
281             else:
282                 message = _("Phonecall has been <b>created and opened</b>.")
283             phonecall.message_append_note(body=message)
284         return True
285
286     def _call_set_partner_send_note(self, cr, uid, ids, context=None):
287         return self.message_append_note(cr, uid, ids, body=_("Partner has been <b>created</b>"), context=context)
288
289
290 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: