diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index b13874b0c58..308fc25e4fe 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -262,11 +262,10 @@ class crm_lead(base_stage, osv.osv):
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:
+ if obj.message_thread_read == False 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)
@@ -756,64 +755,6 @@ class crm_lead(base_stage, osv.osv):
'type': 'ir.actions.act_window',
}
-
- def message_new(self, cr, uid, msg, custom_values=None, context=None):
- """Automatically calls when new email message arrives"""
- res_id = super(crm_lead, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
- subject = msg.get('subject') or _("No Subject")
- body = msg.get('body_text')
-
- msg_from = msg.get('from')
- priority = msg.get('priority')
- vals = {
- 'name': subject,
- 'email_from': msg_from,
- 'email_cc': msg.get('cc'),
- 'description': body,
- 'user_id': False,
- }
- if priority:
- vals['priority'] = priority
- vals.update(self.message_partner_by_email(cr, uid, msg.get('from', False)))
- self.write(cr, uid, [res_id], vals, context)
- return res_id
-
- def message_update(self, cr, uid, ids, msg, vals=None, default_act='pending', context=None):
- if isinstance(ids, (str, int, long)):
- ids = [ids]
- if vals == None:
- vals = {}
- super(crm_lead, self).message_update(cr, uid, ids, msg, context=context)
-
- if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
- vals['priority'] = msg.get('priority')
- maps = {
- 'cost':'planned_cost',
- 'revenue': 'planned_revenue',
- 'probability':'probability'
- }
- vls = {}
- for line in msg['body_text'].split('\n'):
- line = line.strip()
- res = tools.misc.command_re.match(line)
- if res and maps.get(res.group(1).lower()):
- key = maps.get(res.group(1).lower())
- vls[key] = res.group(2).lower()
- vals.update(vls)
-
- # Unfortunately the API is based on lists
- # but we want to update the state based on the
- # previous state, so we have to loop:
- for case in self.browse(cr, uid, ids, context=context):
- values = dict(vals)
- if case.state in CRM_LEAD_PENDING_STATES:
- #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)
- res = self.write(cr, uid, [case.id], values, context=context)
- return res
-
def action_makeMeeting(self, cr, uid, ids, context=None):
"""
This opens Meeting's calendar view to schedule meeting on current Opportunity
@@ -868,18 +809,66 @@ class crm_lead(base_stage, osv.osv):
if stage.on_change:
vals['probability'] = stage.probability
return super(crm_lead,self).write(cr, uid, ids, vals, context)
-
+
+ # ----------------------------------------
+ # Mail Gateway
+ # ----------------------------------------
+
+ def message_new(self, cr, uid, msg, custom_values=None, context=None):
+ """ Overrides mail_thread message_new that is called by the mailgateway
+ through message_process.
+ This override updates the document according to the email.
+ """
+ if custom_values is None: custom_values = {}
+ custom_values.update({
+ 'name': msg.get('subject') or _("No Subject"),
+ 'description': msg.get('body_text'),
+ 'email_from': msg.get('from'),
+ 'email_cc': msg.get('cc'),
+ 'user_id': False,
+ })
+ if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
+ custom_values['priority'] = msg.get('priority')
+ custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from', False), context=context))
+ return super(crm_lead, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
+
+ def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
+ """ Overrides mail_thread message_update that is called by the mailgateway
+ through message_process.
+ This method updates the document according to the email.
+ """
+ if isinstance(ids, (str, int, long)):
+ ids = [ids]
+ if update_vals is None: update_vals = {}
+
+ if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
+ vals['priority'] = msg.get('priority')
+ maps = {
+ 'cost':'planned_cost',
+ 'revenue': 'planned_revenue',
+ 'probability':'probability',
+ }
+ for line in msg.get('body_text', '').split('\n'):
+ line = line.strip()
+ res = tools.misc.command_re.match(line)
+ if res and maps.get(res.group(1).lower()):
+ key = maps.get(res.group(1).lower())
+ vals[key] = res.group(2).lower()
+
+ return super(crm_lead, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
+
# ----------------------------------------
# OpenChatter methods and notifications
# ----------------------------------------
- def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
- user_ids = super(crm_lead, self).message_get_subscribers(cr, uid, ids, True, context=context)
+ def message_get_subscribers(self, cr, uid, ids, context=None):
+ """ Override to add the salesman. """
+ user_ids = super(crm_lead, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
- self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
- return super(crm_lead, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
-
+ user_ids.append(obj.user_id.id)
+ return user_ids
+
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
stage_name = self.pool.get('crm.case.stage').name_get(cr, uid, [stage_id], context=context)[0][1]
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index f99b29a9a17..7c9b04db562 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -70,11 +70,17 @@
states="cancel"/>
+
+
+
+
0)
+ if sub_user_id in self.message_get_subscribers(cr, uid, ids, context=context):
+ return True
+ return False
def message_subscribe(self, cr, uid, ids, user_ids = None, context=None):
+ """ Subscribe the user (or user_ids) to the current document.
+
+ :param user_ids: a list of user_ids; if not set, subscribe
+ uid instead
+ """
subscription_obj = self.pool.get('mail.subscription')
to_subscribe_uids = [uid] if user_ids is None else user_ids
create_ids = []
for id in ids:
+ already_subscribed_user_ids = self.message_get_subscribers(cr, uid, [id], context=context)
for user_id in to_subscribe_uids:
- if self.message_is_subscriber(cr, uid, [id], user_id=user_id, context=context): continue
+ if user_id in already_subscribed_user_ids: continue
create_ids.append(subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context))
return create_ids
def message_unsubscribe(self, cr, uid, ids, user_ids = None, context=None):
- if not user_ids and not uid in self.message_get_subscribers(cr, uid, ids, True, context=context):
+ """ Unsubscribe the user (or user_ids) from the current document.
+
+ :param user_ids: a list of user_ids; if not set, subscribe
+ uid instead
+ """
+ # Trying to unsubscribe somebody not in subscribers: returns False
+ # if special management is needed; allows to know that an automatically
+ # subscribed user tries to unsubscribe and allows to warn him
+ if not user_ids and not uid in self.message_get_subscribers(cr, uid, ids, context=context):
return False
subscription_obj = self.pool.get('mail.subscription')
to_unsubscribe_uids = [uid] if user_ids is None else user_ids
to_delete_sub_ids = subscription_obj.search(cr, uid,
['&', '&', ('res_model', '=', self._name), ('res_id', 'in', ids), ('user_id', 'in', to_unsubscribe_uids)], context=context)
- subscription_obj.unlink(cr, uid, to_delete_sub_ids, context=context)
- return True
+ return subscription_obj.unlink(cr, uid, to_delete_sub_ids, context=context)
def message_subscription_hide(self, cr, uid, ids, subtype=None, context=None):
"""Hide notifications, allowing to tune the messages displayed on
@@ -936,4 +974,15 @@ class mail_thread(osv.osv):
to_del_notif_ids = notif_obj.search(cr, uid, ['&', ('user_id', '=', uid), ('message_id', 'in', notif_msg_ids)], context=context)
return notif_obj.unlink(cr, uid, to_del_notif_ids, context=context)
+ #------------------------------------------------------
+ # Thread_state
+ #------------------------------------------------------
+
+ def message_mark_as_read(self, cr, uid, ids, context=None):
+ return self.write(cr, uid, ids, {'message_thread_read': True}, context=context)
+
+ def message_mark_as_unread(self, cr, uid, ids, context=None):
+ return self.write(cr, uid, ids, {'message_thread_read': False}, context=context)
+
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index 1a80ef1ae83..bef94955047 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -474,7 +474,7 @@ openerp.mail = function(session) {
},
fetch_subscribers: function () {
- return this.ds.call('message_get_subscribers', [[this.view.datarecord.id]]).then(this.proxy('display_subscribers'));
+ return this.ds.call('message_read_subscribers', [[this.view.datarecord.id]]).then(this.proxy('display_subscribers'));
},
display_subscribers: function (records) {
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py
index 64110990b6b..dd883bf5cca 100644
--- a/addons/mrp/mrp.py
+++ b/addons/mrp/mrp.py
@@ -1041,12 +1041,13 @@ class mrp_production(osv.osv):
result[obj.id] = [obj.user_id.id]
return result
- def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
- user_ids = super(mrp_production, self).message_get_subscribers(cr, uid, ids, True, context=context)
+ def message_get_subscribers(self, cr, uid, ids, context=None):
+ """ Override to add responsible user. """
+ user_ids = super(mrp_production, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
- self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
- return super(mrp_production, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
+ user_ids.append(obj.user_id.id)
+ return user_ids
def create_send_note(self, cr, uid, ids, context=None):
self.message_append_note(cr, uid, ids, body=_("Manufacturing order has been created."), context=context)
diff --git a/addons/project/project.py b/addons/project/project.py
index f85efb58716..804b725e6fa 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -474,12 +474,13 @@ def Project():
result[obj.id] = [obj.user_id.id]
return result
- def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
- user_ids = super(project, self).message_get_subscribers(cr, uid, ids, True, context=context)
+ def message_get_subscribers(self, cr, uid, ids, context=None):
+ """ Override to add responsible user. """
+ user_ids = super(project, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
- self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
- return super(project, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
+ user_ids.append(obj.user_id.id)
+ return user_ids
def create(self, cr, uid, vals, context=None):
obj_id = super(project, self).create(cr, uid, vals, context=context)
@@ -1151,14 +1152,15 @@ class task(base_stage, osv.osv):
result[obj.id] = [obj.user_id.id]
return result
- def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
- user_ids = super(task, self).message_get_subscribers(cr, uid, ids, True, context=context)
+ def message_get_subscribers(self, cr, uid, ids, context=None):
+ """ Override to add responsible user and project manager. """
+ user_ids = super(task, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
- self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
+ user_ids.append(obj.user_id.id)
if obj.manager_id and not obj.manager_id.id in user_ids:
- self.message_subscribe(cr, uid, [obj.id], [obj.manager_id.id], context=context)
- return super(task, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
+ user_ids.append(obj.manager_id.id)
+ return user_ids
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py
index 21ec79fe097..4996221aca5 100644
--- a/addons/project_issue/project_issue.py
+++ b/addons/project_issue/project_issue.py
@@ -467,69 +467,56 @@ class project_issue(base_stage, osv.osv):
# -------------------------------------------------------
def message_new(self, cr, uid, msg, custom_values=None, context=None):
- """Automatically called when new email message arrives"""
- if context is None:
- context = {}
- subject = msg.get('subject') or _('No Title')
- body = msg.get('body_text')
- msg_from = msg.get('from')
- priority = msg.get('priority')
- vals = {
- 'name': subject,
- 'email_from': msg_from,
+ """ Overrides mail_thread message_new that is called by the mailgateway
+ through message_process.
+ This override updates the document according to the email.
+ """
+ if custom_values is None: custom_values = {}
+ if context is None: context = {}
+ context['state_to'] = 'draft'
+
+ custom_values.update({
+ 'name': msg.get('subject') or _("No Subject"),
+ 'description': msg.get('body_text'),
+ 'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
- 'description': body,
'user_id': False,
- }
- if priority:
- vals['priority'] = priority
- vals.update(self.message_partner_by_email(cr, uid, msg_from))
- context.update({'state_to' : 'draft'})
+ })
+ if msg.get('priority'):
+ custom_values['priority'] = msg.get('priority')
+ custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from'), context=context))
- if custom_values and isinstance(custom_values, dict):
- vals.update(custom_values)
-
- res_id = self.create(cr, uid, vals, context)
- self.message_append_dict(cr, uid, [res_id], msg, context=context)
+ res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
self.convert_to_bug(cr, uid, [res_id], context=context)
return res_id
- def message_update(self, cr, uid, ids, msg, vals=None, default_act='pending', context=None):
- if vals is None:
- vals = {}
-
+ def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
+ """ Overrides mail_thread message_update that is called by the mailgateway
+ through message_process.
+ This method updates the document according to the email.
+ """
if isinstance(ids, (str, int, long)):
ids = [ids]
+ if update_vals is None: update_vals = {}
- vals.update({
- 'description': msg['body_text']
- })
- if msg.get('priority', False):
- vals['priority'] = msg.get('priority')
-
+ # Update doc values according to the message
+ update_vals['description'] = msg.get('body_text', '')
+ if msg.get('priority'):
+ update_vals['priority'] = msg.get('priority')
+ # Parse 'body_text' to find values to update
maps = {
'cost': 'planned_cost',
'revenue': 'planned_revenue',
- 'probability': 'probability'
+ 'probability': 'probability',
}
-
- # Reassign the 'open' state to the case if this one is in pending or done
- for record in self.browse(cr, uid, ids, context=context):
- if record.state in ('pending', 'done'):
- self.case_set(cr, uid, ids, 'open', {}, context=context)
-
- vls = { }
- for line in msg['body_text'].split('\n'):
+ for line in msg.get('body_text', '').split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
- vls[key] = res.group(2).lower()
+ update_vals[key] = res.group(2).lower()
- vals.update(vls)
- res = self.write(cr, uid, ids, vals)
- self.message_append_dict(cr, uid, ids, msg, context=context)
- return res
+ return super(project_issue, self).message_update(cr, uid, ids, update_vals=update_vals, context=context)
# -------------------------------------------------------
# OpenChatter methods and notifications
@@ -542,12 +529,18 @@ class project_issue(base_stage, osv.osv):
result[obj.id] = [obj.user_id.id]
return result
- def message_get_subscribers(self, cr, uid, ids, get_ids=False, context=None):
- user_ids = super(project_issue, self).message_get_subscribers(cr, uid, ids, True, context=context)
+ def message_get_subscribers(self, cr, uid, ids, context=None):
+ """ Override to add responsible user. """
+ user_ids = super(project_issue, self).message_get_subscribers(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
if obj.user_id and not obj.user_id.id in user_ids:
- self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
- return super(project_issue, self).message_get_subscribers(cr, uid, ids, get_ids, context=context)
+ user_ids.append(obj.user_id.id)
+ return user_ids
+
+ def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
+ """ Override of the (void) default notification method. """
+ stage_name = self.pool.get('project.task.type').name_get(cr, uid, [stage_id], context=context)[0][1]
+ return self.message_append_note(cr, uid, ids, body= _("Stage changed to %s.") % (stage_name), context=context)
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
""" Override of default prefix for notifications. """
diff --git a/addons/project_mailgate/project_mailgate.py b/addons/project_mailgate/project_mailgate.py
index a36366f450e..0ca2687b7f0 100644
--- a/addons/project_mailgate/project_mailgate.py
+++ b/addons/project_mailgate/project_mailgate.py
@@ -19,30 +19,35 @@
#
##############################################################################
+import binascii
from osv import fields, osv
from tools.translate import _
import tools
-import binascii
-
class project_tasks(osv.osv):
_inherit = 'project.task'
def message_new(self, cr, uid, msg, custom_values=None, context=None):
- res_id = super(project_tasks,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
- subject = msg.get('subject')
- msg_from = msg.get('from')
- data = {
+ """ Overrides mail_thread message_new that is called by the mailgateway
+ through message_process.
+ This override updates the document according to the email.
+ """
+ if custom_values is None: custom_values = {}
+ custom_values.update({
'name': subject,
'planned_hours': 0.0,
- }
- data.update(self.message_partner_by_email(cr, uid, msg_from))
- self.write(cr, uid, [res_id], data, context)
- return res_id
-
- def message_update(self, cr, uid, ids, msg, data={}, default_act='pending'):
- act = 'do_'+default_act
+ 'subject': msg.get('subject'),
+ })
+ custom_values.update(self.message_partner_by_email(cr, uid, msg.get('from', False), context=context))
+ return super(project_tasks,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
+ def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
+ """ Overrides mail_thread message_update that is called by the mailgateway
+ through message_process.
+ This method updates the task according to the email.
+ """
+ if update_vals is None: update_vals = {}
+ act = False
maps = {
'cost':'planned_hours',
}
@@ -54,17 +59,15 @@ class project_tasks(osv.osv):
field = maps.get(match)
if field:
try:
- data[field] = float(res.group(2).lower())
+ update_vals[field] = float(res.group(2).lower())
except (ValueError, TypeError):
pass
elif match.lower() == 'state' \
and res.group(2).lower() in ['cancel','close','draft','open','pending']:
act = 'do_%s' % res.group(2).lower()
-
- self.write(cr, uid, ids, data, context=context)
- getattr(self,act)(cr, uid, ids, context=context)
- self.message_append_note(cr, uid, [res_id], body=msg, context=context)
- return True
+ if act:
+ getattr(self,act)(cr, uid, ids, context=context)
+ return super(project_tasks,self).message_update(cr, uid, msg, update_vals=update_vals, context=context)
def message_thread_followers(self, cr, uid, ids, context=None):
followers = super(project_tasks,self).message_thread_followers(cr, uid, ids, context=context)
@@ -74,5 +77,5 @@ class project_tasks(osv.osv):
followers[task.id] = filter(None, task_followers)
return followers
-project_tasks()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index 6c69dd38a75..c1f81cf521d 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -135,6 +135,7 @@
+
@@ -211,23 +212,17 @@
-
+
+
+
-
-
+
diff --git a/addons/sale_margin/sale_margin_view.xml b/addons/sale_margin/sale_margin_view.xml
index a0b8f39565c..ad0b8440f19 100644
--- a/addons/sale_margin/sale_margin_view.xml
+++ b/addons/sale_margin/sale_margin_view.xml
@@ -8,11 +8,9 @@
sale.order
-
-
-
-
-
+
+
+