1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2009-today OpenERP SA (<http://www.openerp.com>)
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>
20 ##############################################################################
22 from openerp import SUPERUSER_ID
24 from osv import fields
28 class mail_followers(osv.Model):
29 """ mail_followers holds the data related to the follow mechanism inside
30 OpenERP. Partners can choose to follow documents (records) of any kind
31 that inherits from mail.thread. Following documents allow to receive
32 notifications for new messages.
33 A subscription is characterized by:
34 :param: res_model: model of the followed objects
35 :param: res_id: ID of resource (may be 0 for every objects)
37 _name = 'mail.followers'
38 _rec_name = 'partner_id'
40 _description = 'Document Followers'
42 'res_model': fields.char('Related Document Model', size=128,
43 required=True, select=1,
44 help='Model of the followed resource'),
45 'res_id': fields.integer('Related Document ID', select=1,
46 help='Id of the followed resource'),
47 'partner_id': fields.many2one('res.partner', string='Related Partner',
48 ondelete='cascade', required=True, select=1),
49 'subtype_ids': fields.many2many('mail.message.subtype', string='Subtype',
50 help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall."),
54 class mail_notification(osv.Model):
55 """ Class holding notifications pushed to partners. Followers and partners
56 added in 'contacts to notify' receive notifications. """
57 _name = 'mail.notification'
58 _rec_name = 'partner_id'
60 _description = 'Notifications'
63 'partner_id': fields.many2one('res.partner', string='Contact',
64 ondelete='cascade', required=True, select=1),
65 'read': fields.boolean('Read', select=1),
66 'message_id': fields.many2one('mail.message', string='Message',
67 ondelete='cascade', required=True, select=1),
75 cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_notification_partner_id_read_message_id',))
77 cr.execute('CREATE INDEX mail_notification_partner_id_read_message_id ON mail_notification (partner_id, read, message_id)')
79 def create(self, cr, uid, vals, context=None):
80 """ Override of create to check that we can not create a notification
81 for a message the user can not read. """
82 if self.pool.get('mail.message').check_access_rights(cr, uid, 'read'):
83 return super(mail_notification, self).create(cr, uid, vals, context=context)
86 def set_message_read(self, cr, uid, msg_ids, read=None, context=None):
87 """ Set messages as (un)read. Technically, the notifications related
88 to uid are set to (un)read. If for some msg_ids there are missing
89 notifications (i.e. due to load more or thread parent fetching),
92 :param bool read: (un)read notification
94 user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
95 notif_ids = self.search(cr, uid, [
96 ('partner_id', '=', user_pid),
97 ('message_id', 'in', msg_ids)
100 # all message have notifications: already set them as (un)read
101 if len(notif_ids) == len(msg_ids):
102 return self.write(cr, uid, notif_ids, {'read': read}, context=context)
104 # some messages do not have notifications: find which one, create notification, update read status
105 notified_msg_ids = [notification.message_id.id for notification in self.browse(cr, uid, notif_ids, context=context)]
106 to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids))
107 for msg_id in to_create_msg_ids:
108 self.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context)
109 return self.write(cr, uid, notif_ids, {'read': read}, context=context)
111 def get_partners_to_notify(self, cr, uid, message, context=None):
112 """ Return the list of partners to notify, based on their preferences.
114 :param browse_record message: mail.message to notify
117 for notification in message.notification_ids:
118 if notification.read:
120 partner = notification.partner_id
121 # Do not send an email to the writer
122 if partner.user_ids and partner.user_ids[0].id == uid:
124 # Do not send to partners without email address defined
125 if not partner.email:
127 # Partner does not want to receive any emails
128 if partner.notification_email_send == 'none':
130 # Partner wants to receive only emails and comments
131 if partner.notification_email_send == 'comment' and message.type not in ('email', 'comment'):
133 # Partner wants to receive only emails
134 if partner.notification_email_send == 'email' and message.type != 'email':
136 notify_pids.append(partner.id)
139 def _notify(self, cr, uid, msg_id, context=None):
140 """ Send by email the notification depending on the user preferences """
143 # mail_noemail (do not send email) or no partner_ids: do not send, return
144 if context.get('mail_noemail'):
146 msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
148 notify_partner_ids = self.get_partners_to_notify(cr, uid, msg, context=context)
149 if not notify_partner_ids:
152 # add the context in the email
153 # TDE FIXME: commented, to be improved in a future branch
154 # quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context)
156 mail_mail = self.pool.get('mail.mail')
160 # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
161 signature = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].signature or ''
163 body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div')
166 'mail_message_id': msg.id,
169 'body_html': body_html,
172 mail_values['email_to'] = ', '.join(mail_values['email_to'])
173 email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
174 return mail_mail.send(cr, uid, [email_notif_id], recipient_ids=notify_partner_ids, context=context)