added users
diff --git a/erpnext/utilities/page/messages/messages.js b/erpnext/utilities/page/messages/messages.js
index 39f7974..43adce4 100644
--- a/erpnext/utilities/page/messages/messages.js
+++ b/erpnext/utilities/page/messages/messages.js
@@ -1,3 +1,19 @@
+// ERPNext - web based ERP (http://erpnext.com)
+// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
wn.provide('erpnext.messages');
wn.pages.messages.onload = function(wrapper) {
diff --git a/erpnext/utilities/page/messages/messages.py b/erpnext/utilities/page/messages/messages.py
index d7c6026..8e92ff9 100644
--- a/erpnext/utilities/page/messages/messages.py
+++ b/erpnext/utilities/page/messages/messages.py
@@ -1,3 +1,19 @@
+# ERPNext - web based ERP (http://erpnext.com)
+# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
import webnotes
@webnotes.whitelist()
diff --git a/erpnext/utilities/page/todo/todo.js b/erpnext/utilities/page/todo/todo.js
index 77e4625..4350023 100644
--- a/erpnext/utilities/page/todo/todo.js
+++ b/erpnext/utilities/page/todo/todo.js
@@ -1,3 +1,19 @@
+// ERPNext - web based ERP (http://erpnext.com)
+// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
wn.provide('erpnext.todo');
erpnext.todo.refresh = function() {
diff --git a/erpnext/utilities/page/todo/todo.py b/erpnext/utilities/page/todo/todo.py
index c10809e..05d55fe 100644
--- a/erpnext/utilities/page/todo/todo.py
+++ b/erpnext/utilities/page/todo/todo.py
@@ -1,3 +1,19 @@
+# ERPNext - web based ERP (http://erpnext.com)
+# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
import webnotes
from webnotes.model.doc import Document
diff --git a/erpnext/utilities/page/users/__init__.py b/erpnext/utilities/page/users/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/utilities/page/users/__init__.py
diff --git a/erpnext/utilities/page/users/users.css b/erpnext/utilities/page/users/users.css
new file mode 100644
index 0000000..1a85d15
--- /dev/null
+++ b/erpnext/utilities/page/users/users.css
@@ -0,0 +1,35 @@
+.user-card {
+ border-radius: 5px;
+ width: 200px;
+ margin: 11px;
+ padding: 11px;
+ background-color: #FFEDBD;
+ box-shadow: 3px 3px 5px #888;
+ float: left;
+ overflow: hidden;
+}
+
+.user-card.disabled {
+ background-color: #eee;
+}
+
+.user-card img {
+ height: 60px;
+}
+
+.user-role {
+ padding: 5px;
+ width: 45%;
+ float: left;
+}
+
+table.user-perm {
+ border-collapse: collapse;
+}
+
+table.user-perm td, table.user-perm th {
+ padding: 5px;
+ text-align: center;
+ border-bottom: 1px solid #aaa;
+ min-width: 30px;
+}
\ No newline at end of file
diff --git a/erpnext/utilities/page/users/users.html b/erpnext/utilities/page/users/users.html
new file mode 100644
index 0000000..fe2f000
--- /dev/null
+++ b/erpnext/utilities/page/users/users.html
@@ -0,0 +1,13 @@
+<div class="layout-wrapper">
+ <a class="close" onclick="window.history.back();">×</a>
+ <h1>Users</h1>
+ <hr>
+ <div class="help" style="margin-bottom: 20px">Add, disable, delete users and change their roles, passwords and security settings</div>
+ <div style="margin: 11px">
+ <button class="btn btn-small add-user" onclick="wn.pages.users.add_user()"
+ ><i class="icon-plus"></i> Add User</button>
+ </div>
+ <div class="users-area">
+ </div>
+ <div style="clear: both"></div>
+</div>
\ No newline at end of file
diff --git a/erpnext/utilities/page/users/users.js b/erpnext/utilities/page/users/users.js
new file mode 100644
index 0000000..21519b8
--- /dev/null
+++ b/erpnext/utilities/page/users/users.js
@@ -0,0 +1,377 @@
+// ERPNext - web based ERP (http://erpnext.com)
+// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+$.extend(wn.pages.users, {
+ onload: function(wrapper) {
+ wn.pages.users.profiles = {};
+ wn.pages.users.refresh();
+ wn.pages.users.setup();
+ wn.pages.users.role_editor = new erpnext.RoleEditor();
+ },
+ setup: function() {
+ // set roles
+ $('.users-area').on('click', '.btn.user-roles', function() {
+ var uid = $(this).parent().parent().attr('data-name');
+ wn.pages.users.role_editor.show(uid);
+ });
+
+ // settings
+ $('.users-area').on('click', '.btn.user-settings', function() {
+ var uid = $(this).parent().parent().attr('data-name');
+ wn.pages.users.show_settings(uid);
+ });
+
+ // delete
+ $('.users-area').on('click', 'a.close', function() {
+ $card = $(this).parent();
+ var uid = $card.attr('data-name');
+ $card.css('opacity', 0.6);
+ wn.call({
+ method: 'utilities.page.users.users.delete',
+ args: {'uid': uid},
+ callback: function(r,rt) {
+ if(!r.exc)
+ $card.fadeOut()
+ }
+ });
+ })
+
+ },
+ refresh: function() {
+ // make the list
+ wn.call({
+ method:'utilities.page.users.users.get',
+ callback: function(r, rt) {
+ $('.users-area').empty();
+ for(var i in r.message) {
+ var p = r.message[i];
+ wn.pages.users.profiles[p.name] = p;
+ wn.pages.users.render(p);
+ }
+ }
+ });
+ },
+ render: function(data) {
+ if(data.file_list) {
+ data.imgsrc = 'files/' + data.files_list.split('\n')[0].split(',')[1];
+ } else {
+ data.imgsrc = 'lib/images/ui/no_img_' + (data.gender=='Female' ? 'f' : 'm');
+ }
+ data.fullname = wn.boot.user_fullnames[data.name];
+ data.delete_html = '';
+ if(!data.enabled)
+ data.delete_html = '<a class="close" title="delete">×</a>';
+
+ $('.users-area').append(repl('<div class="user-card" data-name="%(name)s">\
+ %(delete_html)s\
+ <img src="%(imgsrc)s">\
+ <div class="user-info">\
+ <b class="user-fullname">%(fullname)s</b><br>\
+ %(name)s<br>\
+ <button class="btn btn-small user-roles"><i class="icon-user"></i> Roles</button>\
+ <button class="btn btn-small user-settings"><i class="icon-cog"></i> Settings</button>\
+ </div>\
+ </div>', data));
+
+ if(!data.enabled) {
+ $('.users-area .user-card:last')
+ .addClass('disabled')
+ .find('.user-fullname').html('Disabled');
+ }
+ },
+ show_settings: function(uid) {
+ var me = wn.pages.users;
+ if(!me.settings_dialog)
+ me.make_settings_dialog();
+
+ var p = me.profiles[uid];
+ me.uid = uid;
+
+ me.settings_dialog.set_values({
+ restrict_ip: p.restrict_ip || '',
+ login_before: p.login_before || '',
+ login_after: p.login_after || '',
+ enabled: p.enabled || 0,
+ new_password: ''
+ });
+
+ me.settings_dialog.show();
+
+ },
+ make_settings_dialog: function() {
+ var me = wn.pages.users;
+ me.settings_dialog = new wn.widgets.Dialog({
+ title: 'Set User Security',
+ width: 500,
+ fields: [
+ {
+ label:'Enabled',
+ description: 'Uncheck to disable',
+ fieldtype: 'Check', fieldname: 'enabled'
+ },
+ {
+ label:'IP Address',
+ description: 'Restrict user login by IP address, partial ips (111.111.111), \
+ multiple addresses (separated by commas) allowed',
+ fieldname:'restrict_ip', fieldtype:'Data'
+ },
+ {
+ label:'Login After',
+ description: 'User can only login after this hour (0-24)',
+ fieldtype: 'Int', fieldname: 'login_after'
+ },
+ {
+ label:'Login Before',
+ description: 'User can only login before this hour (0-24)',
+ fieldtype: 'Int', fieldname: 'login_before'
+ },
+ {
+ label:'New Password',
+ description: 'Update the current user password',
+ fieldtype: 'Data', fieldname: 'new_password'
+ },
+ {
+ label:'Update', fieldtype:'Button', fieldname:'update'
+ }
+ ]
+ });
+
+ this.settings_dialog.fields_dict.update.input.onclick = function() {
+ var btn = this;
+ this.set_working();
+ var args = me.settings_dialog.get_values();
+ args.user = me.uid;
+
+ if (args.new_password) {
+ me.get_password(btn, args);
+ } else {
+ btn.set_working();
+ me.update_security(args);
+ }
+ };
+
+ },
+ update_security: function(args) {
+ var me = wn.pages.users;
+ $c_page('utilities', 'users', 'update_security', JSON.stringify(args), function(r,rt) {
+ if(r.exc) {
+ msgprint(r.exc);
+ return;
+ }
+ me.settings_dialog.hide();
+ $.extend(me.profiles[me.uid], me.settings_dialog.get_values());
+ me.refresh();
+ });
+ },
+ get_password: function(btn, args) {
+ var me = wn.pages.users;
+ var pass_d = new wn.widgets.Dialog({
+ title: 'Your Password',
+ width: 300,
+ fields: [
+ {
+ label: 'Please Enter <b style="color: black">Your Password</b>',
+ description: "Your password is required to update the user's password",
+ fieldtype: 'Password', fieldname: 'sys_admin_pwd', reqd: 1
+ },
+ {
+ label: 'Continue', fieldtype: 'Button', fieldname: 'continue'
+ }
+ ]
+ });
+
+ pass_d.fields_dict.continue.input.onclick = function() {
+ btn.pwd_dialog.hide();
+ args.sys_admin_pwd = btn.pwd_dialog.get_values().sys_admin_pwd;
+ btn.set_working();
+ me.update_security(args);
+ btn.done_working();
+ }
+
+ pass_d.show();
+ btn.pwd_dialog = pass_d;
+ btn.done_working();
+ },
+ add_user: function() {
+ var me = wn.pages.users;
+ var d = new wn.widgets.Dialog({
+ title: 'Add User',
+ width: 400,
+ fields: [{
+ fieldtype: 'Data', fieldname: 'user', reqd: 1,
+ label: 'Email Id of the user to add'
+ }, {
+ fieldtype: 'Data', fieldname: 'first_name', reqd: 1, label: 'First Name'
+ }, {
+ fieldtype: 'Data', fieldname: 'last_name', label: 'Last Name'
+ }, {
+ fieldtype: 'Data', fieldname: 'password', reqd: 1, label: 'Password'
+ }, {
+ fieldtype: 'Button', label: 'Add', fieldname: 'add'
+ }]
+ });
+
+ d.make();
+ d.fields_dict.add.input.onclick = function() {
+ v = d.get_values();
+ if(v) {
+ d.fields_dict.add.input.set_working();
+ $c_page('utilities', 'users', 'add_user', v, function(r,rt) {
+ if(r.exc) { msgprint(r.exc); return; }
+ else {
+ d.hide();
+ me.refresh();
+ }
+ })
+ }
+ }
+ d.show();
+ }
+});
+
+erpnext.RoleEditor = Class.extend({
+ init: function() {
+ this.dialog = new wn.widgets.Dialog({
+ title: 'Set Roles'
+ });
+ var me = this;
+ $(this.dialog.body).html('<div class="help">Loading...</div>')
+ wn.call({
+ method:'utilities.page.users.users.get_roles',
+ callback: function(r) {
+ me.roles = r.message;
+ me.show_roles();
+ }
+ });
+ },
+ show_roles: function() {
+ var me = this;
+ $(this.dialog.body).empty();
+ for(var i in this.roles) {
+ $(this.dialog.body).append(repl('<div class="user-role" \
+ data-user-role="%(role)s">\
+ <input type="checkbox"> \
+ <a href="#"><i class="icon-question-sign"></i></a> %(role)s\
+ </div>', {role: this.roles[i]}));
+ }
+ $(this.dialog.body).append('<div style="clear: both">\
+ <button class="btn btn-small btn-primary">Save</button></div>');
+ $(this.dialog.body).find('button.btn-primary').click(function() {
+ me.save();
+ });
+ $(this.dialog.body).find('.user-role a').click(function() {
+ me.show_permissions($(this).parent().attr('data-user-role'))
+ return false;
+ })
+ },
+ show: function(uid) {
+ var me = this;
+ this.uid = uid;
+ this.dialog.show();
+ // set user roles
+ wn.call({
+ method:'utilities.page.users.users.get_user_roles',
+ args: {uid:uid},
+ callback: function(r, rt) {
+ $(me.dialog.body).find('input[type="checkbox"]').attr('checked', false);
+ for(var i in r.message) {
+ $(me.dialog.body)
+ .find('[data-user-role="'+r.message[i]
+ +'"] input[type="checkbox"]').attr('checked',true);
+ }
+ }
+ })
+ },
+ save: function() {
+ var set_roles = [];
+ var unset_roles = [];
+ $(this.dialog.body).find('[data-user-role]').each(function() {
+ var $check = $(this).find('input[type="checkbox"]');
+ if($check.attr('checked')) {
+ set_roles.push($(this).attr('data-user-role'));
+ } else {
+ unset_roles.push($(this).attr('data-user-role'));
+ }
+ })
+ wn.call({
+ method:'utilities.page.users.users.update_roles',
+ args: {
+ set_roles: JSON.stringify(set_roles),
+ unset_roles: JSON.stringify(unset_roles),
+ uid: this.uid
+ },
+ btn: $(this.dialog.body).find('.btn-primary').get(0),
+ callback: function() {
+
+ }
+ })
+ },
+ show_permissions: function(role) {
+ // show permissions for a role
+ var me = this;
+ if(!this.perm_dialog)
+ this.make_perm_dialog()
+ $(this.perm_dialog.body).empty();
+ wn.call({
+ method:'utilities.page.users.users.get_perm_info',
+ args: {role: role},
+ callback: function(r) {
+ var $body = $(me.perm_dialog.body);
+ $body.append('<table class="user-perm"><tbody><tr>\
+ <th style="text-align: left">Document Type</th>\
+ <th>Level</th>\
+ <th>Read</th>\
+ <th>Write</th>\
+ <th>Submit</th>\
+ <th>Cancel</th>\
+ <th>Amend</th></tr></tbody></table>');
+ for(var i in r.message) {
+ var perm = r.message[i];
+
+ // if permission -> icon
+ for(key in perm) {
+ if(key!='parent' && key!='permlevel') {
+ if(perm[key]) {
+ perm[key] = '<i class="icon-ok"></i>';
+ } else {
+ perm[key] = '';
+ }
+ }
+ }
+
+ $body.find('tbody').append(repl('<tr>\
+ <td style="text-align: left">%(parent)s</td>\
+ <td>%(permlevel)s</td>\
+ <td>%(read)s</td>\
+ <td>%(write)s</td>\
+ <td>%(submit)s</td>\
+ <td>%(cancel)s</td>\
+ <td>%(amend)s</td>\
+ </tr>', perm))
+ }
+
+ me.perm_dialog.show();
+ }
+ });
+
+ },
+ make_perm_dialog: function() {
+ this.perm_dialog = new wn.widgets.Dialog({
+ title:'Role Permissions',
+ width: 500
+ });
+ }
+})
diff --git a/erpnext/utilities/page/users/users.py b/erpnext/utilities/page/users/users.py
new file mode 100644
index 0000000..44e2fb2
--- /dev/null
+++ b/erpnext/utilities/page/users/users.py
@@ -0,0 +1,192 @@
+# ERPNext - web based ERP (http://erpnext.com)
+# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import webnotes
+import json
+
+from webnotes.model.doc import Document
+from webnotes.utils import cint
+
+@webnotes.whitelist()
+def get(arg=None):
+ """return all users"""
+ return webnotes.conn.sql("""select name, file_list, enabled, gender,
+ restrict_ip, login_before, login_after from tabProfile
+ where docstatus<2 and name not in ('Administrator', 'Guest') order by
+ ifnull(enabled,0) desc, name""", as_dict=1)
+
+@webnotes.whitelist()
+def get_roles(arg=None):
+ """return all roles"""
+ return [r[0] for r in webnotes.conn.sql("""select name from tabRole
+ where name not in ('Administrator', 'Guest', 'All') order by name""")]
+
+@webnotes.whitelist()
+def get_user_roles(arg=None):
+ """get roles for a user"""
+ return [r[0] for r in webnotes.conn.sql("""select role from tabUserRole
+ where parent=%s""", webnotes.form_dict['uid'])]
+
+@webnotes.whitelist()
+def get_perm_info(arg=None):
+ """get permission info"""
+ return webnotes.conn.sql("""select parent, permlevel, `read`, `write`, submit,
+ cancel, amend from tabDocPerm where role=%s
+ and docstatus<2 order by parent, permlevel""",
+ webnotes.form_dict['role'], as_dict=1)
+
+@webnotes.whitelist()
+def update_roles(arg=None):
+ """update set and unset roles"""
+ # remove roles
+ unset = json.loads(webnotes.form_dict['unset_roles'])
+ webnotes.conn.sql("""delete from tabUserRole where parent='%s'
+ and role in ('%s')""" % (webnotes.form_dict['uid'], "','".join(unset)))
+
+ # check for 1 system manager
+ if not webnotes.conn.sql("""select parent from tabUserRole where role='System Manager'
+ and docstatus<2"""):
+ webnotes.msgprint("Sorry there must be atleast one 'System Manager'")
+ raise webnotes.ValidationError
+
+ # add roles
+ roles = get_user_roles()
+ toset = json.loads(webnotes.form_dict['set_roles'])
+ for role in toset:
+ if not role in roles:
+ d = Document('UserRole')
+ d.role = role
+ d.parent = webnotes.form_dict['uid']
+ d.save()
+
+ webnotes.msgprint('Roles Updated')
+
+@webnotes.whitelist()
+def update_security(args=''):
+ args = json.loads(args)
+ webnotes.conn.set_value('Profile', args['user'], 'restrict_ip', args.get('restrict_ip'))
+ webnotes.conn.set_value('Profile', args['user'], 'login_after', args.get('login_after'))
+ webnotes.conn.set_value('Profile', args['user'], 'login_before', args.get('login_before'))
+ webnotes.conn.set_value('Profile', args['user'], 'enabled', int(args.get('enabled',0)) or 0)
+
+ if 'new_password' in args:
+ if cint(webnotes.conn.get_value('Control Panel',None,'sync_with_gateway')):
+ import server_tools.gateway_utils
+ res = server_tools.gateway_utils.change_password('', args['new_password'],
+ args['user'], args['sys_admin_pwd'])
+ if 'Traceback' not in res['message']:
+ webnotes.msgprint(res['message'])
+ webnotes.conn.sql("update tabProfile set password=password(%s) where name=%s",
+ (args['new_password'], args['user']))
+ else:
+ webnotes.msgprint('Settings Updated')
+
+
+
+#
+# user addition
+#
+
+@webnotes.whitelist()
+def add_user(args):
+ args = json.loads(args)
+ # erpnext-saas
+ if cint(webnotes.conn.get_value('Control Panel', None, 'sync_with_gateway')):
+ from server_tools.gateway_utils import add_user_gateway
+ add_user_gateway(args['user'])
+
+ add_profile(args)
+
+@webnotes.whitelist()
+def add_profile(args):
+ from webnotes.utils import validate_email_add, now
+ email = args['user']
+
+ sql = webnotes.conn.sql
+
+ if not email:
+ email = webnotes.form_dict.get('user')
+ if not validate_email_add(email):
+ raise Exception
+ return 'Invalid Email Id'
+
+ if sql("select name from tabProfile where name = %s", email):
+ # exists, enable it
+ sql("update tabProfile set enabled = 1, docstatus=0 where name = %s", email)
+ webnotes.msgprint('Profile exists, enabled it with new password')
+ else:
+ # does not exist, create it!
+ pr = Document('Profile')
+ pr.name = email
+ pr.email = email
+ pr.first_name = args.get('first_name')
+ pr.last_name = args.get('last_name')
+ pr.enabled = 1
+ pr.user_type = 'System User'
+ pr.save(1)
+
+ if args.get('password'):
+ sql("""
+ UPDATE tabProfile
+ SET password = PASSWORD(%s), modified = %s
+ WHERE name = %s""", (args.get('password'), now, email))
+
+ send_welcome_mail(email, args)
+
+@webnotes.whitelist()
+def send_welcome_mail(email, args):
+ """send welcome mail to user with password and login url"""
+ pr = Document('Profile', email)
+ from webnotes.utils.email_lib import sendmail_md
+ args.update({
+ 'company': webnotes.conn.get_default('company'),
+ 'password': args.get('password'),
+ 'account_url': webnotes.conn.get_default('account_url')
+ })
+ if not args.get('last_name'): args['last_name'] = ''
+ sendmail_md(pr.email, subject="Welcome to ERPNext", msg=welcome_txt % args, from_defs=1)
+
+#
+# delete user
+#
+@webnotes.whitelist()
+def delete(arg=None):
+ """delete user"""
+ webnotes.conn.sql("update tabProfile set enabled=0, docstatus=2 where name=%s",
+ webnotes.form_dict['uid'])
+ # erpnext-saas
+ if int(webnotes.conn.get_value('Control Panel', None, 'sync_with_gateway')):
+ from server_tools.gateway_utils import remove_user_gateway
+ remove_user_gateway(webnotes.form_dict['uid'])
+
+ webnotes.login_manager.logout(user=webnotes.form_dict['uid'])
+
+welcome_txt = """
+## %(company)s
+
+Dear %(first_name)s %(last_name)s
+
+Welcome!
+
+A new account has been created for you, here are your details:
+
+login-id: %(user)s
+password: %(password)s
+
+To login to your new ERPNext account, please go to:
+
+%(account_url)s
+"""
\ No newline at end of file
diff --git a/erpnext/utilities/page/users/users.txt b/erpnext/utilities/page/users/users.txt
new file mode 100644
index 0000000..165cc16
--- /dev/null
+++ b/erpnext/utilities/page/users/users.txt
@@ -0,0 +1,28 @@
+# Page, users
+[
+
+ # These values are common in all dictionaries
+ {
+ 'creation': '2012-02-28 10:29:39',
+ 'docstatus': 0,
+ 'modified': '2012-02-28 10:29:39',
+ 'modified_by': u'Administrator',
+ 'owner': u'Administrator'
+ },
+
+ # These values are common for all Page
+ {
+ 'doctype': 'Page',
+ 'module': u'Utilities',
+ 'name': '__common__',
+ 'page_name': u'users',
+ 'standard': u'Yes',
+ 'title': u'Users'
+ },
+
+ # Page, users
+ {
+ 'doctype': 'Page',
+ 'name': u'users'
+ }
+]
\ No newline at end of file