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),
65 'read': fields.boolean('Read'),
66 'message_id': fields.many2one('mail.message', string='Message',
67 ondelete='cascade', required=True),
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 a message and its child messages as (un)read for uid.
89 :param bool read: read / unread
91 # TDE note: use child_of or front-end send correct values ?
92 user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
93 notif_ids = self.search(cr, uid, [
94 ('partner_id', '=', user_pid),
95 ('message_id', 'in', msg_ids)
98 # all message have notifications: already set them as (un)read
99 if len(notif_ids) == len(msg_ids):
100 return self.write(cr, uid, notif_ids, {'read': read}, context=context)
102 # some messages do not have notifications: find which one, create notification, update read status
103 exist_notification = dict.fromkeys(msg_ids, False)
104 for notification in self.browse(cr, uid, notif_ids, context=context):
105 exist_notification[notification.message_id] = True
106 for msg_id in exist_notification.keys():
107 self.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context)
108 return self.write(cr, uid, notif_ids, {'read': read}, context=context)
110 def get_partners_to_notify(self, cr, uid, message, context=None):
111 """ Return the list of partners to notify, based on their preferences.
113 :param browse_record message: mail.message to notify
116 for notification in message.notification_ids:
117 if notification.read:
119 partner = notification.partner_id
120 # Do not send an email to the writer
121 if partner.user_ids and partner.user_ids[0].id == uid:
123 # Do not send to partners without email address defined
124 if not partner.email:
126 # Partner does not want to receive any emails
127 if partner.notification_email_send == 'none':
129 # Partner wants to receive only emails and comments
130 if partner.notification_email_send == 'comment' and message.type not in ('email', 'comment'):
132 # Partner wants to receive only emails
133 if partner.notification_email_send == 'email' and message.type != 'email':
135 notify_pids.append(partner.id)
138 def _notify(self, cr, uid, msg_id, context=None):
139 """ Send by email the notification depending on the user preferences """
142 # mail_noemail (do not send email) or no partner_ids: do not send, return
143 if context.get('mail_noemail'):
145 msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
147 notify_partner_ids = self.get_partners_to_notify(cr, uid, msg, context=context)
148 if not notify_partner_ids:
151 # add the context in the email
152 # TDE FIXME: commented, to be improved in a future branch
153 # quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context)
155 mail_mail = self.pool.get('mail.mail')
159 # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
160 signature = msg.author_id and msg.author_id.user_ids[0].signature or ''
162 body_html = tools.append_content_to_html(body_html, signature)
165 'mail_message_id': msg.id,
168 'body_html': body_html,
171 mail_values['email_to'] = ', '.join(mail_values['email_to'])
172 email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
173 return mail_mail.send(cr, uid, [email_notif_id], recipient_ids=notify_partner_ids, context=context)