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"
37 'id': fields.integer('ID', readonly=True),
38 'name': fields.char('Call Summary', size=64, required=True),
39 'active': fields.boolean('Active', required=False),
40 'date_action_last': fields.datetime('Last Action', readonly=1),
41 'date_action_next': fields.datetime('Next Action', readonly=1),
42 'create_date': fields.datetime('Creation Date' , readonly=True),
43 'section_id': fields.many2one('crm.case.section', 'Sales Team', \
44 select=True, help='Sales team to which Case belongs to.'),
45 'user_id': fields.many2one('res.users', 'Responsible'),
46 'partner_id': fields.many2one('res.partner', 'Partner'),
47 'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
48 domain="[('partner_id','=',partner_id)]"),
49 'company_id': fields.many2one('res.company', 'Company'),
50 'description': fields.text('Description'),
51 'state': fields.selection([
54 ('cancel', 'Cancelled'),
56 ('pending', 'Not Held'),
57 ], 'State', size=16, readonly=True,
58 help='The state is set to \'Todo\', when a case is created.\
59 \nIf the case is in progress the state is set to \'Open\'.\
60 \nWhen the call is over, the state is set to \'Held\'.\
61 \nIf the call needs to be done then the state is set to \'Not Held\'.'),
62 'email_from': fields.char('Email', size=128, help="These people will receive email."),
63 'date_open': fields.datetime('Opened', readonly=True),
65 'duration': fields.float('Duration', help="Duration in Minutes"),
66 'categ_id': fields.many2one('crm.case.categ', 'Category', \
67 domain="['|',('section_id','=',section_id),('section_id','=',False),\
68 ('object_id.model', '=', 'crm.phonecall')]"),
69 'partner_phone': fields.char('Phone', size=32),
70 'partner_contact': fields.related('partner_address_id', 'name', \
71 type="char", string="Contact", size=128),
72 'partner_mobile': fields.char('Mobile', size=32),
73 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
74 'date_closed': fields.datetime('Closed', readonly=True),
75 'date': fields.datetime('Date'),
76 'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
77 'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
80 def _get_default_state(self, cr, uid, context=None):
81 if context and context.get('default_state', False):
82 return context.get('default_state')
86 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
87 'priority': crm.AVAILABLE_PRIORITIES[2][0],
88 'state': _get_default_state,
89 'user_id': lambda self,cr,uid,ctx: uid,
94 def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
95 res = super(crm_phonecall, self).onchange_partner_address_id(cr, uid, ids, add, email)
96 res.setdefault('value', {})
98 address = self.pool.get('res.partner.address').browse(cr, uid, add)
99 res['value']['partner_phone'] = address.phone
100 res['value']['partner_mobile'] = address.mobile
103 def case_close(self, cr, uid, ids, *args):
104 """Overrides close for crm_case for setting close date
107 for phone in self.browse(cr, uid, ids):
109 data = {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}
110 if phone.duration <=0:
111 duration = datetime.now() - datetime.strptime(phone.date, '%Y-%m-%d %H:%M:%S')
112 data.update({'duration': duration.seconds/float(60)})
113 res = super(crm_phonecall, self).case_close(cr, uid, [phone_id], args)
114 self.write(cr, uid, [phone_id], data)
117 def case_reset(self, cr, uid, ids, *args):
118 """Resets case as Todo
120 res = super(crm_phonecall, self).case_reset(cr, uid, ids, args, 'crm.phonecall')
121 self.write(cr, uid, ids, {'duration': 0.0, 'state':'open'})
125 def case_open(self, cr, uid, ids, *args):
126 """Overrides cancel for crm_case for setting Open Date
128 res = super(crm_phonecall, self).case_open(cr, uid, ids, *args)
129 self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')})
132 def schedule_another_phonecall(self, cr, uid, ids, schedule_time, call_summary, \
133 user_id=False, section_id=False, categ_id=False, action='schedule', context=None):
135 action :('schedule','Schedule a call'), ('log','Log a call')
137 model_data = self.pool.get('ir.model.data')
140 res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
142 categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
143 for call in self.browse(cr, uid, ids, context=context):
145 section_id = call.section_id and call.section_id.id or False
147 user_id = call.user_id and call.user_id.id or False
149 'name' : call_summary,
150 'user_id' : user_id or False,
151 'categ_id' : categ_id or False,
152 'description' : call.description or False,
153 'date' : schedule_time,
154 'section_id' : section_id or False,
155 'partner_id': call.partner_id and call.partner_id.id or False,
156 'partner_address_id': call.partner_address_id and call.partner_address_id.id or False,
157 'partner_phone' : call.partner_phone,
158 'partner_mobile' : call.partner_mobile,
159 'priority': call.priority,
162 new_id = self.create(cr, uid, vals, context=context)
163 self.case_open(cr, uid, [new_id])
165 self.case_close(cr, uid, [new_id])
166 phonecall_dict[call.id] = new_id
167 return phonecall_dict
169 def _call_create_partner(self, cr, uid, phonecall, context=None):
170 partner = self.pool.get('res.partner')
171 partner_id = partner.create(cr, uid, {
172 'name': phonecall.name,
173 'user_id': phonecall.user_id.id,
174 'comment': phonecall.description,
179 def _call_set_partner(self, cr, uid, ids, partner_id, context=None):
180 return self.write(cr, uid, ids, {'partner_id' : partner_id}, context=context)
182 def _call_create_partner_address(self, cr, uid, phonecall, partner_id, context=None):
183 address = self.pool.get('res.partner.address')
184 return address.create(cr, uid, {
185 'partner_id': partner_id,
186 'name': phonecall.name,
187 'phone': phonecall.partner_phone,
190 def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
192 This function convert partner based on action.
193 if action is 'create', create new partner with contact and assign lead to new partner_id.
194 otherwise assign lead to specified partner_id
199 force_partner_id = partner_id
200 for call in self.browse(cr, uid, ids, context=context):
201 if action == 'create':
202 partner_id = force_partner_id or self._call_create_partner(cr, uid, call, context=context)
203 self._call_create_partner_address(cr, uid, call, partner_id, context=context)
204 self._call_set_partner(cr, uid, [call.id], partner_id, context=context)
205 partner_ids[call.id] = partner_id
209 def redirect_phonecall_view(self, cr, uid, phonecall_id, context=None):
210 model_data = self.pool.get('ir.model.data')
212 tree_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_tree_view')
213 form_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_form_view')
214 search_view = model_data.get_object_reference(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
216 'name': _('Phone Call'),
218 'view_mode': 'tree,form',
219 'res_model': 'crm.phonecall',
220 'res_id' : int(phonecall_id),
221 'views': [(form_view and form_view[1] or False, 'form'), (tree_view and tree_view[1] or False, 'tree'), (False, 'calendar')],
222 'type': 'ir.actions.act_window',
223 'search_view_id': search_view and search_view[1] or False,
228 def convert_opportunity(self, cr, uid, ids, opportunity_summary=False, partner_id=False, planned_revenue=0.0, probability=0.0, context=None):
229 partner = self.pool.get('res.partner')
230 address = self.pool.get('res.partner.address')
231 opportunity = self.pool.get('crm.lead')
232 opportunity_dict = {}
233 default_contact = False
234 for call in self.browse(cr, uid, ids, context=context):
236 partner_id = call.partner_id and call.partner_id.id or False
238 address_id = partner.address_get(cr, uid, [partner_id])['default']
240 default_contact = address.browse(cr, uid, address_id, context=context)
241 opportunity_id = opportunity.create(cr, uid, {
242 'name': opportunity_summary or call.name,
243 'planned_revenue': planned_revenue,
244 'probability': probability,
245 'partner_id': partner_id or False,
246 'partner_address_id': default_contact and default_contact.id,
247 'phone': default_contact and default_contact.phone,
248 'mobile': default_contact and default_contact.mobile,
249 'section_id': call.section_id and call.section_id.id or False,
250 'description': call.description or False,
251 'priority': call.priority,
252 'type': 'opportunity',
253 'phone': call.partner_phone or False,
254 'email_from': default_contact and default_contact.email,
257 'partner_id': partner_id,
258 'opportunity_id' : opportunity_id,
260 self.write(cr, uid, [call.id], vals)
261 self.case_close(cr, uid, [call.id])
262 opportunity.case_open(cr, uid, [opportunity_id])
263 opportunity_dict[call.id] = opportunity_id
264 return opportunity_dict
266 def action_make_meeting(self, cr, uid, ids, context=None):
268 This opens Meeting's calendar view to schedule meeting on current Phonecall
269 @return : Dictionary value for created Meeting view
272 for phonecall in self.browse(cr, uid, ids, context=context):
273 data_obj = self.pool.get('ir.model.data')
276 result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter')
277 res = data_obj.read(cr, uid, result, ['res_id'])
278 id1 = data_obj._get_id(cr, uid, 'crm', 'crm_case_calendar_view_meet')
279 id2 = data_obj._get_id(cr, uid, 'crm', 'crm_case_form_view_meet')
280 id3 = data_obj._get_id(cr, uid, 'crm', 'crm_case_tree_view_meet')
282 id1 = data_obj.browse(cr, uid, id1, context=context).res_id
284 id2 = data_obj.browse(cr, uid, id2, context=context).res_id
286 id3 = data_obj.browse(cr, uid, id3, context=context).res_id
289 'default_phonecall_id': phonecall.id,
290 'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
291 'default_email': phonecall.email_from ,
292 'default_name': phonecall.name
296 'name': _('Meetings'),
297 'domain' : "[('user_id','=',%s)]" % (uid),
300 'view_mode': 'calendar,form,tree',
301 'res_model': 'crm.meeting',
303 'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
304 'type': 'ir.actions.act_window',
305 'search_view_id': res['res_id'],
314 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: