[MERGE] mail/chatter complete review/refactoring
[odoo/odoo.git] / addons / portal / wizard / portal_wizard.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2011 OpenERP S.A (<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 import logging
23 import random
24
25 from osv import osv, fields
26 from tools.misc import email_re
27 from tools.translate import _
28
29 from base.res.res_partner import _lang_get
30 _logger = logging.getLogger(__name__)
31
32
33 # welcome email sent to new portal users (note that calling tools.translate._
34 # has no effect except exporting those strings for translation)
35 WELCOME_EMAIL_SUBJECT = _("Your OpenERP account at %(company)s")
36 WELCOME_EMAIL_BODY = _("""Dear %(name)s,
37
38 You have been created an OpenERP account at %(url)s.
39
40 Your login account data is:
41 Database: %(db)s
42 User:     %(login)s
43 Password: %(password)s
44
45 %(message)s
46
47 --
48 OpenERP - Open Source Business Applications
49 http://www.openerp.com
50 """)
51
52 ROOT_UID = 1
53
54 # character sets for passwords, excluding 0, O, o, 1, I, l
55 _PASSU = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'
56 _PASSL = 'abcdefghijkmnpqrstuvwxyz'
57 _PASSD = '23456789'
58
59 def random_password():
60     # get 3 uppercase letters, 3 lowercase letters, 2 digits, and shuffle them
61     chars = map(random.choice, [_PASSU] * 3 + [_PASSL] * 3 + [_PASSD] * 2)
62     random.shuffle(chars)
63     return ''.join(chars)
64
65 def extract_email(email):
66     """ extract the email address from a user-friendly email address """
67     m = email_re.search(email or "")
68     return m and m.group(0) or ""
69
70
71
72 class wizard(osv.osv_memory):
73     """
74         A wizard to create portal users from instances of 'res.partner'. The purpose
75         is to provide an OpenERP database access to customers or suppliers.
76     """
77     _name = 'res.portal.wizard'
78     _description = 'Portal Wizard'
79     
80     _columns = {
81         'portal_id': fields.many2one('res.portal', required=True,
82             string='Portal',
83             help="The portal in which new users must be added"),
84         'user_ids': fields.one2many('res.portal.wizard.user', 'wizard_id',
85             string='Users'),
86         'message': fields.text(string='Invitation message',
87             help="This text is included in the welcome email sent to the users"),
88     }
89
90     def _default_user_ids(self, cr, uid, context):
91         """ determine default user_ids from the active records """
92         def create_user_from_address(address):
93             if isinstance(address, int):
94                 res_partner_obj = self.pool.get('res.partner')
95                 address = res_partner_obj.browse(cr, uid, address, context=context)
96                 lang = address.id and address.lang or 'en_US'
97                 partner_id = address.id
98                 
99             else:
100                 lang = address.parent_id and address.parent_id.lang or 'en_US'
101                 partner_id = address.parent_id and address.parent_id.id
102             
103             return{
104                    'name': address.name,
105                    'email': extract_email(address.email),
106                    'lang': lang,
107                    'partner_id': partner_id,
108                    }
109         
110         user_ids = []
111         if context.get('active_model') == 'res.partner':
112             partner_obj = self.pool.get('res.partner')
113             partner_ids = context.get('active_ids', [])
114             partners = partner_obj.browse(cr, uid, partner_ids, context)
115             for p in partners:
116                 # add one user per contact, or one user if no contact
117                 if p.child_ids:
118                     user_ids.extend(map(create_user_from_address, p.child_ids))
119                 elif p.is_company == False and p.customer == True:
120                     user_ids.extend(map(create_user_from_address, [p.id]))
121                 else:
122                     user_ids.append({'lang': p.lang or 'en_US', 'parent_id': p.id})
123         
124         return user_ids
125
126     _defaults = {
127         'user_ids': _default_user_ids
128     }
129
130     def action_create(self, cr, uid, ids, context=None):
131         """ create new users in portal(s), and notify them by email """
132         # we copy the context to change the language for translating emails
133         context0 = context or {}
134         context0['noshortcut'] = True           # prevent shortcut creation
135         context = context0.copy()
136         
137         user_obj = self.pool.get('res.users')
138         user = user_obj.browse(cr, ROOT_UID, uid, context0)
139         if not user.email:
140             raise osv.except_osv(_('Email required'),
141                 _('You must have an email address in your User Preferences'
142                   ' to send emails.'))
143         
144         portal_obj = self.pool.get('res.portal')
145         for wiz in self.browse(cr, uid, ids, context):
146             # determine existing users
147             login_cond = [('login', 'in', [u.email for u in wiz.user_ids])]
148             existing_uids = user_obj.search(cr, ROOT_UID, login_cond)
149             existing_users = user_obj.browse(cr, ROOT_UID, existing_uids)
150             existing_logins = [u.login for u in existing_users]
151             
152             # create new users in portal (skip existing logins)
153             new_users_data = [ {
154                     'name': u.name,
155                     'login': u.email,
156                     'password': random_password(),
157                     'email': u.email,
158                     'lang': u.lang,
159                     'share': True,
160                     'action_id': wiz.portal_id.home_action_id and wiz.portal_id.home_action_id.id or False,
161                     'partner_id': u.partner_id and u.partner_id.id,
162                     'groups_id': [(6, 0, [])],
163                 } for u in wiz.user_ids if u.email not in existing_logins ]
164             portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
165                 {'users': [(0, 0, data) for data in new_users_data]}, context0)
166             
167             # send email to all users (translated in their language)
168             data = {
169                 'company': user.company_id.name,
170                 'message': wiz.message or "",
171                 'url': wiz.portal_id.url or _("(missing url)"),
172                 'db': cr.dbname,
173             }
174             mail_mail_obj = self.pool.get('mail.mail')
175             dest_uids = user_obj.search(cr, ROOT_UID, login_cond)
176             dest_users = user_obj.browse(cr, ROOT_UID, dest_uids)
177             for dest_user in dest_users:
178                 context['lang'] = dest_user.lang
179                 data['login'] = dest_user.login
180                 data['password'] = dest_user.password
181                 data['name'] = dest_user.name
182                 
183                 email_from = user.email
184                 email_to = dest_user.email
185                 subject = _(WELCOME_EMAIL_SUBJECT) % data
186                 body = _(WELCOME_EMAIL_BODY) % data
187                 mail_id = mail_mail_obj.create(cr, uid, {
188                             'email_from': email_from ,
189                             'email_to': email_to,
190                             'subject': subject,
191                             'state': 'outgoing',
192                             'body_html': '<pre>%s</pre>' % body}, context=context)
193         
194         return {'type': 'ir.actions.act_window_close'}
195
196 wizard()
197
198
199
200 class wizard_user(osv.osv_memory):
201     """
202         A model to configure users in the portal wizard.
203     """
204     _name = 'res.portal.wizard.user'
205     _description = 'Portal User Config'
206
207     _columns = {
208         'wizard_id': fields.many2one('res.portal.wizard', required=True,
209             string='Wizard'),
210         'name': fields.char(size=64, required=True,
211             string='User Name',
212             help="The user's real name"),
213         'email': fields.char(size=64, required=True,
214             string='Email',
215             help="Will be used as user login.  "  
216                  "Also necessary to send the account information to new users"),
217         'lang': fields.selection(_lang_get, required=True,
218             string='Language',
219             help="The language for the user's user interface"),
220         'partner_id': fields.many2one('res.partner',
221             string='Partner'),
222     }
223
224     def _check_email(self, cr, uid, ids):
225         """ check syntax of email address """
226         for wuser in self.browse(cr, uid, ids):
227             if not email_re.match(wuser.email): return False
228         return True
229
230     _constraints = [
231         (_check_email, 'Invalid email address', ['email']),
232     ]
233
234 wizard_user()
235
236
237
238
239 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: