1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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.
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.
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/>.
20 ##############################################################################
22 from crm import crm_base
23 from osv import fields, osv
24 from tools.translate import _
27 from datetime import datetime
29 class crm_phonecall(crm_base, osv.osv):
30 """ Phonecall Cases """
32 _name = "crm.phonecall"
33 _description = "Phonecall"
35 _inherit = ['mail.thread']
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([
55 ('cancel', 'Cancelled'),
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),
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)]),
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')
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,
94 def get_needaction_user_id(self, cr, uid, ids, name, arg, context=None):
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
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)
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)
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)
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)
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)
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', {})
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
144 def case_close(self, cr, uid, ids, context=None):
145 """Overrides close for crm_case for setting close date
148 for phone in self.browse(cr, uid, ids):
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);
159 def case_reset(self, cr, uid, ids, context=None):
160 """Resets case as Todo
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)
168 def case_open(self, cr, uid, ids, context=None):
169 """Overrides cancel for crm_case for setting Open Date
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')})
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):
178 action :('schedule','Schedule a call'), ('log','Log a call')
180 model_data = self.pool.get('ir.model.data')
183 res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
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):
188 section_id = call.section_id and call.section_id.id or False
190 user_id = call.user_id and call.user_id.id or False
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,
204 new_id = self.create(cr, uid, vals, context=context)
205 self.case_open(cr, uid, [new_id])
207 self.case_close(cr, uid, [new_id])
208 phonecall_dict[call.id] = new_id
209 return phonecall_dict
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,
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)
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,
233 def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
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
242 for call in self.browse(cr, uid, ids, context=context):
243 if action == 'create':
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
252 def redirect_phonecall_view(self, cr, uid, phonecall_id, context=None):
253 model_data = self.pool.get('ir.model.data')
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')
259 'name': _('Phone Call'),
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,
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):
279 partner_id = call.partner_id and call.partner_id.id or False
281 address_id = partner.address_get(cr, uid, [partner_id])['default']
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,
300 'partner_id': partner_id,
301 'opportunity_id' : opportunity_id,
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
309 def action_make_meeting(self, cr, uid, ids, context=None):
311 This opens Meeting's calendar view to schedule meeting on current Phonecall
312 @return : Dictionary value for created Meeting view
315 for phonecall in self.browse(cr, uid, ids, context=context):
316 data_obj = self.pool.get('ir.model.data')
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')
325 id1 = data_obj.browse(cr, uid, id1, context=context).res_id
327 id2 = data_obj.browse(cr, uid, id2, context=context).res_id
329 id3 = data_obj.browse(cr, uid, id3, context=context).res_id
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
339 'name': _('Meetings'),
340 'domain' : "[('user_id','=',%s)]" % (uid),
343 'view_mode': 'calendar,form,tree',
344 'res_model': 'crm.meeting',
346 'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
347 'type': 'ir.actions.act_window',
348 'search_view_id': res['res_id'],
357 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: