self.assertEqual(message_pigs.body, _body_html1, 'mail.message body on Pigs incorrect')
self.assertEqual(message_bird.body, _body_html2, 'mail.message body on Bird incorrect')
# Test: partner_ids: p_a_id (default) + 3 newly created partners
- message_pigs_pids = [partner.id for partner in message_pigs.partner_ids]
- message_bird_pids = [partner.id for partner in message_bird.partner_ids]
+ message_pigs_pids = [partner.id for partner in message_pigs.notified_partner_ids]
+ message_bird_pids = [partner.id for partner in message_bird.notified_partner_ids]
partner_ids = self.res_partner.search(cr, uid, [('email', 'in', ['b@b.b', 'c@c.c', 'd@d.d'])])
- self.assertEqual(len(message_pigs_pids), len(partner_ids), 'mail.message on pigs incorrect number of partner_ids')
- self.assertEqual(set(message_pigs_pids), set(partner_ids), 'mail.message on pigs incorrect number of partner_ids')
-
- self.assertEqual(len(message_bird_pids), len(partner_ids), 'mail.message on bird partner_ids incorrect')
- self.assertEqual(set(message_bird_pids), set(partner_ids), 'mail.message on bird partner_ids incorrect')
+ self.assertEqual(set(message_pigs_pids), set(partner_ids), 'mail.message on pigs incorrect number of notified_partner_ids')
+ self.assertEqual(set(message_bird_pids), set(partner_ids), 'mail.message on bird notified_partner_ids incorrect')
], 'Type',
help="Message type: email for email message, notification for system "\
"message, comment for other messages such as user replies"),
- 'author_id': fields.many2one('res.partner', 'Author', required=True),
- 'partner_ids': fields.many2many('res.partner', 'mail_notification', 'message_id', 'partner_id', 'Recipients'),
+ 'from': fields.char('From',
+ help="Email address of the sender, to use if it does not match any partner."),
+ 'author_id': fields.many2one('res.partner', 'Author',
+ help="Partner that did write the message. If not set, try to use the From field instead."),
+ 'partner_ids': fields.many2many('res.partner', string='Recipients'),
+ 'notified_partner_ids': fields.many2many('res.partner', 'mail_notification',
+ 'message_id', 'partner_id', 'Recipients'),
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel',
'message_id', 'attachment_id', 'Attachments'),
'parent_id': fields.many2one('mail.message', 'Parent Message', select=True, ondelete='set null', help="Initial thread message."),
is_author = False
if message['author_id']:
is_author = message['author_id'][0] == self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
+ author_id = message['author_id']
+ elif message['from']:
+ author_id = (0, message['from'])
has_voted = False
if uid in message.get('vote_user_ids'):
if uid in message.get('favorite_user_ids'):
is_favorite = True
- is_private = False
+ is_private = True
if message.get('model') and message.get('res_id'):
- is_private = True
+ is_private = False
try:
attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, message['attachment_ids'], context=context)]
'record_name': message['record_name'],
'subject': message['subject'],
'date': message['date'],
- 'author_id': message['author_id'],
+ 'author_id': author_id,
'is_author': is_author,
- # TDE note: is this useful ? to check
'partner_ids': partner_ids,
'ancestor_id': False,
'vote_nb': len(message['vote_user_ids']),
author_ids, partner_ids, allowed_ids = set([]), set([]), set([])
model_ids = {}
- messages = super(mail_message, self).read(cr, uid, ids, ['author_id', 'model', 'res_id', 'partner_ids'], context=context)
+ messages = super(mail_message, self).read(cr, uid, ids, ['author_id', 'model', 'res_id', 'notified_partner_ids'], context=context)
for message in messages:
if message.get('author_id') and message.get('author_id')[0] == pid:
author_ids.add(message.get('id'))
- elif pid in message.get('partner_ids'):
+ elif pid in message.get('notified_partner_ids'):
partner_ids.add(message.get('id'))
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'))
# Messaging API
#------------------------------------------------------
- def _notify_followers(self, cr, uid, newid, message, context=None):
- """ Add the related record followers to the destination partner_ids.
+ def _notify(self, cr, uid, newid, context=None):
+ """ Add the related record followers to the destination partner_ids if is not a private message.
+ Call mail_notification.notify to manage the email sending
"""
+ message = self.read(cr, uid, newid, ['model', 'res_id', 'author_id', 'subtype_id', 'partner_ids'], context=context)
+
partners_to_notify = set([])
# message has no subtype_id: pure log message -> no partners, no one notified
- if not message.subtype_id:
- message.write({'partner_ids': [5]})
+ if not message.get('subtype_id'):
return True
# all partner_ids of the mail.message have to be notified
- if message.partner_ids:
- partners_to_notify |= set(partner.id for partner in message.partner_ids)
+ if message.get('partner_ids'):
+ partners_to_notify |= set(message.get('partner_ids'))
# all followers of the mail.message document have to be added as partners and notified
- if message.model and message.res_id:
+ if message.get('model') and message.get('res_id'):
fol_obj = self.pool.get("mail.followers")
- fol_ids = fol_obj.search(cr, uid, [('res_model', '=', message.model), ('res_id', '=', message.res_id), ('subtype_ids', 'in', message.subtype_id.id)], context=context)
- fol_objs = fol_obj.browse(cr, uid, fol_ids, context=context)
- extra_notified = set(fol.partner_id.id for fol in fol_objs)
- missing_notified = extra_notified - partners_to_notify
- if missing_notified:
- self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, p_id) for p_id in missing_notified]}, context=context)
-
- def _notify(self, cr, uid, newid, context=None):
- """ Add the related record followers to the destination partner_ids if is not a private message.
- Call mail_notification.notify to manage the email sending
- """
- message = self.browse(cr, uid, newid, context=context)
- if message.model and message.res_id:
- self._notify_followers(cr, uid, newid, message, context=context)
-
+ fol_ids = fol_obj.search(cr, uid, [
+ ('res_model', '=', message.get('model')),
+ ('res_id', '=', message.get('res_id')),
+ ('subtype_ids', 'in', message.get('subtype_id')[0])
+ ], context=context)
+ fol_objs = fol_obj.read(cr, uid, fol_ids, ['partner_id'], context=context)
+ partners_to_notify |= set(fol['partner_id'][0] for fol in fol_objs)
# add myself if I wrote on my wall, otherwise remove myself author
- if ((message.model == "res.partner" and message.res_id == message.author_id.id)):
- self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, message.author_id.id)]}, context=context)
+ if message.get('author_id') and message.get('model') == "res.partner" and message.get('res_id') == message.get('author_id')[0]:
+ partners_to_notify |= set([message.get('author_id')[0]])
else:
- self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(3, message.author_id.id)]}, context=context)
+ partners_to_notify = partners_to_notify - set([message.get('author_id')[0]])
+ if partners_to_notify:
+ self.write(cr, SUPERUSER_ID, [newid], {'notified_partner_ids': [(4, p_id) for p_id in partners_to_notify]}, context=context)
self.pool.get('mail.notification')._notify(cr, uid, newid, context=context)
('file2', 'bytes')}
}
"""
- msg_dict = {}
+ msg_dict = {
+ 'type': 'email',
+ 'subtype': 'mail.mt_comment',
+ }
if not isinstance(message, Message):
if isinstance(message, unicode):
# Warning: message_from_string doesn't always work correctly on unicode,
author_ids = self._message_find_partners(cr, uid, message, ['From'], context=context)
if author_ids:
msg_dict['author_id'] = author_ids[0]
+ else:
+ msg_dict['from'] = message.get('from')
partner_ids = self._message_find_partners(cr, uid, message, ['From', 'To', 'Cc'], context=context)
msg_dict['partner_ids'] = partner_ids
return mail_message.create(cr, uid, values, context=context)
def message_post_api(self, cr, uid, thread_id, body='', subject=False, type='notification',
- subtype=None, parent_id=False, attachment_ids=None, context=None):
+ parent_id=False, attachment_ids=None, context=None):
""" Wrapper on message_post, used only in Chatter (JS). The purpose is
to handle attachments.
# TDE FIXME: body is plaintext: convert it into html
"""
new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=type,
- subtype=subtype, parent_id=parent_id, context=context)
+ subtype='mail.mt_comment', parent_id=parent_id, context=context)
# HACK FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
if attachment_ids:
mail.ChatterUtils.get_text2html(body),
false,
'comment',
- 'mail.mt_comment',
this.context.default_parent_id,
attachments,
this.parent_thread.context
# the html2plaintext uses etree or beautiful soup, so the result may be slighly different
# depending if you have installed beautiful soup.
self.assertIn(sent_email['body_alternative'], _mail_bodyalt1 + '\nBert Tartopoils\n', 'sent_email body_alternative is incorrect')
- # Test: mail_message: partner_ids = group followers
- message_pids = set([partner.id for partner in message.partner_ids])
+ # Test: mail_message: notified_partner_ids = group followers
+ message_pids = set([partner.id for partner in message.notified_partner_ids])
test_pids = set([p_b_id, p_c_id])
self.assertEqual(test_pids, message_pids, 'mail.message partners incorrect')
- # Test: notification linked to this message = group followers = partner_ids
+ # Test: notification linked to this message = group followers = notified_partner_ids
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', message.id)])
notif_pids = set([notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)])
self.assertEqual(notif_pids, test_pids, 'mail.message notification partners incorrect')
self.assertEqual(sent_email['subject'], _mail_subject, 'sent_email subject incorrect')
self.assertIn(_mail_body2, sent_email['body'], 'sent_email body incorrect')
self.assertIn(_mail_bodyalt2, sent_email['body_alternative'], 'sent_email body_alternative incorrect')
- # Test: mail_message: partner_ids = group followers
- message_pids = set([partner.id for partner in message.partner_ids])
+ # Test: mail_message: notified_partner_ids = group followers
+ message_pids = set([partner.id for partner in message.notified_partner_ids])
test_pids = set([p_b_id, p_c_id, p_d_id])
self.assertEqual(message_pids, test_pids, 'mail.message partners incorrect')
- # Test: notifications linked to this message = group followers = partner_ids
+ # Test: notifications linked to this message = group followers = notified_partner_ids
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', message.id)])
notif_pids = set([notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)])
self.assertEqual(notif_pids, test_pids, 'mail.message notification partners incorrect')
# Test: mail.message: subject, body inside pre
self.assertEqual(message.subject, False, 'mail.message incorrect subject')
self.assertEqual(message.body, _msg_body, 'mail.message incorrect body')
- # Test: mail.message: partner_ids = entries in mail.notification: group_pigs fans (a, b) + mail.compose.message partner_ids (c, d)
- msg_pids = [partner.id for partner in message.partner_ids]
+ # Test: mail.message: notified_partner_ids = entries in mail.notification: group_pigs fans (a, b) + mail.compose.message partner_ids (c, d)
+ msg_pids = [partner.id for partner in message.notified_partner_ids]
test_pids = [p_b_id, p_c_id, p_d_id]
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', message.id)])
self.assertEqual(len(notif_ids), 3, 'mail.message: too much notifications created')
- self.assertEqual(set(msg_pids), set(test_pids), 'mail.message partner_ids incorrect')
+ self.assertEqual(set(msg_pids), set(test_pids), 'mail.message notified_partner_ids incorrect')
# ----------------------------------------
# CASE2: reply to last comment with attachments
cr, uid, group_pigs_id = self.cr, self.uid, self.group_pigs_id
partner_bert_id, partner_raoul_id = self.partner_bert_id, self.partner_raoul_id
user_bert_id, user_raoul_id = self.user_bert_id, self.user_raoul_id
+ # Data: comment subtype for mail.message creation
+ ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'mail', 'mt_comment')
+ subtype_id = ref and ref[1] or False
# Data: Birds group, private
group_birds_id = self.mail_group.create(self.cr, self.uid, {'name': 'Birds', 'public': 'private'})
# Data: raoul is member of Pigs
self.mail_group.message_subscribe(cr, uid, [group_pigs_id], [partner_raoul_id])
# Data: various author_ids, partner_ids, documents
- msg_id1 = self.mail_message.create(cr, uid, {'subject': 'Test', 'body': 'A'})
- msg_id2 = self.mail_message.create(cr, uid, {'subject': 'Test', 'body': 'A+B', 'partner_ids': [(6, 0, [partner_bert_id])]})
- msg_id3 = self.mail_message.create(cr, uid, {'subject': 'Test', 'body': 'A Pigs', 'model': 'mail.group', 'res_id': group_pigs_id})
- msg_id4 = self.mail_message.create(cr, uid, {'subject': 'Test', 'body': 'A+B Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'partner_ids': [(6, 0, [partner_bert_id])]})
- msg_id5 = self.mail_message.create(cr, uid, {'subject': 'Test', 'body': 'A+R Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'partner_ids': [(6, 0, [partner_raoul_id])]})
- msg_id6 = self.mail_message.create(cr, uid, {'subject': 'Test', 'body': 'A Birds', 'model': 'mail.group', 'res_id': group_birds_id})
- msg_id7 = self.mail_message.create(cr, user_bert_id, {'subject': 'Test', 'body': 'B'})
- msg_id8 = self.mail_message.create(cr, user_bert_id, {'subject': 'Test', 'body': 'B+R', 'partner_ids': [(6, 0, [partner_raoul_id])]})
+ msg_id1 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A', 'subtype_id': subtype_id})
+ msg_id2 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A+B', 'partner_ids': [(6, 0, [partner_bert_id])], 'subtype_id': subtype_id})
+ msg_id3 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'subtype_id': subtype_id})
+ msg_id4 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A+B Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'partner_ids': [(6, 0, [partner_bert_id])], 'subtype_id': subtype_id})
+ msg_id5 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A+R Pigs', 'model': 'mail.group', 'res_id': group_pigs_id, 'partner_ids': [(6, 0, [partner_raoul_id])], 'subtype_id': subtype_id})
+ msg_id6 = self.mail_message.create(cr, uid, {'subject': '_Test', 'body': 'A Birds', 'model': 'mail.group', 'res_id': group_birds_id, 'subtype_id': subtype_id})
+ msg_id7 = self.mail_message.create(cr, user_bert_id, {'subject': '_Test', 'body': 'B', 'subtype_id': subtype_id})
+ msg_id8 = self.mail_message.create(cr, user_bert_id, {'subject': '_Test', 'body': 'B+R', 'partner_ids': [(6, 0, [partner_raoul_id])], 'subtype_id': subtype_id})
# Test: Bert: 2 messages that have Bert in partner_ids + 2 messages as author
- msg_ids = self.mail_message.search(cr, user_bert_id, [('subject', 'like', 'Test')])
+ msg_ids = self.mail_message.search(cr, user_bert_id, [('subject', 'like', '_Test')])
self.assertEqual(set([msg_id2, msg_id4, msg_id7, msg_id8]), set(msg_ids), 'mail_message search failed')
# Test: Raoul: 3 messages on Pigs Raoul can read (employee can read group with default values), 0 on Birds (private group)
- msg_ids = self.mail_message.search(cr, user_raoul_id, [('body', 'like', 'A')])
+ msg_ids = self.mail_message.search(cr, user_raoul_id, [('subject', 'like', '_Test'), ('body', 'like', 'A')])
self.assertEqual(set([msg_id3, msg_id4, msg_id5]), set(msg_ids), 'mail_message search failed')
# Test: Admin: all messages
- msg_ids = self.mail_message.search(cr, uid, [('subject', 'like', 'Test')])
+ msg_ids = self.mail_message.search(cr, uid, [('subject', 'like', '_Test')])
self.assertEqual(set([msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8]), set(msg_ids), 'mail_message search failed')
def test_05_mail_message_read_access_rights(self):