[MERGE] mail/chatter complete review/refactoring
[odoo/odoo.git] / addons / mail / mail_followers.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2009-today OpenERP SA (<http://www.openerp.com>)
6 #
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
11 #
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
16 #
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/>
19 #
20 ##############################################################################
21
22 from osv import osv
23 from osv import fields
24 import tools
25
26 class mail_followers(osv.Model):
27     """ mail_followers holds the data related to the follow mechanism inside
28         OpenERP. Partners can choose to follow documents (records) of any kind
29         that inherits from mail.thread. Following documents allow to receive
30         notifications for new messages.
31         A subscription is characterized by:
32             :param: res_model: model of the followed objects
33             :param: res_id: ID of resource (may be 0 for every objects)
34     """
35     _name = 'mail.followers'
36     _rec_name = 'partner_id'
37     _log_access = False
38     _description = 'Document Followers'
39     _columns = {
40         'res_model': fields.char('Related Document Model', size=128,
41                         required=True, select=1,
42                         help='Model of the followed resource'),
43         'res_id': fields.integer('Related Document ID', select=1,
44                         help='Id of the followed resource'),
45         'partner_id': fields.many2one('res.partner', string='Related Partner',
46                         ondelete='cascade', required=True, select=1),
47     }
48
49
50 class mail_notification(osv.Model):
51     """ Class holding notifications pushed to partners. Followers and partners
52         added in 'contacts to notify' receive notifications. """
53     _name = 'mail.notification'
54     _rec_name = 'partner_id'
55     _log_access = False
56     _description = 'Notifications'
57
58     _columns = {
59         'partner_id': fields.many2one('res.partner', string='Contact',
60                         ondelete='cascade', required=True),
61         'read': fields.boolean('Read'),
62         'message_id': fields.many2one('mail.message', string='Message',
63                         ondelete='cascade', required=True),
64     }
65
66     _defaults = {
67         'read': False,
68     }
69
70     def init(self, cr):
71         cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_notification_partner_id_read_message_id',))
72         if not cr.fetchone():
73             cr.execute('CREATE INDEX mail_notification_partner_id_read_message_id ON mail_notification (partner_id, read, message_id)')
74
75     def create(self, cr, uid, vals, context=None):
76         """ Override of create to check that we can not create a notification
77             for a message the user can not read. """
78         if self.pool.get('mail.message').check_access_rights(cr, uid, 'read'):
79             return super(mail_notification, self).create(cr, uid, vals, context=context)
80         return False
81
82     def set_message_read(self, cr, uid, msg_id, context=None):
83         partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
84         notif_ids = self.search(cr, uid, [('partner_id', '=', partner_id), ('message_id', '=', msg_id)], context=context)
85         return self.write(cr, uid, notif_ids, {'read': True}, context=context)
86
87     def notify(self, cr, uid, partner_ids, msg_id, context=None):
88         """ Send by email the notification depending on the user preferences """
89         context = context or {}
90         # mail_noemail (do not send email) or no partner_ids: do not send, return
91         if context.get('mail_noemail') or not partner_ids:
92             return True
93
94         mail_mail = self.pool.get('mail.mail')
95         msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
96
97         # add signature
98         body_html = msg.body
99         signature = msg.author_id and msg.author_id.user_ids[0].signature or ''
100         if signature:
101             body_html = tools.append_content_to_html(body_html, signature)
102
103         mail_values = {
104             'mail_message_id': msg.id,
105             'email_to': [],
106             'auto_delete': True,
107             'body_html': body_html,
108             'state': 'outgoing',
109         }
110
111         for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
112             # Do not send an email to the writer
113             if partner.user_ids and partner.user_ids[0].id == uid:
114                 continue
115             # Do not send to partners without email address defined
116             if not partner.email:
117                 continue
118             # Partner does not want to receive any emails
119             if partner.notification_email_send == 'none':
120                 continue
121             # Partner wants to receive only emails and comments
122             if partner.notification_email_send == 'comment' and msg.type not in ('email', 'comment'):
123                 continue
124             # Partner wants to receive only emails
125             if partner.notification_email_send == 'email' and msg.type != 'email':
126                 continue
127             if partner.email not in mail_values['email_to']:
128                 mail_values['email_to'].append(partner.email)
129         if mail_values['email_to']:
130             mail_values['email_to'] = ', '.join(mail_values['email_to'])
131             email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
132             mail_mail.send(cr, uid, [email_notif_id], context=context)
133         return True