[IMP] res.users: enable cache on context_get, used by the _() translation function
[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 openerp import SUPERUSER_ID
23 from openerp.osv import osv, fields
24 from openerp import tools
25
26
27 class mail_followers(osv.Model):
28     """ mail_followers holds the data related to the follow mechanism inside
29         OpenERP. Partners can choose to follow documents (records) of any kind
30         that inherits from mail.thread. Following documents allow to receive
31         notifications for new messages.
32         A subscription is characterized by:
33             :param: res_model: model of the followed objects
34             :param: res_id: ID of resource (may be 0 for every objects)
35     """
36     _name = 'mail.followers'
37     _rec_name = 'partner_id'
38     _log_access = False
39     _description = 'Document Followers'
40     _columns = {
41         'res_model': fields.char('Related Document Model', size=128,
42                         required=True, select=1,
43                         help='Model of the followed resource'),
44         'res_id': fields.integer('Related Document ID', select=1,
45                         help='Id of the followed resource'),
46         'partner_id': fields.many2one('res.partner', string='Related Partner',
47                         ondelete='cascade', required=True, select=1),
48         'subtype_ids': fields.many2many('mail.message.subtype', string='Subtype',
49             help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall."),
50     }
51
52
53 class mail_notification(osv.Model):
54     """ Class holding notifications pushed to partners. Followers and partners
55         added in 'contacts to notify' receive notifications. """
56     _name = 'mail.notification'
57     _rec_name = 'partner_id'
58     _log_access = False
59     _description = 'Notifications'
60
61     _columns = {
62         'partner_id': fields.many2one('res.partner', string='Contact',
63                         ondelete='cascade', required=True, select=1),
64         'read': fields.boolean('Read', select=1),
65         'starred': fields.boolean('Starred', select=1,
66             help='Starred message that goes into the todo mailbox'),
67         'message_id': fields.many2one('mail.message', string='Message',
68                         ondelete='cascade', required=True, select=1),
69     }
70
71     _defaults = {
72         'read': False,
73         'starred': False,
74     }
75
76     def init(self, cr):
77         cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_notification_partner_id_read_starred_message_id',))
78         if not cr.fetchone():
79             cr.execute('CREATE INDEX mail_notification_partner_id_read_starred_message_id ON mail_notification (partner_id, read, starred, message_id)')
80
81     def create(self, cr, uid, vals, context=None):
82         """ Override of create to check that we can not create a notification
83             for a message the user can not read. """
84         if self.pool.get('mail.message').check_access_rights(cr, uid, 'read'):
85             return super(mail_notification, self).create(cr, uid, vals, context=context)
86         return False
87
88     def get_partners_to_notify(self, cr, uid, message, context=None):
89         """ Return the list of partners to notify, based on their preferences.
90
91             :param browse_record message: mail.message to notify
92         """
93         notify_pids = []
94         for notification in message.notification_ids:
95             if notification.read:
96                 continue
97             partner = notification.partner_id
98             # Do not send an email to the writer
99             if partner.user_ids and partner.user_ids[0].id == uid:
100                 continue
101             # Do not send to partners without email address defined
102             if not partner.email:
103                 continue
104             # Partner does not want to receive any emails
105             if partner.notification_email_send == 'none':
106                 continue
107             # Partner wants to receive only emails and comments
108             if partner.notification_email_send == 'comment' and message.type not in ('email', 'comment'):
109                 continue
110             # Partner wants to receive only emails
111             if partner.notification_email_send == 'email' and message.type != 'email':
112                 continue
113             notify_pids.append(partner.id)
114         return notify_pids
115
116     def _notify(self, cr, uid, msg_id, context=None):
117         """ Send by email the notification depending on the user preferences """
118         if context is None:
119             context = {}
120         # mail_noemail (do not send email) or no partner_ids: do not send, return
121         if context.get('mail_noemail'):
122             return True
123         # browse as SUPERUSER_ID because of access to res_partner not necessarily allowed
124         msg = self.pool.get('mail.message').browse(cr, SUPERUSER_ID, msg_id, context=context)
125         notify_partner_ids = self.get_partners_to_notify(cr, uid, msg, context=context)
126         if not notify_partner_ids:
127             return True
128
129         # add the context in the email
130         # TDE FIXME: commented, to be improved in a future branch
131         # quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context)
132
133         mail_mail = self.pool.get('mail.mail')
134         # add signature
135         body_html = msg.body
136         # if quote_context:
137             # body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
138         signature = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].signature or ''
139         if signature:
140             body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div')
141
142         mail_values = {
143             'mail_message_id': msg.id,
144             'email_to': [],
145             'auto_delete': True,
146             'body_html': body_html,
147             'state': 'outgoing',
148         }
149         mail_values['email_to'] = ', '.join(mail_values['email_to'])
150         email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
151         return mail_mail.send(cr, uid, [email_notif_id], recipient_ids=notify_partner_ids, context=context)