import time
import base64
import tools
+
from osv import fields
from osv import osv
from tools.translate import _
class crm_case(object):
"""A simple python class to be used for common functions """
+ def _find_lost_stage(self, cr, uid, type, section_id):
+ return self._find_percent_stage(cr, uid, 0.0, type, section_id)
+
+ def _find_won_stage(self, cr, uid, type, section_id):
+ return self._find_percent_stage(cr, uid, 100.0, type, section_id)
+
+ 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])])
+ else :
+ ids = stage_pool.search(cr, uid, [("probability", '=', percent), ("type", 'like', type)])
+
+ if ids:
+ return ids[0]
+ return False
+
+
+ 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])])
+ else :
+ ids = stage_pool.search(cr, uid, [("sequence", '>', 0), ("type", 'like', type)])
+
+ 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
+ else :
+ return False
+
+ def onchange_stage_id(self, cr, uid, ids, stage_id, context={}):
+
+ """ @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 """
+
+ if not stage_id:
+ return {'value':{}}
+
+ stage = self.pool.get('crm.case.stage').browse(cr, uid, stage_id, context)
+
+ if not stage.on_change:
+ return {'value':{}}
+ return {'value':{'probability': stage.probability}}
+
def _get_default_partner_address(self, cr, uid, context=None):
+
"""Gives id of default address for current user
@param self: The object pointer
@param cr: the current row, from the database cursor,
default = {}
default.update({
- 'message_ids': [],
+ 'message_ids': [],
})
if hasattr(self, '_columns'):
if self._columns.get('date_closed'):
default.update({
- 'date_closed': False,
+ 'date_closed': False,
})
if self._columns.get('date_open'):
default.update({
'date_open': False
})
return super(osv.osv, self).copy(cr, uid, id, default, context=context)
-
+
def _get_default_email(self, cr, uid, context=None):
"""Gives default email address for current user
@param self: The object pointer
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
return user.context_section_id.id or False
+ 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
+ if not current_seq :
+ current_seq = 0
+
+ if (abs(next_seq - current_seq)) >= 1:
+ return next_stage
+ else :
+ return self._find_next_stage(cr, uid, stage_list, index + 1, current_seq, stage_pool)
+
+ def stage_change(self, cr, uid, ids, context=None, order='sequence'):
+ if context is None:
+ context = {}
+
+ stage_pool = self.pool.get('crm.case.stage')
+ stage_type = context and context.get('stage_type','')
+ current_seq = False
+ next_stage_id = False
+
+ for case in self.browse(cr, uid, ids, context=context):
+
+ next_stage = False
+ value = {}
+ if case.section_id.id :
+ domain = [('type', '=', stage_type),('section_ids', '=', case.section_id.id)]
+ else :
+ domain = [('type', '=', stage_type)]
+
+
+ stages = stage_pool.search(cr, uid, domain, order=order)
+ current_seq = case.stage_id.sequence
+ index = -1
+ if case.stage_id and case.stage_id.id in stages:
+ index = stages.index(case.stage_id.id)
+
+ next_stage = self._find_next_stage(cr, uid, stages, index, current_seq, stage_pool, context=context)
+
+ if next_stage:
+ next_stage_id = next_stage.id
+ value.update({'stage_id': next_stage.id})
+ if next_stage.on_change:
+ value.update({'probability': next_stage.probability})
+ self.write(cr, uid, [case.id], value, context=context)
+
+
+ return next_stage_id #FIXME should return a list of all id
+
+
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 uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param context: A standard dictionary for contextual values"""
- stage_pool = self.pool.get('crm.case.stage')
- model = self._name
- for case in self.browse(cr, uid, ids, context=context):
- next_stage = False
- data = {}
- domain = [('object_id.model', '=', model),('section_ids', '=', case.section_id.id)]
- if case.section_id and case.section_id.stage_ids:
- domain.append(('id', 'in', map(lambda x: x.id, case.section_id.stage_ids)))
- stages = stage_pool.search(cr, uid, domain, order='sequence')
- index = -1
- if case.stage_id and case.stage_id.id in stages:
- index = stages.index(case.stage_id.id)
- if index + 1 == len(stages):
- return False
- else:
- next_stage = stages[index + 1]
- if next_stage:
- data = {'stage_id': next_stage}
- stage = stage_pool.browse(cr, uid, next_stage, context=context)
- if stage.on_change:
- data.update({'probability': stage.probability})
- self.write(cr, uid, [case.id], data, context=context)
- return next_stage
+
+ return self.stage_change(cr, uid, ids, context=context, order='sequence')
def stage_previous(self, cr, uid, ids, context=None):
"""This function computes previous stage for case from its current stage
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param context: A standard dictionary for contextual values"""
- stage_pool = self.pool.get('crm.case.stage')
- model = self._name
- for case in self.browse(cr, uid, ids, context=context):
- prev_stage = False
- data = {}
- domain = [('object_id.model', '=', model),('section_ids', '=', case.section_id.id)]
- if case.section_id and case.section_id.stage_ids:
- domain.append(('id', 'in', map(lambda x: x.id, case.section_id.stage_ids)))
- stages = stage_pool.search(cr, uid, domain, order='sequence')
- index = 0
- if case.stage_id and case.stage_id.id in stages:
- index = stages.index(case.stage_id.id)
- if index == 0:
- return False
- else:
- prev_stage = stages[index - 1]
- if prev_stage:
- data = {'stage_id': prev_stage}
- stage = stage_pool.browse(cr, uid, prev_stage, context=context)
- if stage.on_change:
- data.update({'probability': stage.probability})
- self.write(cr, uid, [case.id], data, context=context)
- return prev_stage
+ return self.stage_change(cr, uid, ids, context=context, order='sequence desc')
def onchange_partner_id(self, cr, uid, ids, part, email=False):
"""This function returns value of partner address based on partner
@param part: Partner's id
@email: Partner's email ID
"""
- if not part:
- return {'value': {'partner_address_id': False,
- 'email_from': False,
- 'phone': False
- }}
- 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'])
+ 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 onchange_partner_address_id(self, cr, uid, ids, add, email=False):
if not add:
return {'value': {'email_from': False}}
address = self.pool.get('res.partner.address').browse(cr, uid, add)
- return {'value': {'email_from': address.email, 'phone': address.phone}}
+ if address.email:
+ return {'value': {'email_from': address.email, 'phone': address.phone}}
+ else:
+ return {'value': {'phone': address.phone}}
def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, email_from=False, message_id=False, attach=[], context=None):
- mailgate_pool = self.pool.get('mailgate.thread')
+ mailgate_pool = self.pool.get('email.thread')
return mailgate_pool.history(cr, uid, cases, keyword, history=history,\
subject=subject, email=email, \
details=details, email_from=email_from,\
@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:
if not case.user_id:
data['user_id'] = uid
self.write(cr, uid, case.id, data)
+
+
self._action(cr, uid, cases, 'open')
return True
@param context: A standard dictionary for contextual values
"""
+
return self.remind_user(cr, uid, ids, context, attach,
destination=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 user's IDs
+ @param ids: List of case's IDs to remind
@param context: A standard dictionary for contextual values
-
"""
+ email_message_obj = self.pool.get('email.message')
for case in self.browse(cr, uid, ids, context=context):
- 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:
+ if not destination and 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
- body = case.description or ""
- if case.message_ids:
- body = case.message_ids[0].description or ""
- if not destination:
- src, dest = dest, src
- 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)
+ if not case.user_id.user_email:
+ raise osv.except_osv(_('Error!'), ("User Email is not specified in Case"))
+
+ if destination and case.section_id.user_id:
+ case_email = case.section_id.user_id.user_email
+ else:
+ case_email = case.user_id.user_email
+
+ 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)
# Send an email
subject = "Reminder: [%s] %s" % (str(case.id), case.name, )
- tools.email_send(
+ email_message_obj.schedule_with_attach(cr, uid,
src,
[dest],
- subject,
+ subject,
body,
+ model='crm.case',
reply_to=case.section_id.reply_to,
openobject_id=str(case.id),
attach=attach_to_send
_rec_name = 'name'
_order = "sequence"
+
+
+ def _get_type_value(self, cr, user, context):
+ return [('lead','Lead'),('opportunity','Opportunity')]
+
+
_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."),
- 'object_id': fields.many2one('ir.model', 'Object Name'),
'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."),
- 'requirements': fields.text('Requirements')
+ 'requirements': fields.text('Requirements'),
+ 'type': fields.selection(_get_type_value, 'Type', required=True),
}
- def _find_object_id(self, cr, uid, context=None):
- """Finds id for case object
+
+
+ def _find_stage_type(self, cr, uid, context=None):
+ """Finds type of stage according to object.
@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
"""
- object_id = context and context.get('object_id', False) or False
- ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', object_id)])
- return ids and ids[0]
+ type = context and context.get('type', '') or ''
+ return type
_defaults = {
'sequence': lambda *args: 1,
'probability': lambda *args: 0.0,
- 'object_id' : _find_object_id
+ 'type': _find_stage_type,
}
crm_case_stage()
'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', "Resource's Calendar"),
+ 'resource_calendar_id': fields.many2one('resource.calendar', "Working Time"),
'note': fields.text('Description'),
- 'working_hours': fields.float('Working Hours', digits=(16,2 )),
+ 'working_hours': fields.float('Working Hours', digits=(16,2 )),
'stage_ids': fields.many2many('crm.case.stage', 'section_stage_rel', 'section_id', 'stage_id', 'Stages'),
}
_columns = {
'section_ids':fields.many2many('crm.case.section', 'section_stage_rel', 'stage_id', 'section_id', 'Sections'),
}
+
crm_case_stage()
_columns = {
'context_section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
+
+ def create(self, cr, uid, vals, context=None):
+ res = super(users, self).create(cr, uid, vals, context=context)
+ section_obj=self.pool.get('crm.case.section')
+
+ if vals.get('context_section_id', False):
+ section_obj.write(cr, uid, [vals['context_section_id']], {'member_ids':[(4, res)]}, context)
+ return res
users()