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-02-16 13:57:41 +00:00
from datetime import datetime
from datetime import timedelta
2010-07-06 11:46:25 +00:00
import base64
2010-03-22 13:08:05 +00:00
import tools
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
]
2010-05-05 11:55:13 +00:00
class crm_case ( object ) :
""" A simple python class to be used for common functions """
def _get_default_partner_address ( self , cr , uid , context ) :
""" Gives id of default address for current user
@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
"""
if not context . get ( ' portal ' , False ) :
return False
return self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context ) . address_id . id
def _get_default_partner ( self , cr , uid , context ) :
""" Gives id of partner for current user
@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
"""
if not context . get ( ' portal ' , False ) :
return False
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context )
if not user . address_id :
return False
return user . address_id . partner_id . id
def _get_default_email ( self , cr , uid , context ) :
""" Gives default email address for current user
@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
"""
if not context . get ( ' portal ' , False ) :
return False
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context )
if not user . address_id :
return False
return user . address_id . email
def _get_default_user ( self , cr , uid , context ) :
""" Gives current user id
@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
"""
if context . get ( ' portal ' , False ) :
return False
return uid
def _get_section ( self , cr , uid , context ) :
""" Gives section id for current User
@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
"""
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
return user . context_section_id . id or False
2010-06-10 13:04:07 +00:00
2010-05-05 11:55:13 +00:00
def stage_next ( self , cr , uid , ids , context = None ) :
""" This function computes next 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 """
if not context :
context = { }
s = self . get_stage_dict ( cr , uid , ids , context = context )
2010-06-09 05:49:31 +00:00
section = self . _name
2010-06-25 08:46:21 +00:00
stage = False
2010-06-24 12:59:07 +00:00
stage_pool = self . pool . get ( ' crm.case.stage ' )
2010-05-05 11:55:13 +00:00
for case in self . browse ( cr , uid , ids , context ) :
if section in s :
2010-07-12 22:10:32 +00:00
st = not context . get ( ' force_domain ' , False ) and case . stage_id . id or False
2010-05-05 11:55:13 +00:00
if st in s [ section ] :
2010-06-24 12:59:07 +00:00
data = { ' stage_id ' : s [ section ] [ st ] }
2010-06-25 08:46:21 +00:00
stage = s [ section ] [ st ]
2010-06-24 12:59:07 +00:00
self . write ( cr , uid , [ case . id ] , data )
2010-06-25 08:46:21 +00:00
return stage
2010-05-05 11:55:13 +00:00
def get_stage_dict ( self , cr , uid , ids , context = None ) :
""" This function gives dictionary for stage according to stage levels
@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 """
if not context :
context = { }
2010-06-09 05:49:31 +00:00
stage_obj = self . pool . get ( ' crm.case.stage ' )
2010-07-12 22:10:32 +00:00
tmp = self . read ( cr , uid , ids , [ ' section_id ' ] , context ) [ 0 ] [ ' section_id ' ]
section_id = tmp and tmp [ 0 ] or False
domain = [ ( ' object_id.model ' , ' = ' , self . _name ) , ( ' section_id ' , ' = ' , section_id ) ]
if ' force_domain ' in context and context [ ' force_domain ' ] :
domain + = context [ ' force_domain ' ]
sid = stage_obj . search ( cr , uid , domain , context = context )
2010-05-05 11:55:13 +00:00
s = { }
previous = { }
2010-06-09 05:49:31 +00:00
section = self . _name
for stage in stage_obj . browse ( cr , uid , sid , context = context ) :
2010-05-05 11:55:13 +00:00
s . setdefault ( section , { } )
s [ section ] [ previous . get ( section , False ) ] = stage . id
previous [ section ] = stage . id
return s
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 """
if not context :
context = { }
s = self . get_stage_dict ( cr , uid , ids , context = context )
2010-06-09 05:49:31 +00:00
section = self . _name
2010-06-24 12:59:07 +00:00
stage_pool = self . pool . get ( ' crm.case.stage ' )
2010-05-05 11:55:13 +00:00
for case in self . browse ( cr , uid , ids , context ) :
if section in s :
2010-07-12 22:10:32 +00:00
st = not context . get ( ' force_domain ' , False ) and case . stage_id . id or False
2010-05-05 11:55:13 +00:00
s [ section ] = dict ( [ ( v , k ) for ( k , v ) in s [ section ] . iteritems ( ) ] )
if st in s [ section ] :
2010-06-24 12:59:07 +00:00
data = { ' stage_id ' : s [ section ] [ st ] }
2010-06-25 08:46:21 +00:00
if s [ section ] [ st ] :
stage = stage_pool . browse ( cr , uid , s [ section ] [ st ] , context = context )
if stage . on_change :
data . update ( { ' probability ' : stage . probability } )
2010-06-24 12:59:07 +00:00
self . write ( cr , uid , [ case . id ] , data )
2010-05-05 11:55:13 +00:00
return True
def onchange_partner_id ( self , cr , uid , ids , part , email = False ) :
""" This function returns value of partner address based on partner
@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 part : Partner ' s id
2010-06-10 13:04:07 +00:00
@email : Partner ' s email ID
2010-05-05 11:55:13 +00:00
"""
if not part :
2010-06-10 13:04:07 +00:00
return { ' value ' : { ' partner_address_id ' : False ,
2010-06-24 12:59:07 +00:00
' email_from ' : False ,
' phone ' : False
2010-05-05 11:55:13 +00:00
} }
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 onchange_partner_address_id ( self , cr , uid , ids , add , email = False ) :
""" This function returns value of partner email based on Partner Address
@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 add : Id of Partner ' s address
2010-06-10 13:04:07 +00:00
@email : Partner ' s email ID
2010-05-05 11:55:13 +00:00
"""
if not add :
return { ' value ' : { ' email_from ' : False } }
address = self . pool . get ( ' res.partner.address ' ) . browse ( cr , uid , add )
2010-06-24 12:59:07 +00:00
return { ' value ' : { ' email_from ' : address . email , ' phone ' : address . phone } }
2010-06-10 13:04:07 +00:00
2010-07-02 05:38:19 +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 = { } ) :
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
"""
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 )
self . _action ( cr , uid , cases , ' open ' )
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 ' )
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
"""
cases = self . browse ( cr , uid , ids )
cases [ 0 ] . state # to fill the browse record cache
self . _history ( cr , uid , cases , _ ( ' Draft ' ) )
self . write ( cr , uid , ids , { ' state ' : ' draft ' , ' active ' : True } )
self . _action ( cr , uid , cases , ' draft ' )
return True
2010-06-10 13:04:07 +00:00
2010-05-19 13:42:43 +00:00
def remind_partner ( self , cr , uid , ids , context = { } , attach = False ) :
"""
@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
"""
return self . remind_user ( cr , uid , ids , context , attach ,
destination = False )
def remind_user ( self , cr , uid , ids , context = { } , attach = False , destination = True ) :
"""
@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 user ' s IDs
@param context : A standard dictionary for contextual values
"""
for case in self . browse ( cr , uid , ids ) :
if not case . section_id . reply_to :
raise osv . except_osv ( _ ( ' Error! ' ) , ( " Reply To is not specified in the sales team " ) )
if not case . email_from :
raise osv . except_osv ( _ ( ' Error! ' ) , ( " Partner Email is not specified in Case " ) )
if case . section_id . reply_to and case . email_from :
src = case . email_from
dest = case . section_id . reply_to
2010-07-06 11:46:25 +00:00
body = case . description or " "
if case . message_ids :
body = case . message_ids [ 0 ] . description or " "
2010-05-19 13:42:43 +00:00
if not destination :
src , dest = dest , src
if body and case . user_id . signature :
body + = ' \n \n %s ' % ( case . user_id . signature )
body = self . format_body ( body )
attach_to_send = None
if attach :
2010-07-06 11:46:25 +00:00
attach_ids = self . pool . get ( ' ir.attachment ' ) . search ( cr , uid , [ ( ' res_model ' , ' = ' , self . _name ) , ( ' res_id ' , ' = ' , case . id ) ] )
2010-05-19 13:42:43 +00:00
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 )
# Send an email
2010-07-01 10:46:31 +00:00
subject = " Reminder: [ %s ] %s " % ( str ( case . id ) , case . name , )
2010-05-19 13:42:43 +00:00
flag = tools . email_send (
src ,
2010-07-01 10:46:31 +00:00
[ dest ] ,
2010-07-02 05:38:19 +00:00
subject ,
2010-05-19 13:42:43 +00:00
body ,
reply_to = case . section_id . reply_to ,
openobject_id = str ( case . id ) ,
attach = attach_to_send
)
2010-07-02 05:38:19 +00:00
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
def _check ( self , cr , uid , ids = False , context = { } ) :
"""
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 [ ] )
cases = self . browse ( cr , uid , ids2 , context )
return self . _action ( cr , uid , cases , False , context = context )
def _action ( self , cr , uid , cases , state_to , scrit = None , context = { } ) :
if not context :
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 , [ ( ' name ' , ' = ' , model_ids [ 0 ] ) ] )
return rule_obj . _action ( cr , uid , rule_ids , cases , scrit = scrit , context = context )
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
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-01-09 14:30:02 +00:00
_order = " name "
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 ) ,
' code ' : fields . char ( ' Code ' , size = 8 ) ,
2010-03-22 09:52:30 +00:00
' active ' : fields . boolean ( ' Active ' , help = " If the active field is set to \
2010-06-10 13:04:07 +00:00
true , it will allow you to hide the sales team without removing it . " ),
' 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-03-22 09:52:30 +00:00
' reply_to ' : fields . char ( ' Reply-To ' , size = 64 , help = " The email address put \
in the ' Reply-To ' of all emails sent by Open ERP 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-04-05 06:12:50 +00:00
' resource_calendar_id ' : fields . many2one ( ' resource.calendar ' , " Resource ' s Calendar " ) ,
2010-04-17 21:07:21 +00:00
' note ' : fields . text ( ' Description ' ) ,
2010-05-14 06:04:32 +00:00
' working_hours ' : fields . float ( ' Working Hours ' , digits = ( 16 , 2 ) ) ,
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
2008-07-22 15:11:28 +00:00
def _check_recursion ( self , cr , uid , ids ) :
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-04-06 10:20:15 +00:00
if not context :
context = { }
2010-03-22 09:52:30 +00:00
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 "
_description = " Category of case "
2010-01-18 14:42:02 +00:00
2010-01-18 10:03:52 +00:00
_columns = {
2010-06-10 13:04:07 +00:00
' name ' : fields . char ( ' Case Category Name ' , size = 64 , required = True , translate = True ) ,
' 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-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 "
_description = " Resource Type of case "
_rec_name = " name "
2010-03-22 09:52:30 +00:00
2010-01-18 10:03:52 +00:00
_columns = {
2010-06-24 12:59:07 +00:00
' name ' : fields . char ( ' Resource Type ' , 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-01-18 14:42:02 +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 09:45:56 +00:00
return ids and ids [ 0 ]
2010-03-22 10:40:26 +00:00
2010-01-18 14:42:02 +00:00
_defaults = {
' object_id ' : _find_object_id
2010-03-22 13:08:05 +00:00
}
2010-03-22 10:40:26 +00:00
2010-01-18 10:03:52 +00:00
crm_case_resource_type ( )
class crm_case_stage ( osv . osv ) :
2010-03-22 09:52:30 +00:00
""" Stage of case """
2010-01-18 10:03:52 +00:00
_name = " crm.case.stage "
_description = " Stage of case "
_rec_name = ' name '
_order = " sequence "
2010-03-22 09:52:30 +00:00
2010-01-18 10:03:52 +00:00
_columns = {
2010-06-10 13:04:07 +00:00
' name ' : fields . char ( ' Stage Name ' , size = 64 , required = True , translate = True ) ,
' section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' ) ,
2010-03-22 09:52:30 +00:00
' sequence ' : fields . integer ( ' Sequence ' , help = " Gives the sequence order \
2010-06-10 13:04:07 +00:00
when displaying a list of case stages . " ),
' object_id ' : fields . many2one ( ' ir.model ' , ' Object Name ' ) ,
' probability ' : fields . float ( ' Probability ( % ) ' , required = True ) ,
2010-04-06 10:20:15 +00:00
' on_change ' : fields . boolean ( ' Change Probability Automatically ' , \
2010-06-10 13:04:07 +00:00
help = " Change Probability on next and previous stages. " ) ,
2010-03-17 06:21:16 +00:00
' requirements ' : fields . text ( ' Requirements ' )
2010-01-18 10:03:52 +00:00
}
2010-01-18 14:42:02 +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-03-22 10:40:26 +00:00
2010-01-18 10:03:52 +00:00
_defaults = {
2010-06-10 13:04:07 +00:00
' sequence ' : lambda * args : 1 ,
' probability ' : lambda * args : 0.0 ,
2010-01-18 14:42:02 +00:00
' object_id ' : _find_object_id
2010-01-18 10:03:52 +00:00
}
2010-03-22 09:45:56 +00:00
2010-01-18 10:03:52 +00:00
crm_case_stage ( )
2010-01-13 09:37:24 +00:00
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
"""
2010-04-06 10:20:15 +00:00
if not context :
context = { }
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
}
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 ( )
2010-07-10 10:00:16 +00:00
class crm_case_section_custom ( osv . osv ) :
_name = " crm.case.section.custom "
_description = ' Custom CRM Case Section '
_columns = {
' name ' : fields . char ( ' Case Section ' , size = 64 , required = True , translate = True ) ,
' code ' : fields . char ( ' Section Code ' , size = 8 ) ,
' active ' : fields . boolean ( ' Active ' ) ,
' allow_unlink ' : fields . boolean ( ' Allow Delete ' , help = " Allows to delete non draft cases " ) ,
' sequence ' : fields . integer ( ' Sequence ' ) ,
' user_id ' : fields . many2one ( ' res.users ' , ' Responsible User ' ) ,
' reply_to ' : fields . char ( ' Reply-To ' , size = 64 , help = " The email address put in the ' Reply-To ' of all emails sent by Open ERP about cases in this section " ) ,
2010-07-10 10:22:48 +00:00
' parent_id ' : fields . many2one ( ' crm.case.section.custom ' , ' Parent Section ' ) ,
2010-07-10 10:00:16 +00:00
' note ' : fields . text ( ' Notes ' ) ,
}
_defaults = {
' active ' : 1 ,
' allow_unlink ' : 1 ,
}
_sql_constraints = [
( ' code_uniq ' , ' unique (code) ' , ' The code of the section must be unique ! ' )
]
def _check_recursion ( self , cr , uid , ids ) :
level = 100
while len ( ids ) :
2010-07-10 10:22:48 +00:00
cr . execute ( ' SELECT DISTINCT parent_id FROM crm_case_section_custom ' \
2010-07-10 10:00:16 +00:00
' WHERE id IN %s ' ,
( tuple ( ids ) , ) )
ids = filter ( None , map ( lambda x : x [ 0 ] , cr . fetchall ( ) ) )
if not level :
return False
level - = 1
return True
_constraints = [
( _check_recursion , ' Error ! You cannot create recursive sections. ' , [ ' parent_id ' ] )
]
crm_case_section_custom ( )
class crm_case_custom ( osv . osv , crm_case ) :
_name = ' crm.case.custom '
_inherit = ' mailgate.thread '
_description = " Custom CRM Case "
_columns = {
' id ' : fields . integer ( ' ID ' , readonly = True ) ,
' name ' : fields . char ( ' Name ' , size = 64 , required = True ) ,
' priority ' : fields . selection ( AVAILABLE_PRIORITIES , ' Priority ' ) ,
' active ' : fields . boolean ( ' Active ' ) ,
' description ' : fields . text ( ' Description ' ) ,
' section_id ' : fields . many2one ( ' crm.case.section.custom ' , ' Section ' , required = True , select = True ) ,
' probability ' : fields . float ( ' Probability ( % ) ' ) ,
' email_from ' : fields . char ( ' Partner Email ' , size = 128 ) ,
' email_cc ' : fields . char ( ' CC ' , size = 252 ) ,
' partner_id ' : fields . many2one ( ' res.partner ' , ' Partner ' ) ,
' partner_address_id ' : fields . many2one ( ' res.partner.address ' , ' Partner Contact ' , domain = " [( ' partner_id ' , ' = ' ,partner_id)] " ) ,
' date ' : fields . datetime ( ' Date ' ) ,
' create_date ' : fields . datetime ( ' Created ' , readonly = True ) ,
' date_deadline ' : fields . datetime ( ' Deadline ' ) ,
' date_closed ' : fields . datetime ( ' Closed ' , readonly = True ) ,
' user_id ' : fields . many2one ( ' res.users ' , ' Responsible ' ) ,
' state ' : fields . selection ( AVAILABLE_STATES , ' Status ' , size = 16 , readonly = True ) ,
' ref ' : fields . reference ( ' Reference ' , selection = _links_get , size = 128 ) ,
' date_action_last ' : fields . datetime ( ' Last Action ' , readonly = 1 ) ,
' date_action_next ' : fields . datetime ( ' Next Action ' , readonly = 1 ) ,
}
_defaults = {
' active ' : 1 ,
' state ' : ' draft ' ,
' priority ' : AVAILABLE_PRIORITIES [ 2 ] [ 0 ] ,
' date ' : time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ,
}
crm_case_custom ( )
2010-03-05 10:40:27 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: