[FIX] mail.message: all recipients explicitly mentioned should receive a notification...
[odoo/odoo.git] / addons / mail / mail_message.py
index 2751e33..562a48f 100644 (file)
@@ -20,7 +20,7 @@
 ##############################################################################
 
 import logging
-import tools
+from openerp import tools
 
 from email.header import decode_header
 from openerp import SUPERUSER_ID
@@ -76,7 +76,7 @@ class mail_message(osv.Model):
         # TDE note: regroup by model/ids, to have less queries to perform
         result = dict.fromkeys(ids, False)
         for message in self.read(cr, uid, ids, ['model', 'res_id'], context=context):
-            if not message.get('model') or not message.get('res_id'):
+            if not message.get('model') or not message.get('res_id') or not self.pool.get(message['model']):
                 continue
             result[message['id']] = self._shorten_name(self.pool.get(message['model']).name_get(cr, SUPERUSER_ID, [message['res_id']], context=context)[0][1])
         return result
@@ -303,12 +303,11 @@ class mail_message(osv.Model):
                 partner_ids |= set([partner.id for partner in message.partner_ids])
             if message.attachment_ids:
                 attachment_ids |= set([attachment.id for attachment in message.attachment_ids])
-
-        # Filter author_ids uid can see
+        # Read partners as SUPERUSER -> display the names like classic m2o even if no access
         partners = res_partner_obj.name_get(cr, SUPERUSER_ID, list(partner_ids), context=context)
         partner_tree = dict((partner[0], partner) for partner in partners)
 
-        # 2. Attachments
+        # 2. Attachments as SUPERUSER, because could receive msg and attachments for doc uid cannot see
         attachments = ir_attachment_obj.read(cr, SUPERUSER_ID, list(attachment_ids), ['id', 'datas_fname'], context=context)
         attachments_tree = dict((attachment['id'], {'id': attachment['id'], 'filename': attachment['datas_fname']}) for attachment in attachments)
 
@@ -549,6 +548,20 @@ class mail_message(osv.Model):
         if not cr.fetchone():
             cr.execute("""CREATE INDEX mail_message_model_res_id_idx ON mail_message (model, res_id)""")
 
+    def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None):
+        doc_ids = doc_dict.keys()
+        allowed_doc_ids = self.pool.get(doc_model).search(cr, uid, [('id', 'in', doc_ids)], context=context)
+        return set([message_id for allowed_doc_id in allowed_doc_ids for message_id in doc_dict[allowed_doc_id]])
+
+    def _find_allowed_doc_ids(self, cr, uid, model_ids, context=None):
+        model_access_obj = self.pool.get('ir.model.access')
+        allowed_ids = set()
+        for doc_model, doc_dict in model_ids.iteritems():
+            if not model_access_obj.check(cr, uid, doc_model, 'read', False):
+                continue
+            allowed_ids |= self._find_allowed_model_wise(cr, uid, doc_model, doc_dict, context=context)
+        return allowed_ids
+
     def _search(self, cr, uid, args, offset=0, limit=None, order=None,
         context=None, count=False, access_rights_uid=None):
         """ Override that adds specific access rights of mail.message, to remove
@@ -586,13 +599,7 @@ class mail_message(osv.Model):
             elif message.get('model') and message.get('res_id'):
                 model_ids.setdefault(message.get('model'), {}).setdefault(message.get('res_id'), set()).add(message.get('id'))
 
-        model_access_obj = self.pool.get('ir.model.access')
-        for doc_model, doc_dict in model_ids.iteritems():
-            if not model_access_obj.check(cr, uid, doc_model, 'read', False):
-                continue
-            doc_ids = doc_dict.keys()
-            allowed_doc_ids = self.pool.get(doc_model).search(cr, uid, [('id', 'in', doc_ids)], context=context)
-            allowed_ids |= set([message_id for allowed_doc_id in allowed_doc_ids for message_id in doc_dict[allowed_doc_id]])
+        allowed_ids = self._find_allowed_doc_ids(cr, uid, model_ids, context=context)
 
         final_ids = author_ids | partner_ids | allowed_ids
         if count:
@@ -842,12 +849,10 @@ class mail_message(osv.Model):
         # message has no subtype_id: pure log message -> no partners, no one notified
         if not message.subtype_id:
             return True
-        # all partner_ids of the mail.message have to be notified
-        if message.partner_ids:
-            partners_to_notify |= set(message.partner_ids)
         # all followers of the mail.message document have to be added as partners and notified
         if message.model and message.res_id:
             fol_obj = self.pool.get("mail.followers")
+            # browse as SUPERUSER because rules could restrict the search results
             fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
                 ('res_model', '=', message.model),
                 ('res_id', '=', message.res_id),
@@ -858,20 +863,23 @@ class mail_message(osv.Model):
         if message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
             partners_to_notify |= set([message.author_id])
         elif message.author_id:
-            partners_to_notify = partners_to_notify - set([message.author_id])
+            partners_to_notify -= set([message.author_id])
 
+        # all partner_ids of the mail.message have to be notified regardless of the above (even the author if explicitly added!)
+        if message.partner_ids:
+            partners_to_notify |= set(message.partner_ids)
+
+        # notify
         if partners_to_notify:
             self.write(cr, SUPERUSER_ID, [newid], {'notified_partner_ids': [(4, p.id) for p in partners_to_notify]}, context=context)
-
         notification_obj._notify(cr, uid, newid, context=context)
+        message.refresh()
 
-        # An error appear when a user receive a notify to a message without notify to his parent message.
-        # Add a notification with read = true to the parented message if there are no notification
+        # An error appear when a user receive a notification without notifying
+        # the parent message -> add a read notification for the parent
         if message.parent_id:
             # all notified_partner_ids of the mail.message have to be notified for the parented messages
-            if message.notified_partner_ids:
-                partners_to_notify |= set(message.notified_partner_ids)
-            partners_to_parent_notify = set(partners_to_notify) - set(message.parent_id.notified_partner_ids)
+            partners_to_parent_notify = set(message.notified_partner_ids).difference(message.parent_id.notified_partner_ids)
             for partner in partners_to_parent_notify:
                 notification_obj.create(cr, uid, {
                         'message_id': message.parent_id.id,