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
2012-05-22 08:14:13 +00:00
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
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 = [
2011-09-14 13:11:11 +00:00
( ' draft ' , ' New ' ) ,
2010-06-10 13:04:07 +00:00
( ' cancel ' , ' Cancelled ' ) ,
2011-09-14 13:11:11 +00:00
( ' open ' , ' In Progress ' ) ,
2012-05-22 08:14:13 +00:00
( ' pending ' , ' Pending ' ) ,
2012-05-01 11:11:34 +00:00
( ' done ' , ' Closed ' )
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-08-27 23:31:30 +00:00
class crm_case_channel ( osv . osv ) :
_name = " crm.case.channel "
_description = " Channels "
_order = ' name '
_columns = {
' name ' : fields . char ( ' Channel Name ' , size = 64 , required = True ) ,
' active ' : fields . boolean ( ' Active ' ) ,
}
_defaults = {
' active ' : lambda * a : 1 ,
}
2011-08-25 04:10:37 +00:00
class crm_case_stage ( osv . osv ) :
2012-05-22 08:14:13 +00:00
""" Model for case stages. This models the main stages of a document
management flow . Main CRM objects ( leads , opportunities , project
issues , . . . ) will now use only stages , instead of state and stages .
Stages are for example used to display the kanban view of records .
"""
2011-08-25 04:10:37 +00:00
_name = " crm.case.stage "
_description = " Stage of case "
_rec_name = ' name '
_order = " sequence "
_columns = {
' name ' : fields . char ( ' Stage Name ' , size = 64 , required = True , translate = True ) ,
2012-05-22 08:14:13 +00:00
' sequence ' : fields . integer ( ' Sequence ' , help = " Used to order stages. Lower is better. " ) ,
2011-08-25 04:10:37 +00:00
' 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 = " Setting this stage will change the probability automatically on the opportunity. " ) ,
' requirements ' : fields . text ( ' Requirements ' ) ,
2012-05-22 08:14:13 +00:00
' section_ids ' : fields . many2many ( ' crm.case.section ' , ' section_stage_rel ' , ' stage_id ' , ' section_id ' , string = ' Sections ' ,
help = " Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams. " ) ,
2012-05-08 13:19:50 +00:00
' state ' : fields . selection ( AVAILABLE_STATES , ' State ' , required = True , help = " The related state for the stage. The state of your document will automatically change regarding the selected stage. Example, a stage is related to the state ' Close ' , when your document reach this stage, it will be automatically closed. " ) ,
2011-10-01 21:15:29 +00:00
' case_default ' : fields . boolean ( ' Common to All Teams ' , help = " If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams. " ) ,
2011-08-25 04:10:37 +00:00
}
_defaults = {
' sequence ' : lambda * args : 1 ,
' probability ' : lambda * args : 0.0 ,
2012-04-18 09:06:17 +00:00
' state ' : ' draft ' ,
2011-08-25 04:10:37 +00:00
}
class crm_case_section ( osv . osv ) :
2012-05-22 08:14:13 +00:00
""" Model for sales teams. """
2011-08-25 04:10:37 +00:00
_name = " crm.case.section "
_description = " Sales Teams "
_order = " complete_name "
def get_full_name ( self , cr , uid , ids , field_name , arg , context = None ) :
return dict ( self . name_get ( cr , uid , ids , context = context ) )
_columns = {
' name ' : fields . char ( ' Sales Team ' , size = 64 , required = True , translate = True ) ,
' complete_name ' : fields . function ( get_full_name , type = ' char ' , size = 256 , readonly = True , store = True ) ,
' code ' : fields . char ( ' Code ' , size = 8 ) ,
' 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. " ) ,
' allow_unlink ' : fields . boolean ( ' Allow Delete ' , help = " Allows to delete non draft cases " ) ,
' change_responsible ' : fields . boolean ( ' Reassign Escalated ' , help = " When escalating to this team override the saleman with the team leader. " ) ,
' user_id ' : fields . many2one ( ' res.users ' , ' Team Leader ' ) ,
' member_ids ' : fields . many2many ( ' res.users ' , ' sale_member_rel ' , ' section_id ' , ' member_id ' , ' Team Members ' ) ,
' 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 " ) ,
' parent_id ' : fields . many2one ( ' crm.case.section ' , ' Parent Team ' ) ,
' child_ids ' : fields . one2many ( ' crm.case.section ' , ' parent_id ' , ' Child Teams ' ) ,
' resource_calendar_id ' : fields . many2one ( ' resource.calendar ' , " Working Time " , help = " Used to compute open days " ) ,
' note ' : fields . text ( ' Description ' ) ,
' working_hours ' : fields . float ( ' Working Hours ' , digits = ( 16 , 2 ) ) ,
' stage_ids ' : fields . many2many ( ' crm.case.stage ' , ' section_stage_rel ' , ' section_id ' , ' stage_id ' , ' Stages ' ) ,
}
2012-05-22 08:14:13 +00:00
2011-10-01 21:15:29 +00:00
def _get_stage_common ( self , cr , uid , context ) :
ids = self . pool . get ( ' crm.case.stage ' ) . search ( cr , uid , [ ( ' case_default ' , ' = ' , 1 ) ] , context = context )
return ids
2011-08-25 04:10:37 +00:00
_defaults = {
' active ' : lambda * a : 1 ,
' allow_unlink ' : lambda * a : 1 ,
2011-10-01 21:15:29 +00:00
' stage_ids ' : _get_stage_common
2011-08-25 04:10:37 +00:00
}
_sql_constraints = [
( ' code_uniq ' , ' unique (code) ' , ' The code of the sales team must be unique ! ' )
]
_constraints = [
2011-08-27 21:19:48 +00:00
( osv . osv . _check_recursion , ' Error ! You cannot create recursive Sales team. ' , [ ' parent_id ' ] )
2011-08-25 04:10:37 +00:00
]
def name_get ( self , cr , uid , ids , context = None ) :
2011-08-27 21:19:48 +00:00
""" Overrides orm name_get method """
2012-02-23 10:46:41 +00:00
if not isinstance ( ids , list ) :
2011-08-25 04:10:37 +00:00
ids = [ ids ]
res = [ ]
if not ids :
return res
reads = self . read ( cr , uid , ids , [ ' name ' , ' parent_id ' ] , context )
for record in reads :
name = record [ ' name ' ]
if record [ ' parent_id ' ] :
name = record [ ' parent_id ' ] [ 1 ] + ' / ' + name
res . append ( ( record [ ' id ' ] , name ) )
return res
class crm_case_categ ( osv . osv ) :
""" Category of Case """
_name = " crm.case.categ "
_description = " Category of Case "
_columns = {
' name ' : fields . char ( ' Name ' , size = 64 , required = True , translate = True ) ,
' section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' ) ,
' object_id ' : fields . many2one ( ' ir.model ' , ' Object Name ' ) ,
}
def _find_object_id ( self , cr , uid , context = None ) :
2011-08-27 21:19:48 +00:00
""" Finds id for case object """
2011-08-25 04:10:37 +00:00
object_id = context and context . get ( ' object_id ' , False ) or False
2011-12-22 10:20:53 +00:00
ids = self . pool . get ( ' ir.model ' ) . search ( cr , uid , [ ( ' id ' , ' = ' , object_id ) ] )
2011-11-14 21:33:19 +00:00
return ids and ids [ 0 ] or False
2011-08-25 04:10:37 +00:00
_defaults = {
' object_id ' : _find_object_id
}
class crm_case_resource_type ( osv . osv ) :
""" Resource Type of case """
_name = " crm.case.resource.type "
_description = " Campaign "
_rec_name = " name "
_columns = {
' name ' : fields . char ( ' Campaign Name ' , size = 64 , required = True , translate = True ) ,
' section_id ' : fields . many2one ( ' crm.case.section ' , ' Sales Team ' ) ,
}
2011-05-31 13:32:32 +00:00
class crm_base ( object ) :
2012-05-21 12:01:55 +00:00
""" Base utility mixin class for crm objects.
Object subclassing this should define colums :
2012-05-22 08:28:57 +00:00
- date_open ( datetime field )
- date_closed ( datetime field )
- user_id ( many2one to res . users )
- partner_id ( many2one to res . partner )
2012-05-21 12:01:55 +00:00
- state ( selection field )
2011-05-31 13:32:32 +00:00
"""
2012-05-21 12:01:55 +00:00
2011-05-31 13:32:32 +00:00
def _get_default_partner_address ( self , cr , uid , context = None ) :
2012-05-22 08:28:57 +00:00
""" Gives id of default address for current user
: 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
2011-08-03 10:06:02 +00:00
# was user.address_id.id, but address_id has been removed
2011-08-09 23:44:28 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
if hasattr ( user , ' partner_address_id ' ) and user . partner_address_id :
return user . partner_address_id
2011-08-03 05:42:15 +00:00
return False
2011-05-31 13:32:32 +00:00
def _get_default_partner ( self , cr , uid , context = None ) :
2012-05-22 08:28:57 +00:00
""" Gives id of partner for current user
: 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 )
2011-08-09 23:44:28 +00:00
if hasattr ( user , ' partner_address_id ' ) and user . partner_address_id :
return user . partner_address_id
2011-08-03 10:06:02 +00:00
return user . company_id . partner_id . id
2011-08-25 04:10:37 +00:00
2011-05-31 13:32:32 +00:00
def _get_default_email ( self , cr , uid , context = None ) :
2012-05-22 08:28:57 +00:00
""" Gives default email address for current user
: 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 )
2011-07-28 06:11:56 +00:00
return user . user_email
2011-08-25 04:10:37 +00:00
2011-05-31 13:32:32 +00:00
def _get_default_user ( self , cr , uid , context = None ) :
2012-05-22 08:28:57 +00:00
""" Gives current user id
: 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
2012-05-22 08:42:02 +00:00
def _get_section ( self , cr , uid , context = None ) :
return False
2011-05-31 13:32:32 +00:00
def onchange_partner_address_id ( self , cr , uid , ids , add , email = False ) :
""" This function returns value of partner email based on Partner Address
2011-08-09 23:44:28 +00:00
: param ids : List of case IDs
: param add : Id of Partner ' s address
: param email : Partner ' s email ID
2011-05-31 13:32:32 +00:00
"""
2011-10-25 09:18:37 +00:00
data = { ' value ' : { ' email_from ' : False , ' phone ' : False } }
if add :
2012-02-29 12:41:42 +00:00
address = self . pool . get ( ' res.partner ' ) . browse ( cr , uid , add )
2011-10-25 09:18:37 +00:00
data [ ' value ' ] = { ' email_from ' : address and address . email or False ,
' phone ' : address and address . phone or False }
2011-11-14 21:33:19 +00:00
if ' phone ' not in self . _columns :
del data [ ' value ' ] [ ' phone ' ]
2011-10-25 09:18:37 +00:00
return data
2011-08-25 04:10:37 +00:00
2011-05-31 13:32:32 +00:00
def onchange_partner_id ( self , cr , uid , ids , part , email = False ) :
""" This function returns value of partner address based on partner
2011-08-09 23:44:28 +00:00
: param ids : List of case IDs
: param part : Partner ' s id
: param email : Partner ' s email ID
2011-05-31 13:32:32 +00:00
"""
data = { }
if part :
addr = self . pool . get ( ' res.partner ' ) . address_get ( cr , uid , [ part ] , [ ' contact ' ] )
data . update ( self . onchange_partner_address_id ( cr , uid , ids , addr [ ' contact ' ] ) [ ' value ' ] )
return { ' value ' : data }
2011-08-25 04:10:37 +00:00
2012-02-23 10:46:41 +00:00
def case_open ( self , cr , uid , ids , context = None ) :
2012-05-21 12:01:55 +00:00
""" Opens case """
cases = self . browse ( cr , uid , ids , context = context )
2011-05-31 13:32:32 +00:00
for case in cases :
2012-05-22 08:28:57 +00:00
values = { ' active ' : True }
2012-05-21 14:23:17 +00:00
if case . state == ' draft ' :
2012-05-22 08:28:57 +00:00
values [ ' date_open ' ] = fields . datetime . now ( )
2011-05-31 13:32:32 +00:00
if not case . user_id :
2012-05-22 08:28:57 +00:00
values [ ' user_id ' ] = uid
self . case_set ( cr , uid , [ case . id ] , ' done ' , values , context = context )
self . case_open_send_note ( cr , uid , [ case . id ] , context = context )
2011-05-31 13:32:32 +00:00
return True
2012-02-23 10:46:41 +00:00
def case_close ( self , cr , uid , ids , context = None ) :
2012-05-21 12:01:55 +00:00
""" Closes case """
2012-05-22 08:28:57 +00:00
self . case_set ( cr , uid , ids , ' done ' , { ' date_closed ' : fields . datetime . now ( ) } , context = context )
2012-03-13 10:55:28 +00:00
self . case_close_send_note ( cr , uid , ids , context = context )
2011-05-31 13:32:32 +00:00
return True
2012-02-23 10:46:41 +00:00
def case_cancel ( self , cr , uid , ids , context = None ) :
2012-05-21 12:01:55 +00:00
""" Cancels case """
2012-05-22 08:28:57 +00:00
self . case_set ( cr , uid , ids , ' cancel ' , { ' active ' : True } , context = context )
2012-03-13 10:55:28 +00:00
self . case_cancel_send_note ( cr , uid , ids , context = context )
2012-05-22 08:28:57 +00:00
return True
def case_pending ( self , cr , uid , ids , context = None ) :
2012-05-22 08:40:28 +00:00
""" Set case as pending """
2012-05-22 08:28:57 +00:00
self . case_set ( cr , uid , ids , ' pending ' , { ' active ' : True } , context = context )
2012-05-22 08:40:28 +00:00
self . case_pending_send_note ( cr , uid , ids , context = context )
2011-05-31 13:32:32 +00:00
return True
2012-02-23 10:46:41 +00:00
def case_reset ( self , cr , uid , ids , context = None ) :
2012-05-21 12:01:55 +00:00
""" Resets case as draft """
2012-05-22 08:28:57 +00:00
self . case_set ( cr , uid , ids , ' draft ' , { ' active ' : True } , context = context )
2012-05-22 08:40:28 +00:00
self . case_close_send_note ( cr , uid , ids , context = context )
2011-05-31 13:32:32 +00:00
return True
2012-05-22 08:28:57 +00:00
def case_set ( self , cr , uid , ids , state_name , update_values = None , context = None ) :
2012-05-22 08:40:28 +00:00
""" Generic method for setting case. This methods wraps the update
of the record , as well as call to _action and browse record
case setting .
: params : state_name : the new value of the state , such as
' draft ' or ' close ' .
: params : update_values : values that will be added with the state
update when writing values to the record .
"""
2012-05-22 08:28:57 +00:00
cases = self . browse ( cr , uid , ids , context = context )
cases [ 0 ] . state # fill browse record cache, for _action having old and new values
if update_values is None :
update_values = { }
update_values . update ( { ' state ' : state_name } )
self . write ( cr , uid , ids , update_values , context = context )
self . case_reset_send_note ( cr , uid , ids , context = context )
self . _action ( cr , uid , cases , state_name , context = context )
2011-08-09 23:44:28 +00:00
2011-05-31 13:32:32 +00:00
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 )
2012-05-21 12:01:55 +00:00
# ******************************
# Notifications
# ******************************
def case_get_note_msg_prefix ( self , cr , uid , id , context = None ) :
return ' '
def case_open_send_note ( self , cr , uid , ids , context = None ) :
for id in ids :
msg = ' %s has been <b>opened</b>. ' % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) )
self . message_append_note ( cr , uid , [ id ] , body = msg , context = context )
return True
def case_close_send_note ( self , cr , uid , ids , context = None ) :
for id in ids :
msg = ' %s has been <b>closed</b>. ' % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) )
self . message_append_note ( cr , uid , [ id ] , body = msg , context = context )
return True
def case_cancel_send_note ( self , cr , uid , ids , context = None ) :
for id in ids :
msg = ' %s has been <b>canceled</b>. ' % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) )
self . message_append_note ( cr , uid , [ id ] , body = msg , context = context )
2012-05-22 08:30:17 +00:00
return True
def case_pending_send_note ( self , cr , uid , ids , context = None ) :
for id in ids :
msg = ' %s is now <b>pending</b>. ' % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) )
self . message_append_note ( cr , uid , [ id ] , body = msg , context = context )
2012-05-21 12:01:55 +00:00
return True
def case_reset_send_note ( self , cr , uid , ids , context = None ) :
for id in ids :
msg = ' %s has been <b>renewed</b>. ' % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) )
self . message_append_note ( cr , uid , [ id ] , body = msg , context = context )
return True
2011-05-31 13:32:32 +00:00
class crm_case ( crm_base ) :
2012-02-23 10:46:41 +00:00
""" A simple python class to be used for common functions
2012-05-22 08:40:28 +00:00
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
2011-05-31 13:32:32 +00:00
"""
2012-03-21 08:59:10 +00:00
2012-05-21 16:15:45 +00:00
def _get_default_stage_id ( self , cr , uid , context = None ) :
""" Gives default stage_id """
return self . stage_find ( cr , uid , False , [ ( ' state ' , ' = ' , ' draft ' ) ] , context = context )
2012-05-21 12:40:46 +00:00
def stage_set_with_state_name ( self , cr , uid , cases , state_name , context = None ) :
""" TODO
"""
for case in cases :
section_id = case . section_id . id if case . section_id else None
stage_id = self . stage_find ( cr , uid , section_id , [ ( ' state ' , ' = ' , state_name ) ] , context = context )
if stage_id :
self . stage_set ( cr , uid , [ case . id ] , stage_id , context = context )
return True
def stage_find ( self , cr , uid , section_id , domain = [ ] , order = ' sequence ' , context = None ) :
2011-08-25 04:10:37 +00:00
domain = list ( domain )
if section_id :
domain . append ( ( ' section_ids ' , ' = ' , section_id ) )
2012-05-21 12:40:46 +00:00
stage_ids = self . pool . get ( ' crm.case.stage ' ) . search ( cr , uid , domain , order = order , context = context )
2011-08-25 04:10:37 +00:00
if stage_ids :
return stage_ids [ 0 ]
2011-09-13 08:52:49 +00:00
return False
2011-08-25 04:10:37 +00:00
def stage_set ( self , cr , uid , ids , stage_id , context = None ) :
value = { }
if hasattr ( self , ' onchange_stage_id ' ) :
value = self . onchange_stage_id ( cr , uid , ids , stage_id ) [ ' value ' ]
2011-08-25 04:54:55 +00:00
value [ ' stage_id ' ] = stage_id
2011-09-13 08:52:49 +00:00
return self . write ( cr , uid , ids , value , context = context )
2011-08-25 04:10:37 +00:00
def stage_change ( self , cr , uid , ids , op , order , context = None ) :
if context is None :
context = { }
for case in self . browse ( cr , uid , ids , context = context ) :
seq = 0
if case . stage_id :
seq = case . stage_id . sequence
section_id = None
if case . section_id :
section_id = case . section_id . id
next_stage_id = self . stage_find ( cr , uid , section_id , [ ( ' sequence ' , op , seq ) ] , order )
if next_stage_id :
2011-09-13 08:52:49 +00:00
return self . stage_set ( cr , uid , [ case . id ] , next_stage_id , context = context )
return False
2010-12-28 08:29:54 +00:00
2011-08-25 04:10:37 +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
2010-12-16 10:28:40 +00:00
"""
2011-09-13 08:52:49 +00:00
return self . stage_change ( cr , uid , ids , ' > ' , ' sequence ' , context )
2011-02-18 09:54:19 +00:00
2011-08-25 04:10:37 +00:00
def stage_previous ( self , cr , uid , ids , context = None ) :
""" This function computes previous stage for case from its current
stage using available stage for that case type
2010-12-16 10:28:40 +00:00
"""
2011-09-13 08:52:49 +00:00
return self . stage_change ( cr , uid , ids , ' < ' , ' sequence desc ' , context )
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 ) :
2011-07-22 18:23:37 +00:00
""" Overrides orm copy method to avoid copying messages,
as well as date_closed and date_open columns if they
exist . """
2010-08-17 12:54:00 +00:00
if default is None :
default = { }
2011-08-25 04:10:37 +00:00
default . update ( { ' message_ids ' : [ ] , } )
2010-08-17 12:54:00 +00:00
if hasattr ( self , ' _columns ' ) :
if self . _columns . get ( ' date_closed ' ) :
2011-08-25 04:10:37 +00:00
default . update ( { ' date_closed ' : False , } )
2010-08-17 12:54:00 +00:00
if self . _columns . get ( ' date_open ' ) :
2011-08-25 04:10:37 +00:00
default . update ( { ' date_open ' : False } )
2011-08-16 10:32:48 +00:00
return super ( crm_case , self ) . copy ( cr , uid , id , default , context = context )
2011-02-18 09:54:19 +00:00
2012-02-23 10:46:41 +00:00
def case_escalate ( self , cr , uid , ids , context = None ) :
2011-07-22 18:23:37 +00:00
""" Escalates case to parent level """
2012-05-21 12:40:46 +00:00
cases = self . browse ( cr , uid , ids , context = context )
cases [ 0 ] . state # fill browse record cache, for _action having old and new values
2010-05-05 11:55:13 +00:00
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 :
2011-12-31 07:57:20 +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 )
2012-05-21 12:40:46 +00:00
case . case_escalate_send_note ( case . section_id . parent_id , context = context )
cases = self . browse ( cr , uid , ids , context = context )
self . _action ( cr , uid , cases , ' escalate ' , context = context )
return True
def case_open ( self , cr , uid , ids , context = None ) :
""" Opens case """
cases = self . browse ( cr , uid , ids , context = context )
cases [ 0 ] . state # fill browse record cache, for _action having old and new values
self . stage_set_with_state_name ( cr , uid , cases , ' open ' , context = context )
for case in cases :
2012-05-21 14:07:05 +00:00
data = { ' active ' : True , ' date_open ' : fields . datetime . now ( ) }
2012-05-21 14:23:17 +00:00
if case . stage_id and case . stage_id . state == ' draft ' :
data [ ' date_open ' ] = fields . datetime . now ( )
2012-05-21 12:40:46 +00:00
if not case . user_id :
data [ ' user_id ' ] = uid
self . write ( cr , uid , [ case . id ] , data , context = context )
self . _action ( cr , uid , cases , ' open ' , context = context )
self . case_open_send_note ( cr , uid , ids , context = context )
return True
def case_close ( self , cr , uid , ids , context = None ) :
""" Closes case """
2012-05-21 15:31:43 +00:00
self . case_set ( cr , uid , ids , ' done ' , { ' active ' : True , ' date_closed ' : fields . datetime . now ( ) } , context = context )
2012-05-21 12:40:46 +00:00
self . case_close_send_note ( cr , uid , ids , context = context )
2010-05-05 11:55:13 +00:00
return True
2010-05-12 10:12:56 +00:00
2012-02-23 10:46:41 +00:00
def case_cancel ( self , cr , uid , ids , context = None ) :
2012-05-21 12:40:46 +00:00
""" Cancels case """
2012-05-21 15:31:43 +00:00
self . case_set ( cr , uid , ids , ' cancel ' , { ' active ' : True } , context = context )
2012-03-13 10:55:28 +00:00
self . case_cancel_send_note ( cr , uid , ids , context = context )
2012-05-22 08:40:28 +00:00
return True
def case_pending ( self , cr , uid , ids , context = None ) :
""" Set case as pending """
self . case_set ( cr , uid , ids , ' pending ' , { ' active ' : True } , context = context )
self . case_pending_send_note ( cr , uid , ids , context = context )
2010-05-05 11:55:13 +00:00
return True
2012-02-23 10:46:41 +00:00
def case_reset ( self , cr , uid , ids , context = None ) :
2012-05-21 12:40:46 +00:00
""" Resets case as draft """
2012-05-21 14:01:35 +00:00
self . case_set ( cr , uid , ids , ' draft ' , { ' active ' : True } , context = context )
2012-03-15 13:32:52 +00:00
self . case_reset_send_note ( cr , uid , ids , context = context )
2010-05-05 11:55:13 +00:00
return True
2010-06-10 13:04:07 +00:00
2012-05-21 14:01:35 +00:00
def case_set ( self , cr , uid , ids , new_state_name = None , values_to_update = None , new_stage_id = None , context = None ) :
""" TODO """
cases = self . browse ( cr , uid , ids , context = context )
cases [ 0 ] . state # fill browse record cache, for _action having old and new values
# 1. update the stage
if new_state_name :
self . stage_set_with_state_name ( cr , uid , cases , new_state_name , context = context )
elif not ( new_stage_id is None ) :
self . stage_set ( cr , uid , ids , new_stage_id , context = context )
# 2. update values
if values_to_update :
self . write ( cr , uid , ids , values_to_update , context = context )
# 3. call _action for base action rule
if new_state_name :
self . _action ( cr , uid , cases , new_state_name , context = context )
elif not ( new_stage_id is None ) :
stage = self . pool . get ( ' crm.case.stage ' ) . browse ( cr , uid , [ new_stage_id ] , context = context ) [ 0 ]
new_state_name = stage . state
self . _action ( cr , uid , cases , new_state_name , context = context )
return True
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
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 ) :
2011-07-22 18:23:37 +00:00
mail_message = self . pool . get ( ' mail.message ' )
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
2011-10-05 09:05:32 +00:00
dest = case . user_id . user_email or " "
2011-03-04 12:13:36 +00:00
body = case . description or " "
2011-04-22 11:41:11 +00:00
for message in case . message_ids :
2012-03-08 15:58:35 +00:00
if message . email_from and message . body_text :
body = message . body_text
2011-04-22 11:41:11 +00:00
break
2011-03-04 12:13:36 +00:00
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 )
2011-04-20 09:54:58 +00:00
attach_to_send = { }
2011-03-04 12:13:36 +00:00
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 ' ] )
2011-04-20 09:54:58 +00:00
attach_to_send = dict ( map ( lambda x : ( x [ ' datas_fname ' ] , base64 . decodestring ( x [ ' datas ' ] ) ) , attach_to_send ) )
2010-05-19 13:42:43 +00:00
2011-04-06 05:45:13 +00:00
# Send an email
2011-03-29 12:27:36 +00:00
subject = " Reminder: [ %s ] %s " % ( str ( case . id ) , case . name , )
2011-07-22 18:23:37 +00:00
mail_message . schedule_with_attach ( cr , uid ,
2011-03-04 12:13:36 +00:00
src ,
[ dest ] ,
subject ,
body ,
2012-03-08 15:58:35 +00:00
model = self . _name ,
2011-03-29 12:27:36 +00:00
reply_to = case . section_id . reply_to ,
2011-08-22 17:16:59 +00:00
res_id = case . id ,
attachments = attach_to_send ,
context = context
2011-03-04 12:13:36 +00:00
)
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 ) :
2011-07-22 18:23:37 +00:00
""" Function called by the scheduler to process cases for date actions
Only works on not done and cancelled cases
2010-05-19 13:42:43 +00:00
"""
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 )
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
2011-08-23 17:58:09 +00:00
def message_thread_followers ( self , cr , uid , ids , context = None ) :
2010-08-17 13:00:44 +00:00
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
2012-05-21 12:40:46 +00:00
# ******************************
# Notifications
# ******************************
def case_get_note_msg_prefix ( self , cr , uid , id , context = None ) :
return ' '
def case_escalate_send_note ( self , cr , uid , ids , new_section = None , context = None ) :
for id in ids :
if new_section :
msg = ' %s has been <b>escalated</b> to <b> %s </b>. ' % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) , new_section . name )
else :
msg = ' %s has been <b>escalated</b>. ' % ( self . case_get_note_msg_prefix ( cr , uid , id , context = context ) )
self . message_append_note ( cr , uid , [ id ] , ' System Notification ' , msg , context = context )
return True
2010-08-17 13:00:44 +00:00
2010-04-06 10:20:15 +00:00
def _links_get ( self , cr , uid , context = None ) :
2011-07-22 18:23:37 +00:00
""" Gets links value for reference field """
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
2011-11-22 08:51:38 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: