diff --git a/js/wn/views/doclistview.js b/js/wn/views/doclistview.js
index 57d66a5437..cbf1b8818f 100644
--- a/js/wn/views/doclistview.js
+++ b/js/wn/views/doclistview.js
@@ -178,7 +178,7 @@ wn.views.DocListView = wn.ui.Listing.extend({
return this.listview.fields;
},
get_args: function() {
- return {
+ var args = {
doctype: this.doctype,
fields: this.get_query_fields(),
filters: this.filter_list.get_filters(),
@@ -187,6 +187,13 @@ wn.views.DocListView = wn.ui.Listing.extend({
order_by: this.listview.order_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() {
var me = this;
@@ -550,9 +557,11 @@ wn.views.RecordListView = wn.views.DocListView.extend({
get_args: function() {
var args = this._super();
+
$.each((this.default_filters || []), function(i, f) {
args.filters.push(f);
});
+
args.docstatus = args.docstatus.concat((this.default_docstatus || []));
return args;
},
diff --git a/js/wn/views/grid_report.js b/js/wn/views/grid_report.js
index 4a97f3462a..f5318d0b55 100644
--- a/js/wn/views/grid_report.js
+++ b/js/wn/views/grid_report.js
@@ -278,6 +278,7 @@ wn.views.GridReport = Class.extend({
});
},
make: function() {
+ var me = this;
// plot wrapper
this.plot_area = $('
'user_fullname': get_user_fullname(webnotes.session['user'])
}
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):
# do not allow renaming administrator and guest
@@ -241,17 +251,4 @@ def get_perm_info(arg=None):
@webnotes.whitelist()
def get_defaults(arg=None):
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'])
\ No newline at end of file
diff --git a/py/core/doctype/profile/profile_list.js b/py/core/doctype/profile/profile_list.js
new file mode 100644
index 0000000000..fe7f01e407
--- /dev/null
+++ b/py/core/doctype/profile/profile_list.js
@@ -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('', {
+ 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'}},
+
+ ]
+});
\ No newline at end of file
diff --git a/py/webnotes/__init__.py b/py/webnotes/__init__.py
index 1131833667..e4aac65d82 100644
--- a/py/webnotes/__init__.py
+++ b/py/webnotes/__init__.py
@@ -36,6 +36,17 @@ code_fields_dict = {
'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'
form_dict = {}
auth_obj = None
diff --git a/py/webnotes/db.py b/py/webnotes/db.py
index 9389c74a93..48a1b35432 100644
--- a/py/webnotes/db.py
+++ b/py/webnotes/db.py
@@ -106,13 +106,13 @@ class Database:
result = self._cursor.fetchall()
ret = []
for r in result:
- dict = {}
+ row_dict = webnotes.DictObj({})
for i in range(len(r)):
val = self.convert_to_simple_type(r[i], formatted)
if as_utf8 and type(val) is unicode:
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
def validate_query(self, q):
@@ -264,35 +264,54 @@ class Database:
# ======================================================================================
# 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:
- 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:
if e.args[0]==1054 and ignore:
return None
else:
raise e
+
return r and (len(r[0]) > 1 and r[0] or r[0][0]) or None
+
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):
from webnotes.utils import now
diff --git a/py/webnotes/model/__init__.py b/py/webnotes/model/__init__.py
index 760149f42c..b9407202fc 100644
--- a/py/webnotes/model/__init__.py
+++ b/py/webnotes/model/__init__.py
@@ -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):
"""
Raises excption if the given doc(dt, dn) is linked in another record.
diff --git a/py/webnotes/model/db_schema.py b/py/webnotes/model/db_schema.py
index 1027168599..2d39a7a01f 100644
--- a/py/webnotes/model/db_schema.py
+++ b/py/webnotes/model/db_schema.py
@@ -91,7 +91,7 @@ class DbTable:
# index
t = self.get_index_definitions()
if t: add_text += ',\n'.join(self.get_index_definitions()) + ',\n'
-
+
# create table
webnotes.conn.sql("""create table `%s` (
name varchar(120) not null primary key,
diff --git a/py/webnotes/model/doclist.py b/py/webnotes/model/doclist.py
index 9fa6456cd4..3a57e20db0 100644
--- a/py/webnotes/model/doclist.py
+++ b/py/webnotes/model/doclist.py
@@ -30,6 +30,7 @@ Group actions like save, etc are performed on doclists
import webnotes
from webnotes.utils import cint
+from webnotes.model.doc import Document
class DocList:
"""
@@ -42,9 +43,7 @@ class DocList:
if dt and dn:
self.load_from_db(dt, dn)
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'):
"""
@@ -78,24 +77,19 @@ class DocList:
"""
from webnotes.model.utils import expand
self.docs = expand(data)
- self.objectify(docname)
+ self.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.doc, self.children = docs[0], docs[1:]
if self.obj:
self.obj.doclist = self.doclist
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):
"""
Create a DocType object
@@ -215,11 +209,11 @@ class DocList:
child_map = {}
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')))
child_map.setdefault(d.doctype, []).append(d.name)
diff --git a/py/webnotes/profile.py b/py/webnotes/profile.py
index e26439a11d..b2742e1d02 100644
--- a/py/webnotes/profile.py
+++ b/py/webnotes/profile.py
@@ -248,6 +248,7 @@ class Profile:
self.can_get_report = d['can_get_report']
self.allow_modules = d['allow_modules']
self.all_read = d['all_read']
+ self.in_create = d['in_create']
self.roles = d['roles']
self.defaults = d['defaults']
diff --git a/py/webnotes/utils/nestedset.py b/py/webnotes/utils/nestedset.py
index fb1650ba1b..b4e7250c87 100644
--- a/py/webnotes/utils/nestedset.py
+++ b/py/webnotes/utils/nestedset.py
@@ -345,6 +345,6 @@ class DocTypeNestedSet:
elif self.doc.name!=root and not self.doc.parent_account:
msgprint("Parent is mandatory for %s" % (self.doc.name, ), raise_exception=1)
-if __name__=="__main__":
- webnotes.connect()
- unittest.main()
\ No newline at end of file
+# if __name__=="__main__":
+# webnotes.connect()
+# unittest.main()
\ No newline at end of file
diff --git a/wnf.py b/wnf.py
index 648e7d61ac..6b369493be 100755
--- a/wnf.py
+++ b/wnf.py
@@ -225,6 +225,9 @@ def setup_options():
parser.add_option("--backup", help="Takes backup of database in backup folder",
default=False, action="store_true")
+
+ parser.add_option("--test", help="Run test", metavar="MODULE",
+ nargs=1)
return parser.parse_args()
@@ -359,7 +362,7 @@ def run():
elif options.build_web_cache:
import website.web_cache
- website.web_cache.refresh_cache(True)
+ website.web_cache.refresh_cache(["Blog"])
elif options.append_future_import:
append_future_import()
@@ -367,10 +370,19 @@ def run():
elif options.backup:
from webnotes.utils.backups import scheduled_backup
scheduled_backup()
-
+
# print messages
if 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__':
run()