diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index bd74e5eb0d0..9af688be533 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -119,74 +119,67 @@ class mail_message(osv.Model): # Message loading for web interface #------------------------------------------------------ - _limit = 3 - def _message_dict_get(self, cr, uid, msg, context={}): - attachs = self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context) - author = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0] - # TDE: need user to show 'delete' link -> necessary ? - author_user = self.pool.get('res.users').name_get(cr, uid, [x.id for x in msg.author_id.user_ids], context=context)[0] + def _message_dict_get(self, cr, uid, msg, context=None): + """ Return a dict representation of the message browse record. """ + attachment_ids = self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context) + author_id = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0] + author_user_id = self.pool.get('res.users').name_get(cr, uid, [msg.author_id.user_ids[0].id], context=context)[0] partner_ids = self.pool.get('res.partner').name_get(cr, uid, [x.id for x in msg.partner_ids], context=context) return { 'id': msg.id, 'type': msg.type, - 'attachment_ids': attachs, + 'attachment_ids': attachment_ids, 'body': msg.body, 'model': msg.model, 'res_id': msg.res_id, 'record_name': msg.record_name, 'subject': msg.subject, 'date': msg.date, - 'author_id': author, - 'author_user_id': author_user, + 'author_id': author_id, + 'author_user_id': author_user_id, 'partner_ids': partner_ids, - 'child_ids': [] + 'child_ids': [], } - def message_read(self, cr, uid, ids=False, domain=[], thread_level=0, context=None): - """ - If IDS are provided, fetch these records, otherwise use the domain to - fetch the matching records. After having fetched the records provided - by IDS, it will fetch children (according to thread_level). - - Return [ - - ] + def message_read_tree_get(self, cr, uid, messages, flat=True, context=None): + """ Get a tree representation of the browse records. + :param messages: mail.message browse record list """ - context = context or {} - if ids is False: - ids = self.search(cr, uid, domain, context=context, limit=10) - - # FP Todo: flatten to max X level of mail_thread - messages = self.browse(cr, uid, ids, context=context) - - result = [] + roots = [] tree = {} # key: ID, value: record for msg in messages: - if len(result)<(self._limit-1): - record = self._message_dict_get(cr, uid, msg, context=context) - if thread_level and msg.parent_id: - while msg.parent_id: - if msg.parent_id.id in tree: - record_parent = tree[msg.parent_id.id] - else: - record_parent = self._message_dict_get(cr, uid, msg.parent_id, context=context) - if msg.parent_id.parent_id: - tree[msg.parent_id.id] = record_parent - record_parent['child_ids'].append(record) - record = record_parent - msg = msg.parent_id - if msg.id not in tree: - result.append(record) - tree[msg.id] = record - else: - result.append({ - 'type': 'expandable', - 'domain': [('id','<=', msg.id)]+domain, - 'context': context, - 'thread_level': thread_level # should be improve accodting to level of records - }) - break - return result + record = self._message_dict_get(cr, uid, msg, context=context) + if not flat and msg.parent_id: + while msg.parent_id: + if msg.parent_id.id in tree: + record_parent = tree[msg.parent_id.id] + else: + record_parent = self._message_dict_get(cr, uid, msg.parent_id, context=context) + if msg.parent_id.parent_id: + tree[msg.parent_id.id] = record_parent + record_parent['child_ids'].append(record) + record = record_parent + msg = msg.parent_id + if msg.id not in tree: + roots.append(record) + tree[msg.id] = record + return roots + + def message_read(self, cr, uid, ids=False, domain=[], thread_level=0, limit=None, context=None): + """ Fetch and read messages. If IDs are provided, fetch these records. + Otherwise use the domain to fetch the matching records. After having + fetched the records provided by IDS, it will fetch children + according to thread_level. + + :return result: A tree structure: list of msg_dict, with child_ids + being also msg_dict. + """ + limit = limit or self._message_read_limit + if ids is False: + ids = self.search(cr, uid, domain, context=context, limit=limit) + messages = self.browse(cr, uid, ids, context=context) + # FP note - TDE note: TODO: flatten - order + return self.message_read_tree_get(cr, uid, messages, thread_level>0, context=context) #------------------------------------------------------ diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py index 29db0bc529e..61181832579 100644 --- a/addons/mail/tests/test_mail.py +++ b/addons/mail/tests/test_mail.py @@ -234,6 +234,39 @@ class test_mail(common.TransactionCase): self.assertTrue(all(id in follower_ids for id in [user_admin.partner_id.id]), 'Admin the only Pigs group followers') + def test_03_message_read(self): + """ Tests designed for message_read. """ + def _flatten(read_dict): + res = [] + for val in read_dict: + current = {'_id': val['id']} + if val.get('child_ids'): + current['child_ids'] = _flatten(val.get('child_ids')) + res.append(current) + return res + + # TDE NOTE: this test is not finished, as the message_read method is not fully specified. + # It wil be updated as soon as we have fixed specs ! + cr, uid = self.cr, self.uid + group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) + + # Add a few messages to pigs group + msgid1 = group_pigs.message_post(body='My Body', subject='1', parent_id=False) + msgid2 = group_pigs.message_post(body='My Body', subject='1-1', parent_id=msgid1) + msgid3 = group_pigs.message_post(body='My Body', subject='1-2', parent_id=msgid1) + msgid4 = group_pigs.message_post(body='My Body', subject='2', parent_id=False) + msgid5 = group_pigs.message_post(body='My Body', subject='1-1-1', parent_id=msgid2) + msgid6 = group_pigs.message_post(body='My Body', subject='2-1', parent_id=msgid4) + msgid7 = group_pigs.message_post(body='My Body', subject='1-3', parent_id=msgid1) + msgid8 = group_pigs.message_post(body='My Body', subject='1-3-1', parent_id=msgid7) + + # First try: read flat + first_try_ids = [msgid8, msgid7, msgid6, msgid5, msgid4, msgid3, msgid2, msgid1] + res = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], thread_level=0) + + # Second try: read with thread_level 1 + res = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], thread_level=1) + def test_10_mail_composer(self): """ Tests designed for the mail.compose.message wizard. """ cr, uid = self.cr, self.uid @@ -296,14 +329,12 @@ class test_mail(common.TransactionCase): self.assertTrue(all(email in mail_emails for email in expected_emails) and len(mail_emails) == 2, 'Send email emails are %s; should be %s' % (mail_emails, expected_emails)) - # Create a reply to the last comment, with default partners + # Create a reply to the last comment compose_id = mail_compose.create(cr, uid, {}, {'mail.compose.message.mode': 'reply', 'default_model': 'mail.thread', 'default_res_id': self.group_pigs_id, 'active_id': first_com.id}) compose = mail_compose.browse(cr, uid, compose_id) self.assertTrue(compose.model == 'mail.group' and compose.res_id == self.group_pigs_id, 'Wizard message has model: %s and res_id:%s; should be mail.group and %s' % (compose.model, compose.res_id, self.group_pigs_id)) - self.assertTrue(compose.parent_id.id == first_com.id and len(compose.partner_ids) == 5, - 'Wizard parent_id is %d; should be %d; or wrong partner_ids (TO BE CONTINUED)' % (compose.parent_id.id, first_com.id)) - - \ No newline at end of file + self.assertTrue(compose.parent_id.id == first_com.id, + 'Wizard parent_id is %d; should be %d' % (compose.parent_id.id, first_com.id))