2009-12-30 10:20:44 +00:00
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
2012-05-25 15:20:46 +00:00
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
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/>.
#
##############################################################################
2012-05-29 14:03:14 +00:00
from base_status . base_stage import base_stage
2010-01-13 13:34:09 +00:00
import crm
2012-05-25 15:20:46 +00:00
from datetime import datetime
from osv import fields , osv
2010-04-05 09:50:29 +00:00
import time
2010-06-24 19:53:32 +00:00
import tools
2012-05-25 15:20:46 +00:00
from tools . translate import _
2010-07-08 14:03:52 +00:00
2012-09-13 18:19:52 +00:00
from base . res . res_partner import format_address
2010-07-08 14:03:52 +00:00
CRM_LEAD_PENDING_STATES = (
crm . AVAILABLE_STATES [ 2 ] [ 0 ] , # Cancelled
crm . AVAILABLE_STATES [ 3 ] [ 0 ] , # Done
crm . AVAILABLE_STATES [ 4 ] [ 0 ] , # Pending
)
2012-09-13 18:19:52 +00:00
class crm_lead ( base_stage , format_address , 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-08-22 15:31:45 +00:00
_inherit = [ ' mail.thread ' , ' ir.needaction_mixin ' ]
2011-08-25 04:10:37 +00:00
2012-05-24 14:26:16 +00:00
def _get_default_section_id ( self , cr , uid , context = None ) :
""" Gives default section by checking if present in the context """
2012-05-25 15:20:46 +00:00
return ( self . _resolve_section_id_from_context ( cr , uid , context = context ) or False )
2012-05-24 14:26:16 +00:00
2012-05-25 11:51:02 +00:00
def _get_default_stage_id ( self , cr , uid , context = None ) :
""" Gives default stage_id """
section_id = self . _get_default_section_id ( cr , uid , context = context )
return self . stage_find ( cr , uid , [ ] , section_id , [ ( ' state ' , ' = ' , ' draft ' ) , ( ' type ' , ' = ' , ' both ' ) ] , context = context )
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 '
2012-05-24 14:26:16 +00:00
context key , or None if it cannot be resolved to a single
Sales Team .
2012-05-22 14:11:27 +00:00
"""
if context is None :
context = { }
2012-05-24 14:26:16 +00:00
if type ( context . get ( ' default_section_id ' ) ) in ( int , long ) :
return context . get ( ' default_section_id ' )
if isinstance ( context . get ( ' default_section_id ' ) , basestring ) :
section_name = context [ ' default_section_id ' ]
2012-05-22 14:29:54 +00:00
section_ids = self . pool . get ( ' crm.case.section ' ) . name_search ( cr , uid , name = section_name , context = context )
if len ( section_ids ) == 1 :
2012-05-24 14:26:16 +00:00
return int ( section_ids [ 0 ] [ 0 ] )
2012-05-25 15:20:46 +00:00
return None
def _resolve_type_from_context ( self , cr , uid , context = None ) :
""" Returns the type (lead or opportunity) from the type context
key . Returns None if it cannot be resolved .
"""
if context is None :
context = { }
return context . get ( ' default_type ' )
2012-05-22 14:11:27 +00:00
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
2011-11-13 12:07:15 +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-31 13:16:26 +00:00
# - ('id', 'in', 'ids'): add columns that should be present
# - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded
# - OR ('section_ids', '=', section_id), ('fold', '=', False) if section_id: add section columns that are not folded
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 :
2012-09-06 16:18:12 +00:00
search_domain + = [ ' | ' , ( ' section_ids ' , ' = ' , section_id ) ]
search_domain + = [ ' | ' , ( ' id ' , ' in ' , ids ) , ( ' case_default ' , ' = ' , True ) ]
2012-05-31 13:16:26 +00:00
# retrieve type from the context (if set: choose 'type' or 'both')
type = self . _resolve_type_from_context ( cr , uid , context = context )
2012-05-25 15:20:46 +00:00
if type :
search_domain + = [ ' | ' , ( ' type ' , ' = ' , type ) , ( ' type ' , ' = ' , ' both ' ) ]
2012-05-22 14:11:27 +00:00
# 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 ] ) ) )
2012-09-06 15:23:03 +00:00
fold = { }
for stage in stage_obj . browse ( cr , access_rights_uid , stage_ids , context = context ) :
fold [ stage . id ] = stage . fold or False
return result , fold
2011-11-12 00:44:05 +00:00
2012-09-13 18:19:52 +00:00
def fields_view_get ( self , cr , user , view_id = None , view_type = ' form ' , context = None , toolbar = False , submenu = False ) :
res = super ( crm_lead , self ) . fields_view_get ( cr , user , view_id , view_type , context , toolbar = toolbar , submenu = submenu )
if view_type == ' form ' :
res [ ' arch ' ] = self . fields_view_get_address ( cr , user , res [ ' arch ' ] , context = context )
return res
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 ' ) ]
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 ) ,
2012-06-04 08:26:46 +00:00
' name ' : fields . char ( ' Subject ' , size = 64 , required = True , 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 ) ,
2012-06-25 13:42:53 +00:00
' email_from ' : fields . char ( ' Email ' , size = 128 , help = " Email 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 ) ,
2012-07-06 11:06:21 +00:00
' categ_ids ' : fields . many2many ( ' crm.case.categ ' , ' crm_lead_category_rel ' , ' lead_id ' , ' category_id ' , ' Categories ' , \
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_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 ) ,
2012-05-24 16:19:55 +00:00
' stage_id ' : fields . many2one ( ' crm.case.stage ' , ' Stage ' ,
2012-09-05 05:56:27 +00:00
domain = " [ ' & ' , ( ' fold ' , ' = ' , False), ' & ' , ' | ' , ( ' section_ids ' , ' = ' , section_id), ( ' case_default ' , ' = ' , True), ' | ' , ( ' type ' , ' = ' , type), ( ' type ' , ' = ' , ' both ' )] " ) ,
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 \' . ' ) ,
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-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 ) ,
2012-08-10 14:43:39 +00:00
' user_email ' : fields . related ( ' user_id ' , ' email ' , type = ' char ' , string = ' User Email ' , readonly = True ) ,
2011-09-13 16:29:07 +00:00
' user_login ' : fields . related ( ' user_id ' , ' login ' , type = ' char ' , string = ' User Login ' , readonly = True ) ,
2012-08-04 18:46:05 +00:00
2012-06-28 14:05:16 +00:00
# Fields for address, due to separation from crm and res.partner
' street ' : fields . char ( ' Street ' , size = 128 ) ,
' street2 ' : fields . char ( ' Street2 ' , size = 128 ) ,
' zip ' : fields . char ( ' Zip ' , change_default = True , size = 24 ) ,
' city ' : fields . char ( ' City ' , size = 128 ) ,
' state_id ' : fields . many2one ( " res.country.state " , ' State ' , domain = " [( ' country_id ' , ' = ' ,country_id)] " ) ,
' country_id ' : fields . many2one ( ' res.country ' , ' Country ' ) ,
' phone ' : fields . char ( ' Phone ' , size = 64 ) ,
' fax ' : fields . char ( ' Fax ' , size = 64 ) ,
' mobile ' : fields . char ( ' Mobile ' , size = 64 ) ,
' function ' : fields . char ( ' Function ' , size = 128 ) ,
2012-06-28 15:12:32 +00:00
' title ' : fields . many2one ( ' res.partner.title ' , ' Title ' ) ,
2012-06-28 14:05:16 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , select = 1 ) ,
2012-07-31 10:40:43 +00:00
' payment_mode ' : fields . many2one ( ' crm.payment.mode ' , ' Payment Mode ' , \
2012-07-31 09:49:32 +00:00
domain = " [( ' section_id ' , ' = ' ,section_id)] " ) ,
' planned_cost ' : fields . float ( ' Planned Costs ' ) ,
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 ,
2012-05-25 15:20:46 +00:00
' type ' : ' lead ' ,
2012-05-24 14:26:16 +00:00
' user_id ' : lambda s , cr , uid , c : s . _get_default_user ( cr , uid , c ) ,
' email_from ' : lambda s , cr , uid , c : s . _get_default_email ( cr , uid , c ) ,
' stage_id ' : lambda s , cr , uid , c : s . _get_default_stage_id ( cr , uid , c ) ,
' section_id ' : lambda s , cr , uid , c : s . _get_default_section_id ( cr , uid , c ) ,
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-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-09-24 12:51:39 +00:00
section_id = self . browse ( cr , uid , obj_id , context = context ) . section_id
if section_id :
followers = [ follow . id for follow in section_id . message_follower_ids ]
self . message_subscribe ( cr , uid , [ obj_id ] , followers , context = 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-08-06 17:07:32 +00:00
2012-08-03 07:40:51 +00:00
def onchange_stage_id ( self , cr , uid , ids , stage_id , context = None ) :
2011-08-25 04:10:37 +00:00
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 } }
2012-08-03 07:40:51 +00:00
def on_change_partner ( self , cr , uid , ids , partner_id , context = None ) :
result = { }
2012-08-23 14:35:21 +00:00
values = { }
2012-08-03 07:40:51 +00:00
if partner_id :
partner = self . pool . get ( ' res.partner ' ) . browse ( cr , uid , partner_id , context = context )
2012-08-08 09:08:46 +00:00
values = {
' partner_name ' : partner . name ,
' street ' : partner . street ,
' street2 ' : partner . street2 ,
' city ' : partner . city ,
' state_id ' : partner . state_id and partner . state_id . id or False ,
' country_id ' : partner . country_id and partner . country_id . id or False ,
}
return { ' value ' : values }
2012-08-03 07:40:51 +00:00
2012-05-29 14:03:14 +00:00
def _check ( self , cr , uid , ids = False , context = None ) :
""" Override of the base.stage method.
Function called by the scheduler to process cases for date actions
Only works on not done and cancelled cases
"""
cr . execute ( ' select * from crm_case \
where ( date_action_last < % s or date_action_last is null ) \
and ( date_action_next < = % s or date_action_next is null ) \
and state not in ( \' cancel \' , \' done \' ) ' ,
( time . strftime ( " % Y- % m- %d % H: % M: % S " ) ,
time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ) )
ids2 = map ( lambda x : x [ 0 ] , cr . fetchall ( ) or [ ] )
cases = self . browse ( cr , uid , ids2 , context = context )
return self . _action ( cr , uid , cases , False , context = context )
2012-05-24 14:26:16 +00:00
def stage_find ( self , cr , uid , cases , section_id , domain = [ ] , order = ' sequence ' , context = None ) :
""" Override of the base.stage method
Parameter of the stage search taken from the lead :
- type : stage type must be the same or ' both '
- section_id : if set , stages must belong to this section or
2012-05-25 15:20:46 +00:00
be a default stage ; if not set , stages must be default
stages
2010-05-05 11:55:13 +00:00
"""
2012-05-24 14:26:16 +00:00
if isinstance ( cases , ( int , long ) ) :
cases = self . browse ( cr , uid , cases , context = context )
2012-05-31 14:19:30 +00:00
# collect all section_ids
section_ids = [ ]
types = [ ' both ' ]
2012-05-24 14:26:16 +00:00
if section_id :
2012-05-31 14:19:30 +00:00
section_ids . append ( section_id )
2012-05-24 14:26:16 +00:00
for lead in cases :
2012-05-31 14:19:30 +00:00
if lead . section_id :
section_ids . append ( lead . section_id . id )
if lead . type not in types :
types . append ( lead . type )
# OR all section_ids and OR with case_default
search_domain = [ ]
if section_ids :
search_domain + = [ ( ' | ' ) ] * len ( section_ids )
for section_id in section_ids :
search_domain . append ( ( ' section_ids ' , ' = ' , section_id ) )
search_domain . append ( ( ' case_default ' , ' = ' , True ) )
# AND with cases types
search_domain . append ( ( ' type ' , ' in ' , types ) )
# AND with the domain in parameter
search_domain + = list ( domain )
# perform search, return the first found
stage_ids = self . pool . get ( ' crm.case.stage ' ) . search ( cr , uid , search_domain , order = order , context = context )
2012-05-24 14:26:16 +00:00
if stage_ids :
return stage_ids [ 0 ]
2011-08-25 04:10:37 +00:00
return False
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 ) :
2012-05-29 14:56:01 +00:00
""" Overrides case_cancel from base_stage to set 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 ) :
2012-05-29 14:56:01 +00:00
""" Overrides case_reset from base_stage to set probability """
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 ) :
2012-05-29 14:56:01 +00:00
""" Mark the case as lost: state=cancel and probability=0 """
2012-02-23 10:46:41 +00:00
for lead in self . browse ( cr , uid , ids ) :
2012-05-24 14:58:17 +00:00
stage_id = self . stage_find ( cr , uid , [ lead ] , lead . section_id . id or False , [ ( ' probability ' , ' = ' , 0.0 ) ] , context = context )
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 ) :
2012-05-29 14:56:01 +00:00
""" Mark the case as lost: state=done and probability=100 """
2012-02-23 10:46:41 +00:00
for lead in self . browse ( cr , uid , ids ) :
2012-05-24 14:58:17 +00:00
stage_id = self . stage_find ( cr , uid , [ lead ] , lead . section_id . id or False , [ ( ' probability ' , ' = ' , 100.0 ) ] , context = context )
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 ) :
2012-05-30 09:03:40 +00:00
""" Set lead priority
2011-09-13 16:29:07 +00:00
"""
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 ) :
2012-05-30 09:03:40 +00:00
""" Set lead priority to high
2011-09-13 16:29:07 +00:00
"""
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 ) :
2012-05-30 09:03:40 +00:00
""" Set lead priority to normal
2011-09-13 16:29:07 +00:00
"""
return self . set_priority ( cr , uid , ids , ' 3 ' )
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 )
2012-08-17 12:06:06 +00:00
def _mail_body ( self , cr , uid , lead , fields , title = False , context = None ) :
2011-10-26 09:21:33 +00:00
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 ]
2012-08-13 12:58:22 +00:00
fields = [ ' name ' , ' partner_id ' , ' stage_id ' , ' section_id ' , ' user_id ' , ' categ_ids ' , ' channel_id ' , ' company_id ' , ' contact_name ' ,
2011-10-26 09:21:33 +00:00
' 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 )
2012-08-17 12:06:06 +00:00
details . append ( self . _mail_body ( 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-08-22 11:34:39 +00:00
return self . message_post ( cr , uid , [ opportunity_id ] , body = details , subject = subject , context = context )
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 :
2012-08-07 11:34:14 +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 ]
2012-08-23 20:06:29 +00:00
tail_opportunities = opportunities_list + ctx_opportunities [ 1 : ]
2011-10-21 07:01:11 +00:00
else :
first_opportunity = opportunities_list [ 0 ]
tail_opportunities = opportunities_list [ 1 : ]
2012-08-13 12:58:22 +00:00
fields = [ ' partner_id ' , ' title ' , ' name ' , ' categ_ids ' , ' 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
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 )
2012-03-13 10:55:28 +00:00
self . convert_opportunity_send_note ( cr , uid , lead , context = context )
2012-08-23 20:06:29 +00:00
if user_ids or section_id :
self . allocate_salesman ( cr , uid , ids , user_ids , section_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 ,
2012-08-16 16:43:11 +00:00
' email ' : lead . email_from and tools . email_split ( lead . email_from ) [ 0 ] ,
2012-03-05 11:03:46 +00:00
' 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 )
2012-08-23 19:31:30 +00:00
partner_id = 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 = { }
2012-08-23 20:06:29 +00:00
force_partner_id = partner_id
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 )
2012-08-23 20:06:29 +00:00
partner_id = force_partner_id or self . _create_lead_partner ( cr , uid , lead , context = 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 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-08-25 04:10:37 +00:00
def action_makeMeeting ( self , cr , uid , ids , context = None ) :
2012-07-06 12:29:59 +00:00
""" This opens Meeting ' s calendar view to schedule meeting on current Opportunity
@return : Dictionary value for created Meeting view
2011-08-25 04:10:37 +00:00
"""
2012-07-06 12:29:59 +00:00
opportunity = self . browse ( cr , uid , ids [ 0 ] , context )
res = self . pool . get ( ' ir.actions.act_window ' ) . for_xml_id ( cr , uid , ' base_calendar ' , ' action_crm_meeting ' , context )
res [ ' context ' ] = {
' default_opportunity_id ' : opportunity . id ,
' default_partner_id ' : opportunity . partner_id and opportunity . partner_id . id or False ,
2012-07-26 12:03:35 +00:00
' default_partner_ids ' : opportunity . partner_id and [ opportunity . partner_id . id ] or False ,
2012-07-06 12:29:59 +00:00
' default_user_id ' : uid ,
' default_section_id ' : opportunity . section_id and opportunity . section_id . id or False ,
' default_email_from ' : opportunity . email_from ,
' default_state ' : ' open ' ,
' default_name ' : opportunity . name ,
}
return res
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 ' ) :
2012-08-07 11:31:37 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) ,
2012-08-06 17:07:32 +00:00
_ ( " You cannot delete lead ' %s ' because it is not in ' Draft ' state. " \
" You can still 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 ) :
2012-05-30 09:03:40 +00:00
if vals . get ( ' stage_id ' ) and not vals . get ( ' probability ' ) :
2012-01-30 10:29:39 +00:00
# change probability of lead(s) if required by stage
2012-05-30 09:03:40 +00:00
stage = self . pool . get ( ' crm.case.stage ' ) . browse ( cr , uid , vals [ ' stage_id ' ] , context = context )
if stage . on_change :
2012-01-30 10:29:39 +00:00
vals [ ' probability ' ] = stage . probability
2012-09-26 16:02:33 +00:00
for lead in self . browse ( cr , uid , ids , context = context ) :
if lead . section_id :
2012-09-26 18:44:45 +00:00
vals [ ' message_follower_ids ' ] = [ ( 4 , follower . id ) for follower in lead . section_id . message_follower_ids ]
2012-09-26 16:02:33 +00:00
return super ( crm_lead , self ) . write ( cr , uid , ids , vals , context )
2012-06-04 10:20:49 +00:00
# ----------------------------------------
# Mail Gateway
# ----------------------------------------
def message_new ( self , cr , uid , msg , custom_values = None , context = None ) :
2012-06-04 14:12:54 +00:00
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process .
This override updates the document according to the email .
2012-06-04 10:20:49 +00:00
"""
2012-06-04 14:12:54 +00:00
if custom_values is None : custom_values = { }
custom_values . update ( {
' name ' : msg . get ( ' subject ' ) or _ ( " No Subject " ) ,
2012-08-17 12:06:06 +00:00
' description ' : msg . get ( ' body ' ) ,
2012-06-04 14:12:54 +00:00
' email_from ' : msg . get ( ' from ' ) ,
' email_cc ' : msg . get ( ' cc ' ) ,
2012-06-04 10:20:49 +00:00
' user_id ' : False ,
2012-06-04 14:12:54 +00:00
} )
2012-06-04 10:20:49 +00:00
if msg . get ( ' priority ' ) in dict ( crm . AVAILABLE_PRIORITIES ) :
2012-06-04 14:12:54 +00:00
custom_values [ ' priority ' ] = msg . get ( ' priority ' )
return super ( crm_lead , self ) . message_new ( cr , uid , msg , custom_values = custom_values , context = context )
def message_update ( self , cr , uid , ids , msg , update_vals = None , context = None ) :
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process .
This method updates the document according to the email .
2012-06-04 10:20:49 +00:00
"""
if isinstance ( ids , ( str , int , long ) ) :
ids = [ ids ]
2012-06-04 14:12:54 +00:00
if update_vals is None : update_vals = { }
2012-06-04 10:20:49 +00:00
if msg . get ( ' priority ' ) in dict ( crm . AVAILABLE_PRIORITIES ) :
2012-08-23 20:06:29 +00:00
update_vals [ ' priority ' ] = msg . get ( ' priority ' )
2012-06-04 10:20:49 +00:00
maps = {
' cost ' : ' planned_cost ' ,
' revenue ' : ' planned_revenue ' ,
2012-06-04 14:12:54 +00:00
' probability ' : ' probability ' ,
2012-06-04 10:20:49 +00:00
}
2012-08-17 12:06:06 +00:00
for line in msg . get ( ' body ' , ' ' ) . split ( ' \n ' ) :
2012-06-04 10:20:49 +00:00
line = line . strip ( )
res = tools . misc . command_re . match ( line )
if res and maps . get ( res . group ( 1 ) . lower ( ) ) :
key = maps . get ( res . group ( 1 ) . lower ( ) )
2012-08-23 20:06:29 +00:00
update_vals [ key ] = res . group ( 2 ) . lower ( )
2012-06-04 14:12:54 +00:00
return super ( crm_lead , self ) . message_update ( cr , uid , ids , msg , update_vals = update_vals , context = context )
2012-06-04 10:20:49 +00:00
2012-04-02 17:14:14 +00:00
# ----------------------------------------
# OpenChatter methods and notifications
# ----------------------------------------
2012-05-30 09:03:40 +00:00
def stage_set_send_note ( self , cr , uid , ids , stage_id , context = None ) :
""" Override of the (void) default notification method. """
stage_name = self . pool . get ( ' crm.case.stage ' ) . name_get ( cr , uid , [ stage_id ] , context = context ) [ 0 ] [ 1 ]
2012-08-17 10:03:02 +00:00
return self . message_post ( cr , uid , ids , body = _ ( " Stage changed to <b> %s </b>. " ) % ( stage_name ) , context = context )
2012-08-06 17:07:32 +00:00
2012-04-02 17:14:14 +00:00
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-08-06 17:07:32 +00:00
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 ) )
2012-08-17 10:03:02 +00:00
self . message_post ( cr , uid , [ id ] , body = message , context = context )
2012-04-02 17:14:14 +00:00
return True
def case_mark_lost_send_note ( self , cr , uid , ids , context = None ) :
message = _ ( " Opportunity has been <b>lost</b>. " )
2012-08-17 10:03:02 +00:00
return self . message_post ( cr , uid , ids , body = message , context = context )
2012-04-02 17:14:14 +00:00
def case_mark_won_send_note ( self , cr , uid , ids , context = None ) :
message = _ ( " Opportunity has been <b>won</b>. " )
2012-08-17 10:03:02 +00:00
return self . message_post ( cr , uid , ids , body = message , context = context )
2012-04-02 17:14:14 +00:00
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 )
2012-08-17 10:03:02 +00:00
return self . message_post ( cr , uid , ids , body = message , context = context )
2012-04-02 17:14:14 +00:00
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 ) )
2012-08-17 10:03:02 +00:00
lead . message_post ( body = message )
2012-04-02 17:14:14 +00:00
return True
2012-08-06 17:07:32 +00:00
2012-04-02 17:14:14 +00:00
def convert_opportunity_send_note ( self , cr , uid , lead , context = None ) :
message = _ ( " Lead has been <b>converted to an opportunity</b>. " )
2012-08-17 10:03:02 +00:00
lead . message_post ( body = message )
2012-04-02 17:14:14 +00:00
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: