2009-12-30 10:20:44 +00:00
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2009-12-30 10:20:44 +00:00
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2010-07-28 17:20:37 +00:00
from osv import fields , osv
from datetime import datetime
2010-01-13 13:34:09 +00:00
import crm
2010-04-05 09:50:29 +00:00
import time
2010-03-23 14:12:01 +00:00
from tools . translate import _
2010-05-05 11:55:13 +00:00
from crm import crm_case
2010-06-24 19:53:32 +00:00
import binascii
import tools
2011-10-24 13:30:10 +00:00
from mail . mail_message import to_email
2010-07-08 14:03:52 +00:00
CRM_LEAD_PENDING_STATES = (
crm . AVAILABLE_STATES [ 2 ] [ 0 ] , # Cancelled
crm . AVAILABLE_STATES [ 3 ] [ 0 ] , # Done
2012-05-22 15:08:11 +00:00
crm . AVAILABLE_STATES [ 4 ] [ 0 ] , # Pending
2010-07-08 14:03:52 +00:00
)
2010-08-17 12:54:00 +00:00
class crm_lead ( crm_case , osv . osv ) :
2010-03-23 14:12:01 +00:00
""" CRM Lead Case """
2009-12-30 10:20:44 +00:00
_name = " crm.lead "
2010-12-20 11:38:20 +00:00
_description = " Lead/Opportunity "
2011-08-25 04:10:37 +00:00
_order = " priority,date_action,id desc "
2012-04-03 17:21:08 +00:00
_inherit = [ ' ir.needaction_mixin ' , ' mail.thread ' , ' res.partner ' ]
2011-08-25 04:10:37 +00:00
2012-05-22 14:11:27 +00:00
def _resolve_section_id_from_context ( self , cr , uid , context = None ) :
""" Returns ID of section based on the value of ' section_id '
context key , or None if it cannot be resolved to a single project
"""
if context is None :
context = { }
2012-05-22 14:29:54 +00:00
if type ( context . get ( ' section_id ' ) ) in ( int , long ) :
return context . get ( ' section_id ' )
if isinstance ( context . get ( ' section_id ' ) , basestring ) :
section_name = context [ ' section_id ' ]
section_ids = self . pool . get ( ' crm.case.section ' ) . name_search ( cr , uid , name = section_name , context = context )
if len ( section_ids ) == 1 :
return section_ids [ 0 ] [ 0 ]
2012-05-22 14:11:27 +00:00
return None
2011-11-23 13:31:32 +00:00
def _read_group_stage_ids ( self , cr , uid , ids , domain , read_group_order = None , access_rights_uid = None , context = None ) :
access_rights_uid = access_rights_uid or uid
2012-05-22 15:39:28 +00:00
stage_obj = self . pool . get ( ' crm.case.stage ' )
2011-11-21 16:49:40 +00:00
order = stage_obj . _order
2012-05-22 15:08:11 +00:00
# lame hack to allow reverting search, should just work in the trivial case
2011-11-21 16:49:40 +00:00
if read_group_order == ' stage_id desc ' :
order = " %s desc " % order
2012-05-22 15:08:11 +00:00
# retrieve section_id from the context and write the domain
2012-05-22 14:11:27 +00:00
search_domain = [ ]
2012-05-22 15:08:11 +00:00
section_id = self . _resolve_section_id_from_context ( cr , uid , context = context )
2012-05-22 14:11:27 +00:00
if section_id :
search_domain + = [ ' | ' , ' & ' , ( ' section_ids ' , ' = ' , section_id ) , ( ' fold ' , ' = ' , True ) ]
search_domain + = [ ' | ' , ( ' id ' , ' in ' , ids ) , ' & ' , ( ' case_default ' , ' = ' , 1 ) , ( ' fold ' , ' = ' , False ) ]
# perform search
stage_ids = stage_obj . _search ( cr , uid , search_domain , order = order , access_rights_uid = access_rights_uid , context = context )
2011-11-23 13:31:32 +00:00
result = stage_obj . name_get ( cr , access_rights_uid , stage_ids , context = context )
2011-11-21 16:49:40 +00:00
# restore order of the search
result . sort ( lambda x , y : cmp ( stage_ids . index ( x [ 0 ] ) , stage_ids . index ( y [ 0 ] ) ) )
return result
2011-11-12 00:44:05 +00:00
2011-11-13 12:07:15 +00:00
_group_by_full = {
' stage_id ' : _read_group_stage_ids
}
2011-11-12 00:44:05 +00:00
2010-11-19 13:48:01 +00:00
def _compute_day ( self , cr , uid , ids , fields , args , context = None ) :
2010-03-22 10:40:26 +00:00
"""
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of Openday ’ s IDs
@return : difference between current date and log date
@param context : A standard dictionary for contextual values
2010-04-22 06:40:17 +00:00
"""
cal_obj = self . pool . get ( ' resource.calendar ' )
res_obj = self . pool . get ( ' resource.resource ' )
2010-04-05 06:12:50 +00:00
res = { }
2010-11-19 13:48:01 +00:00
for lead in self . browse ( cr , uid , ids , context = context ) :
2010-04-05 06:12:50 +00:00
for field in fields :
res [ lead . id ] = { }
duration = 0
2010-04-07 11:08:20 +00:00
ans = False
2010-04-05 06:12:50 +00:00
if field == ' day_open ' :
if lead . date_open :
date_create = datetime . strptime ( lead . create_date , " % Y- % m- %d % H: % M: % S " )
date_open = datetime . strptime ( lead . date_open , " % Y- % m- %d % H: % M: % S " )
ans = date_open - date_create
2010-04-07 11:08:20 +00:00
date_until = lead . date_open
2010-04-05 06:12:50 +00:00
elif field == ' day_close ' :
if lead . date_closed :
date_create = datetime . strptime ( lead . create_date , " % Y- % m- %d % H: % M: % S " )
date_close = datetime . strptime ( lead . date_closed , " % Y- % m- %d % H: % M: % S " )
2010-04-07 11:08:20 +00:00
date_until = lead . date_closed
2010-04-05 06:12:50 +00:00
ans = date_close - date_create
2010-04-07 11:08:20 +00:00
if ans :
resource_id = False
if lead . user_id :
resource_ids = res_obj . search ( cr , uid , [ ( ' user_id ' , ' = ' , lead . user_id . id ) ] )
2010-04-09 14:33:13 +00:00
if len ( resource_ids ) :
resource_id = resource_ids [ 0 ]
2010-04-07 11:08:20 +00:00
duration = float ( ans . days )
2010-04-20 05:57:54 +00:00
if lead . section_id and lead . section_id . resource_calendar_id :
2010-05-14 11:33:09 +00:00
duration = float ( ans . days ) * 24
2010-04-07 11:08:20 +00:00
new_dates = cal_obj . interval_get ( cr ,
uid ,
lead . section_id . resource_calendar_id and lead . section_id . resource_calendar_id . id or False ,
2010-09-29 08:05:01 +00:00
datetime . strptime ( lead . create_date , ' % Y- % m- %d % H: % M: % S ' ) ,
2010-04-07 11:08:20 +00:00
duration ,
resource = resource_id
)
no_days = [ ]
2010-09-29 08:05:01 +00:00
date_until = datetime . strptime ( date_until , ' % Y- % m- %d % H: % M: % S ' )
2010-04-07 11:08:20 +00:00
for in_time , out_time in new_dates :
if in_time . date not in no_days :
2010-04-22 06:40:17 +00:00
no_days . append ( in_time . date )
2010-04-07 11:08:20 +00:00
if out_time > date_until :
2010-04-22 06:40:17 +00:00
break
2010-04-07 11:08:20 +00:00
duration = len ( no_days )
2010-04-05 06:12:50 +00:00
res [ lead . id ] [ field ] = abs ( int ( duration ) )
return res
2010-03-10 06:25:59 +00:00
2011-03-24 14:34:28 +00:00
def _history_search ( self , cr , uid , obj , name , args , context = None ) :
res = [ ]
2011-07-22 18:23:37 +00:00
msg_obj = self . pool . get ( ' mail.message ' )
message_ids = msg_obj . search ( cr , uid , [ ( ' email_from ' , ' != ' , False ) , ( ' subject ' , args [ 0 ] [ 1 ] , args [ 0 ] [ 2 ] ) ] , context = context )
2011-03-24 14:34:28 +00:00
lead_ids = self . search ( cr , uid , [ ( ' message_ids ' , ' in ' , message_ids ) ] , context = context )
if lead_ids :
return [ ( ' id ' , ' in ' , lead_ids ) ]
else :
return [ ( ' id ' , ' = ' , ' 0 ' ) ]
2011-03-23 16:22:06 +00:00
def _get_email_subject ( self , cr , uid , ids , fields , args , context = None ) :
res = { }
for obj in self . browse ( cr , uid , ids , context = context ) :
res [ obj . id ] = ' '
for msg in obj . message_ids :
2011-07-22 18:23:37 +00:00
if msg . email_from :
2011-04-21 08:01:56 +00:00
res [ obj . id ] = msg . subject
2011-03-24 14:34:28 +00:00
break
2011-03-23 16:22:06 +00:00
return res
2012-05-22 15:08:11 +00:00
2010-01-11 12:57:42 +00:00
_columns = {
2011-02-24 15:03:09 +00:00
' partner_id ' : fields . many2one ( ' res.partner ' , ' Partner ' , ondelete = ' set null ' ,
2010-07-08 14:03:52 +00:00
select = True , help = " Optional linked partner, usually after conversion of the lead " ) ,
2010-10-08 14:40:49 +00:00
2011-10-12 11:11:42 +00:00
' id ' : fields . integer ( ' ID ' , readonly = True ) ,
2011-08-18 19:30:44 +00:00
' name ' : fields . char ( ' Name ' , size = 64 , select = 1 ) ,
2010-06-25 17:41:41 +00:00
' active ' : fields . boolean ( ' Active ' , required = False ) ,
2010-05-19 13:42:43 +00:00
' date_action_last ' : fields . datetime ( ' Last Action ' , readonly = 1 ) ,
' date_action_next ' : fields . datetime ( ' Next Action ' , readonly = 1 ) ,
2011-08-18 19:30:44 +00:00
' email_from ' : fields . char ( ' Email ' , size = 128 , help = " E-mail address of the contact " , select = 1 ) ,
2010-05-03 12:30:48 +00:00
' section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' , \
2011-08-25 00:19:47 +00:00
select = True , help = ' When sending mails, the default email address is taken from the sales team. ' ) ,
2010-05-03 12:30:48 +00:00
' create_date ' : fields . datetime ( ' Creation Date ' , readonly = True ) ,
2010-09-21 16:39:51 +00:00
' email_cc ' : fields . text ( ' Global CC ' , size = 252 , help = " These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma " ) ,
2010-05-20 17:34:35 +00:00
' description ' : fields . text ( ' Notes ' ) ,
2010-06-25 17:41:41 +00:00
' write_date ' : fields . datetime ( ' Update Date ' , readonly = True ) ,
2010-05-05 11:55:13 +00:00
2010-09-09 16:04:47 +00:00
' categ_id ' : fields . many2one ( ' crm.case.categ ' , ' Category ' , \
2010-11-10 07:35:40 +00:00
domain = " [ ' | ' ,( ' section_id ' , ' = ' ,section_id),( ' section_id ' , ' = ' ,False), ( ' object_id.model ' , ' = ' , ' crm.lead ' )] " ) ,
2010-09-21 16:39:51 +00:00
' type_id ' : fields . many2one ( ' crm.case.resource.type ' , ' Campaign ' , \
2011-07-19 09:06:02 +00:00
domain = " [ ' | ' ,( ' section_id ' , ' = ' ,section_id),( ' section_id ' , ' = ' ,False)] " , help = " From which campaign (seminar, marketing campaign, mass mailing, ...) did this contact come from? " ) ,
2011-08-27 23:31:30 +00:00
' channel_id ' : fields . many2one ( ' crm.case.channel ' , ' Channel ' , help = " Communication channel (mail, direct, phone, ...) " ) ,
2011-02-24 15:03:09 +00:00
' contact_name ' : fields . char ( ' Contact Name ' , size = 64 ) ,
2012-03-05 11:03:46 +00:00
' partner_name ' : fields . char ( " Customer Name " , size = 64 , help = ' The name of the future partner company that will be created while converting the lead into opportunity ' , select = 1 ) ,
2012-05-10 07:48:13 +00:00
' opt_in ' : fields . boolean ( ' Opt-In ' , oldname = ' optin ' , help = " If opt-in is checked, this contact has accepted to receive emails. " ) ,
' opt_out ' : fields . boolean ( ' Opt-Out ' , oldname = ' optout ' , help = " If opt-out is checked, this contact has refused to receive emails or unsubscribed to a campaign. " ) ,
2011-08-25 04:10:37 +00:00
' type ' : fields . selection ( [ ( ' lead ' , ' Lead ' ) , ( ' opportunity ' , ' Opportunity ' ) , ] , ' Type ' , help = " Type is used to separate Leads and Opportunities " ) ,
2011-12-09 06:03:08 +00:00
' priority ' : fields . selection ( crm . AVAILABLE_PRIORITIES , ' Priority ' , select = True ) ,
2010-04-05 06:12:50 +00:00
' date_closed ' : fields . datetime ( ' Closed ' , readonly = True ) ,
2011-08-25 12:56:50 +00:00
' stage_id ' : fields . many2one ( ' crm.case.stage ' , ' Stage ' , domain = " [( ' section_ids ' , ' = ' , section_id)] " ) ,
2012-05-04 12:13:26 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' Salesperson ' ) ,
2010-04-18 15:32:44 +00:00
' referred ' : fields . char ( ' Referred By ' , size = 64 ) ,
2010-04-05 08:40:54 +00:00
' date_open ' : fields . datetime ( ' Opened ' , readonly = True ) ,
2010-04-05 06:12:50 +00:00
' day_open ' : fields . function ( _compute_day , string = ' Days to Open ' , \
2011-07-05 12:28:57 +00:00
multi = ' day_open ' , type = " float " , store = True ) ,
2010-04-05 06:12:50 +00:00
' day_close ' : fields . function ( _compute_day , string = ' Days to Close ' , \
2011-07-05 12:28:57 +00:00
multi = ' day_close ' , type = " float " , store = True ) ,
2012-05-21 12:40:46 +00:00
' state ' : fields . related ( ' stage_id ' , ' state ' , type = " selection " , store = True ,
2012-05-21 10:00:43 +00:00
selection = crm . AVAILABLE_STATES , string = " State " , readonly = True ,
2012-05-18 15:16:37 +00:00
help = ' The state is set to \' Draft \' , when a case is created. \
2012-05-21 10:00:43 +00:00
If the case is in progress the state is set to \' Open \' . \
When the case is over , the state is set to \' Done \' . \
If the case needs to be reviewed then the state is \
set to \' Pending \' . ' ) ,
2012-02-24 09:17:22 +00:00
' message_ids ' : fields . one2many ( ' mail.message ' , ' res_id ' , ' Messages ' , domain = [ ( ' model ' , ' = ' , _name ) ] ) ,
2011-07-01 23:41:24 +00:00
' subjects ' : fields . function ( _get_email_subject , fnct_search = _history_search , string = ' Subject of Email ' , type = ' char ' , size = 64 ) ,
2011-02-24 15:03:09 +00:00
2011-08-25 04:10:37 +00:00
# Only used for type opportunity
2012-05-04 10:45:06 +00:00
' probability ' : fields . float ( ' Success Rate ( % ) ' , group_operator = " avg " ) ,
2011-08-25 04:10:37 +00:00
' planned_revenue ' : fields . float ( ' Expected Revenue ' ) ,
' ref ' : fields . reference ( ' Reference ' , selection = crm . _links_get , size = 128 ) ,
' ref2 ' : fields . reference ( ' Reference 2 ' , selection = crm . _links_get , size = 128 ) ,
' phone ' : fields . char ( " Phone " , size = 64 ) ,
' date_deadline ' : fields . date ( ' Expected Closing ' ) ,
2011-12-09 06:03:08 +00:00
' date_action ' : fields . date ( ' Next Action Date ' , select = True ) ,
2011-08-25 04:10:37 +00:00
' title_action ' : fields . char ( ' Next Action ' , size = 64 ) ,
2011-08-25 12:56:50 +00:00
' stage_id ' : fields . many2one ( ' crm.case.stage ' , ' Stage ' , domain = " [( ' section_ids ' , ' = ' , section_id)] " ) ,
2011-09-13 16:29:07 +00:00
' color ' : fields . integer ( ' Color Index ' ) ,
2012-02-29 12:41:42 +00:00
' partner_address_name ' : fields . related ( ' partner_id ' , ' name ' , type = ' char ' , string = ' Partner Contact Name ' , readonly = True ) ,
' partner_address_email ' : fields . related ( ' partner_id ' , ' email ' , type = ' char ' , string = ' Partner Contact Email ' , readonly = True ) ,
2011-09-13 16:29:07 +00:00
' company_currency ' : fields . related ( ' company_id ' , ' currency_id ' , ' symbol ' , type = ' char ' , string = ' Company Currency ' , readonly = True ) ,
' user_email ' : fields . related ( ' user_id ' , ' user_email ' , type = ' char ' , string = ' User Email ' , readonly = True ) ,
' user_login ' : fields . related ( ' user_id ' , ' login ' , type = ' char ' , string = ' User Login ' , readonly = True ) ,
2011-08-25 04:10:37 +00:00
}
2010-02-28 13:21:56 +00:00
_defaults = {
2012-04-19 13:33:09 +00:00
' active ' : 1 ,
2010-05-14 11:33:09 +00:00
' user_id ' : crm_case . _get_default_user ,
' email_from ' : crm_case . _get_default_email ,
2012-04-19 13:33:09 +00:00
' type ' : ' lead ' ,
2012-05-21 16:15:45 +00:00
' stage_id ' : crm_case . _get_default_stage_id ,
2010-05-14 11:33:09 +00:00
' section_id ' : crm_case . _get_section ,
2010-04-05 06:12:50 +00:00
' company_id ' : lambda s , cr , uid , c : s . pool . get ( ' res.company ' ) . _company_default_get ( cr , uid , ' crm.lead ' , context = c ) ,
' priority ' : lambda * a : crm . AVAILABLE_PRIORITIES [ 2 ] [ 0 ] ,
2011-09-13 16:29:07 +00:00
' color ' : 0 ,
2010-02-28 13:21:56 +00:00
}
2011-02-24 15:03:09 +00:00
2012-04-02 17:14:14 +00:00
def get_needaction_user_ids ( self , cr , uid , ids , context = None ) :
result = dict . fromkeys ( ids , [ ] )
for obj in self . browse ( cr , uid , ids , context = context ) :
# salesman must perform an action when in draft mode
if obj . state == ' draft ' and obj . user_id :
result [ obj . id ] = [ obj . user_id . id ]
return result
2012-02-28 05:50:38 +00:00
def create ( self , cr , uid , vals , context = None ) :
obj_id = super ( crm_lead , self ) . create ( cr , uid , vals , context )
2012-03-16 13:19:30 +00:00
self . create_send_note ( cr , uid , [ obj_id ] , context = context )
2012-02-28 05:50:38 +00:00
return obj_id
2012-04-02 17:14:14 +00:00
2012-05-08 07:43:38 +00:00
def on_change_opt_in ( self , cr , uid , ids , opt_in ) :
return { ' value ' : { ' opt_in ' : opt_in , ' opt_out ' : False } }
2011-08-25 04:10:37 +00:00
2012-05-08 07:43:38 +00:00
def on_change_opt_out ( self , cr , uid , ids , opt_out ) :
return { ' value ' : { ' opt_out ' : opt_out , ' opt_in ' : False } }
2011-08-25 04:10:37 +00:00
def onchange_stage_id ( self , cr , uid , ids , stage_id , context = { } ) :
if not stage_id :
return { ' value ' : { } }
stage = self . pool . get ( ' crm.case.stage ' ) . browse ( cr , uid , stage_id , context )
if not stage . on_change :
return { ' value ' : { } }
return { ' value ' : { ' probability ' : stage . probability } }
def stage_find_percent ( self , cr , uid , percent , section_id ) :
""" Return the first stage with a probability == percent
2010-05-05 11:55:13 +00:00
"""
2011-08-25 04:10:37 +00:00
stage_pool = self . pool . get ( ' crm.case.stage ' )
if section_id :
ids = stage_pool . search ( cr , uid , [ ( " probability " , ' = ' , percent ) , ( " section_ids " , ' in ' , [ section_id ] ) ] )
else :
ids = stage_pool . search ( cr , uid , [ ( " probability " , ' = ' , percent ) ] )
2011-02-24 15:03:09 +00:00
2011-08-25 04:10:37 +00:00
if ids :
return ids [ 0 ]
return False
2011-02-24 15:03:09 +00:00
2011-08-25 04:10:37 +00:00
def stage_find_lost ( self , cr , uid , section_id ) :
return self . stage_find_percent ( cr , uid , 0.0 , section_id )
2011-02-24 15:03:09 +00:00
2011-08-25 04:10:37 +00:00
def stage_find_won ( self , cr , uid , section_id ) :
return self . stage_find_percent ( cr , uid , 100.0 , section_id )
2011-02-24 15:03:09 +00:00
2012-02-23 10:46:41 +00:00
def case_cancel ( self , cr , uid , ids , context = None ) :
2011-08-25 04:10:37 +00:00
""" Overrides cancel for crm_case for setting probability
"""
2012-05-21 14:02:16 +00:00
res = super ( crm_lead , self ) . case_cancel ( cr , uid , ids , context = context )
self . write ( cr , uid , ids , { ' probability ' : 0.0 } , context = context )
2011-08-25 04:10:37 +00:00
return res
2012-02-23 10:46:41 +00:00
def case_reset ( self , cr , uid , ids , context = None ) :
2011-08-25 04:10:37 +00:00
""" Overrides reset as draft in order to set the stage field as empty
"""
2012-05-21 14:02:16 +00:00
res = super ( crm_lead , self ) . case_reset ( cr , uid , ids , context = context )
self . write ( cr , uid , ids , { ' probability ' : 0.0 } , context = context )
2011-08-25 04:10:37 +00:00
return res
2012-02-23 10:46:41 +00:00
def case_mark_lost ( self , cr , uid , ids , context = None ) :
2011-08-25 04:10:37 +00:00
""" Mark the case as lost: state = done and probability = 0 %
"""
2012-02-23 10:46:41 +00:00
for lead in self . browse ( cr , uid , ids ) :
stage_id = self . stage_find_lost ( cr , uid , lead . section_id . id or False )
2011-08-25 04:10:37 +00:00
if stage_id :
2012-05-21 14:02:16 +00:00
self . case_set ( cr , uid , [ lead . id ] , values_to_update = { ' probability ' : 0.0 } , new_stage_id = stage_id , context = context )
2012-05-22 15:08:11 +00:00
self . case_mark_lost_send_note ( cr , uid , ids , context = context )
2012-05-21 14:02:16 +00:00
return True
2011-08-25 04:10:37 +00:00
2012-02-23 10:46:41 +00:00
def case_mark_won ( self , cr , uid , ids , context = None ) :
2011-08-25 04:10:37 +00:00
""" Mark the case as lost: state = done and probability = 0 %
"""
2012-02-23 10:46:41 +00:00
for lead in self . browse ( cr , uid , ids ) :
stage_id = self . stage_find_won ( cr , uid , lead . section_id . id or False )
2011-08-25 04:10:37 +00:00
if stage_id :
2012-05-21 14:23:17 +00:00
self . case_set ( cr , uid , [ lead . id ] , values_to_update = { ' probability ' : 100.0 } , new_stage_id = stage_id , context = context )
2012-05-22 15:08:11 +00:00
self . case_mark_won_send_note ( cr , uid , ids , context = context )
2012-05-21 14:02:16 +00:00
return True
2011-08-25 04:10:37 +00:00
2011-09-13 16:29:07 +00:00
def set_priority ( self , cr , uid , ids , priority ) :
""" Set lead priority
"""
return self . write ( cr , uid , ids , { ' priority ' : priority } )
2012-02-23 10:46:41 +00:00
def set_high_priority ( self , cr , uid , ids , context = None ) :
2011-09-13 16:29:07 +00:00
""" Set lead priority to high
"""
return self . set_priority ( cr , uid , ids , ' 1 ' )
2012-02-23 10:46:41 +00:00
def set_normal_priority ( self , cr , uid , ids , context = None ) :
2011-09-13 16:29:07 +00:00
""" Set lead priority to normal
"""
return self . set_priority ( cr , uid , ids , ' 3 ' )
2011-12-31 07:57:20 +00:00
2011-10-26 09:21:33 +00:00
def _merge_data ( self , cr , uid , ids , oldest , fields , context = None ) :
2011-10-21 07:01:11 +00:00
# prepare opportunity data into dictionary for merging
opportunities = self . browse ( cr , uid , ids , context = context )
def _get_first_not_null ( attr ) :
if hasattr ( oldest , attr ) :
return getattr ( oldest , attr )
for opportunity in opportunities :
if hasattr ( opportunity , attr ) :
return getattr ( opportunity , attr )
return False
def _get_first_not_null_id ( attr ) :
res = _get_first_not_null ( attr )
return res and res . id or False
2011-12-31 07:57:20 +00:00
2011-10-21 07:01:11 +00:00
def _concat_all ( attr ) :
2011-11-30 13:06:14 +00:00
return ' , ' . join ( filter ( lambda x : x , [ getattr ( opportunity , attr ) or ' ' for opportunity in opportunities if hasattr ( opportunity , attr ) ] ) )
2011-10-21 07:01:11 +00:00
2011-10-26 09:21:33 +00:00
data = { }
for field_name in fields :
field_info = self . _all_columns . get ( field_name )
if field_info is None :
continue
field = field_info . column
if field . _type in ( ' many2many ' , ' one2many ' ) :
2011-12-31 07:57:20 +00:00
continue
2011-10-26 09:21:33 +00:00
elif field . _type == ' many2one ' :
data [ field_name ] = _get_first_not_null_id ( field_name ) # !!
elif field . _type == ' text ' :
data [ field_name ] = _concat_all ( field_name ) #not lost
else :
data [ field_name ] = _get_first_not_null ( field_name ) #not lost
2011-10-21 07:01:11 +00:00
return data
def _merge_find_oldest ( self , cr , uid , ids , context = None ) :
if context is None :
context = { }
2011-10-24 13:30:10 +00:00
#TOCHECK: where pass 'convert' in context ?
2011-10-21 07:01:11 +00:00
if context . get ( ' convert ' ) :
ids = list ( set ( ids ) - set ( context . get ( ' lead_ids ' , False ) ) )
#search opportunities order by create date
2011-10-24 13:30:10 +00:00
opportunity_ids = self . search ( cr , uid , [ ( ' id ' , ' in ' , ids ) ] , order = ' create_date ' , context = context )
2011-10-21 07:01:11 +00:00
oldest_id = opportunity_ids [ 0 ]
return self . browse ( cr , uid , oldest_id , context = context )
2011-10-26 09:21:33 +00:00
def _mail_body_text ( self , cr , uid , lead , fields , title = False , context = None ) :
body = [ ]
if title :
body . append ( " %s \n " % ( title ) )
for field_name in fields :
field_info = self . _all_columns . get ( field_name )
if field_info is None :
continue
field = field_info . column
value = None
if field . _type == ' selection ' :
if hasattr ( field . selection , ' __call__ ' ) :
key = field . selection ( self , cr , uid , context = context )
else :
key = field . selection
value = dict ( key ) . get ( lead [ field_name ] , lead [ field_name ] )
elif field . _type == ' many2one ' :
if lead [ field_name ] :
value = lead [ field_name ] . name_get ( ) [ 0 ] [ 1 ]
else :
value = lead [ field_name ]
2011-11-30 12:06:40 +00:00
body . append ( " %s : %s " % ( field . string , value or ' ' ) )
2011-10-26 09:21:33 +00:00
return " \n " . join ( body + [ ' --- ' ] )
2011-10-21 07:01:11 +00:00
def _merge_notification ( self , cr , uid , opportunity_id , opportunities , context = None ) :
#TOFIX: mail template should be used instead of fix body, subject text
details = [ ]
merge_message = _ ( ' Merged opportunities ' )
subject = [ merge_message ]
2011-10-26 09:21:33 +00:00
fields = [ ' name ' , ' partner_id ' , ' stage_id ' , ' section_id ' , ' user_id ' , ' categ_id ' , ' channel_id ' , ' company_id ' , ' contact_name ' ,
' email_from ' , ' phone ' , ' fax ' , ' mobile ' , ' state_id ' , ' description ' , ' probability ' , ' planned_revenue ' ,
' country_id ' , ' city ' , ' street ' , ' street2 ' , ' zip ' ]
2011-10-21 07:01:11 +00:00
for opportunity in opportunities :
subject . append ( opportunity . name )
2011-10-26 09:21:33 +00:00
title = " %s : %s " % ( merge_message , opportunity . name )
details . append ( self . _mail_body_text ( cr , uid , opportunity , fields , title = title , context = context ) )
2011-12-31 07:57:20 +00:00
2011-10-21 07:01:11 +00:00
subject = subject [ 0 ] + " , " . join ( subject [ 1 : ] )
details = " \n \n " . join ( details )
2012-04-02 17:14:14 +00:00
return self . message_append_note ( cr , uid , [ opportunity_id ] , subject = subject , body = details )
2011-12-31 07:57:20 +00:00
2011-10-21 07:01:11 +00:00
def _merge_opportunity_history ( self , cr , uid , opportunity_id , opportunities , context = None ) :
message = self . pool . get ( ' mail.message ' )
for opportunity in opportunities :
for history in opportunity . message_ids :
message . write ( cr , uid , history . id , {
2011-12-31 07:57:20 +00:00
' res_id ' : opportunity_id ,
' subject ' : _ ( " From %s : %s " ) % ( opportunity . name , history . subject )
2011-10-21 07:01:11 +00:00
} , context = context )
return True
def _merge_opportunity_attachments ( self , cr , uid , opportunity_id , opportunities , context = None ) :
attachment = self . pool . get ( ' ir.attachment ' )
# return attachments of opportunity
def _get_attachments ( opportunity_id ) :
attachment_ids = attachment . search ( cr , uid , [ ( ' res_model ' , ' = ' , self . _name ) , ( ' res_id ' , ' = ' , opportunity_id ) ] , context = context )
return attachment . browse ( cr , uid , attachment_ids , context = context )
count = 1
first_attachments = _get_attachments ( opportunity_id )
for opportunity in opportunities :
attachments = _get_attachments ( opportunity . id )
for first in first_attachments :
for attachment in attachments :
if attachment . name == first . name :
values = dict (
name = " %s ( %s ) " % ( attachment . name , count , ) ,
res_id = opportunity_id ,
)
attachment . write ( values )
count + = 1
2011-12-31 07:57:20 +00:00
return True
2011-10-21 07:01:11 +00:00
def merge_opportunity ( self , cr , uid , ids , context = None ) :
"""
To merge opportunities
: param ids : list of opportunities ids to merge
"""
if context is None : context = { }
2011-12-31 07:57:20 +00:00
2011-10-21 07:01:11 +00:00
#TOCHECK: where pass lead_ids in context?
lead_ids = context and context . get ( ' lead_ids ' , [ ] ) or [ ]
if len ( ids ) < = 1 :
2011-12-31 07:57:20 +00:00
raise osv . except_osv ( _ ( ' Warning ! ' ) , _ ( ' Please select more than one opportunity from the list view. ' ) )
2011-10-21 07:01:11 +00:00
2011-10-24 13:30:10 +00:00
ctx_opportunities = self . browse ( cr , uid , lead_ids , context = context )
opportunities = self . browse ( cr , uid , ids , context = context )
opportunities_list = list ( set ( opportunities ) - set ( ctx_opportunities ) )
oldest = self . _merge_find_oldest ( cr , uid , ids , context = context )
if ctx_opportunities :
first_opportunity = ctx_opportunities [ 0 ]
2011-10-21 07:01:11 +00:00
tail_opportunities = opportunities_list
else :
first_opportunity = opportunities_list [ 0 ]
tail_opportunities = opportunities_list [ 1 : ]
2012-02-29 12:41:42 +00:00
fields = [ ' partner_id ' , ' title ' , ' name ' , ' categ_id ' , ' channel_id ' , ' city ' , ' company_id ' , ' contact_name ' , ' country_id ' , ' type_id ' , ' user_id ' , ' section_id ' , ' state_id ' , ' description ' , ' email ' , ' fax ' , ' mobile ' ,
2011-10-26 09:21:33 +00:00
' partner_name ' , ' phone ' , ' probability ' , ' planned_revenue ' , ' street ' , ' street2 ' , ' zip ' , ' create_date ' , ' date_action_last ' ,
' date_action_next ' , ' email_from ' , ' email_cc ' , ' partner_name ' ]
2011-12-31 07:57:20 +00:00
2011-10-26 09:21:33 +00:00
data = self . _merge_data ( cr , uid , ids , oldest , fields , context = context )
2011-10-21 07:01:11 +00:00
# merge data into first opportunity
self . write ( cr , uid , [ first_opportunity . id ] , data , context = context )
#copy message and attachements into the first opportunity
self . _merge_opportunity_history ( cr , uid , first_opportunity . id , tail_opportunities , context = context )
2011-12-31 07:57:20 +00:00
self . _merge_opportunity_attachments ( cr , uid , first_opportunity . id , tail_opportunities , context = context )
2011-10-21 07:01:11 +00:00
#Notification about loss of information
self . _merge_notification ( cr , uid , first_opportunity , opportunities , context = context )
#delete tail opportunities
self . unlink ( cr , uid , [ x . id for x in tail_opportunities ] , context = context )
2011-10-26 09:21:33 +00:00
#open first opportunity
self . case_open ( cr , uid , [ first_opportunity . id ] )
2011-10-21 07:01:11 +00:00
return first_opportunity . id
2011-10-24 13:30:10 +00:00
def _convert_opportunity_data ( self , cr , uid , lead , customer , section_id = False , context = None ) :
2011-10-21 07:01:11 +00:00
crm_stage = self . pool . get ( ' crm.case.stage ' )
2011-11-23 07:20:20 +00:00
contact_id = False
if customer :
contact_id = self . pool . get ( ' res.partner ' ) . address_get ( cr , uid , [ customer . id ] ) [ ' default ' ]
2011-10-24 13:30:10 +00:00
if not section_id :
section_id = lead . section_id and lead . section_id . id or False
if section_id :
stage_ids = crm_stage . search ( cr , uid , [ ( ' sequence ' , ' >= ' , 1 ) , ( ' section_ids ' , ' = ' , section_id ) ] )
2011-10-21 07:01:11 +00:00
else :
2011-12-31 07:57:20 +00:00
stage_ids = crm_stage . search ( cr , uid , [ ( ' sequence ' , ' >= ' , 1 ) ] )
2011-10-24 13:30:10 +00:00
stage_id = stage_ids and stage_ids [ 0 ] or False
2011-10-21 07:01:11 +00:00
return {
' planned_revenue ' : lead . planned_revenue ,
' probability ' : lead . probability ,
' name ' : lead . name ,
2011-11-23 07:20:20 +00:00
' partner_id ' : customer and customer . id or False ,
2011-10-21 07:01:11 +00:00
' user_id ' : ( lead . user_id and lead . user_id . id ) ,
' type ' : ' opportunity ' ,
2011-10-24 13:30:10 +00:00
' stage_id ' : stage_id or False ,
2011-10-21 07:01:11 +00:00
' date_action ' : time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ,
2012-01-25 16:04:17 +00:00
' date_open ' : time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ,
2011-10-21 07:01:11 +00:00
}
2012-01-25 16:04:17 +00:00
2011-10-24 13:30:10 +00:00
def convert_opportunity ( self , cr , uid , ids , partner_id , user_ids = False , section_id = False , context = None ) :
2011-10-21 07:01:11 +00:00
partner = self . pool . get ( ' res.partner ' )
mail_message = self . pool . get ( ' mail.message ' )
2011-11-23 07:20:20 +00:00
customer = False
if partner_id :
customer = partner . browse ( cr , uid , partner_id , context = context )
2011-10-21 07:01:11 +00:00
for lead in self . browse ( cr , uid , ids , context = context ) :
2011-10-24 13:30:10 +00:00
if lead . state in ( ' done ' , ' cancel ' ) :
continue
if user_ids or section_id :
self . allocate_salesman ( cr , uid , [ lead . id ] , user_ids , section_id , context = context )
2011-12-31 07:57:20 +00:00
2011-10-24 13:30:10 +00:00
vals = self . _convert_opportunity_data ( cr , uid , lead , customer , section_id , context = context )
2011-10-21 07:01:11 +00:00
self . write ( cr , uid , [ lead . id ] , vals , context = context )
2011-12-31 07:57:20 +00:00
2012-03-13 10:55:28 +00:00
self . convert_opportunity_send_note ( cr , uid , lead , context = context )
2011-10-21 07:01:11 +00:00
#TOCHECK: why need to change partner details in all messages of lead ?
if lead . partner_id :
msg_ids = [ x . id for x in lead . message_ids ]
mail_message . write ( cr , uid , msg_ids , {
' partner_id ' : lead . partner_id . id
} , context = context )
2011-10-24 13:30:10 +00:00
return True
2011-10-21 07:01:11 +00:00
2012-03-05 11:03:46 +00:00
def _lead_create_contact ( self , cr , uid , lead , name , is_company , parent_id = False , context = None ) :
2011-10-21 07:01:11 +00:00
partner = self . pool . get ( ' res.partner ' )
2012-03-05 11:03:46 +00:00
vals = { ' name ' : name ,
' user_id ' : lead . user_id . id ,
' comment ' : lead . description ,
' section_id ' : lead . section_id . id or False ,
' parent_id ' : parent_id ,
' phone ' : lead . phone ,
' mobile ' : lead . mobile ,
' email ' : lead . email_from and to_email ( lead . email_from ) [ 0 ] ,
' fax ' : lead . fax ,
' title ' : lead . title and lead . title . id or False ,
' function ' : lead . function ,
' street ' : lead . street ,
' street2 ' : lead . street2 ,
' zip ' : lead . zip ,
' city ' : lead . city ,
' country_id ' : lead . country_id and lead . country_id . id or False ,
' state_id ' : lead . state_id and lead . state_id . id or False ,
' is_company ' : is_company ,
2012-03-06 11:12:07 +00:00
' type ' : ' contact '
2012-03-05 11:03:46 +00:00
}
partner = partner . create ( cr , uid , vals , context )
return partner
def _create_lead_partner ( self , cr , uid , lead , context = None ) :
partner_id = False
if lead . partner_name and lead . contact_name :
2012-03-09 04:48:43 +00:00
partner_id = self . _lead_create_contact ( cr , uid , lead , lead . partner_name , True , context = context )
self . _lead_create_contact ( cr , uid , lead , lead . contact_name , False , partner_id , context = context )
2012-03-05 11:03:46 +00:00
elif lead . partner_name and not lead . contact_name :
2012-03-09 04:48:43 +00:00
partner_id = self . _lead_create_contact ( cr , uid , lead , lead . partner_name , True , context = context )
2012-03-05 11:03:46 +00:00
elif not lead . partner_name and lead . contact_name :
2012-03-09 04:48:43 +00:00
partner_id = self . _lead_create_contact ( cr , uid , lead , lead . contact_name , False , context = context )
2012-03-05 11:03:46 +00:00
else :
2012-03-09 04:48:43 +00:00
partner_id = self . _lead_create_contact ( cr , uid , lead , lead . name , False , context = context )
2011-10-21 07:01:11 +00:00
return partner_id
2011-10-26 16:27:27 +00:00
def _lead_set_partner ( self , cr , uid , lead , partner_id , context = None ) :
2011-10-26 09:21:33 +00:00
res = False
res_partner = self . pool . get ( ' res.partner ' )
if partner_id :
2011-11-23 06:42:38 +00:00
res_partner . write ( cr , uid , partner_id , { ' section_id ' : lead . section_id . id or False } )
2011-10-26 09:21:33 +00:00
contact_id = res_partner . address_get ( cr , uid , [ partner_id ] ) [ ' default ' ]
2012-02-29 12:41:42 +00:00
res = lead . write ( { ' partner_id ' : partner_id , } , context = context )
2012-03-16 13:19:30 +00:00
self . _lead_set_partner_send_note ( cr , uid , [ lead . id ] , context )
2011-10-26 09:21:33 +00:00
return res
2011-10-21 07:01:11 +00:00
2011-10-24 13:30:10 +00:00
def convert_partner ( self , cr , uid , ids , action = ' create ' , partner_id = False , context = None ) :
2011-10-21 07:01:11 +00:00
"""
This function convert partner based on action .
2011-10-26 16:27:27 +00:00
if action is ' create ' , create new partner with contact and assign lead to new partner_id .
2011-10-21 07:01:11 +00:00
otherwise assign lead to specified partner_id
"""
if context is None :
context = { }
2011-10-24 13:30:10 +00:00
partner_ids = { }
2011-10-21 07:01:11 +00:00
for lead in self . browse ( cr , uid , ids , context = context ) :
2011-12-31 07:57:20 +00:00
if action == ' create ' :
2011-10-24 13:30:10 +00:00
if not partner_id :
2012-03-05 11:03:46 +00:00
partner_id = self . _create_lead_partner ( cr , uid , lead , context )
2011-10-26 16:27:27 +00:00
self . _lead_set_partner ( cr , uid , lead , partner_id , context = context )
2011-10-24 13:30:10 +00:00
partner_ids [ lead . id ] = partner_id
2011-10-21 07:01:11 +00:00
return partner_ids
def _send_mail_to_salesman ( self , cr , uid , lead , context = None ) :
"""
Send mail to salesman with updated Lead details .
@ lead : browse record of ' crm.lead ' object .
"""
2011-12-31 07:57:20 +00:00
#TOFIX: mail template should be used here instead of fix subject, body text.
2011-10-21 07:01:11 +00:00
message = self . pool . get ( ' mail.message ' )
email_to = lead . user_id and lead . user_id . user_email
if not email_to :
return False
2011-12-31 07:57:20 +00:00
2011-10-21 07:01:11 +00:00
email_from = lead . section_id and lead . section_id . user_id and lead . section_id . user_id . user_email or email_to
partner = lead . partner_id and lead . partner_id . name or lead . partner_name
subject = " lead %s converted into opportunity " % lead . name
body = " Info \n Id : %s \n Subject: %s \n Partner: %s \n Description : %s " % ( lead . id , lead . name , lead . partner_id . name , lead . description )
return message . schedule_with_attach ( cr , uid , email_from , [ email_to ] , subject , body )
def allocate_salesman ( self , cr , uid , ids , user_ids , team_id = False , context = None ) :
index = 0
for lead_id in ids :
value = { }
if team_id :
value [ ' section_id ' ] = team_id
if index < len ( user_ids ) :
value [ ' user_id ' ] = user_ids [ index ]
index + = 1
if value :
self . write ( cr , uid , [ lead_id ] , value , context = context )
return True
2011-11-25 06:27:03 +00:00
def schedule_phonecall ( self , cr , uid , ids , schedule_time , call_summary , desc , phone , contact_name , user_id = False , section_id = False , categ_id = False , action = ' schedule ' , context = None ) :
2011-10-24 13:30:10 +00:00
"""
action : ( ' schedule ' , ' Schedule a call ' ) , ( ' log ' , ' Log a call ' )
"""
phonecall = self . pool . get ( ' crm.phonecall ' )
model_data = self . pool . get ( ' ir.model.data ' )
phonecall_dict = { }
if not categ_id :
res_id = model_data . _get_id ( cr , uid , ' crm ' , ' categ_phone2 ' )
if res_id :
categ_id = model_data . browse ( cr , uid , res_id , context = context ) . res_id
for lead in self . browse ( cr , uid , ids , context = context ) :
if not section_id :
section_id = lead . section_id and lead . section_id . id or False
if not user_id :
user_id = lead . user_id and lead . user_id . id or False
vals = {
' name ' : call_summary ,
' opportunity_id ' : lead . id ,
' user_id ' : user_id or False ,
' categ_id ' : categ_id or False ,
2011-11-25 06:27:03 +00:00
' description ' : desc or ' ' ,
2011-10-24 13:30:10 +00:00
' date ' : schedule_time ,
' section_id ' : section_id or False ,
' partner_id ' : lead . partner_id and lead . partner_id . id or False ,
2012-02-29 12:41:42 +00:00
' partner_phone ' : phone or lead . phone or ( lead . partner_id and lead . partner_id . phone or False ) ,
' partner_mobile ' : lead . partner_id and lead . partner_id . mobile or False ,
2011-10-24 13:30:10 +00:00
' priority ' : lead . priority ,
}
new_id = phonecall . create ( cr , uid , vals , context = context )
2012-03-20 13:22:11 +00:00
phonecall . case_open ( cr , uid , [ new_id ] , context = context )
2011-10-24 13:30:10 +00:00
if action == ' log ' :
2012-03-20 13:22:11 +00:00
phonecall . case_close ( cr , uid , [ new_id ] , context = context )
2011-10-24 13:30:10 +00:00
phonecall_dict [ lead . id ] = new_id
2012-03-20 13:22:11 +00:00
self . schedule_phonecall_send_note ( cr , uid , [ lead . id ] , new_id , action , context = context )
2011-10-24 13:30:10 +00:00
return phonecall_dict
2011-10-21 07:01:11 +00:00
def redirect_opportunity_view ( self , cr , uid , opportunity_id , context = None ) :
models_data = self . pool . get ( ' ir.model.data ' )
# Get Opportunity views
2011-11-03 06:14:32 +00:00
form_view = models_data . get_object_reference ( cr , uid , ' crm ' , ' crm_case_form_view_oppor ' )
tree_view = models_data . get_object_reference ( cr , uid , ' crm ' , ' crm_case_tree_view_oppor ' )
2011-10-21 07:01:11 +00:00
return {
' name ' : _ ( ' Opportunity ' ) ,
' view_type ' : ' form ' ,
' view_mode ' : ' tree, form ' ,
' res_model ' : ' crm.lead ' ,
' domain ' : [ ( ' type ' , ' = ' , ' opportunity ' ) ] ,
' res_id ' : int ( opportunity_id ) ,
' view_id ' : False ,
2011-11-03 06:14:32 +00:00
' views ' : [ ( form_view and form_view [ 1 ] or False , ' form ' ) ,
( tree_view and tree_view [ 1 ] or False , ' tree ' ) ,
2011-10-21 07:01:11 +00:00
( False , ' calendar ' ) , ( False , ' graph ' ) ] ,
' type ' : ' ir.actions.act_window ' ,
}
2011-07-22 18:23:37 +00:00
def message_new ( self , cr , uid , msg , custom_values = None , context = None ) :
""" Automatically calls when new email message arrives """
2011-08-25 12:27:57 +00:00
res_id = super ( crm_lead , self ) . message_new ( cr , uid , msg , custom_values = custom_values , context = context )
2011-08-09 23:44:28 +00:00
subject = msg . get ( ' subject ' ) or _ ( " No Subject " )
2011-07-22 18:23:37 +00:00
body = msg . get ( ' body_text ' )
2010-06-24 19:53:32 +00:00
msg_from = msg . get ( ' from ' )
priority = msg . get ( ' priority ' )
vals = {
' name ' : subject ,
' email_from ' : msg_from ,
' email_cc ' : msg . get ( ' cc ' ) ,
' description ' : body ,
' user_id ' : False ,
}
2011-08-22 17:16:59 +00:00
if priority :
2010-06-24 19:53:32 +00:00
vals [ ' priority ' ] = priority
2011-08-25 12:27:57 +00:00
vals . update ( self . message_partner_by_email ( cr , uid , msg . get ( ' from ' , False ) ) )
2011-09-07 14:23:31 +00:00
self . write ( cr , uid , [ res_id ] , vals , context )
2011-04-20 06:06:05 +00:00
return res_id
2010-06-24 19:53:32 +00:00
2011-12-09 14:28:39 +00:00
def message_update ( self , cr , uid , ids , msg , vals = None , default_act = ' pending ' , context = None ) :
2010-06-24 19:53:32 +00:00
if isinstance ( ids , ( str , int , long ) ) :
ids = [ ids ]
2011-12-09 14:28:39 +00:00
if vals == None :
vals = { }
2011-09-07 14:23:31 +00:00
super ( crm_lead , self ) . message_update ( cr , uid , ids , msg , context = context )
2011-07-22 18:23:37 +00:00
2010-08-26 15:31:21 +00:00
if msg . get ( ' priority ' ) in dict ( crm . AVAILABLE_PRIORITIES ) :
2010-06-24 19:53:32 +00:00
vals [ ' priority ' ] = msg . get ( ' priority ' )
maps = {
' cost ' : ' planned_cost ' ,
' revenue ' : ' planned_revenue ' ,
' probability ' : ' probability '
}
2010-06-25 12:05:00 +00:00
vls = { }
2011-07-22 18:23:37 +00:00
for line in msg [ ' body_text ' ] . split ( ' \n ' ) :
2010-06-24 19:53:32 +00:00
line = line . strip ( )
res = tools . misc . command_re . match ( line )
2010-06-25 12:05:00 +00:00
if res and maps . get ( res . group ( 1 ) . lower ( ) ) :
2010-06-24 19:53:32 +00:00
key = maps . get ( res . group ( 1 ) . lower ( ) )
vls [ key ] = res . group ( 2 ) . lower ( )
vals . update ( vls )
2010-06-25 17:41:41 +00:00
# Unfortunately the API is based on lists
# but we want to update the state based on the
# previous state, so we have to loop:
for case in self . browse ( cr , uid , ids , context = context ) :
values = dict ( vals )
2010-07-08 14:03:52 +00:00
if case . state in CRM_LEAD_PENDING_STATES :
2012-01-25 16:04:17 +00:00
#re-open
values . update ( state = crm . AVAILABLE_STATES [ 1 ] [ 0 ] )
if not case . date_open :
2012-02-23 10:46:41 +00:00
values [ ' date_open ' ] = time . strftime ( tools . DEFAULT_SERVER_DATETIME_FORMAT )
2010-06-25 17:41:41 +00:00
res = self . write ( cr , uid , [ case . id ] , values , context = context )
2010-06-24 19:53:32 +00:00
return res
2011-08-25 04:10:37 +00:00
def action_makeMeeting ( self , cr , uid , ids , context = None ) :
"""
This opens Meeting ' s calendar view to schedule meeting on current Opportunity
@return : Dictionary value for created Meeting view
"""
2011-11-17 13:39:29 +00:00
if context is None :
context = { }
2011-08-25 04:10:37 +00:00
value = { }
2011-11-18 11:51:20 +00:00
data_obj = self . pool . get ( ' ir.model.data ' )
2011-08-25 04:10:37 +00:00
for opp in self . browse ( cr , uid , ids , context = context ) :
# Get meeting views
2011-11-03 07:20:58 +00:00
tree_view = data_obj . get_object_reference ( cr , uid , ' crm ' , ' crm_case_tree_view_meet ' )
form_view = data_obj . get_object_reference ( cr , uid , ' crm ' , ' crm_case_form_view_meet ' )
calander_view = data_obj . get_object_reference ( cr , uid , ' crm ' , ' crm_case_calendar_view_meet ' )
search_view = data_obj . get_object_reference ( cr , uid , ' crm ' , ' view_crm_case_meetings_filter ' )
2011-11-18 11:59:18 +00:00
context . update ( {
2011-08-25 04:10:37 +00:00
' default_opportunity_id ' : opp . id ,
' default_partner_id ' : opp . partner_id and opp . partner_id . id or False ,
2011-12-31 07:57:20 +00:00
' default_user_id ' : uid ,
2011-08-25 04:10:37 +00:00
' default_section_id ' : opp . section_id and opp . section_id . id or False ,
' default_email_from ' : opp . email_from ,
2011-12-31 07:57:20 +00:00
' default_state ' : ' open ' ,
2011-08-25 04:10:37 +00:00
' default_name ' : opp . name
2011-11-17 13:39:29 +00:00
} )
2011-08-25 04:10:37 +00:00
value = {
' name ' : _ ( ' Meetings ' ) ,
' context ' : context ,
' view_type ' : ' form ' ,
' view_mode ' : ' calendar,form,tree ' ,
' res_model ' : ' crm.meeting ' ,
' view_id ' : False ,
2011-11-03 07:20:58 +00:00
' views ' : [ ( calander_view and calander_view [ 1 ] or False , ' calendar ' ) , ( form_view and form_view [ 1 ] or False , ' form ' ) , ( tree_view and tree_view [ 1 ] or False , ' tree ' ) ] ,
2011-08-25 04:10:37 +00:00
' type ' : ' ir.actions.act_window ' ,
2011-11-03 07:20:58 +00:00
' search_view_id ' : search_view and search_view [ 1 ] or False ,
2011-08-25 04:10:37 +00:00
' nodestroy ' : True
}
return value
2011-08-27 21:19:48 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
for lead in self . browse ( cr , uid , ids , context ) :
2012-01-30 10:01:34 +00:00
if ( not lead . section_id . allow_unlink ) and ( lead . state != ' draft ' ) :
raise osv . except_osv ( _ ( ' Error ' ) ,
_ ( " You cannot delete lead ' %s ' ; it must be in state ' Draft ' to be deleted. " \
" You should better cancel it, instead of deleting it. " ) % lead . name )
2011-08-27 21:19:48 +00:00
return super ( crm_lead , self ) . unlink ( cr , uid , ids , context )
2011-08-25 04:10:37 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
if not context :
context = { }
if ' date_closed ' in vals :
return super ( crm_lead , self ) . write ( cr , uid , ids , vals , context = context )
2012-01-30 10:29:39 +00:00
if vals . get ( ' stage_id ' ) :
stage = self . pool . get ( ' crm.case.stage ' ) . browse ( cr , uid , vals [ ' stage_id ' ] , context = context )
# change probability of lead(s) if required by stage
if not vals . get ( ' probability ' ) and stage . on_change :
vals [ ' probability ' ] = stage . probability
2011-08-25 04:10:37 +00:00
for case in self . browse ( cr , uid , ids , context = context ) :
2012-03-13 10:55:28 +00:00
message = _ ( " Stage changed to <b> %s </b>. " ) % ( stage . name )
2012-04-02 17:14:14 +00:00
case . message_append_note ( body = message )
2011-08-25 04:10:37 +00:00
return super ( crm_lead , self ) . write ( cr , uid , ids , vals , context )
2012-04-02 17:14:14 +00:00
# ----------------------------------------
# OpenChatter methods and notifications
# ----------------------------------------
def message_get_subscribers ( self , cr , uid , ids , context = None ) :
sub_ids = self . message_get_subscribers_ids ( cr , uid , ids , context = context )
# add salesman to the subscribers
for obj in self . browse ( cr , uid , ids , context = context ) :
if obj . user_id :
sub_ids . append ( obj . user_id . id )
return self . pool . get ( ' res.users ' ) . read ( cr , uid , sub_ids , context = context )
def case_get_note_msg_prefix ( self , cr , uid , lead , context = None ) :
if isinstance ( lead , ( int , long ) ) :
lead = self . browse ( cr , uid , [ lead ] , context = context ) [ 0 ]
2012-04-03 07:41:22 +00:00
return ( ' Opportunity ' if lead . type == ' opportunity ' else ' Lead ' )
2012-04-02 17:14:14 +00:00
def create_send_note ( self , cr , uid , ids , context = None ) :
for id in ids :
message = _ ( " %s has been <b>created</b>. " ) % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) )
self . message_append_note ( cr , uid , [ id ] , body = message , context = context )
return True
def case_mark_lost_send_note ( self , cr , uid , ids , context = None ) :
message = _ ( " Opportunity has been <b>lost</b>. " )
return self . message_append_note ( cr , uid , ids , body = message , context = context )
def case_mark_won_send_note ( self , cr , uid , ids , context = None ) :
message = _ ( " Opportunity has been <b>won</b>. " )
return self . message_append_note ( cr , uid , ids , body = message , context = context )
def schedule_phonecall_send_note ( self , cr , uid , ids , phonecall_id , action , context = None ) :
phonecall = self . pool . get ( ' crm.phonecall ' ) . browse ( cr , uid , [ phonecall_id ] , context = context ) [ 0 ]
if action == ' log ' : prefix = ' Logged '
else : prefix = ' Scheduled '
message = _ ( " <b> %s a call</b> for the <em> %s </em>. " ) % ( prefix , phonecall . date )
return self . message_append_note ( cr , uid , ids , body = message , context = context )
def _lead_set_partner_send_note ( self , cr , uid , ids , context = None ) :
for lead in self . browse ( cr , uid , ids , context = context ) :
message = _ ( " %s <b>partner</b> is now set to <em> %s </em>. " % ( self . case_get_note_msg_prefix ( cr , uid , lead , context = context ) , lead . partner_id . name ) )
lead . message_append_note ( body = message )
return True
def convert_opportunity_send_note ( self , cr , uid , lead , context = None ) :
message = _ ( " Lead has been <b>converted to an opportunity</b>. " )
lead . message_append_note ( body = message )
return True
2011-02-24 15:03:09 +00:00
2009-12-30 10:20:44 +00:00
crm_lead ( )
2010-03-22 10:40:26 +00:00
2010-03-23 14:12:01 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: