diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index d8d86073ef8..9bb1e833307 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -127,7 +127,7 @@ class crm_case_section(osv.osv):
def name_get(self, cr, uid, ids, context=None):
"""Overrides orm name_get method"""
- if not isinstance(ids, list) :
+ if not isinstance(ids, list) :
ids = [ids]
res = []
if not ids:
@@ -256,7 +256,40 @@ class crm_base(object):
data.update(self.onchange_partner_address_id(cr, uid, ids, addr['contact'])['value'])
return {'value': data}
- def case_open(self, cr, uid, ids, *args):
+ 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 opened.' % (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 closed.'% (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 canceled.' % (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_pending_send_note(self, cr, uid, ids, context=None):
+ for id in ids:
+ msg = '%s is now pending.' % (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_reset_send_note(self, cr, uid, ids, context=None):
+ for id in ids:
+ msg = '%s has been renewed.' % (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_open(self, cr, uid, ids, context=None):
"""Opens Case
:param ids: List of case Ids
"""
@@ -266,11 +299,12 @@ class crm_base(object):
if not case.user_id:
data['user_id'] = uid
self.write(cr, uid, [case.id], data)
-
+ self.case_open_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'open')
+
return True
- def case_close(self, cr, uid, ids, *args):
+ def case_close(self, cr, uid, ids, context=None):
"""Closes Case
:param ids: List of case Ids
"""
@@ -278,10 +312,11 @@ class crm_base(object):
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'done', 'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'), })
# We use the cache of cases to keep the old case state
+ self.case_close_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'done')
return True
- def case_cancel(self, cr, uid, ids, *args):
+ def case_cancel(self, cr, uid, ids, context=None):
"""Cancels Case
:param ids: List of case Ids
"""
@@ -289,26 +324,29 @@ class crm_base(object):
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'cancel', 'active': True})
# We use the cache of cases to keep the old case state
+ self.case_cancel_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'cancel')
return True
- def case_pending(self, cr, uid, ids, *args):
+ def case_pending(self, cr, uid, ids, context=None):
"""Marks case as pending
:param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'pending', 'active': True})
+ self.case_pending_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'pending')
return True
- def case_reset(self, cr, uid, ids, *args):
+ def case_reset(self, cr, uid, ids, context=None):
"""Resets case as draft
:param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'draft', 'active': True})
+ self.case_reset_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'draft')
return True
@@ -323,12 +361,12 @@ class crm_base(object):
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
class crm_case(crm_base):
- """ A simple python class to be used for common functions
+ """ A simple python class to be used for common functions
Object that inherit from this class should inherit from mailgate.thread
And need a stage_id field
- And object that inherit (orm inheritance) from a class the overwrite copy
+ And object that inherit (orm inheritance) from a class the overwrite copy
"""
-
+
def stage_find(self, cr, uid, section_id, domain=[], order='sequence'):
domain = list(domain)
if section_id:
@@ -387,8 +425,16 @@ class crm_case(crm_base):
default.update({ 'date_open': False })
return super(crm_case, self).copy(cr, uid, id, default, context=context)
+ 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 escalated to %s.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context), new_section.name)
+ else:
+ msg = '%s has been escalated.' % (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
- def case_open(self, cr, uid, ids, *args):
+ def case_open(self, cr, uid, ids, context=None):
"""Opens Case"""
cases = self.browse(cr, uid, ids)
for case in cases:
@@ -396,10 +442,11 @@ class crm_case(crm_base):
if not case.user_id:
data['user_id'] = uid
self.write(cr, uid, [case.id], data)
+ self.case_open_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'open')
return True
- def case_close(self, cr, uid, ids, *args):
+ def case_close(self, cr, uid, ids, context=None):
"""Closes Case"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
@@ -409,10 +456,11 @@ class crm_case(crm_base):
#
# We use the cache of cases to keep the old case state
#
+ self.case_close_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'done')
return True
- def case_escalate(self, cr, uid, ids, *args):
+ def case_escalate(self, cr, uid, ids, context=None):
"""Escalates case to parent level"""
cases = self.browse(cr, uid, ids)
for case in cases:
@@ -425,38 +473,37 @@ class crm_case(crm_base):
else:
raise osv.except_osv(_('Error !'), _('You can not escalate, you are already at the top level regarding your sales-team category.'))
self.write(cr, uid, [case.id], data)
+ case.case_escalate_send_note(case.section_id.parent_id)
cases = self.browse(cr, uid, ids)
self._action(cr, uid, cases, 'escalate')
return True
- def case_cancel(self, cr, uid, ids, *args):
+ def case_cancel(self, cr, uid, ids, context=None):
"""Cancels Case"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'cancel',
'active': True})
+ self.case_cancel_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'cancel')
- for case in cases:
- message = _("The case '%s' has been cancelled.") % (case.name,)
- self.log(cr, uid, case.id, message)
return True
- def case_pending(self, cr, uid, ids, *args):
+ def case_pending(self, cr, uid, ids, context=None):
"""Marks case as pending"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'pending', 'active': True})
+ self.case_pending_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, 'pending')
return True
- def case_reset(self, cr, uid, ids, *args):
+ def case_reset(self, cr, uid, ids, context=None):
"""Resets case as draft"""
state = 'draft'
- if 'crm.phonecall' in args:
- state = 'open'
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': state, 'active': True})
+ self.case_reset_send_note(cr, uid, ids, context=context)
self._action(cr, uid, cases, state)
return True
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index 2b319e565da..28830bfc5cd 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -40,7 +40,7 @@ class crm_lead(crm_case, osv.osv):
_name = "crm.lead"
_description = "Lead/Opportunity"
_order = "priority,date_action,id desc"
- _inherit = ['mail.thread','res.partner']
+ _inherit = ['ir.needaction', 'mail.thread','res.partner']
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
access_rights_uid = access_rights_uid or uid
@@ -183,7 +183,6 @@ class crm_lead(crm_case, osv.osv):
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
'subjects': fields.function(_get_email_subject, fnct_search=_history_search, string='Subject of Email', type='char', size=64),
-
# Only used for type opportunity
'probability': fields.float('Probability (%)',group_operator="avg"),
'planned_revenue': fields.float('Expected Revenue'),
@@ -215,6 +214,19 @@ class crm_lead(crm_case, osv.osv):
'color': 0,
}
+ def get_needaction_user_ids(self, cr, uid, ids, context=None):
+ result = dict.fromkeys(ids, [])
+ for obj in self.browse(cr, uid, ids, context=context):
+ # salesman must perform an action when in draft mode
+ if obj.state == 'draft' and obj.user_id:
+ result[obj.id] = [obj.user_id.id]
+ return result
+
+ def create(self, cr, uid, vals, context=None):
+ obj_id = super(crm_lead, self).create(cr, uid, vals, context)
+ self.create_send_note(cr, uid, [obj_id], context=context)
+ return obj_id
+
def on_change_optin(self, cr, uid, ids, optin):
return {'value':{'optin':optin,'optout':False}}
@@ -248,75 +260,58 @@ class crm_lead(crm_case, osv.osv):
def stage_find_won(self, cr, uid, section_id):
return self.stage_find_percent(cr, uid, 100.0, section_id)
- def case_open(self, cr, uid, ids, *args):
- for l in self.browse(cr, uid, ids):
- # When coming from draft override date and stage otherwise just set state
- if l.state == 'draft':
- if l.type == 'lead':
- message = _("The lead '%s' has been opened.") % l.name
- elif l.type == 'opportunity':
- message = _("The opportunity '%s' has been opened.") % l.name
- else:
- message = _("The case '%s' has been opened.") % l.name
- self.log(cr, uid, l.id, message)
+ def case_open(self, cr, uid, ids, context=None):
+ for lead in self.browse(cr, uid, ids, context=context):
+ if lead.state == 'draft':
value = {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')}
- self.write(cr, uid, [l.id], value)
- if l.type == 'opportunity' and not l.stage_id:
- stage_id = self.stage_find(cr, uid, l.section_id.id or False, [('sequence','>',0)])
+ self.write(cr, uid, [lead.id], value)
+ if lead.type == 'opportunity' and not lead.stage_id:
+ stage_id = self.stage_find(cr, uid, lead.section_id.id or False, [('sequence','>',0)])
if stage_id:
- self.stage_set(cr, uid, [l.id], stage_id)
- res = super(crm_lead, self).case_open(cr, uid, ids, *args)
+ self.stage_set(cr, uid, [lead.id], stage_id)
+ res = super(crm_lead, self).case_open(cr, uid, ids, context)
return res
- def case_close(self, cr, uid, ids, *args):
- res = super(crm_lead, self).case_close(cr, uid, ids, *args)
+ def case_close(self, cr, uid, ids, context=None):
+ res = super(crm_lead, self).case_close(cr, uid, ids, context)
self.write(cr, uid, ids, {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')})
- for case in self.browse(cr, uid, ids):
- if case.type == 'lead':
- message = _("The lead '%s' has been closed.") % case.name
- else:
- message = _("The case '%s' has been closed.") % case.name
- self.log(cr, uid, case.id, message)
return res
- def case_cancel(self, cr, uid, ids, *args):
+ def case_cancel(self, cr, uid, ids, context=None):
"""Overrides cancel for crm_case for setting probability
"""
- res = super(crm_lead, self).case_cancel(cr, uid, ids, args)
+ res = super(crm_lead, self).case_cancel(cr, uid, ids, context)
self.write(cr, uid, ids, {'probability' : 0.0})
return res
- def case_reset(self, cr, uid, ids, *args):
+ def case_reset(self, cr, uid, ids, context=None):
"""Overrides reset as draft in order to set the stage field as empty
"""
- res = super(crm_lead, self).case_reset(cr, uid, ids, *args)
+ res = super(crm_lead, self).case_reset(cr, uid, ids, context)
self.write(cr, uid, ids, {'stage_id': False, 'probability': 0.0})
return res
- def case_mark_lost(self, cr, uid, ids, *args):
+ def case_mark_lost(self, cr, uid, ids, context=None):
"""Mark the case as lost: state = done and probability = 0%
"""
- res = super(crm_lead, self).case_close(cr, uid, ids, *args)
+ res = super(crm_lead, self).case_close(cr, uid, ids, context)
self.write(cr, uid, ids, {'probability' : 0.0})
- for l in self.browse(cr, uid, ids):
- stage_id = self.stage_find_lost(cr, uid, l.section_id.id or False)
+ for lead in self.browse(cr, uid, ids):
+ stage_id = self.stage_find_lost(cr, uid, lead.section_id.id or False)
if stage_id:
- self.stage_set(cr, uid, [l.id], stage_id)
- message = _("The opportunity '%s' has been marked as lost.") % l.name
- self.log(cr, uid, l.id, message)
+ self.stage_set(cr, uid, [lead.id], stage_id)
return res
- def case_mark_won(self, cr, uid, ids, *args):
+ def case_mark_won(self, cr, uid, ids, context=None):
"""Mark the case as lost: state = done and probability = 0%
"""
- res = super(crm_lead, self).case_close(cr, uid, ids, *args)
+ res = super(crm_lead, self).case_close(cr, uid, ids, context=None)
self.write(cr, uid, ids, {'probability' : 100.0})
- for l in self.browse(cr, uid, ids):
- stage_id = self.stage_find_won(cr, uid, l.section_id.id or False)
+ for lead in self.browse(cr, uid, ids):
+ stage_id = self.stage_find_won(cr, uid, lead.section_id.id or False)
if stage_id:
- self.stage_set(cr, uid, [l.id], stage_id)
- message = _("The opportunity '%s' has been been won.") % l.name
- self.log(cr, uid, l.id, message)
+ self.stage_set(cr, uid, [lead.id], stage_id)
+ self.case_mark_won_send_note(cr, uid, [lead.id], context=context)
return res
def set_priority(self, cr, uid, ids, priority):
@@ -324,12 +319,12 @@ class crm_lead(crm_case, osv.osv):
"""
return self.write(cr, uid, ids, {'priority' : priority})
- def set_high_priority(self, cr, uid, ids, *args):
+ def set_high_priority(self, cr, uid, ids, context=None):
"""Set lead priority to high
"""
return self.set_priority(cr, uid, ids, '1')
- def set_normal_priority(self, cr, uid, ids, *args):
+ def set_normal_priority(self, cr, uid, ids, context=None):
"""Set lead priority to normal
"""
return self.set_priority(cr, uid, ids, '3')
@@ -422,7 +417,7 @@ class crm_lead(crm_case, osv.osv):
subject = subject[0] + ", ".join(subject[1:])
details = "\n\n".join(details)
- return self.message_append(cr, uid, [opportunity_id], subject, body_text=details, context=context)
+ return self.message_append_note(cr, uid, [opportunity_id], subject=subject, body=details)
def _merge_opportunity_history(self, cr, uid, opportunity_id, opportunities, context=None):
message = self.pool.get('mail.message')
@@ -529,13 +524,6 @@ class crm_lead(crm_case, osv.osv):
'date_open': time.strftime('%Y-%m-%d %H:%M:%S'),
}
- def _convert_opportunity_notification(self, cr, uid, lead, context=None):
- success_message = _("Lead '%s' has been converted to an opportunity.") % lead.name
- self.message_append(cr, uid, [lead.id], success_message, body_text=success_message, context=context)
- self.log(cr, uid, lead.id, success_message)
- self._send_mail_to_salesman(cr, uid, lead, context=context)
- return True
-
def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None):
partner = self.pool.get('res.partner')
mail_message = self.pool.get('mail.message')
@@ -551,7 +539,7 @@ class crm_lead(crm_case, osv.osv):
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
self.write(cr, uid, [lead.id], vals, context=context)
- self._convert_opportunity_notification(cr, uid, lead, context=context)
+ self.convert_opportunity_send_note(cr, uid, lead, context=context)
#TOCHECK: why need to change partner details in all messages of lead ?
if lead.partner_id:
msg_ids = [ x.id for x in lead.message_ids]
@@ -605,6 +593,7 @@ class crm_lead(crm_case, osv.osv):
res_partner.write(cr, uid, partner_id, {'section_id': lead.section_id.id or False})
contact_id = res_partner.address_get(cr, uid, [partner_id])['default']
res = lead.write({'partner_id' : partner_id, }, context=context)
+ self._lead_set_partner_send_note(cr, uid, [lead.id], context)
return res
def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
@@ -684,12 +673,12 @@ class crm_lead(crm_case, osv.osv):
'partner_mobile' : lead.partner_id and lead.partner_id.mobile or False,
'priority': lead.priority,
}
-
new_id = phonecall.create(cr, uid, vals, context=context)
- phonecall.case_open(cr, uid, [new_id])
+ phonecall.case_open(cr, uid, [new_id], context=context)
if action == 'log':
- phonecall.case_close(cr, uid, [new_id])
+ phonecall.case_close(cr, uid, [new_id], context=context)
phonecall_dict[lead.id] = new_id
+ self.schedule_phonecall_send_note(cr, uid, [lead.id], new_id, action, context=context)
return phonecall_dict
@@ -767,7 +756,7 @@ class crm_lead(crm_case, osv.osv):
#re-open
values.update(state=crm.AVAILABLE_STATES[1][0])
if not case.date_open:
- values['date_open'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
+ values['date_open'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
res = self.write(cr, uid, [case.id], values, context=context)
return res
@@ -831,17 +820,59 @@ class crm_lead(crm_case, osv.osv):
# change probability of lead(s) if required by stage
if not vals.get('probability') and stage.on_change:
vals['probability'] = stage.probability
- text = _("Changed Stage to: %s") % stage.name
- self.message_append(cr, uid, ids, text, body_text=text, context=context)
for case in self.browse(cr, uid, ids, context=context):
- if case.type == 'lead' or context.get('stage_type') == 'lead':
- message = _("The stage of lead '%s' has been changed to '%s'.") % (case.name, stage.name)
- self.log(cr, uid, case.id, message)
- elif case.type == 'opportunity':
- message = _("The stage of opportunity '%s' has been changed to '%s'.") % (case.name, stage.name)
- self.log(cr, uid, case.id, message)
-
+ message = _("Stage changed to %s.") % (stage.name)
+ case.message_append_note(body=message)
return super(crm_lead,self).write(cr, uid, ids, vals, context)
+
+ # ----------------------------------------
+ # OpenChatter methods and notifications
+ # ----------------------------------------
+
+ def message_get_subscribers(self, cr, uid, ids, context=None):
+ sub_ids = self.message_get_subscribers_ids(cr, uid, ids, context=context)
+ # add salesman to the subscribers
+ for obj in self.browse(cr, uid, ids, context=context):
+ if obj.user_id:
+ sub_ids.append(obj.user_id.id)
+ return self.pool.get('res.users').read(cr, uid, sub_ids, context=context)
+
+ def case_get_note_msg_prefix(self, cr, uid, lead, context=None):
+ if isinstance(lead, (int, long)):
+ lead = self.browse(cr, uid, [lead], context=context)[0]
+ return ('Opportunity' if lead.type == 'opportunity' else 'Lead')
+
+ def create_send_note(self, cr, uid, ids, context=None):
+ for id in ids:
+ message = _("%s has been created.")% (self.case_get_note_msg_prefix(cr, uid, id, context=context))
+ self.message_append_note(cr, uid, [id], body=message, context=context)
+ return True
+
+ def case_mark_lost_send_note(self, cr, uid, ids, context=None):
+ message = _("Opportunity has been lost.")
+ return self.message_append_note(cr, uid, ids, body=message, context=context)
+
+ def case_mark_won_send_note(self, cr, uid, ids, context=None):
+ message = _("Opportunity has been won.")
+ return self.message_append_note(cr, uid, ids, body=message, context=context)
+
+ def schedule_phonecall_send_note(self, cr, uid, ids, phonecall_id, action, context=None):
+ phonecall = self.pool.get('crm.phonecall').browse(cr, uid, [phonecall_id], context=context)[0]
+ if action == 'log': prefix = 'Logged'
+ else: prefix = 'Scheduled'
+ message = _("%s a call for the %s.") % (prefix, phonecall.date)
+ return self. message_append_note(cr, uid, ids, body=message, context=context)
+
+ def _lead_set_partner_send_note(self, cr, uid, ids, context=None):
+ for lead in self.browse(cr, uid, ids, context=context):
+ message = _("%s partner is now set to %s." % (self.case_get_note_msg_prefix(cr, uid, lead, context=context), lead.partner_id.name))
+ lead.message_append_note(body=message)
+ return True
+
+ def convert_opportunity_send_note(self, cr, uid, lead, context=None):
+ message = _("Lead has been converted to an opportunity.")
+ lead.message_append_note(body=message)
+ return True
crm_lead()
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index cc9f13b2658..52b7c88c2d4 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -143,29 +143,6 @@
type="object" icon="gtk-convert" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -176,13 +153,6 @@
-
-
-
-
-
-
-
@@ -195,6 +165,7 @@
+
@@ -545,37 +516,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -588,6 +529,7 @@
+
diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py
index 3b4d701590c..3577be4878f 100644
--- a/addons/crm/crm_meeting.py
+++ b/addons/crm/crm_meeting.py
@@ -42,7 +42,7 @@ class crm_meeting(crm_base, osv.osv):
_name = 'crm.meeting'
_description = "Meeting"
_order = "id desc"
- _inherit = "calendar.event"
+ _inherit = ["calendar.event", 'ir.needaction', "mail.thread"]
_columns = {
# From crm.case
'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
@@ -78,7 +78,55 @@ class crm_meeting(crm_base, osv.osv):
'user_id': lambda self, cr, uid, ctx: uid,
}
- def case_open(self, cr, uid, ids, *args):
+ def create(self, cr, uid, vals, context=None):
+ obj_id = super(crm_meeting, self).create(cr, uid, vals, context=context)
+ self.create_send_note(cr, uid, [obj_id], context=context)
+ return obj_id
+
+ def get_needaction_user_ids(self, cr, uid, ids, context=None):
+ result = dict.fromkeys(ids, [])
+ for obj in self.browse(cr, uid, ids, context=context):
+ if (obj.state == 'draft' and obj.user_id):
+ result[obj.id] = [obj.user_id.id]
+ return result
+
+ def case_get_note_msg_prefix(self, cr, uid, id, context=None):
+ return 'Meeting'
+
+ def create_send_note(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ # update context: if come from phonecall, default state values can make the message_append_note crash
+ context.pop('default_state', False)
+ for meeting in self.browse(cr, uid, ids, context=context):
+ message = _("A meeting has been scheduled on %s.") % (meeting.date)
+ if meeting.opportunity_id: # meeting can be create from phonecalls or opportunities, therefore checking for the parent
+ lead = meeting.opportunity_id
+ parent_message = _("Meeting linked to the opportunity %s has been created and cscheduled on %s.") % (lead.name, meeting.date)
+ lead.message_append_note(_('System Notification'), message)
+ elif meeting.phonecall_id:
+ phonecall = meeting.phonecall_id
+ parent_message = _("Meeting linked to the phonecall %s has been created and cscheduled on %s.") % (phonecall.name, meeting.date)
+ phonecall.message_append_note(body=message)
+ else:
+ parent_message = message
+ if parent_message:
+ meeting.message_append_note(body=parent_message)
+ return True
+
+ def case_close_send_note(self, cr, uid, ids, context=None):
+ message = _("Meeting has been done.")
+ return self.message_append_note(cr, uid, ids, body=message, context=context)
+
+ def case_open_send_note(self, cr, uid, ids, context=None):
+ for meeting in self.browse(cr, uid, ids, context=context):
+ if meeting.state != 'draft':
+ return False
+ message = _("Meeting has been confirmed.")
+ meeting.message_append_note(body=message)
+ return True
+
+ def case_open(self, cr, uid, ids, context=None):
"""Confirms meeting
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -86,11 +134,9 @@ class crm_meeting(crm_base, osv.osv):
@param ids: List of Meeting Ids
@param *args: Tuple Value for additional Params
"""
- res = super(crm_meeting, self).case_open(cr, uid, ids, args)
+ res = super(crm_meeting, self).case_open(cr, uid, ids, context)
for (id, name) in self.name_get(cr, uid, ids):
- message = _("The meeting '%s' has been confirmed.") % name
id=base_calendar.base_calendar_id2real_id(id)
- self.log(cr, uid, id, message)
return res
crm_meeting()
diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml
index d94fe9e8566..a82a34d80ce 100644
--- a/addons/crm/crm_meeting_view.xml
+++ b/addons/crm/crm_meeting_view.xml
@@ -212,6 +212,7 @@
+
diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py
index c6a59d9aace..26cbd7e8698 100644
--- a/addons/crm/crm_phonecall.py
+++ b/addons/crm/crm_phonecall.py
@@ -32,6 +32,7 @@ class crm_phonecall(crm_base, osv.osv):
_name = "crm.phonecall"
_description = "Phonecall"
_order = "id desc"
+ _inherit = ['ir.needaction', 'mail.thread']
_columns = {
# From crm.case
'id': fields.integer('ID', readonly=True),
@@ -47,12 +48,12 @@ class crm_phonecall(crm_base, osv.osv):
'company_id': fields.many2one('res.company', 'Company'),
'description': fields.text('Description'),
'state': fields.selection([
- ('draft', 'Draft'),
- ('open', 'Todo'),
- ('cancel', 'Cancelled'),
- ('done', 'Held'),
+ ('draft', 'Draft'),
+ ('open', 'Todo'),
+ ('cancel', 'Cancelled'),
+ ('done', 'Held'),
('pending', 'Not Held'),
- ], 'State', size=16, readonly=True,
+ ], 'State', size=16, readonly=True,
help='The state is set to \'Todo\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the call is over, the state is set to \'Held\'.\
@@ -67,9 +68,9 @@ class crm_phonecall(crm_base, osv.osv):
'partner_phone': fields.char('Phone', size=32),
'partner_mobile': fields.char('Mobile', size=32),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
- 'date_closed': fields.datetime('Closed', readonly=True),
- 'date': fields.datetime('Date'),
- 'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
+ 'date_closed': fields.datetime('Closed', readonly=True),
+ 'date': fields.datetime('Date'),
+ 'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
}
@@ -80,13 +81,30 @@ class crm_phonecall(crm_base, osv.osv):
_defaults = {
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
- 'priority': crm.AVAILABLE_PRIORITIES[2][0],
- 'state': _get_default_state,
+ 'priority': crm.AVAILABLE_PRIORITIES[2][0],
+ 'state': _get_default_state,
'user_id': lambda self,cr,uid,ctx: uid,
'active': 1,
}
- def case_close(self, cr, uid, ids, *args):
+ def create(self, cr, uid, vals, context=None):
+ obj_id = super(crm_phonecall, self).create(cr, uid, vals, context)
+ for phonecall in self.browse(cr, uid, [obj_id], context=context):
+ if not phonecall.opportunity_id:
+ self.case_open_send_note(cr, uid, [obj_id], context=context)
+ return obj_id
+
+ # From crm.case
+ def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
+ res = super(crm_phonecall, self).onchange_partner_address_id(cr, uid, ids, add, email)
+ res.setdefault('value', {})
+ if add:
+ address = self.pool.get('res.partner.address').browse(cr, uid, add)
+ res['value']['partner_phone'] = address.phone
+ res['value']['partner_mobile'] = address.mobile
+ return res
+
+ def case_close(self, cr, uid, ids, context=None):
"""Overrides close for crm_case for setting close date
"""
res = True
@@ -96,22 +114,22 @@ class crm_phonecall(crm_base, osv.osv):
if phone.duration <=0:
duration = datetime.now() - datetime.strptime(phone.date, '%Y-%m-%d %H:%M:%S')
data.update({'duration': duration.seconds/float(60)})
- res = super(crm_phonecall, self).case_close(cr, uid, [phone_id], args)
+ res = super(crm_phonecall, self).case_close(cr, uid, [phone_id], context)
self.write(cr, uid, [phone_id], data)
return res
- def case_reset(self, cr, uid, ids, *args):
+ def case_reset(self, cr, uid, ids, context=None):
"""Resets case as Todo
"""
- res = super(crm_phonecall, self).case_reset(cr, uid, ids, args, 'crm.phonecall')
+ res = super(crm_phonecall, self).case_reset(cr, uid, ids, context)
self.write(cr, uid, ids, {'duration': 0.0, 'state':'open'})
return res
- def case_open(self, cr, uid, ids, *args):
+ def case_open(self, cr, uid, ids, context=None):
"""Overrides cancel for crm_case for setting Open Date
"""
- res = super(crm_phonecall, self).case_open(cr, uid, ids, *args)
+ res = super(crm_phonecall, self).case_open(cr, uid, ids, context)
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')})
return res
@@ -143,9 +161,7 @@ class crm_phonecall(crm_base, osv.osv):
'partner_mobile' : call.partner_mobile,
'priority': call.priority,
}
-
new_id = self.create(cr, uid, vals, context=context)
- self.case_open(cr, uid, [new_id])
if action == 'log':
self.case_close(cr, uid, [new_id])
phonecall_dict[call.id] = new_id
@@ -162,7 +178,9 @@ class crm_phonecall(crm_base, osv.osv):
return partner_id
def _call_set_partner(self, cr, uid, ids, partner_id, context=None):
- return self.write(cr, uid, ids, {'partner_id' : partner_id}, context=context)
+ write_res = self.write(cr, uid, ids, {'partner_id' : partner_id}, context=context)
+ self._call_set_partner_send_note(cr, uid, ids, context)
+ return write_res
def _call_create_partner_address(self, cr, uid, phonecall, partner_id, context=None):
address = self.pool.get('res.partner')
@@ -231,7 +249,7 @@ class crm_phonecall(crm_base, osv.osv):
'section_id': call.section_id and call.section_id.id or False,
'description': call.description or False,
'priority': call.priority,
- 'type': 'opportunity',
+ 'type': 'opportunity',
'phone': call.partner_phone or False,
'email_from': default_contact and default_contact.email,
})
@@ -243,7 +261,7 @@ class crm_phonecall(crm_base, osv.osv):
self.case_close(cr, uid, [call.id])
opportunity.case_open(cr, uid, [opportunity_id])
opportunity_dict[call.id] = opportunity_id
- return opportunity_dict
+ return opportunity_dict
def action_make_meeting(self, cr, uid, ids, context=None):
"""
@@ -289,6 +307,41 @@ class crm_phonecall(crm_base, osv.osv):
}
return value
+
+ # ----------------------------------------
+ # OpenChatter methods and notifications
+ # ----------------------------------------
+
+ def get_needaction_user_ids(self, cr, uid, ids, context=None):
+ result = dict.fromkeys(ids)
+ for obj in self.browse(cr, uid, ids, context=context):
+ result[obj.id] = []
+ if (obj.state == 'draft' and obj.user_id):
+ result[obj.id] = [obj.user_id.id]
+ return result
+
+ def case_get_note_msg_prefix(self, cr, uid, id, context=None):
+ return 'Phonecall'
+
+ def case_reset_send_note(self, cr, uid, ids, context=None):
+ message = _('Phonecall has been reset and set as open.')
+ return self.message_append_note(cr, uid, ids, body=message, context=context)
+
+ def case_open_send_note(self, cr, uid, ids, context=None):
+ lead_obj = self.pool.get('crm.lead')
+ for phonecall in self.browse(cr, uid, ids, context=context):
+ phonecall.message_subscribe([phonecall.user_id.id], context=context)
+ if phonecall.opportunity_id:
+ lead = phonecall.opportunity_id
+ message = _("Phonecall linked to the opportunity %s has been created and scheduled on %s.") % (lead.name, phonecall.date)
+ else:
+ message = _("Phonecall has been created and opened.")
+ phonecall.message_append_note(body=message)
+ return True
+
+ def _call_set_partner_send_note(self, cr, uid, ids, context=None):
+ return self.message_append_note(cr, uid, ids, body=_("Partner has been created"), context=context)
+
crm_phonecall()
diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml
index 74a6a7ec6aa..ae0e0ce7f3c 100644
--- a/addons/crm/crm_phonecall_view.xml
+++ b/addons/crm/crm_phonecall_view.xml
@@ -120,6 +120,7 @@
states="cancel" type="object"
icon="gtk-convert" />
+
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py
index 32562501901..9673ba5e430 100644
--- a/addons/crm_claim/crm_claim.py
+++ b/addons/crm_claim/crm_claim.py
@@ -95,6 +95,9 @@ class crm_claim(crm.crm_case, osv.osv):
'active': lambda *a: 1
}
+ def case_get_note_msg_prefix(self, cr, uid, id, context=None):
+ return 'Claim'
+
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
diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py
index 371565872b2..48ac8cb8c7b 100644
--- a/addons/mail/mail_message.py
+++ b/addons/mail/mail_message.py
@@ -304,6 +304,7 @@ class mail_message(osv.osv):
'headers': headers, # serialize the dict on the fly
'mail_server_id': mail_server_id,
'state': 'outgoing',
+ 'type': 'email',
'auto_delete': auto_delete
}
email_msg_id = self.create(cr, uid, msg_vals, context)
diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml
index 1823abb96b1..7730f9a148e 100644
--- a/addons/mail/mail_thread_view.xml
+++ b/addons/mail/mail_thread_view.xml
@@ -23,6 +23,5 @@
-
diff --git a/addons/sale_crm/wizard/crm_make_sale.py b/addons/sale_crm/wizard/crm_make_sale.py
index fe79815fbee..3923336eb5b 100644
--- a/addons/sale_crm/wizard/crm_make_sale.py
+++ b/addons/sale_crm/wizard/crm_make_sale.py
@@ -105,9 +105,8 @@ class crm_make_sale(osv.osv_memory):
sale_order = sale_obj.browse(cr, uid, new_id, context=context)
case_obj.write(cr, uid, [case.id], {'ref': 'sale.order,%s' % new_id})
new_ids.append(new_id)
- message = _("Opportunity '%s' is converted to Quotation.") % (case.name)
- self.log(cr, uid, case.id, message)
- case_obj.message_append(cr, uid, [case], _("Converted to Sales Quotation(%s).") % (sale_order.name), context=context)
+ message = _("Opportunity has been converted to the quotation %s.") % (sale_order.name)
+ case.message_append_note(body=message)
if make.close:
case_obj.case_close(cr, uid, data)