2009-10-13 05:58:37 +00:00
# -*- coding: utf-8 -*-
2006-12-07 13:41:40 +00:00
##############################################################################
2009-12-01 07:19:53 +00:00
#
2009-02-04 09:46:57 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2008-06-16 11:00:21 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 11:15:34 +00:00
# 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.
2006-12-07 13:41:40 +00:00
#
2008-11-03 19:18:56 +00:00
# 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
2009-10-14 11:15:34 +00:00
# GNU Affero General Public License for more details.
2006-12-07 13:41:40 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2009-12-01 07:19:53 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2006-12-07 13:41:40 +00:00
#
##############################################################################
2010-03-22 13:08:05 +00:00
import time
2010-07-06 11:46:25 +00:00
import base64
2010-03-22 13:08:05 +00:00
import tools
2010-12-10 17:54:55 +00:00
2010-02-16 13:57:41 +00:00
from osv import fields
from osv import osv
from tools . translate import _
2009-09-24 10:46:21 +00:00
2006-12-07 13:41:40 +00:00
MAX_LEVEL = 15
AVAILABLE_STATES = [
2010-06-10 13:04:07 +00:00
( ' draft ' , ' Draft ' ) ,
( ' open ' , ' Open ' ) ,
( ' cancel ' , ' Cancelled ' ) ,
( ' done ' , ' Closed ' ) ,
2010-04-28 07:20:02 +00:00
( ' pending ' , ' Pending ' ) ,
2006-12-07 13:41:40 +00:00
]
AVAILABLE_PRIORITIES = [
2010-04-28 07:20:02 +00:00
( ' 1 ' , ' Highest ' ) ,
2010-06-10 13:04:07 +00:00
( ' 2 ' , ' High ' ) ,
( ' 3 ' , ' Normal ' ) ,
( ' 4 ' , ' Low ' ) ,
( ' 5 ' , ' Lowest ' ) ,
2006-12-07 13:41:40 +00:00
]
2011-05-31 13:32:32 +00:00
class crm_base ( object ) :
"""
Base classe for crm object ,
Object that inherit from this class should have
date_open
date_closed
user_id
partner_id
partner_address_id
as field to be compatible with this class
"""
def _get_default_partner_address ( self , cr , uid , context = None ) :
""" Gives id of default address for current user
2011-06-29 11:05:31 +00:00
: param context : if portal in context is false return false anyway
2011-05-31 13:32:32 +00:00
"""
if context is None :
context = { }
2011-06-29 11:05:31 +00:00
if not context . get ( ' portal ' ) :
2011-05-31 13:32:32 +00:00
return False
return self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context ) . address_id . id
def _get_default_partner ( self , cr , uid , context = None ) :
""" Gives id of partner for current user
2011-06-29 11:05:31 +00:00
: param context : if portal in context is false return false anyway
2011-05-31 13:32:32 +00:00
"""
if context is None :
context = { }
if not context . get ( ' portal ' , False ) :
return False
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
if not user . address_id :
return False
return user . address_id . partner_id . id
def _get_default_email ( self , cr , uid , context = None ) :
""" Gives default email address for current user
2011-06-29 11:05:31 +00:00
: param context : if portal in context is false return false anyway
2011-05-31 13:32:32 +00:00
"""
if not context . get ( ' portal ' , False ) :
return False
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
if not user . address_id :
return False
return user . address_id . email
def _get_default_user ( self , cr , uid , context = None ) :
""" Gives current user id
2011-06-29 11:05:31 +00:00
: param context : if portal in context is false return false anyway
2011-05-31 13:32:32 +00:00
"""
if context and context . get ( ' portal ' , False ) :
return False
return uid
def _get_section ( self , cr , uid , context = None ) :
""" Gives section id for current User
"""
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
return user . context_section_id . id or False
def onchange_partner_address_id ( self , cr , uid , ids , add , email = False ) :
""" This function returns value of partner email based on Partner Address
@param ids : List of case IDs
@param add : Id of Partner ' s address
@email : Partner ' s email ID
"""
if not add :
return { ' value ' : { ' email_from ' : False } }
address = self . pool . get ( ' res.partner.address ' ) . browse ( cr , uid , add )
if address . email :
return { ' value ' : { ' email_from ' : address . email , ' phone ' : address . phone } }
else :
return { ' value ' : { ' phone ' : address . phone } }
def onchange_partner_id ( self , cr , uid , ids , part , email = False ) :
""" This function returns value of partner address based on partner
@param ids : List of case IDs
@param part : Partner ' s id
@email : Partner ' s email ID
"""
data = { }
if part :
addr = self . pool . get ( ' res.partner ' ) . address_get ( cr , uid , [ part ] , [ ' contact ' ] )
data = { ' partner_address_id ' : addr [ ' contact ' ] }
data . update ( self . onchange_partner_address_id ( cr , uid , ids , addr [ ' contact ' ] ) [ ' value ' ] )
return { ' value ' : data }
def case_open ( self , cr , uid , ids , * args ) :
""" Opens Case
@param ids : List of case Ids
"""
cases = self . browse ( cr , uid , ids )
for case in cases :
data = { ' state ' : ' open ' , ' active ' : True }
if not case . user_id :
data [ ' user_id ' ] = uid
self . write ( cr , uid , case . id , data )
self . _action ( cr , uid , cases , ' open ' )
return True
def case_close ( self , cr , uid , ids , * args ) :
""" Closes Case
@param ids : List of case Ids
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . write ( cr , uid , ids , { ' state ' : ' done ' ,
' date_closed ' : time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ,
} )
#
# We use the cache of cases to keep the old case state
#
self . _action ( cr , uid , cases , ' done ' )
return True
def case_cancel ( self , cr , uid , ids , * args ) :
""" Cancels Case
@param ids : List of case Ids
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . write ( cr , uid , ids , { ' state ' : ' cancel ' ,
' active ' : True } )
self . _action ( cr , uid , cases , ' cancel ' )
for case in cases :
message = _ ( " The case ' %s ' has been cancelled. " ) % ( case . name , )
self . log ( cr , uid , case . id , message )
return True
def case_pending ( self , cr , uid , ids , * args ) :
""" Marks case as pending
@param ids : List of case Ids
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . write ( cr , uid , ids , { ' state ' : ' pending ' , ' active ' : True } )
self . _action ( cr , uid , cases , ' pending ' )
return True
def case_reset ( self , cr , uid , ids , * args ) :
""" Resets case as draft
@param ids : List of case Ids
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . write ( cr , uid , ids , { ' state ' : ' draft ' , ' active ' : True } )
self . _action ( cr , uid , cases , ' draft ' )
return True
def _action ( self , cr , uid , cases , state_to , scrit = None , context = None ) :
if context is None :
context = { }
context [ ' state_to ' ] = state_to
rule_obj = self . pool . get ( ' base.action.rule ' )
model_obj = self . pool . get ( ' ir.model ' )
model_ids = model_obj . search ( cr , uid , [ ( ' model ' , ' = ' , self . _name ) ] )
rule_ids = rule_obj . search ( cr , uid , [ ( ' model_id ' , ' = ' , model_ids [ 0 ] ) ] )
return rule_obj . _action ( cr , uid , rule_ids , cases , scrit = scrit , context = context )
class crm_case ( crm_base ) :
"""
A simple python class to be used for common functions
Object that inherit from this class should inherit from mailgate . thread
And need a stage_id field
And object that inherit ( orm inheritance ) from a class the overwrite copy
"""
2010-05-05 11:55:13 +00:00
2010-12-16 10:28:40 +00:00
def _find_lost_stage ( self , cr , uid , type , section_id ) :
return self . _find_percent_stage ( cr , uid , 0.0 , type , section_id )
2011-02-18 09:54:19 +00:00
2010-12-16 10:28:40 +00:00
def _find_won_stage ( self , cr , uid , type , section_id ) :
return self . _find_percent_stage ( cr , uid , 100.0 , type , section_id )
2010-12-28 08:29:54 +00:00
2010-12-16 10:28:40 +00:00
def _find_percent_stage ( self , cr , uid , percent , type , section_id ) :
"""
Return the first stage with a probability == percent
"""
stage_pool = self . pool . get ( ' crm.case.stage ' )
if section_id :
ids = stage_pool . search ( cr , uid , [ ( " probability " , ' = ' , percent ) , ( " type " , ' like ' , type ) , ( " section_ids " , ' in ' , [ section_id ] ) ] )
2011-02-18 09:54:19 +00:00
else :
2010-12-16 10:28:40 +00:00
ids = stage_pool . search ( cr , uid , [ ( " probability " , ' = ' , percent ) , ( " type " , ' like ' , type ) ] )
2011-02-18 09:54:19 +00:00
2010-12-16 10:28:40 +00:00
if ids :
return ids [ 0 ]
return False
2011-02-18 09:54:19 +00:00
2010-12-16 10:28:40 +00:00
def _find_first_stage ( self , cr , uid , type , section_id ) :
"""
return the first stage that has a sequence number equal or higher than sequence
"""
stage_pool = self . pool . get ( ' crm.case.stage ' )
if section_id :
ids = stage_pool . search ( cr , uid , [ ( " sequence " , ' > ' , 0 ) , ( " type " , ' like ' , type ) , ( " section_ids " , ' in ' , [ section_id ] ) ] )
2011-02-18 09:54:19 +00:00
else :
2010-12-16 10:28:40 +00:00
ids = stage_pool . search ( cr , uid , [ ( " sequence " , ' > ' , 0 ) , ( " type " , ' like ' , type ) ] )
2011-02-18 09:54:19 +00:00
2010-12-16 10:28:40 +00:00
if ids :
stages = stage_pool . browse ( cr , uid , ids )
stage_min = stages [ 0 ]
for stage in stages :
if stage_min . sequence > stage . sequence :
stage_min = stage
return stage_min . id
2011-02-18 09:54:19 +00:00
else :
2010-12-16 10:28:40 +00:00
return False
2011-02-18 09:54:19 +00:00
2010-12-16 10:28:40 +00:00
def onchange_stage_id ( self , cr , uid , ids , stage_id , context = { } ) :
2010-05-05 11:55:13 +00:00
2010-12-16 10:28:40 +00:00
""" @param self: The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of stage ’ s IDs
@stage_id : change state id on run time """
2011-02-18 09:54:19 +00:00
2010-12-16 10:28:40 +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 } }
2010-12-16 11:19:37 +00:00
2011-05-31 13:32:32 +00:00
2010-05-05 11:55:13 +00:00
2010-08-17 12:54:00 +00:00
def copy ( self , cr , uid , id , default = None , context = None ) :
"""
Overrides orm copy method .
@param self : the object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param id : Id of mailgate thread
@param default : Dictionary of default values for copy .
@param context : A standard dictionary for contextual values
"""
2011-05-31 13:32:32 +00:00
2010-08-17 12:54:00 +00:00
if context is None :
context = { }
if default is None :
default = { }
default . update ( {
2011-02-18 09:54:19 +00:00
' message_ids ' : [ ] ,
2010-08-17 12:54:00 +00:00
} )
if hasattr ( self , ' _columns ' ) :
if self . _columns . get ( ' date_closed ' ) :
default . update ( {
2011-02-18 09:54:19 +00:00
' date_closed ' : False ,
2010-08-17 12:54:00 +00:00
} )
if self . _columns . get ( ' date_open ' ) :
default . update ( {
' date_open ' : False
} )
return super ( osv . osv , self ) . copy ( cr , uid , id , default , context = context )
2011-02-18 09:54:19 +00:00
2011-05-31 13:32:32 +00:00
2010-05-05 11:55:13 +00:00
2011-05-31 13:32:32 +00:00
2010-06-10 13:04:07 +00:00
2010-12-10 17:54:55 +00:00
def _find_next_stage ( self , cr , uid , stage_list , index , current_seq , stage_pool , context = None ) :
if index + 1 == len ( stage_list ) :
return False
next_stage_id = stage_list [ index + 1 ]
next_stage = stage_pool . browse ( cr , uid , next_stage_id , context = context )
if not next_stage :
return False
next_seq = next_stage . sequence
2010-12-16 10:28:40 +00:00
if not current_seq :
current_seq = 0
2010-12-10 17:54:55 +00:00
if ( abs ( next_seq - current_seq ) ) > = 1 :
return next_stage
else :
2010-12-13 09:39:59 +00:00
return self . _find_next_stage ( cr , uid , stage_list , index + 1 , current_seq , stage_pool )
2011-02-18 09:54:19 +00:00
2010-12-10 17:54:55 +00:00
def stage_change ( self , cr , uid , ids , context = None , order = ' sequence ' ) :
2010-12-14 07:37:12 +00:00
if context is None :
2010-05-05 11:55:13 +00:00
context = { }
2011-02-24 15:03:09 +00:00
2011-02-08 09:52:19 +00:00
stage_pool = self . pool . get ( ' crm.case.stage ' )
2011-02-08 09:48:31 +00:00
stage_type = context and context . get ( ' stage_type ' , ' ' )
2010-12-09 12:56:35 +00:00
current_seq = False
2010-12-10 17:54:55 +00:00
next_stage_id = False
2010-12-16 11:19:37 +00:00
2010-11-19 13:48:01 +00:00
for case in self . browse ( cr , uid , ids , context = context ) :
2011-02-08 09:52:19 +00:00
2010-10-01 12:37:19 +00:00
next_stage = False
2010-12-16 10:54:45 +00:00
value = { }
2011-02-18 09:54:19 +00:00
if case . section_id . id :
2010-12-16 10:54:45 +00:00
domain = [ ( ' type ' , ' = ' , stage_type ) , ( ' section_ids ' , ' = ' , case . section_id . id ) ]
else :
domain = [ ( ' type ' , ' = ' , stage_type ) ]
2010-12-13 09:39:59 +00:00
2011-02-18 09:54:19 +00:00
2010-12-10 17:54:55 +00:00
stages = stage_pool . search ( cr , uid , domain , order = order )
current_seq = case . stage_id . sequence
2010-10-01 12:37:19 +00:00
index = - 1
if case . stage_id and case . stage_id . id in stages :
index = stages . index ( case . stage_id . id )
2010-12-13 09:39:59 +00:00
2010-12-10 17:54:55 +00:00
next_stage = self . _find_next_stage ( cr , uid , stages , index , current_seq , stage_pool , context = context )
2011-02-18 09:54:19 +00:00
2010-10-01 12:37:19 +00:00
if next_stage :
2010-12-10 17:54:55 +00:00
next_stage_id = next_stage . id
2010-12-16 10:54:45 +00:00
value . update ( { ' stage_id ' : next_stage . id } )
2010-12-10 17:54:55 +00:00
if next_stage . on_change :
2010-12-16 10:54:45 +00:00
value . update ( { ' probability ' : next_stage . probability } )
self . write ( cr , uid , [ case . id ] , value , context = context )
2011-02-18 09:54:19 +00:00
2010-12-16 10:54:45 +00:00
return next_stage_id #FIXME should return a list of all id
2011-02-18 09:54:19 +00:00
2010-12-10 17:54:55 +00:00
def stage_next ( self , cr , uid , ids , context = None ) :
""" This function computes next stage for case from its current stage
using available stage for that case type
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case IDs
@param context : A standard dictionary for contextual values """
2011-02-18 09:54:19 +00:00
2010-12-10 17:54:55 +00:00
return self . stage_change ( cr , uid , ids , context = context , order = ' sequence ' )
2011-02-18 09:54:19 +00:00
2010-05-05 11:55:13 +00:00
def stage_previous ( self , cr , uid , ids , context = None ) :
""" This function computes previous stage for case from its current stage
2010-06-10 13:04:07 +00:00
using available stage for that case type
2010-05-05 11:55:13 +00:00
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case IDs
@param context : A standard dictionary for contextual values """
2010-12-10 17:54:55 +00:00
return self . stage_change ( cr , uid , ids , context = context , order = ' sequence desc ' )
2010-05-05 11:55:13 +00:00
2011-05-31 13:32:32 +00:00
2010-05-05 11:55:13 +00:00
2011-05-31 13:32:32 +00:00
2010-06-10 13:04:07 +00:00
2010-11-19 13:48:01 +00:00
def _history ( self , cr , uid , cases , keyword , history = False , subject = None , email = False , details = None , email_from = False , message_id = False , attach = [ ] , context = None ) :
2010-05-19 13:42:43 +00:00
mailgate_pool = self . pool . get ( ' mailgate.thread ' )
2010-07-02 16:31:01 +00:00
return mailgate_pool . history ( cr , uid , cases , keyword , history = history , \
2010-07-02 05:38:19 +00:00
subject = subject , email = email , \
details = details , email_from = email_from , \
message_id = message_id , attach = attach , \
context = context )
2010-06-10 13:04:07 +00:00
2010-05-05 11:55:13 +00:00
def case_open ( self , cr , uid , ids , * args ) :
""" Opens Case
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case Ids
@param * args : Tuple Value for additional Params
"""
2011-02-18 09:54:19 +00:00
2010-05-05 11:55:13 +00:00
cases = self . browse ( cr , uid , ids )
self . _history ( cr , uid , cases , _ ( ' Open ' ) )
for case in cases :
data = { ' state ' : ' open ' , ' active ' : True }
if not case . user_id :
data [ ' user_id ' ] = uid
self . write ( cr , uid , case . id , data )
2011-02-18 09:54:19 +00:00
self . _action ( cr , uid , cases , ' open ' )
2010-05-05 11:55:13 +00:00
return True
def case_close ( self , cr , uid , ids , * args ) :
""" Closes Case
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case Ids
@param * args : Tuple Value for additional Params
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . _history ( cr , uid , cases , _ ( ' Close ' ) )
self . write ( cr , uid , ids , { ' state ' : ' done ' ,
' date_closed ' : time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ,
} )
#
# We use the cache of cases to keep the old case state
#
self . _action ( cr , uid , cases , ' done ' )
return True
def case_escalate ( self , cr , uid , ids , * args ) :
""" Escalates case to top level
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case Ids
@param * args : Tuple Value for additional Params
"""
cases = self . browse ( cr , uid , ids )
for case in cases :
2010-07-09 10:27:44 +00:00
data = { ' active ' : True }
2010-05-05 11:55:13 +00:00
if case . section_id . parent_id :
data [ ' section_id ' ] = case . section_id . parent_id . id
2010-07-09 10:27:44 +00:00
if case . section_id . parent_id . change_responsible :
if case . section_id . parent_id . user_id :
data [ ' user_id ' ] = case . section_id . parent_id . user_id . id
2010-05-05 11:55:13 +00:00
else :
2010-06-10 13:04:07 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' You can not escalate, You are already at the top level regarding your sales-team category. ' ) )
2010-05-05 11:55:13 +00:00
self . write ( cr , uid , [ case . id ] , data )
cases = self . browse ( cr , uid , ids )
self . _history ( cr , uid , cases , _ ( ' Escalate ' ) )
self . _action ( cr , uid , cases , ' escalate ' )
return True
2010-05-12 10:12:56 +00:00
2010-05-05 11:55:13 +00:00
def case_cancel ( self , cr , uid , ids , * args ) :
""" Cancels Case
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case Ids
@param * args : Tuple Value for additional Params
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . _history ( cr , uid , cases , _ ( ' Cancel ' ) )
self . write ( cr , uid , ids , { ' state ' : ' cancel ' ,
' active ' : True } )
self . _action ( cr , uid , cases , ' cancel ' )
2010-07-22 11:00:56 +00:00
for case in cases :
2010-10-16 14:02:41 +00:00
message = _ ( " The case ' %s ' has been cancelled. " ) % ( case . name , )
2010-07-22 11:00:56 +00:00
self . log ( cr , uid , case . id , message )
2010-05-05 11:55:13 +00:00
return True
def case_pending ( self , cr , uid , ids , * args ) :
""" Marks case as pending
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case Ids
@param * args : Tuple Value for additional Params
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . _history ( cr , uid , cases , _ ( ' Pending ' ) )
self . write ( cr , uid , ids , { ' state ' : ' pending ' , ' active ' : True } )
self . _action ( cr , uid , cases , ' pending ' )
return True
def case_reset ( self , cr , uid , ids , * args ) :
""" Resets case as draft
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of case Ids
@param * args : Tuple Value for additional Params
"""
2011-05-16 06:17:45 +00:00
state = ' draft '
if ' crm.phonecall ' in args :
state = ' open '
2010-05-05 11:55:13 +00:00
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . _history ( cr , uid , cases , _ ( ' Draft ' ) )
2011-05-16 06:17:45 +00:00
self . write ( cr , uid , ids , { ' state ' : state , ' active ' : True } )
self . _action ( cr , uid , cases , state )
2010-05-05 11:55:13 +00:00
return True
2010-06-10 13:04:07 +00:00
2010-11-19 13:48:01 +00:00
def remind_partner ( self , cr , uid , ids , context = None , attach = False ) :
2010-05-19 13:42:43 +00:00
"""
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of Remind Partner ' s IDs
@param context : A standard dictionary for contextual values
"""
2011-03-02 12:29:07 +00:00
2010-05-19 13:42:43 +00:00
return self . remind_user ( cr , uid , ids , context , attach ,
destination = False )
2010-11-23 11:31:52 +00:00
def remind_user ( self , cr , uid , ids , context = None , attach = False , destination = True ) :
2010-05-19 13:42:43 +00:00
"""
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
2011-03-04 12:13:36 +00:00
@param ids : List of case ' s IDs to remind
2010-05-19 13:42:43 +00:00
@param context : A standard dictionary for contextual values
"""
2010-11-19 13:48:01 +00:00
for case in self . browse ( cr , uid , ids , context = context ) :
2011-03-02 12:29:07 +00:00
if not destination and not case . email_from :
2011-04-20 15:29:55 +00:00
return False
2011-03-02 10:28:38 +00:00
if not case . user_id . user_email :
2011-04-20 15:29:55 +00:00
return False
2011-03-04 12:13:36 +00:00
if destination and case . section_id . user_id :
2011-03-02 12:29:07 +00:00
case_email = case . section_id . user_id . user_email
2011-03-02 10:28:38 +00:00
else :
2011-03-02 12:29:07 +00:00
case_email = case . user_id . user_email
2011-03-04 12:13:36 +00:00
src = case_email
dest = case . user_id
body = case . description or " "
if case . message_ids :
body = case . message_ids [ 0 ] . description or " "
if not destination :
src , dest = dest , case . email_from
if body and case . user_id . signature :
if body :
body + = ' \n \n %s ' % ( case . user_id . signature )
else :
body = ' \n \n %s ' % ( case . user_id . signature )
body = self . format_body ( body )
attach_to_send = None
if attach :
attach_ids = self . pool . get ( ' ir.attachment ' ) . search ( cr , uid , [ ( ' res_model ' , ' = ' , self . _name ) , ( ' res_id ' , ' = ' , case . id ) ] )
attach_to_send = self . pool . get ( ' ir.attachment ' ) . read ( cr , uid , attach_ids , [ ' datas_fname ' , ' datas ' ] )
attach_to_send = map ( lambda x : ( x [ ' datas_fname ' ] , base64 . decodestring ( x [ ' datas ' ] ) ) , attach_to_send )
2010-05-19 13:42:43 +00:00
# Send an email
2011-03-04 12:13:36 +00:00
subject = " Reminder: [ %s ] %s " % ( str ( case . id ) , case . name , )
tools . email_send (
src ,
[ dest ] ,
subject ,
body ,
reply_to = case . section_id . reply_to or ' ' ,
openobject_id = str ( case . id ) ,
attach = attach_to_send
)
self . _history ( cr , uid , [ case ] , _ ( ' Send ' ) , history = True , subject = subject , email = dest , details = body , email_from = src )
2010-06-10 13:04:07 +00:00
return True
2010-05-19 13:42:43 +00:00
2010-11-19 13:48:01 +00:00
def _check ( self , cr , uid , ids = False , context = None ) :
2010-05-19 13:42:43 +00:00
"""
Function called by the scheduler to process cases for date actions
Only works on not done and cancelled cases
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param context : A standard dictionary for contextual values
"""
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 [ ] )
2010-11-19 13:48:01 +00:00
cases = self . browse ( cr , uid , ids2 , context = context )
2010-05-19 13:42:43 +00:00
return self . _action ( cr , uid , cases , False , context = context )
2011-05-31 13:32:32 +00:00
2010-05-19 13:42:43 +00:00
def format_body ( self , body ) :
return self . pool . get ( ' base.action.rule ' ) . format_body ( body )
def format_mail ( self , obj , body ) :
return self . pool . get ( ' base.action.rule ' ) . format_mail ( obj , body )
2010-05-05 11:55:13 +00:00
2010-08-17 13:00:44 +00:00
def message_followers ( self , cr , uid , ids , context = None ) :
""" Get a list of emails of the people following this thread
"""
res = { }
for case in self . browse ( cr , uid , ids , context = context ) :
l = [ ]
if case . email_cc :
l . append ( case . email_cc )
2010-08-17 19:23:58 +00:00
if case . user_id and case . user_id . user_email :
l . append ( case . user_id . user_email )
2010-08-17 13:00:44 +00:00
res [ case . id ] = l
return res
2010-10-01 12:37:19 +00:00
class crm_case_stage ( osv . osv ) :
""" Stage of case """
_name = " crm.case.stage "
_description = " Stage of case "
_rec_name = ' name '
_order = " sequence "
2011-02-18 09:54:19 +00:00
2010-12-14 13:19:59 +00:00
def _get_type_value ( self , cr , user , context ) :
return [ ( ' lead ' , ' Lead ' ) , ( ' opportunity ' , ' Opportunity ' ) ]
2010-10-01 12:37:19 +00:00
_columns = {
' name ' : fields . char ( ' Stage Name ' , size = 64 , required = True , translate = True ) ,
' sequence ' : fields . integer ( ' Sequence ' , help = " Gives the sequence order when displaying a list of case stages. " ) ,
' probability ' : fields . float ( ' Probability ( % ) ' , required = True , help = " This percentage depicts the default/average probability of the Case for this stage to be a success " ) ,
' on_change ' : fields . boolean ( ' Change Probability Automatically ' , \
help = " Change Probability on next and previous stages. " ) ,
2010-12-09 12:56:35 +00:00
' requirements ' : fields . text ( ' Requirements ' ) ,
2011-02-18 13:20:35 +00:00
' type ' : fields . selection ( _get_type_value , ' Type ' , required = True ) ,
2010-10-01 12:37:19 +00:00
}
2011-02-18 09:54:19 +00:00
2010-12-09 12:56:35 +00:00
def _find_stage_type ( self , cr , uid , context = None ) :
""" Finds type of stage according to object.
2010-10-01 12:37:19 +00:00
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param context : A standard dictionary for contextual values
"""
2010-12-09 12:56:35 +00:00
type = context and context . get ( ' type ' , ' ' ) or ' '
return type
2010-10-01 12:37:19 +00:00
_defaults = {
' sequence ' : lambda * args : 1 ,
' probability ' : lambda * args : 0.0 ,
2010-12-09 12:56:35 +00:00
' type ' : _find_stage_type ,
2010-10-01 12:37:19 +00:00
}
crm_case_stage ( )
2006-12-07 13:41:40 +00:00
class crm_case_section ( osv . osv ) :
2010-04-18 15:32:44 +00:00
""" Sales Team """
2010-03-22 09:45:56 +00:00
2008-07-22 15:11:28 +00:00
_name = " crm.case.section "
2010-02-28 13:21:56 +00:00
_description = " Sales Teams "
2010-09-14 11:45:55 +00:00
_order = " complete_name "
2010-11-19 13:48:01 +00:00
def get_full_name ( self , cr , uid , ids , field_name , arg , context = None ) :
return dict ( self . name_get ( cr , uid , ids , context = context ) )
2010-03-22 09:45:56 +00:00
2008-07-22 15:11:28 +00:00
_columns = {
2010-06-10 13:04:07 +00:00
' name ' : fields . char ( ' Sales Team ' , size = 64 , required = True , translate = True ) ,
2011-07-01 23:41:24 +00:00
' complete_name ' : fields . function ( get_full_name , type = ' char ' , size = 256 , readonly = True , store = True ) ,
2010-06-10 13:04:07 +00:00
' code ' : fields . char ( ' Code ' , size = 8 ) ,
2010-07-15 13:18:56 +00:00
' active ' : fields . boolean ( ' Active ' , help = " If the active field is set to " \
" true, it will allow you to hide the sales team without removing it. " ) ,
2010-06-10 13:04:07 +00:00
' allow_unlink ' : fields . boolean ( ' Allow Delete ' , help = " Allows to delete non draft cases " ) ,
2010-07-12 22:18:59 +00:00
' change_responsible ' : fields . boolean ( ' Change Responsible ' , help = " Thick this box if you want that on escalation, the responsible of this sale team automatically becomes responsible of the lead/opportunity escaladed " ) ,
2010-06-10 13:04:07 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' Responsible User ' ) ,
2010-04-23 09:39:30 +00:00
' member_ids ' : fields . many2many ( ' res.users ' , ' sale_member_rel ' , ' section_id ' , ' member_id ' , ' Team Members ' ) ,
2010-08-10 11:35:06 +00:00
' reply_to ' : fields . char ( ' Reply-To ' , size = 64 , help = " The email address put in the ' Reply-To ' of all emails sent by OpenERP about cases in this sales team " ) ,
2010-04-18 15:32:44 +00:00
' parent_id ' : fields . many2one ( ' crm.case.section ' , ' Parent Team ' ) ,
' child_ids ' : fields . one2many ( ' crm.case.section ' , ' parent_id ' , ' Child Teams ' ) ,
2010-12-13 13:57:55 +00:00
' resource_calendar_id ' : fields . many2one ( ' resource.calendar ' , " Working Time " ) ,
2010-04-17 21:07:21 +00:00
' note ' : fields . text ( ' Description ' ) ,
2011-02-18 09:54:19 +00:00
' working_hours ' : fields . float ( ' Working Hours ' , digits = ( 16 , 2 ) ) ,
2010-10-06 12:11:46 +00:00
' stage_ids ' : fields . many2many ( ' crm.case.stage ' , ' section_stage_rel ' , ' section_id ' , ' stage_id ' , ' Stages ' ) ,
2008-07-22 15:11:28 +00:00
}
2010-03-22 09:45:56 +00:00
2008-07-22 15:11:28 +00:00
_defaults = {
2010-06-10 13:04:07 +00:00
' active ' : lambda * a : 1 ,
' allow_unlink ' : lambda * a : 1 ,
2008-07-22 15:11:28 +00:00
}
2010-03-22 09:45:56 +00:00
2008-07-22 15:11:28 +00:00
_sql_constraints = [
2010-04-18 15:32:44 +00:00
( ' code_uniq ' , ' unique (code) ' , ' The code of the sales team must be unique ! ' )
2008-07-22 15:11:28 +00:00
]
2010-03-22 09:45:56 +00:00
2010-11-19 13:48:01 +00:00
def _check_recursion ( self , cr , uid , ids , context = None ) :
2010-03-23 12:51:25 +00:00
2010-03-22 09:45:56 +00:00
"""
2010-04-23 09:39:30 +00:00
Checks for recursion level for sales team
2010-03-19 11:15:35 +00:00
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
2010-04-23 09:39:30 +00:00
@param ids : List of Sales team ids
2010-03-19 11:15:35 +00:00
"""
2008-07-22 15:11:28 +00:00
level = 100
2010-06-10 13:04:07 +00:00
2008-07-22 15:11:28 +00:00
while len ( ids ) :
2010-06-10 13:34:19 +00:00
cr . execute ( ' select distinct parent_id from crm_case_section where id IN %s ' , ( tuple ( ids ) , ) )
2010-03-19 11:15:35 +00:00
ids = filter ( None , map ( lambda x : x [ 0 ] , cr . fetchall ( ) ) )
2008-07-22 15:11:28 +00:00
if not level :
return False
level - = 1
2010-03-22 09:45:56 +00:00
2008-07-22 15:11:28 +00:00
return True
2010-03-22 09:45:56 +00:00
2008-07-22 15:11:28 +00:00
_constraints = [
2010-04-23 09:39:30 +00:00
( _check_recursion , ' Error ! You cannot create recursive Sales team. ' , [ ' parent_id ' ] )
2008-07-22 15:11:28 +00:00
]
2010-03-22 09:45:56 +00:00
2010-04-06 10:20:15 +00:00
def name_get ( self , cr , uid , ids , context = None ) :
2010-03-23 05:55:46 +00:00
""" Overrides orm name_get method
2010-03-22 09:52:30 +00:00
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
2010-04-23 09:39:30 +00:00
@param ids : List of sales team ids
2010-03-22 09:52:30 +00:00
"""
2010-11-23 07:05:05 +00:00
if context is None :
2010-04-06 10:20:15 +00:00
context = { }
2011-04-19 12:11:32 +00:00
if not isinstance ( ids , list ) :
ids = [ ids ]
2008-07-22 15:11:28 +00:00
res = [ ]
2010-04-06 10:20:15 +00:00
if not ids :
return res
reads = self . read ( cr , uid , ids , [ ' name ' , ' parent_id ' ] , context )
2010-03-22 10:40:26 +00:00
2008-07-22 15:11:28 +00:00
for record in reads :
name = record [ ' name ' ]
if record [ ' parent_id ' ] :
2010-03-19 11:15:35 +00:00
name = record [ ' parent_id ' ] [ 1 ] + ' / ' + name
2008-07-22 15:11:28 +00:00
res . append ( ( record [ ' id ' ] , name ) )
return res
2010-04-06 10:20:15 +00:00
2006-12-07 13:41:40 +00:00
crm_case_section ( )
2010-03-23 05:55:46 +00:00
2010-01-18 10:03:52 +00:00
class crm_case_categ ( osv . osv ) :
2010-03-22 09:52:30 +00:00
""" Category of Case """
2010-01-18 10:03:52 +00:00
_name = " crm.case.categ "
2010-09-28 12:50:08 +00:00
_description = " Category of Case "
2010-01-18 10:03:52 +00:00
_columns = {
2010-09-20 12:06:00 +00:00
' name ' : fields . char ( ' Name ' , size = 64 , required = True , translate = True ) ,
2010-06-10 13:04:07 +00:00
' section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' ) ,
' object_id ' : fields . many2one ( ' ir.model ' , ' Object Name ' ) ,
2010-01-18 10:03:52 +00:00
}
2010-03-22 09:52:30 +00:00
2010-04-20 05:51:17 +00:00
def _find_object_id ( self , cr , uid , context = None ) :
2010-04-06 10:20:15 +00:00
""" Finds id for case object
2010-03-22 09:52:30 +00:00
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param context : A standard dictionary for contextual values
"""
2010-01-18 14:42:02 +00:00
object_id = context and context . get ( ' object_id ' , False ) or False
2010-03-19 11:15:35 +00:00
ids = self . pool . get ( ' ir.model ' ) . search ( cr , uid , [ ( ' model ' , ' = ' , object_id ) ] )
2010-03-22 13:08:05 +00:00
return ids and ids [ 0 ]
2010-04-05 06:12:50 +00:00
_defaults = {
2010-01-18 14:42:02 +00:00
' object_id ' : _find_object_id
2010-04-06 10:20:15 +00:00
2010-01-18 10:03:52 +00:00
}
crm_case_categ ( )
2010-03-23 05:55:46 +00:00
2010-10-06 12:11:46 +00:00
class crm_case_stage ( osv . osv ) :
_inherit = " crm.case.stage "
_columns = {
' section_ids ' : fields . many2many ( ' crm.case.section ' , ' section_stage_rel ' , ' stage_id ' , ' section_id ' , ' Sections ' ) ,
}
2011-02-18 09:54:19 +00:00
2010-10-06 12:11:46 +00:00
crm_case_stage ( )
2010-01-18 10:03:52 +00:00
class crm_case_resource_type ( osv . osv ) :
2010-03-22 09:52:30 +00:00
""" Resource Type of case """
2010-01-18 10:03:52 +00:00
_name = " crm.case.resource.type "
2010-09-21 16:39:51 +00:00
_description = " Campaign "
2010-01-18 10:03:52 +00:00
_rec_name = " name "
_columns = {
2010-09-21 16:39:51 +00:00
' name ' : fields . char ( ' Campaign Name ' , size = 64 , required = True , translate = True ) ,
2010-06-10 13:04:07 +00:00
' section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' ) ,
2010-01-18 10:03:52 +00:00
}
crm_case_resource_type ( )
2010-04-06 10:20:15 +00:00
def _links_get ( self , cr , uid , context = None ) :
""" Gets links value for reference field
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param context : A standard dictionary for contextual values
2010-03-22 09:52:30 +00:00
"""
2008-07-22 15:11:28 +00:00
obj = self . pool . get ( ' res.request.link ' )
ids = obj . search ( cr , uid , [ ] )
res = obj . read ( cr , uid , ids , [ ' object ' , ' name ' ] , context )
return [ ( r [ ' object ' ] , r [ ' name ' ] ) for r in res ]
2006-12-07 13:41:40 +00:00
2010-01-11 09:20:00 +00:00
class users ( osv . osv ) :
_inherit = ' res.users '
_description = " Users "
2010-01-08 11:05:05 +00:00
_columns = {
2010-06-10 13:04:07 +00:00
' context_section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' ) ,
2010-02-01 08:21:18 +00:00
}
2011-02-18 09:54:19 +00:00
def create ( self , cr , uid , vals , context = None ) :
res = super ( users , self ) . create ( cr , uid , vals , context = context )
2011-02-01 11:26:58 +00:00
section_obj = self . pool . get ( ' crm.case.section ' )
2011-02-18 09:54:19 +00:00
if vals . get ( ' context_section_id ' , False ) :
section_obj . write ( cr , uid , [ vals [ ' context_section_id ' ] ] , { ' member_ids ' : [ ( 4 , res ) ] } , context )
return res
2010-01-11 09:20:00 +00:00
users ( )
2010-03-05 10:40:27 +00:00
class res_partner ( osv . osv ) :
_inherit = ' res.partner '
_columns = {
2010-06-10 13:04:07 +00:00
' section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' ) ,
2010-03-05 10:40:27 +00:00
}
res_partner ( )