[IMP]: crm: Major changes in crm

* Removed crm.case
* Inherited other cases from mailgate.thread 
* Changes in lead and opportunity: Removed dependency from crm.case and added for mailgate.thread
* still lot of things to fix(TODO): meeting, phonecall/reports

bzr revid: rpa@tinyerp.com-20100503123048-642v3gt4gorubmrs
This commit is contained in:
rpa (Open ERP) 2010-05-03 18:00:48 +05:30
parent 8c6721d3ab
commit ee4052bc1a
24 changed files with 402 additions and 674 deletions

View File

@ -30,7 +30,7 @@ import crm_opportunity
import crm_phonecall
import crm_installer
import report
#import report
import wizard

View File

@ -91,12 +91,12 @@ between mails and Open ERP.""",
'crm_opportunity_menu.xml',
'security/crm_security.xml',
'security/ir.model.access.csv',
# 'security/ir.model.access.csv',
'report/crm_report_view.xml',
'report/crm_lead_report_view.xml',
# 'report/crm_opportunity_report_view.xml' ,
'report/crm_phonecall_report_view.xml',
## 'report/crm_report_view.xml',
# 'report/crm_lead_report_view.xml',
## 'report/crm_opportunity_report_view.xml' ,
# 'report/crm_phonecall_report_view.xml',
'process/crm_configuration_process.xml',
'crm_installer_view.xml'

View File

@ -241,503 +241,6 @@ def _links_get(self, cr, uid, context=None):
res = obj.read(cr, uid, ids, ['object', 'name'], context)
return [(r['object'], r['name']) for r in res]
class crm_case(osv.osv):
""" CRM Case """
_name = "crm.case"
_description = "Case"
def _email_last(self, cursor, user, ids, name, arg, context=None):
"""Return last email from History
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of cases IDs
@param context: A standard dictionary for contextual values
"""
res = {}
for case in self.browse(cursor, user, ids):
if case.history_line:
res[case.id] = case.history_line[0].description
else:
res[case.id] = False
return res
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 users ID for security checks,
@param ids: List of cases IDs
@param context: A standard dictionary for contextual values
"""
if not context:
context = {}
if not default:
default = {}
default.update({'state': 'draft', 'id': False})
return super(crm_case, self).copy(cr, uid, id, default, context)
def _get_log_ids(self, cr, uid, ids, field_names, arg, context=None):
"""Gets id for case log from history of particular case
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Case IDs
@param context: A standard dictionary for contextual values
@return:Dictionary of History Ids
"""
if not context:
context = {}
result = {}
history_obj = False
model_obj = self.pool.get('ir.model')
if 'history_line' in field_names:
history_obj = self.pool.get('crm.case.history')
name = 'history_line'
if 'log_ids' in field_names:
history_obj = self.pool.get('crm.case.log')
name = 'log_ids'
if not history_obj:
return result
for case in self.browse(cr, uid, ids, context):
model_ids = model_obj.search(cr, uid, [('model', '=', case._name)])
history_ids = history_obj.search(cr, uid, [('model_id', '=', model_ids[0]), \
('res_id', '=', case.id)])
if history_ids:
result[case.id] = {name: history_ids}
else:
result[case.id] = {name: []}
return result
_columns = {
'id': fields.integer('ID', readonly=True),
'name': fields.char('Description', size=1024, required=True),
'active': fields.boolean('Active', help="If the active field is set to\
true, it will allow you to hide the case without removing it."),
'description': fields.text('Description'),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'email_cc': fields.text('Watchers Emails', size=252 , help="These people\
will receive a copy of the future" \
" communication between partner and users by email"),
'probability': fields.float('Probability'),
'email_last': fields.function(_email_last, method=True,
string='Latest E-Mail', type='text'),
'partner_id': fields.many2one('res.partner', 'Partner'),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
domain="[('partner_id','=',partner_id)]"),
'create_date': fields.datetime('Creation Date' , readonly=True),
'write_date': fields.datetime('Update Date' , readonly=True),
'date_deadline': fields.date('Deadline'),
'user_id': fields.many2one('res.users', 'Responsible'),
'history_line': fields.function(_get_log_ids, method=True, type='one2many', \
multi="history_line", relation="crm.case.history", string="Communication"),
'log_ids': fields.function(_get_log_ids, method=True, type='one2many', \
multi="log_ids", relation="crm.case.log", string="Logs History"),
'stage_id': fields.many2one ('crm.case.stage', 'Stage', \
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.lead')]"),
'state': fields.selection(AVAILABLE_STATES, 'State', size=16, readonly=True,
help='The state is set to \'Draft\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'company_id': fields.many2one('res.company', 'Company'),
}
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 users 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 users 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 users 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 users 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 users 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
_defaults = {
'active': lambda *a: 1,
'user_id': _get_default_user,
'partner_id': _get_default_partner,
'partner_address_id': _get_default_partner_address,
'email_from': _get_default_email,
'state': lambda *a: 'draft',
'section_id': _get_section,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
}
_order = 'date_deadline desc, create_date desc,id desc'
def unlink(self, cr, uid, ids, context=None):
"""Overrides orm unlink method
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of case IDs
@param context: A standard dictionary for contextual values
"""
if not context:
context = {}
hist_obj = self.pool.get('crm.case.history')
log_obj = self.pool.get('crm.case.log')
for case in self.browse(cr, uid, ids, context):
if (not case.section_id.allow_unlink) and (case.state <> 'draft'):
raise osv.except_osv(_('Warning !'),
_('You can not delete this case. You should better cancel it.'))
# Also removing history and logs
history_ids = map(lambda x: x.id, case.history_line)
log_ids = map(lambda x: x.id, case.log_ids)
hist_obj.unlink(cr, uid, history_ids, context=context)
log_obj.unlink(cr, uid, log_ids, context=context)
return super(crm_case, self).unlink(cr, uid, ids, context)
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 users 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)
for case in self.browse(cr, uid, ids, context):
section = (case.section_id.id or False)
if section in s:
st = case.stage_id.id or False
if st in s[section]:
self.write(cr, uid, [case.id], {'stage_id': s[section][st]})
return True
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 users ID for security checks,
@param ids: List of case IDs
@param context: A standard dictionary for contextual values"""
if not context:
context = {}
sid = self.pool.get('crm.case.stage').search(cr, uid, \
[('object_id.model', '=', self._name)], context=context)
s = {}
previous = {}
for stage in self.pool.get('crm.case.stage').browse(cr, uid, sid, context=context):
section = stage.section_id.id or False
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
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 users 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)
for case in self.browse(cr, uid, ids, context):
section = (case.section_id.id or False)
if section in s:
st = case.stage_id.id or False
s[section] = dict([(v, k) for (k, v) in s[section].iteritems()])
if st in s[section]:
self.write(cr, uid, [case.id], {'stage_id': s[section][st]})
return True
def __history(self, cr, uid, cases, keyword, history=False, email=False, details=None, email_from=False, message_id=False, context={}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param cases: a browse record list
@param keyword: Case action keyword e.g.: If case is closed "Close" keyword is used
@param history: Value True/False, If True it makes entry in case History otherwise in Case Log
@param email: Email address if any
@param details: Details of case history if any
@param context: A standard dictionary for contextual values"""
if not context:
context = {}
# The mailgate sends the ids of the cases and not the object list
if all(isinstance(case_id, (int, long)) for case_id in cases) and context.get('model'):
cases = self.pool.get(context['model']).browse(cr, uid, cases, context=context)
model_obj = self.pool.get('ir.model')
obj = self.pool.get('crm.case.log')
for case in cases:
model_ids = model_obj.search(cr, uid, [('model', '=', case._name)])
data = {
'name': keyword,
'user_id': uid,
'date': time.strftime('%Y-%m-%d %H:%M:%S'),
'model_id' : model_ids and model_ids[0] or False,
'res_id': case.id,
'section_id': case.section_id.id,
'message_id':message_id
}
if history:
obj = self.pool.get('crm.case.history')
data['description'] = details or case.description
data['email_to'] = email or \
(case.section_id and case.section_id.reply_to) or \
(case.user_id and case.user_id.address_id and \
case.user_id.address_id.email) or tools.config.get('email_from', False)
data['email_from'] = email_from or \
(case.section_id and case.section_id.reply_to) or \
(case.user_id and case.user_id.address_id and \
case.user_id.address_id.email) or tools.config.get('email_from', False)
res = obj.create(cr, uid, data, context)
return True
_history = __history
history = __history
def create(self, cr, uid, *args, **argv):
"""Overrides orm create method
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param *args: Tuple Value for additional Params
@param **argv: Dictionay of Keyword Params
"""
res = super(crm_case, self).create(cr, uid, *args, **argv)
cases = self.browse(cr, uid, [res])
cases[0].state # to fill the browse record cache
self._action(cr, uid, cases, 'draft')
return res
def add_reply(self, cursor, user, ids, context=None):
"""This function finds last email and gives its description value for reply mail
@param self: The object pointer
@param cursor: the current row, from the database cursor,
@param user: the current users ID for security checks
@param ids: List of case IDs
@param context: A standard dictionary for contextual values
"""
for case in self.browse(cursor, user, ids, context=context):
if case.email_last:
description = case.email_last
self.write(cursor, user, case.id, {
'description': '> ' + description.replace('\n', '\n> '),
}, context=context)
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 users ID for security checks,
@param ids: List of case IDs
@param part: Partner's id
@email: Partner's email ID
"""
if not part:
return {'value': {'partner_address_id': False,
'email_from': 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'])
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 users ID for security checks,
@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)
return {'value': {'email_from': address.email}}
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 users 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'),
'probability' : 100.0})
#
# 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 users 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:
data = {'active': True, 'user_id': False}
if case.section_id.parent_id:
data['section_id'] = case.section_id.parent_id.id
if case.section_id.parent_id.user_id:
data['user_id'] = case.section_id.parent_id.user_id.id
else:
raise osv.except_osv(_('Error !'), _('You can not escalate this case.\nYou are already at the top level.'))
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
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 users 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_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 users 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,
'probability' : 0.0})
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 users 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 users 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
crm_case()
class crm_case_log(osv.osv):
""" Case Communication History """

View File

@ -37,7 +37,7 @@ import crm
class case(osv.osv):
""" Case """
_inherit = 'crm.case'
_inherit = 'mailgate.thread'
_description = 'case'
_columns = {
@ -89,7 +89,7 @@ class case(osv.osv):
attach_to_send = None
if attach:
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', 'crm.case'), ('res_id', '=', case.id)])
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', 'mailgate.thread'), ('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)
@ -195,16 +195,18 @@ class base_action_rule(osv.osv):
ok = ok and (not action.trg_section_id or action.trg_section_id.id==obj.section_id.id)
if hasattr(obj, 'categ_id'):
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id==obj.categ_id.id)
if hasattr(obj, 'history_line'):
ok = ok and (not action.trg_max_history or action.trg_max_history<=(len(obj.history_line)+1))
reg_history = action.regex_history
result_history = True
if reg_history:
ptrn = re.compile(str(reg_history))
if obj.history_line:
_result = ptrn.search(str(obj.history_line[0].description))
if not _result:
result_history = False
# TODO: history_line is removed
# if hasattr(obj, 'history_line'):
# ok = ok and (not action.trg_max_history or action.trg_max_history<=(len(obj.history_line)+1))
# reg_history = action.regex_history
# result_history = True
# if reg_history:
# ptrn = re.compile(str(reg_history))
# if obj.history_line:
# _result = ptrn.search(str(obj.history_line[0].description))
# if not _result:
# result_history = False
regex_h = not reg_history or result_history
ok = ok and regex_h
return ok

View File

@ -33,7 +33,7 @@ class crm_lead(osv.osv):
_name = "crm.lead"
_description = "Leads Cases"
_order = "priority, id desc"
_inherit = ['res.partner.address', 'crm.case']
_inherit = ['res.partner.address', 'mailgate.thread']
def case_open(self, cr, uid, ids, *args):
"""
@ -106,7 +106,19 @@ class crm_lead(osv.osv):
return res
_columns = {
# From crm.case
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
'create_date': fields.datetime('Creation Date' , readonly=True),
'email_cc': fields.text('Watchers Emails', size=252 , help="These people\
will receive a copy of the future" \
" communication between partner and users by email"),
'description': fields.text('Description'),
'write_date': fields.datetime('Update Date' , readonly=True),
# Lead fields
'categ_id': fields.many2one('crm.case.categ', 'Lead Source', \
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.lead')]"),
@ -139,7 +151,69 @@ class crm_lead(osv.osv):
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
}
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 users 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)
for case in self.browse(cr, uid, ids, context):
section = (case.section_id.id or False)
if section in s:
st = case.stage_id.id or False
if st in s[section]:
self.write(cr, uid, [case.id], {'stage_id': s[section][st]})
return True
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 users ID for security checks,
@param ids: List of case IDs
@param context: A standard dictionary for contextual values"""
if not context:
context = {}
sid = self.pool.get('crm.case.stage').search(cr, uid, \
[('object_id.model', '=', self._name)], context=context)
s = {}
previous = {}
for stage in self.pool.get('crm.case.stage').browse(cr, uid, sid, context=context):
section = stage.section_id.id or False
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
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 users 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)
for case in self.browse(cr, uid, ids, context):
section = (case.section_id.id or False)
if section in s:
st = case.stage_id.id or False
s[section] = dict([(v, k) for (k, v) in s[section].iteritems()])
if st in s[section]:
self.write(cr, uid, [case.id], {'stage_id': s[section][st]})
return True
def convert_opportunity(self, cr, uid, ids, context=None):
""" Precomputation for converting lead to opportunity
@param cr: the current row, from the database cursor,
@ -193,6 +267,118 @@ class crm_lead(osv.osv):
'nodestroy': True
}
return value
# From crm.case
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 users 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 users 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:
data = {'active': True, 'user_id': False}
if case.section_id.parent_id:
data['section_id'] = case.section_id.parent_id.id
if case.section_id.parent_id.user_id:
data['user_id'] = case.section_id.parent_id.user_id.id
else:
raise osv.except_osv(_('Error !'), _('You can not escalate this case.\nYou are already at the top level.'))
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
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 users 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_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 users 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 users 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 users 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
crm_lead()

View File

@ -40,7 +40,7 @@
<field name="arch" type="xml">
<form string="Leads Form">
<group colspan="4" col="7">
<field name="name" required="1" string="Name"/>
<field name="name" required="1"/>
<field name="priority"/>
<field name="date_deadline"/>
<button
@ -48,8 +48,7 @@
string="Convert"
help="Convert to Opportunity"
icon="gtk-index"
type="object"
attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
type="object"/>
<newline />
<field name="section_id" colspan="1"
widget="selection" />
@ -153,7 +152,8 @@
<group colspan="4">
<field colspan="4" name="email_cc" string="CC"/>
</group>
<field name="history_line" colspan="4" nolabel="1" mode="form,tree">
<!-- TODO-->
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
<form string="Communication history">
<group col="7" colspan="4">
<field name="date"/>
@ -179,7 +179,7 @@
<field name="email_to"/>
<field name="description"/>
</tree>
</field>
</field>
<button colspan="2" string="Send New Email"
name="%(action_crm_send_mail)d"
context="{'mail':'new', 'model': 'crm.lead'}"

View File

@ -38,8 +38,8 @@ from tools import command_re
class crm_cases(osv.osv):
""" crm cases """
_name = "crm.case"
_inherit = "crm.case"
_name = "mailgate.thread"
_inherit = "mailgate.thread"
def message_new(self, cr, uid, msg, context):
"""

View File

@ -26,10 +26,6 @@ from datetime import datetime, timedelta
from tools.translate import _
from base_calendar import base_calendar
class crm_opportunity(osv.osv):
_name = 'crm.opportunity'
crm_opportunity()
class crm_phonecall(osv.osv):
""" CRM Phonecall """
@ -43,14 +39,20 @@ class crm_meeting(osv.osv):
_name = 'crm.meeting'
_description = "Meeting Cases"
_order = "id desc"
_inherit = ["crm.case", "calendar.event"]
_inherit = ["mailgate.thread", "calendar.event"]
_columns = {
# From crm.case
'partner_id': fields.many2one('res.partner', 'Partner'),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
# Meeting fields
'categ_id': fields.many2one('crm.case.categ', 'Meeting Type', \
domain="[('object_id.model', '=', 'crm.meeting')]", \
),
'phonecall_id': fields.many2one ('crm.phonecall', 'Phonecall'),
'opportunity_id': fields.many2one ('crm.opportunity', 'Opportunity'),
'opportunity_id': fields.many2one ('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"),
'attendee_ids': fields.many2many('calendar.attendee', 'meeting_attendee_rel',\
'event_id', 'attendee_id', 'Attendees'),
'date_closed': fields.datetime('Closed', readonly=True),

View File

@ -47,7 +47,7 @@
id="crm_case_categ_meet_case"
name="Schedule a Meeting"
res_model="crm.meeting"
src_model="crm.case"
src_model="mailgate.thread"
view_mode="calendar,tree,form,gantt"
context="{'default_case_id': active_id, 'default_duration': 4.0}"
/>

View File

@ -55,78 +55,16 @@ class crm_opportunity(osv.osv):
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')})
return res
def _compute_day(self, cr, uid, ids, fields, args, context={}):
"""
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Opendays IDs
@return: difference between current date and log date
@param context: A standard dictionary for contextual values
"""
cal_obj = self.pool.get('resource.calendar')
res_obj = self.pool.get('resource.resource')
res = {}
for opportunity in self.browse(cr, uid, ids , context):
for field in fields:
res[opportunity.id] = {}
duration = 0
ans = False
if field == 'day_open':
if opportunity.date_open:
date_create = datetime.strptime(opportunity.create_date, "%Y-%m-%d %H:%M:%S")
date_open = datetime.strptime(opportunity.date_open, "%Y-%m-%d %H:%M:%S")
ans = date_open - date_create
date_until = opportunity.date_open
elif field == 'day_close':
if opportunity.date_closed:
date_create = datetime.strptime(opportunity.create_date, "%Y-%m-%d %H:%M:%S")
date_close = datetime.strptime(opportunity.date_closed, "%Y-%m-%d %H:%M:%S")
date_until = opportunity.date_closed
ans = date_close - date_create
if ans:
resource_id = False
if opportunity.user_id:
resource_ids = res_obj.search(cr, uid, [('user_id','=',opportunity.user_id.id)])
if resource_ids and len(resource_ids):
resource_id = resource_ids[0]
duration = float(ans.days)
if opportunity.section_id and opportunity.section_id.resource_calendar_id:
duration = float(ans.days) * 24
new_dates = cal_obj.interval_get(cr,
uid,
opportunity.section_id.resource_calendar_id and opportunity.section_id.resource_calendar_id.id or False,
mx.DateTime.strptime(opportunity.create_date, '%Y-%m-%d %H:%M:%S'),
duration,
resource=resource_id
)
no_days = []
date_until = mx.DateTime.strptime(date_until, '%Y-%m-%d %H:%M:%S')
for in_time, out_time in new_dates:
if in_time.date not in no_days:
no_days.append(in_time.date)
if out_time > date_until:
break
duration = len(no_days)
res[opportunity.id][field] = abs(int(duration))
return res
_columns = {
'stage_id': fields.many2one ('crm.case.stage', 'Stage', \
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.lead')]"),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="[('section_id','=',section_id), \
('object_id.model', '=', 'crm.lead')]"),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'referred': fields.char('Referred By', size=64),
# From crm.case
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
domain="[('partner_id','=',partner_id)]"),
# Opportunity fields
'probability': fields.float('Probability (%)'),
'planned_revenue': fields.float('Expected Revenue'),
'ref': fields.reference('Reference', selection=crm._links_get, size=128),
'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
'date_closed': fields.datetime('Closed', readonly=True),
'user_id': fields.many2one('res.users', 'Salesman'),
'phone': fields.char("Phone", size=64),
'date_deadline': fields.date('Expected Closing'),
'date_action': fields.date('Next Action'),
@ -136,12 +74,44 @@ class crm_opportunity(osv.osv):
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'date_open': fields.datetime('Opened', readonly=True),
'day_open': fields.function(_compute_day, string='Days to Open', \
method=True, multi='day_open', type="float", store=True),
'day_close': fields.function(_compute_day, string='Days to Close', \
method=True, multi='day_close', type="float", store=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 users 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'),
'probability' : 100.0})
#
# 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 self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users 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,
'probability' : 0.0})
self._action(cr, uid, cases, 'cancel')
return True
def onchange_stage_id(self, cr, uid, ids, stage_id, context={}):
@ -157,35 +127,7 @@ class crm_opportunity(osv.osv):
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 stage_next(self, cr, uid, ids, context={}):
""" @param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of stage nexts IDs
@param context: A standard dictionary for contextual values """
res = super(crm_opportunity, self).stage_next(cr, uid, ids, context=context)
for case in self.browse(cr, uid, ids, context):
if case.stage_id and case.stage_id.on_change:
self.write(cr, uid, [case.id], {'probability': case.stage_id.probability})
return res
def stage_previous(self, cr, uid, ids, context={}):
""" @param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of stage previouss IDs
@param context: A standard dictionary for contextual values """
res = super(crm_opportunity, self).stage_previous(cr, uid, ids, context=context)
for case in self.browse(cr, uid, ids, context):
if case.stage_id and case.stage_id.on_change:
self.write(cr, uid, [case.id], {'probability': case.stage_id.probability})
return res
return {'value':{'probability': stage.probability}}
_defaults = {
'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
@ -246,3 +188,4 @@ class crm_opportunity(osv.osv):
crm_opportunity()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -165,7 +165,7 @@
<group colspan="4">
<field colspan="4" name="email_cc" string="CC"/>
</group>
<field name="history_line" colspan="4" nolabel="1" mode="form,tree">
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
<form string="Communication history">
<group col="7" colspan="4">
<field name="date"/>

View File

@ -30,9 +30,17 @@ class crm_phonecall(osv.osv):
_name = "crm.phonecall"
_description = "Phonecall Cases"
_order = "id desc"
_inherit = 'crm.case'
_inherit = 'mailgate.thread'
_columns = {
# From crm.case
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
'user_id': fields.many2one('res.users', 'Responsible'),
'partner_id': fields.many2one('res.partner', 'Partner'),
# phonecall fields
'duration': fields.float('Duration'),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="[('section_id','=',section_id),\

View File

@ -256,7 +256,7 @@
<record id="crm_case_calendar-view" model="ir.ui.view">
<field name="name">crm.case.calendar</field>
<field name="model">crm.case</field>
<field name="model">mailgate.thread</field>
<field name="type">calendar</field>
<field name="arch" type="xml">
<calendar color="user_id" date_start="create_date"
@ -273,7 +273,7 @@
<record id="crm_case_tree-view" model="ir.ui.view">
<field name="name">crm.case.tree</field>
<field name="model">crm.case</field>
<field name="model">mailgate.thread</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree colors="red:date_deadline&lt;current_date and state=='open';black:state in ('draft', 'cancel','done','pending')" string="Cases">
@ -311,7 +311,7 @@
<record id="crm_case-view" model="ir.ui.view">
<field name="name">crm.case.form</field>
<field name="model">crm.case</field>
<field name="model">mailgate.thread</field>
<field name="type">form</field>
<field name="priority" eval="1"/>
<field name="arch" type="xml">
@ -392,7 +392,8 @@
<group colspan="4">
<field colspan="4" name="email_cc" string="CC"/>
</group>
<field name="history_line" colspan="4" nolabel="1" mode="form,tree">
<!-- TODO-->
<!-- <field name="history_line" colspan="4" nolabel="1" mode="form,tree">
<form string="Communication history">
<group col="7" colspan="4">
<field name="date"/>
@ -416,7 +417,7 @@
<field name="email_to"/>
<field name="date"/>
</tree>
</field>
</field> -->
<button colspan="4" string="Send New Email"
name="%(action_crm_send_mail)d"
context="{'mail':'new', 'model': 'crm.case'}"
@ -431,7 +432,7 @@
<record id="view_crm_case_filter" model="ir.ui.view">
<field name="name">crm.case.select</field>
<field name="model">crm.case</field>
<field name="model">mailgate.thread</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Search Case">
@ -463,7 +464,7 @@
<record id="crm_case_categ0-act" model="ir.actions.act_window">
<field name="name">Cases</field>
<field name="res_model">crm.case</field>
<field name="res_model">mailgate.thread</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm_case_tree-view"/>
<field name="search_view_id" ref="view_crm_case_filter"/>
@ -471,7 +472,7 @@
<record id="crm_case_categ0-act_open" model="ir.actions.act_window">
<field name="name">Open Cases</field>
<field name="res_model">crm.case</field>
<field name="res_model">mailgate.thread</field>
<field name="view_type">form</field>
<field name="domain">
[('state','&lt;&gt;','done'),('state','&lt;&gt;','cancel'),('state','&lt;&gt;','pending')]
@ -481,7 +482,7 @@
<record id="crm_case_section_open_act" model="ir.actions.act_window">
<field name="name">Cases</field>
<field name="res_model">crm.case</field>
<field name="res_model">mailgate.thread</field>
<field name="domain">[('section_id','child_of',[active_id])]</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,calendar</field>

View File

@ -8,7 +8,7 @@
<record id="process_process_contractprocess0" model="process.process">
<field eval="1" name="active"/>
<field name="model_id" ref="crm.model_crm_case"/>
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
<field eval="&quot;&quot;&quot;Contract&quot;&quot;&quot;" name="name"/>
</record>
@ -17,7 +17,7 @@
-->
<record id="process_node_leads0" model="process.node">
<field name="model_id" ref="crm.model_crm_case"/>
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
<field eval="&quot;&quot;&quot;state&quot;&quot;&quot;" name="kind"/>
<field eval="&quot;&quot;&quot;Leads&quot;&quot;&quot;" name="name"/>
<field eval="&quot;&quot;&quot;Very first contact with new prospect&quot;&quot;&quot;" name="note"/>
@ -37,7 +37,7 @@
</record>
<record id="process_node_opportunities0" model="process.node">
<field name="model_id" ref="crm.model_crm_case"/>
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
<field eval="&quot;&quot;&quot;state&quot;&quot;&quot;" name="kind"/>
<field eval="&quot;&quot;&quot;Opportunities&quot;&quot;&quot;" name="name"/>
<field eval="&quot;&quot;&quot;When a real project/opportunity is detected&quot;&quot;&quot;" name="note"/>
@ -47,7 +47,7 @@
</record>
<record id="process_node_meeting0" model="process.node">
<field name="model_id" ref="crm.model_crm_case"/>
<field name="model_id" ref="mail_gateway.model_mailgate_thread"/>
<field eval="&quot;&quot;&quot;state&quot;&quot;&quot;" name="kind"/>
<field eval="&quot;&quot;&quot;Meeting&quot;&quot;&quot;" name="name"/>
<field eval="&quot;&quot;&quot;Schedule a normal or phone meeting&quot;&quot;&quot;" name="note"/>

View File

@ -20,7 +20,7 @@
##############################################################################
#import report_businessopp
import crm_report
#import crm_report
import crm_lead_report
import crm_phonecall_report
#import crm_opportunity_report

View File

@ -34,7 +34,7 @@ class crm_lead_report(osv.osv):
""" CRM Lead Report """
_name = "crm.lead.report"
_auto = False
_inherit = "crm.case.report"
# _inherit = "crm.case.report"
_description = "CRM Lead Report"
_columns = {

View File

@ -28,7 +28,7 @@ class crm_phonecall_report(osv.osv):
_name = "crm.phonecall.report"
_description = "Phone calls by user and section"
_auto = False
_inherit = "crm.case.report"
# _inherit = "crm.case.report"
_columns = {
'delay_close': fields.float('Delay to close', digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"),

View File

@ -3,8 +3,6 @@
"access_crm_segmentation_line","crm.segmentation.line","model_crm_segmentation_line","crm.group_crm_manager",1,1,1,1
"access_crm_case_section","crm.case.section","model_crm_case_section","crm.group_crm_user",1,0,0,0
"access_crm_case_categ","crm.case.categ","model_crm_case_categ","crm.group_crm_user",1,0,0,0
"access_crm_case_manger","crm.case manager","model_crm_case","crm.group_crm_user",1,1,1,1
"access_crm_case","crm.case","model_crm_case","crm.group_crm_manager",1,1,1,1
"access_crm_meeting","crm.meeting","model_crm_meeting","crm.group_crm_manager",1,1,1,1
"access_crm_lead","crm.lead","model_crm_lead","crm.group_crm_manager",1,1,1,1
"access_crm_phonecall","crm.phonecall","model_crm_phonecall","crm.group_crm_manager",1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_crm_segmentation_line crm.segmentation.line model_crm_segmentation_line crm.group_crm_manager 1 1 1 1
4 access_crm_case_section crm.case.section model_crm_case_section crm.group_crm_user 1 0 0 0
5 access_crm_case_categ crm.case.categ model_crm_case_categ crm.group_crm_user 1 0 0 0
access_crm_case_manger crm.case manager model_crm_case crm.group_crm_user 1 1 1 1
access_crm_case crm.case model_crm_case crm.group_crm_manager 1 1 1 1
6 access_crm_meeting crm.meeting model_crm_meeting crm.group_crm_manager 1 1 1 1
7 access_crm_lead crm.lead model_crm_lead crm.group_crm_manager 1 1 1 1
8 access_crm_phonecall crm.phonecall model_crm_phonecall crm.group_crm_manager 1 1 1 1

View File

@ -84,7 +84,7 @@ class crm_opportunity2phonecall(osv.osv_memory):
record_ids = context and context.get('active_ids', []) or []
phonecall_obj = self.pool.get('crm.phonecall')
opp_obj = self.pool.get('crm.opportunity')
opp_obj = self.pool.get('crm.lead')
mod_obj = self.pool.get('ir.model.data')
result = mod_obj._get_id(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
res = mod_obj.read(cr, uid, result, ['res_id'])

View File

@ -55,7 +55,7 @@ class crm_send_new_email(osv.osv_memory):
""" This sends an email to ALL the addresses of the selected partners.
"""
hist_obj = self.pool.get('crm.case.history')
hist_obj = self.pool.get('mailgate.message')
smtp_pool = self.pool.get('email.smtpclient')
if not context:
@ -76,14 +76,14 @@ class crm_send_new_email(osv.osv_memory):
case = case_pool.browse(cr, uid, res_id)
if context.get('mail', 'new') == 'new':
if len(case.history_line):
message_id = case.history_line[0].message_id
if len(case.message_ids):
message_id = case.message_ids[0].message_id
else:
hist = hist_obj.browse(cr, uid, res_id)
message_id = hist.message_id
model = hist.log_id.model_id.model
model = hist.model_id.model
model_pool = self.pool.get(model)
case = model_pool.browse(cr, uid, hist.log_id.res_id)
case = model_pool.browse(cr, uid, hist.res_id)
emails = [data['email_to']] + (data['email_cc'] or '').split(',')
emails = filter(None, emails)
body = data['text']
@ -179,15 +179,15 @@ class crm_send_new_email(osv.osv_memory):
"""
This function gets default values for reply mail
"""
hist_obj = self.pool.get('crm.case.history')
hist_obj = self.pool.get('mailgate.message')
res_ids = context and context.get('active_ids', []) or []
include_original = context and context.get('include_original', False) or False
res = {}
for hist in hist_obj.browse(cr, uid, res_ids):
model = hist.log_id.model_id.model
for hist in hist_obj.browse(cr, uid, res_ids, context=context):
model = hist.model_id.model
model_pool = self.pool.get(model)
case = model_pool.browse(cr, uid, hist.log_id.res_id)
case = model_pool.browse(cr, uid, hist.res_id)
if 'email_to' in fields:
res.update({'email_to': case.email_from or hist.email_from or False})
if 'email_from' in fields:

View File

@ -29,7 +29,7 @@ class crm_claim(osv.osv):
_name = "crm.claim"
_description = "Claim Cases"
_order = "id desc"
_inherit = 'crm.case'
_inherit = 'mailgate.thread'
_columns = {
'date_closed': fields.datetime('Closed', readonly=True),
'date': fields.datetime('Date'),

View File

@ -28,7 +28,7 @@ class crm_fundraising(osv.osv):
_name = "crm.fundraising"
_description = "Fund Raising Cases"
_order = "id desc"
_inherit ='crm.case'
_inherit ='mailgate.thread'
_columns = {
'date_closed': fields.datetime('Closed', readonly=True),

View File

@ -30,7 +30,7 @@ class crm_helpdesk(osv.osv):
_name = "crm.helpdesk"
_description = "Helpdesk Cases"
_order = "id desc"
_inherit = 'crm.case'
_inherit = 'mailgate.thread'
_columns = {
'date_closed': fields.datetime('Closed', readonly=True),

View File

@ -20,13 +20,7 @@
##############################################################################
from osv import osv, fields
from osv import osv
from osv import fields
from osv import osv
from osv import fields
import time
class mailgate_thread(osv.osv):
@ -36,10 +30,100 @@ class mailgate_thread(osv.osv):
_name = 'mailgate.thread'
_description = 'Mailgateway Thread'
def _get_log_ids(self, cr, uid, ids, field_names, arg, context=None):
"""Gets id for case log from history of particular case
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Case IDs
@param context: A standard dictionary for contextual values
@return:Dictionary of History Ids
"""
if not context:
context = {}
result = {}
domain = []
history_obj = False
model_obj = self.pool.get('ir.model')
history_obj = self.pool.get('mailgate.message')
if 'message_ids' in field_names:
name = 'message_ids'
domain += [('email_to', '!=', False)]
if 'log_ids' in field_names:
name = 'log_ids'
domain += [('email_to', '=', False)]
model_ids = model_obj.search(cr, uid, [('model', '=', self._name)])
domain += [('model_id', '=', model_ids[0])]
for case in self.browse(cr, uid, ids, context):
domain1 = domain + [('res_id', '=', case.id)]
history_ids = history_obj.search(cr, uid, domain1, context=context)
if history_ids:
result[case.id] = {name: history_ids}
else:
result[case.id] = {name: []}
return result
_columns = {
'name':fields.char('Name', size=64),
'message_ids':fields.one2many('mailgate.message', 'thread_id', 'Message'),
# 'message_ids':fields.one2many('mailgate.message', 'thread_id', 'Message'),
'message_ids': fields.function(_get_log_ids, method=True, type='one2many', \
multi="message_ids", relation="mailgate.message", string="Messages"),
'log_ids': fields.function(_get_log_ids, method=True, type='one2many', \
multi="log_ids", relation="mailgate.message", string="Logs"),
}
def __history(self, cr, uid, cases, keyword, history=False, email=False, details=None, email_from=False, message_id=False, context={}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param cases: a browse record list
@param keyword: Case action keyword e.g.: If case is closed "Close" keyword is used
@param history: Value True/False, If True it makes entry in case History otherwise in Case Log
@param email: Email address if any
@param details: Details of case history if any
@param context: A standard dictionary for contextual values"""
if not context:
context = {}
# The mailgate sends the ids of the cases and not the object list
if all(isinstance(case_id, (int, long)) for case_id in cases) and context.get('model'):
cases = self.pool.get(context['model']).browse(cr, uid, cases, context=context)
model_obj = self.pool.get('ir.model')
obj = self.pool.get('mailgate.message')
for case in cases:
model_ids = model_obj.search(cr, uid, [('model', '=', case._name)])
data = {
'name': keyword,
'user_id': uid,
'date': time.strftime('%Y-%m-%d %H:%M:%S'),
'model_id' : model_ids and model_ids[0] or False,
'res_id': case.id,
'section_id': case.section_id.id,
'message_id':message_id
}
if history:
data['description'] = details or case.description
data['email_to'] = email or \
(case.section_id and case.section_id.reply_to) or \
(case.user_id and case.user_id.address_id and \
case.user_id.address_id.email) or tools.config.get('email_from', False)
data['email_from'] = email_from or \
(case.section_id and case.section_id.reply_to) or \
(case.user_id and case.user_id.address_id and \
case.user_id.address_id.email) or tools.config.get('email_from', False)
res = obj.create(cr, uid, data, context)
return True
_history = __history
history = __history
mailgate_thread()
@ -51,7 +135,7 @@ class mailgate_message(osv.osv):
_description = 'Mailgateway Message'
_columns = {
'name':fields.char('Message', size=64, required=True),
'name':fields.char('Message', size=64),
'thread_id':fields.many2one('mailgate.thread', 'Thread'),
'date': fields.datetime('Date'),
'model_id': fields.many2one('ir.model', "Model"),
@ -63,6 +147,7 @@ class mailgate_message(osv.osv):
'email_cc': fields.char('Email From', size=84),
'email_bcc': fields.char('Email From', size=84),
'message_id': fields.char('Message Id', size=1024, readonly=True, help="Message Id on Email Server.", select=True),
'description': fields.text('Description'),
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments'),
}