85bd7cee37e9ae05b84e0dd8f555055450c6dfc1
[odoo/odoo.git] / addons / 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, email_send
27 from tools.translate import _
28
29 from base.res.res_user import _lang_get
30
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 --
46 OpenERP - Open Source Business Applications
47 http://www.openerp.com
48 """)
49
50 ROOT_UID = 1
51
52 # character sets for passwords, excluding 0, O, o, 1, I, l
53 _PASSU = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'
54 _PASSL = 'abcdefghijkmnpqrstuvwxyz'
55 _PASSD = '23456789'
56
57 def random_password():
58     # get 3 uppercase letters, 3 lowercase letters, 2 digits, and shuffle them
59     chars = map(random.choice, [_PASSU] * 3 + [_PASSL] * 3 + [_PASSD] * 2)
60     random.shuffle(chars)
61     return ''.join(chars)
62
63
64
65 class wizard(osv.osv_memory):
66     """
67         A wizard to create portal users from instances of either 'res.partner'
68         or 'res.partner.address'.  The purpose is to provide an OpenERP database
69         access to customers or suppliers.
70     """
71     _name = 'res.portal.wizard'
72     _description = 'Portal Wizard'
73     
74     _columns = {
75         'portal_id': fields.many2one('res.portal', required=True,
76             string='Portal',
77             help="The portal in which new users must be added"),
78         'user_ids': fields.one2many('res.portal.wizard.user', 'wizard_id',
79             string='Users'),
80     }
81     _defaults = {
82         'user_ids': (lambda self, *args: self._default_user_ids(*args))
83     }
84
85     def _default_user_ids(self, cr, uid, context):
86         """ determine default user_ids from the active records """
87         # determine relevant res.partner.address(es) depending on context
88         addresses = []
89         if context.get('active_model') == 'res.partner.address':
90             address_obj = self.pool.get('res.partner.address')
91             address_ids = context.get('active_ids', [])
92             addresses = address_obj.browse(cr, uid, address_ids, context)
93         elif context.get('active_model') == 'res.partner':
94             partner_obj = self.pool.get('res.partner')
95             partner_ids = context.get('active_ids', [])
96             partners = partner_obj.browse(cr, uid, partner_ids, context)
97             for p in partners:
98                 if p.address:
99                     # take default address if present, or any address otherwise
100                     def_addrs = filter(lambda a: a.type == 'default', p.address)
101                     addresses.append(def_addrs[0] if def_addrs else p.address[0])
102         
103         # create user configs based on these addresses
104         user_data = lambda address: {
105                         'name': address.name,
106                         'email': address.email,
107                         'lang': address.partner_id and address.partner_id.lang,
108                         'address_id': address.id,
109                     }
110         return map(user_data, addresses)
111
112     def action_create(self, cr, uid, ids, context=None):
113         """ create new users in portal(s), and notify them by email """
114         # we copy the context to change the language for translating emails
115         context0 = context or {}
116         context = context0.copy()
117         
118         user = self.pool.get('res.users').browse(cr, ROOT_UID, uid, context0)
119         if not user.user_email:
120             raise osv.except_osv(_('Email required'),
121                 _('You must have an email address in your User Preferences'
122                   ' to send emails.'))
123         
124         portal_obj = self.pool.get('res.portal')
125         for wiz in self.browse(cr, uid, ids, context):
126             # create new users in portal
127             users_data = [ {
128                     'name': u.name,
129                     'login': u.email,
130                     'password': random_password(),
131                     'user_email': u.email,
132                     'context_lang': u.lang,
133                     'address_id': u.address_id.id,
134                 } for u in wiz.user_ids ]
135             portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
136                 {'users': [(0, 0, data) for data in users_data]}, context0)
137             
138             # send email to new users (translated in their language)
139             for data in users_data:
140                 context['lang'] = data['context_lang']
141                 data['company'] = user.company_id.name
142                 data['db'] = cr.dbname
143                 data['url'] = "(missing url)"
144                 
145                 email_from = user.user_email
146                 email_to = data['user_email']
147                 subject = _(WELCOME_EMAIL_SUBJECT) % data
148                 body = _(WELCOME_EMAIL_BODY) % data
149                 res = email_send(email_from, [email_to], subject, body)
150                 if not res:
151                     logging.getLogger('res.portal.wizard').warning(
152                         'Failed to send email from %s to %s', email_from, email_to)
153         
154         return {'type': 'ir.actions.act_window_close'}
155
156 wizard()
157
158
159
160 class wizard_user(osv.osv_memory):
161     """
162         A model to configure users in the portal wizard.
163     """
164     _name = 'res.portal.wizard.user'
165     _description = 'Portal User Config'
166     
167     _columns = {
168         'wizard_id': fields.many2one('res.portal.wizard', required=True,
169             string='Wizard'),
170         'name': fields.char(size=64, required=True,
171             string='User Name',
172             help="The user's real name"),
173         'email': fields.char(size=64, required=True,
174             string='E-mail',
175             help="Will be used as user login.  "  
176                  "Also necessary to send the account information to new users"),
177         'lang': fields.selection(_lang_get, required=True,
178             string='Language',
179             help="The language for the user's user interface"),
180         'address_id': fields.many2one('res.partner.address', required=True,
181             string='Address'),
182         'partner_id': fields.related('address_id', 'partner_id',
183             type='many2one', relation='res.partner', readonly=True,
184             string='Partner'),
185     }
186
187     def _check_email(self, cr, uid, ids):
188         """ check syntax of email address """
189         for wizard in self.browse(cr, uid, ids):
190             if not email_re.match(wizard.email): return False
191         return True
192
193     def _check_exist(self, cr, uid, ids):
194         """ check whether login (email) already in use """
195         user_obj = self.pool.get('res.users')
196         for wizard in self.browse(cr, uid, ids):
197             condition = [('login', '=', wizard.email)]
198             if user_obj.search(cr, ROOT_UID, condition): return False
199         return True
200
201     _constraints = [
202         (_check_email, 'Invalid email address', ['email']),
203         (_check_exist, 'User login already exists', ['email']),
204     ]
205
206 wizard_user()
207
208
209