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 osv import osv, fields
23 from openerp import SUPERUSER_ID
24 from tools.translate import _
26 class res_users(osv.Model):
27 """ Update of res.users class
28 - add a preference about sending emails about notifications
29 - make a new user follow itself
30 - add a welcome message
33 _inherit = ['res.users']
34 _inherits = {'mail.alias': 'alias_id'}
37 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
38 help="Email address internally associated with this user. Incoming "\
39 "emails will appear in the user's notifications."),
43 'alias_domain': False, # always hide alias during creation
46 def __init__(self, pool, cr):
47 """ Override of __init__ to add access rights on notification_email_send
48 field. Access rights are disabled by default, but allowed on
49 fields defined in self.SELF_WRITEABLE_FIELDS.
51 init_res = super(res_users, self).__init__(pool, cr)
52 # duplicate list to avoid modifying the original reference
53 self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
54 self.SELF_WRITEABLE_FIELDS.append('notification_email_send')
57 def _auto_init(self, cr, context=None):
58 """ Installation hook: aliases, partner following themselves """
59 # create aliases for all users and avoid constraint errors
60 self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(res_users, self)._auto_init,
61 self._columns['alias_id'], 'login', alias_force_key='id', context=context)
62 # make already existing users follow themselves, using SQL to avoid using the ORM during the auto_init
63 cr.execute(""" SELECT p.id FROM res_partner p
64 LEFT JOIN mail_followers n
65 ON (n.partner_id = p.id AND n.res_model = 'res.partner' AND n.res_id = p.id)
68 params = [(res[0], res[0]) for res in cr.fetchall()]
69 cr.executemany(""" INSERT INTO mail_followers (partner_id, res_model, res_id)
70 VALUES (%s, 'res.partner', %s)
73 def create(self, cr, uid, data, context=None):
74 # create default alias same as the login
75 if not data.get('login', False):
76 raise osv.except_osv(_('Invalid Action!'), _('You may not create a user. To create new users, you should use the "Settings > Users" menu.'))
78 mail_alias = self.pool.get('mail.alias')
79 alias_id = mail_alias.create_unique_alias(cr, uid, {'alias_name': data['login']}, model_name=self._name, context=context)
80 data['alias_id'] = alias_id
81 data.pop('alias_name', None) # prevent errors during copy()
83 # create user that follows its related partner
84 user_id = super(res_users, self).create(cr, uid, data, context=context)
85 user = self.browse(cr, uid, user_id, context=context)
86 self.pool.get('res.partner').message_subscribe(cr, uid, [user.partner_id.id], [user.partner_id.id], context=context)
88 mail_alias.write(cr, SUPERUSER_ID, [alias_id], {"alias_force_thread_id": user_id}, context)
89 # create a welcome message
90 self._create_welcome_message(cr, uid, user, context=context)
93 def _create_welcome_message(self, cr, uid, user, context=None):
94 if not self.has_group(cr, uid, 'base.group_user'):
96 company_name = user.company_id.name if user.company_id else ''
97 body = _('%s has joined the %s network.') % (user.name, company_name)
98 # TODO change SUPERUSER_ID into user.id but catch errors
99 return self.pool.get('res.partner').message_post(cr, SUPERUSER_ID, [user.partner_id.id],
100 body=body, context=context)
102 def write(self, cr, uid, ids, vals, context=None):
103 # User alias is sync'ed with login
104 if vals.get('login'):
105 vals['alias_name'] = vals['login']
106 return super(res_users, self).write(cr, uid, ids, vals, context=context)
108 def unlink(self, cr, uid, ids, context=None):
109 # Cascade-delete mail aliases as well, as they should not exist without the user.
110 alias_pool = self.pool.get('mail.alias')
111 alias_ids = [user.alias_id.id for user in self.browse(cr, uid, ids, context=context) if user.alias_id]
112 res = super(res_users, self).unlink(cr, uid, ids, context=context)
113 alias_pool.unlink(cr, uid, alias_ids, context=context)
116 def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False,
117 attachment_ids=None, context=None, content_subtype='plaintext', **kwargs):
118 """ Redirect the posting of message on res.users to the related partner.
119 This is done because when giving the context of Chatter on the
120 various mailboxes, we do not have access to the current partner_id.
121 We therefore post on the user and redirect on its partner. """
122 assert thread_id, "res.users does not support posting global messages"
123 if context and 'thread_model' in context:
124 context['thread_model'] = 'res.partner'
125 if isinstance(thread_id, (list, tuple)):
126 thread_id = thread_id[0]
127 partner_id = self.pool.get('res.users').read(cr, uid, thread_id, ['partner_id'], context=context)['partner_id'][0]
128 return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, body=body, subject=subject,
129 parent_id=parent_id, attachment_ids=attachment_ids, context=context, content_subtype=content_subtype, **kwargs)
131 def message_post(self, cr, uid, thread_id, context=None, **kwargs):
132 """ Redirect the posting of message on res.users to the related partner.
133 This is done because when giving the context of Chatter on the
134 various mailboxes, we do not have access to the current partner_id.
135 We therefore post on the user and redirect on its partner. """
136 assert thread_id, "res.users does not support posting global messages"
137 if context and 'thread_model' in context:
138 context['thread_model'] = 'res.partner'
139 if isinstance(thread_id, (list, tuple)):
140 thread_id = thread_id[0]
141 partner_id = self.pool.get('res.users').read(cr, uid, thread_id, ['partner_id'], context=context)['partner_id'][0]
142 return self.pool.get('res.partner').message_post(cr, uid, partner_id, context=context, **kwargs)
144 def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
145 partner_id = self.pool.get('res.users').browse(cr, uid, ids)[0].partner_id.id
146 return self.pool.get('res.partner').message_update(cr, uid, [partner_id], msg_dict,
147 update_vals=update_vals, context=context)
150 class res_users_mail_group(osv.Model):
151 """ Update of res.users class
152 - if adding groups to an user, check mail.groups linked to this user
153 group, and the user. This is done by overriding the write method.
156 _inherit = ['res.users']
158 # FP Note: to improve, post processing may be better ?
159 def write(self, cr, uid, ids, vals, context=None):
160 write_res = super(res_users_mail_group, self).write(cr, uid, ids, vals, context=context)
161 if vals.get('groups_id'):
162 # form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
163 user_group_ids = [command[1] for command in vals['groups_id'] if command[0] == 4]
164 user_group_ids += [id for command in vals['groups_id'] if command[0] == 6 for id in command[2]]
165 mail_group_obj = self.pool.get('mail.group')
166 mail_group_ids = mail_group_obj.search(cr, uid, [('group_ids', 'in', user_group_ids)], context=context)
167 mail_group_obj.message_subscribe_users(cr, uid, mail_group_ids, ids, context=context)
170 class res_groups_mail_group(osv.Model):
171 """ Update of res.groups class
172 - if adding users from a group, check mail.groups linked to this user
173 group and subscribe them. This is done by overriding the write method.
176 _inherit = 'res.groups'
178 # FP Note: to improve, post processeing, after the super may be better
179 def write(self, cr, uid, ids, vals, context=None):
180 write_res = super(res_groups_mail_group, self).write(cr, uid, ids, vals, context=context)
181 if vals.get('users'):
182 # form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
183 user_ids = [command[1] for command in vals['users'] if command[0] == 4]
184 user_ids += [id for command in vals['users'] if command[0] == 6 for id in command[2]]
185 mail_group_obj = self.pool.get('mail.group')
186 mail_group_ids = mail_group_obj.search(cr, uid, [('group_ids', 'in', ids)], context=context)
187 mail_group_obj.message_subscribe_users(cr, uid, mail_group_ids, user_ids, context=context)