@@ -178,7 +178,7 @@ wn.views.DocListView = wn.ui.Listing.extend({ | |||||
return this.listview.fields; | return this.listview.fields; | ||||
}, | }, | ||||
get_args: function() { | get_args: function() { | ||||
return { | |||||
var args = { | |||||
doctype: this.doctype, | doctype: this.doctype, | ||||
fields: this.get_query_fields(), | fields: this.get_query_fields(), | ||||
filters: this.filter_list.get_filters(), | filters: this.filter_list.get_filters(), | ||||
@@ -187,6 +187,13 @@ wn.views.DocListView = wn.ui.Listing.extend({ | |||||
order_by: this.listview.order_by || undefined, | order_by: this.listview.order_by || undefined, | ||||
group_by: this.listview.group_by || undefined, | group_by: this.listview.group_by || undefined, | ||||
} | } | ||||
// apply default filters, if specified for a listing | |||||
$.each((this.listview.default_filters || []), function(i, f) { | |||||
args.filters.push(f); | |||||
}); | |||||
return args; | |||||
}, | }, | ||||
add_delete_option: function() { | add_delete_option: function() { | ||||
var me = this; | var me = this; | ||||
@@ -550,9 +557,11 @@ wn.views.RecordListView = wn.views.DocListView.extend({ | |||||
get_args: function() { | get_args: function() { | ||||
var args = this._super(); | var args = this._super(); | ||||
$.each((this.default_filters || []), function(i, f) { | $.each((this.default_filters || []), function(i, f) { | ||||
args.filters.push(f); | args.filters.push(f); | ||||
}); | }); | ||||
args.docstatus = args.docstatus.concat((this.default_docstatus || [])); | args.docstatus = args.docstatus.concat((this.default_docstatus || [])); | ||||
return args; | return args; | ||||
}, | }, |
@@ -278,6 +278,7 @@ wn.views.GridReport = Class.extend({ | |||||
}); | }); | ||||
}, | }, | ||||
make: function() { | make: function() { | ||||
var me = this; | |||||
// plot wrapper | // plot wrapper | ||||
this.plot_area = $('<div class="plot" style="margin-bottom: 15px; display: none; \ | this.plot_area = $('<div class="plot" style="margin-bottom: 15px; display: none; \ | ||||
@@ -53,7 +53,9 @@ class DocType: | |||||
self.logout_if_disabled() | self.logout_if_disabled() | ||||
if self.doc.fields.get('__islocal') and not self.doc.new_password: | if self.doc.fields.get('__islocal') and not self.doc.new_password: | ||||
webnotes.msgprint("Password required while creating new doc") | |||||
webnotes.msgprint("Password required while creating new doc", raise_exception=1) | |||||
self.is_new = self.doc.fields.get("__islocal") | |||||
def logout_if_disabled(self): | def logout_if_disabled(self): | ||||
"""logout if disabled""" | """logout if disabled""" | ||||
@@ -102,8 +104,7 @@ class DocType: | |||||
d.save() | d.save() | ||||
def check_one_system_manager(self): | def check_one_system_manager(self): | ||||
if not webnotes.conn.sql("""select parent from tabUserRole where role='System Manager' | |||||
and docstatus<2"""): | |||||
if not webnotes.conn.sql("""select parent from tabUserRole where role='System Manager' and docstatus<2 and parent!='Administrator'"""): | |||||
webnotes.msgprint("""Cannot un-select as System Manager as there must | webnotes.msgprint("""Cannot un-select as System Manager as there must | ||||
be atleast one 'System Manager'""", raise_exception=1) | be atleast one 'System Manager'""", raise_exception=1) | ||||
@@ -119,10 +120,13 @@ class DocType: | |||||
on duplicate key update `password`=password(%s)""", (self.doc.name, | on duplicate key update `password`=password(%s)""", (self.doc.name, | ||||
self.doc.new_password, self.doc.new_password)) | self.doc.new_password, self.doc.new_password)) | ||||
if not self.doc.fields.get('__islocal'): | |||||
self.password_reset_mail(self.doc.new_password) | |||||
webnotes.conn.set(self.doc, 'new_password', '') | webnotes.conn.set(self.doc, 'new_password', '') | ||||
if not self.new: | |||||
self.password_reset_mail(self.doc.new_password) | |||||
else: | |||||
self.send_welcome_mail(self.doc.new_password) | |||||
webnotes.msgprint("Password updated.") | webnotes.msgprint("Password updated.") | ||||
def get_fullname(self): | def get_fullname(self): | ||||
@@ -191,6 +195,12 @@ Thank you,<br> | |||||
'user_fullname': get_user_fullname(webnotes.session['user']) | 'user_fullname': get_user_fullname(webnotes.session['user']) | ||||
} | } | ||||
sendmail_md(self.doc.email, subject="Welcome to " + startup.product_name, msg=txt % args) | sendmail_md(self.doc.email, subject="Welcome to " + startup.product_name, msg=txt % args) | ||||
def on_trash(self): | |||||
if self.name in ["Administrator", "Guest"]: | |||||
webnotes.msgprint("""Hey! You cannot delete user: %s""" % (self.name, ), | |||||
raise_exception=1) | |||||
webnotes.conn.sql("""delete from __Auth where user=%s""", self.name) | |||||
def on_rename(self,newdn,olddn): | def on_rename(self,newdn,olddn): | ||||
# do not allow renaming administrator and guest | # do not allow renaming administrator and guest | ||||
@@ -241,17 +251,4 @@ def get_perm_info(arg=None): | |||||
@webnotes.whitelist() | @webnotes.whitelist() | ||||
def get_defaults(arg=None): | def get_defaults(arg=None): | ||||
return webnotes.conn.sql("""select defkey, defvalue from tabDefaultValue where | return webnotes.conn.sql("""select defkey, defvalue from tabDefaultValue where | ||||
parent=%s and parenttype = 'Profile'""", webnotes.form_dict['profile']) | |||||
@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']) | |||||
webnotes.login_manager.logout(user=webnotes.form_dict['uid']) | |||||
parent=%s and parenttype = 'Profile'""", webnotes.form_dict['profile']) |
@@ -0,0 +1,45 @@ | |||||
// render | |||||
wn.doclistviews['Profile'] = wn.views.ListView.extend({ | |||||
init: function(d) { | |||||
this._super(d) | |||||
this.fields = this.fields.concat([ | |||||
"`tabProfile`.first_name", | |||||
"`tabProfile`.middle_name", | |||||
"`tabProfile`.last_name", | |||||
"`tabProfile`.enabled", | |||||
]); | |||||
this.stats = this.stats.concat(['enabled']); | |||||
// hide Administrator and Guest user | |||||
if(user!="Administrator") { | |||||
this.default_filters = [ | |||||
["Profile", "name", "!=", "Administrator"], | |||||
["Profile", "name", "!=", "Guest"] | |||||
]; | |||||
} | |||||
}, | |||||
prepare_data: function(data) { | |||||
this._super(data); | |||||
data.fullname = $.map([data.first_name, data.middle_name, data.last_name], | |||||
function(val) { return val; }).join(" "); | |||||
}, | |||||
columns: [ | |||||
{width: '3%', content: 'check'}, | |||||
{width: '5%', content: 'avatar'}, | |||||
{width: '3%', content: function(parent, data) { | |||||
var enabled = cint(data.enabled); | |||||
$(parent).html(repl('<span class="docstatus"><i class="%(icon)s" \ | |||||
title="%(title)s"></i></span>', { | |||||
icon: enabled ? "icon-pencil": "icon-exclamation-sign", | |||||
title: enabled ? "Enabled": "Disabled", | |||||
})); | |||||
}}, | |||||
{width: '40%', content: 'name'}, | |||||
{width: '35%', content: 'fullname+tags'}, | |||||
{width: '17%', content:'modified', | |||||
css: {'text-align': 'right', 'color': '#777'}}, | |||||
] | |||||
}); |
@@ -36,6 +36,17 @@ code_fields_dict = { | |||||
'Control Panel':[('startup_code', 'js'), ('startup_css', 'css')] | 'Control Panel':[('startup_code', 'js'), ('startup_css', 'css')] | ||||
} | } | ||||
class DictObj(dict): | |||||
"""dict like object that exposes keys as attributes""" | |||||
def __getattr__(self, key): | |||||
return self.get(key) | |||||
def __setattr__(self, key, value): | |||||
self[key] = value | |||||
def __getstate__(self): | |||||
return self | |||||
def __setstate__(self, d): | |||||
self.update(d) | |||||
version = 'v170' | version = 'v170' | ||||
form_dict = {} | form_dict = {} | ||||
auth_obj = None | auth_obj = None | ||||
@@ -106,13 +106,13 @@ class Database: | |||||
result = self._cursor.fetchall() | result = self._cursor.fetchall() | ||||
ret = [] | ret = [] | ||||
for r in result: | for r in result: | ||||
dict = {} | |||||
row_dict = webnotes.DictObj({}) | |||||
for i in range(len(r)): | for i in range(len(r)): | ||||
val = self.convert_to_simple_type(r[i], formatted) | val = self.convert_to_simple_type(r[i], formatted) | ||||
if as_utf8 and type(val) is unicode: | if as_utf8 and type(val) is unicode: | ||||
val = val.encode('utf-8') | val = val.encode('utf-8') | ||||
dict[self._cursor.description[i][0]] = val | |||||
ret.append(dict) | |||||
row_dict[self._cursor.description[i][0]] = val | |||||
ret.append(row_dict) | |||||
return ret | return ret | ||||
def validate_query(self, q): | def validate_query(self, q): | ||||
@@ -264,35 +264,54 @@ class Database: | |||||
# ====================================================================================== | # ====================================================================================== | ||||
# get a single value from a record | # get a single value from a record | ||||
def build_conditions(self, filters): | |||||
def _build_condition(key): | |||||
""" | |||||
filter's key is passed by map function | |||||
build conditions like: | |||||
* ifnull(`fieldname`, default_value) = %(fieldname)s | |||||
* `fieldname` = %(fieldname)s | |||||
""" | |||||
if "[" in key: | |||||
split_key = key.split("[") | |||||
return "ifnull(`" + split_key[0] + "`, " + split_key[1][:-1] + ") = %(" + key + ")s" | |||||
else: | |||||
return "`" + key + "` = %(" + key + ")s" | |||||
def get_value(self, doctype, docname, fieldname, ignore=None): | |||||
""" | |||||
Get a single / multiple value from a record. | |||||
if isinstance(filters, basestring): | |||||
filters = { "name": filters } | |||||
conditions = map(_build_condition, filters) | |||||
For Single DocType, let docname be = None | |||||
""" | |||||
return " and ".join(conditions), filters | |||||
def get_value(self, doctype, filters=None, fieldname="name", ignore=None, as_dict=False): | |||||
"""Get a single / multiple value from a record. | |||||
For Single DocType, let filters be = None""" | |||||
if filters is not None and (filters!=doctype or filters=='DocType'): | |||||
fl = isinstance(fieldname, basestring) and fieldname or "`, `".join(fieldname) | |||||
conditions, filters = self.build_conditions(filters) | |||||
fl = fieldname | |||||
if docname and (docname!=doctype or docname=='DocType'): | |||||
if type(fieldname) in (list, tuple): | |||||
fl = '`, `'.join(fieldname) | |||||
try: | try: | ||||
import json | |||||
from webnotes.utils import cstr | |||||
r = self.sql("select `%s` from `tab%s` where name='%s'" % (fl, doctype, docname)) | |||||
r = self.sql("select `%s` from `tab%s` where %s" % (fl, doctype, conditions), | |||||
filters, as_dict) | |||||
except Exception, e: | except Exception, e: | ||||
if e.args[0]==1054 and ignore: | if e.args[0]==1054 and ignore: | ||||
return None | return None | ||||
else: | else: | ||||
raise e | raise e | ||||
return r and (len(r[0]) > 1 and r[0] or r[0][0]) or None | return r and (len(r[0]) > 1 and r[0] or r[0][0]) or None | ||||
else: | else: | ||||
if type(fieldname) in (list, tuple): | |||||
fl = "', '".join(fieldname) | |||||
fieldname = isinstance(fieldname, basestring) and [fieldname] or fieldname | |||||
r = self.sql("select value from tabSingles where field in ('%s') and doctype='%s'" % \ | |||||
(fieldname, doctype)) | |||||
return r and (len(r) > 1 and (i[0] for i in r) or r[0][0]) or None | |||||
r = self.sql("select field, value from tabSingles where field in (%s) and \ | |||||
doctype=%s" % (', '.join(['%s']*len(fieldname)), '%s'), tuple(fieldname) + (doctype,), as_dict=False) | |||||
if as_dict: | |||||
return r and webnotes.DictObj(r) or None | |||||
else: | |||||
return r and (len(r) > 1 and [i[0] for i in r] or r[0][1]) or None | |||||
def set_value(self, dt, dn, field, val, modified = None): | def set_value(self, dt, dn, field, val, modified = None): | ||||
from webnotes.utils import now | from webnotes.utils import now | ||||
@@ -29,6 +29,15 @@ default_fields = ['doctype','name','owner','creation','modified','modified_by',' | |||||
#================================================================================= | #================================================================================= | ||||
def insert(doclist): | |||||
from webnotes.model.doclist import DocList | |||||
for d in doclist: | |||||
d["__islocal"] = 1 | |||||
dl = DocList(doclist) | |||||
dl.save() | |||||
return dl | |||||
def check_if_doc_is_linked(dt, dn): | def check_if_doc_is_linked(dt, dn): | ||||
""" | """ | ||||
Raises excption if the given doc(dt, dn) is linked in another record. | Raises excption if the given doc(dt, dn) is linked in another record. | ||||
@@ -91,7 +91,7 @@ class DbTable: | |||||
# index | # index | ||||
t = self.get_index_definitions() | t = self.get_index_definitions() | ||||
if t: add_text += ',\n'.join(self.get_index_definitions()) + ',\n' | if t: add_text += ',\n'.join(self.get_index_definitions()) + ',\n' | ||||
# create table | # create table | ||||
webnotes.conn.sql("""create table `%s` ( | webnotes.conn.sql("""create table `%s` ( | ||||
name varchar(120) not null primary key, | name varchar(120) not null primary key, | ||||
@@ -30,6 +30,7 @@ Group actions like save, etc are performed on doclists | |||||
import webnotes | import webnotes | ||||
from webnotes.utils import cint | from webnotes.utils import cint | ||||
from webnotes.model.doc import Document | |||||
class DocList: | class DocList: | ||||
""" | """ | ||||
@@ -42,9 +43,7 @@ class DocList: | |||||
if dt and dn: | if dt and dn: | ||||
self.load_from_db(dt, dn) | self.load_from_db(dt, dn) | ||||
if type(dt) is list: | if type(dt) is list: | ||||
self.docs = dt | |||||
self.doc = dt[0] | |||||
self.children = dt[1:] | |||||
self.set_doclist(dt) | |||||
def load_from_db(self, dt=None, dn=None, prefix='tab'): | def load_from_db(self, dt=None, dn=None, prefix='tab'): | ||||
""" | """ | ||||
@@ -78,24 +77,19 @@ class DocList: | |||||
""" | """ | ||||
from webnotes.model.utils import expand | from webnotes.model.utils import expand | ||||
self.docs = expand(data) | self.docs = expand(data) | ||||
self.objectify(docname) | |||||
self.set_doclist(self.docs) | |||||
def set_doclist(self, docs): | def set_doclist(self, docs): | ||||
for i, d in enumerate(docs): | |||||
if isinstance(d, dict): | |||||
docs[i] = Document(fielddata=d) | |||||
self.docs = self.doclist = docs | self.docs = self.doclist = docs | ||||
self.doc, self.children = docs[0], docs[1:] | self.doc, self.children = docs[0], docs[1:] | ||||
if self.obj: | if self.obj: | ||||
self.obj.doclist = self.doclist | self.obj.doclist = self.doclist | ||||
self.obj.doc = self.doc | self.obj.doc = self.doc | ||||
def objectify(self, docname=None): | |||||
""" | |||||
Converts self.docs from a list of dicts to list of Documents | |||||
""" | |||||
from webnotes.model.doc import Document | |||||
self.docs = [Document(fielddata=d) for d in self.docs] | |||||
self.set_doclist(self.docs) | |||||
def make_obj(self): | def make_obj(self): | ||||
""" | """ | ||||
Create a DocType object | Create a DocType object | ||||
@@ -215,11 +209,11 @@ class DocList: | |||||
child_map = {} | child_map = {} | ||||
for d in self.children: | for d in self.children: | ||||
if d.fields.has_key('parent'): | |||||
if d.parent: | |||||
d.parent = self.doc.name # rename if reqd | |||||
d.parenttype = self.doc.doctype | |||||
if d.fields.has_key('parent') or d.fields.has_key("parentfield"): | |||||
# if d.parent: | |||||
d.parent = self.doc.name # rename if reqd | |||||
d.parenttype = self.doc.doctype | |||||
d.save(new = cint(d.fields.get('__islocal'))) | d.save(new = cint(d.fields.get('__islocal'))) | ||||
child_map.setdefault(d.doctype, []).append(d.name) | child_map.setdefault(d.doctype, []).append(d.name) | ||||
@@ -248,6 +248,7 @@ class Profile: | |||||
self.can_get_report = d['can_get_report'] | self.can_get_report = d['can_get_report'] | ||||
self.allow_modules = d['allow_modules'] | self.allow_modules = d['allow_modules'] | ||||
self.all_read = d['all_read'] | self.all_read = d['all_read'] | ||||
self.in_create = d['in_create'] | |||||
self.roles = d['roles'] | self.roles = d['roles'] | ||||
self.defaults = d['defaults'] | self.defaults = d['defaults'] | ||||
@@ -345,6 +345,6 @@ class DocTypeNestedSet: | |||||
elif self.doc.name!=root and not self.doc.parent_account: | elif self.doc.name!=root and not self.doc.parent_account: | ||||
msgprint("Parent is mandatory for %s" % (self.doc.name, ), raise_exception=1) | msgprint("Parent is mandatory for %s" % (self.doc.name, ), raise_exception=1) | ||||
if __name__=="__main__": | |||||
webnotes.connect() | |||||
unittest.main() | |||||
# if __name__=="__main__": | |||||
# webnotes.connect() | |||||
# unittest.main() |
@@ -225,6 +225,9 @@ def setup_options(): | |||||
parser.add_option("--backup", help="Takes backup of database in backup folder", | parser.add_option("--backup", help="Takes backup of database in backup folder", | ||||
default=False, action="store_true") | default=False, action="store_true") | ||||
parser.add_option("--test", help="Run test", metavar="MODULE", | |||||
nargs=1) | |||||
return parser.parse_args() | return parser.parse_args() | ||||
@@ -359,7 +362,7 @@ def run(): | |||||
elif options.build_web_cache: | elif options.build_web_cache: | ||||
import website.web_cache | import website.web_cache | ||||
website.web_cache.refresh_cache(True) | |||||
website.web_cache.refresh_cache(["Blog"]) | |||||
elif options.append_future_import: | elif options.append_future_import: | ||||
append_future_import() | append_future_import() | ||||
@@ -367,10 +370,19 @@ def run(): | |||||
elif options.backup: | elif options.backup: | ||||
from webnotes.utils.backups import scheduled_backup | from webnotes.utils.backups import scheduled_backup | ||||
scheduled_backup() | scheduled_backup() | ||||
# print messages | # print messages | ||||
if webnotes.message_log: | if webnotes.message_log: | ||||
print '\n'.join(webnotes.message_log) | print '\n'.join(webnotes.message_log) | ||||
if options.test is not None: | |||||
module_name = options.test | |||||
import unittest | |||||
del sys.argv[1:] | |||||
# is there a better way? | |||||
exec ('from %s import *' % module_name) in globals() | |||||
unittest.main() | |||||
if __name__=='__main__': | if __name__=='__main__': | ||||
run() | run() |