Merge branch 'master' into edge

This commit is contained in:
Anand Doshi 2013-02-21 15:25:46 +05:30
commit 176a722dff
58 changed files with 1712 additions and 368 deletions

View file

@ -144,7 +144,7 @@ class DocType:
def post(self):
"""
Save diff between Customize Form ModelWrapper and DocType ModelWrapper as property setter entries
Save diff between Customize Form Bean and DocType Bean as property setter entries
"""
if self.doc.doc_type:
from webnotes.model import doc

View file

@ -1,8 +1,8 @@
[
{
"creation": "2013-01-15 17:23:52",
"creation": "2013-02-18 13:36:19",
"docstatus": 0,
"modified": "2013-01-22 14:56:00",
"modified": "2013-02-18 17:19:42",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -161,6 +161,13 @@
"reqd": 0,
"search_index": 0
},
{
"description": "Allow Import via Data Import Tool",
"doctype": "DocField",
"fieldname": "allow_import",
"fieldtype": "Check",
"label": "Allow Import"
},
{
"doctype": "DocField",
"fieldname": "cb11",

View file

@ -12,6 +12,7 @@
"Max Attachments",
"Description",
"Is it a Custom DocType created by you?",
"Allow Import",
"Permissions Settings",
"DocType",
"Search Fields",
@ -40,6 +41,7 @@
"Hide Email",
"Is Single",
"Hide Print",
"Allow Import via Data Import Tool",
"User Cannot Search",
"Naming",
"Permissions",

View file

@ -26,7 +26,7 @@ import webnotes
from webnotes.utils import cint, cstr, default_fields, flt
from webnotes.model import db_exists, default_fields
from webnotes.model.doc import Document, addchild, make_autoname
from webnotes.model.wrapper import getlist
from webnotes.model.bean import getlist
from webnotes import msgprint
from webnotes.model.doctype import get
@ -72,8 +72,11 @@ class DocType:
from `tabTable Mapper Detail` where parent ="%s" order by match_id""" \
% self.doc.name, as_dict=1)
if isinstance(from_to_list, basestring):
from_to_list = eval(from_to_list)
for t in tbl_list:
if [t['from_table'], t['to_table']] in eval(from_to_list):
if [t['from_table'], t['to_table']] in from_to_list:
self.map_fields(t, from_doctype, from_docname, to_doc, doclist)
# Doclist is required when called from server side for refreshing table
@ -143,12 +146,12 @@ class DocType:
from_flds = [d.fieldname for d in get(t['from_table']).get_parent_doclist() \
if cint(d.no_copy) == 0 and d.docstatus != 2 and d.fieldname \
and d.fieldtype not in ('Table', 'Section Break', 'Column Break', 'HTML')]
and d.fieldtype not in ('Table', 'Section Break', 'Column Break', 'HTML', 'Button')]
to_flds = [d.fieldname for d in get(t['to_table']).get_parent_doclist() \
if cint(d.no_copy) == 0 and d.docstatus != 2 and d.fieldname \
and d.fieldtype not in ('Table', 'Section Break', 'Column Break', 'HTML')]
and d.fieldtype not in ('Table', 'Section Break', 'Column Break', 'HTML', 'Button')]
similar_flds = [[d, d, 'Yes'] for d in from_flds \
if d in to_flds and d not in exception_flds]

View file

@ -46,20 +46,6 @@ class DocType:
cnt = 1
self.doc.name += '-' + str(cnt)
def validate(self):
"""
Update $image tags
"""
import re
p = re.compile('\$image\( (?P<name> [^)]*) \)', re.VERBOSE)
if self.doc.content:
self.doc.content = p.sub(self.replace_by_img, self.doc.content)
def replace_by_img(self, match):
import webnotes
name = match.group('name')
return '<img src="cgi-bin/getfile.cgi?ac=%s&name=%s">' % (webnotes.conn.get('Control Panel', None, 'account_id'), name)
# export
def on_update(self):
"""

View file

@ -255,9 +255,4 @@ def get_perm_info(arg=None):
cancel, amend from tabDocPerm where role=%s
and docstatus<2 order by parent, permlevel""",
webnotes.form_dict['role'], as_dict=1)
@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'])

View file

@ -1,86 +1,77 @@
[
{
"owner": "Administrator",
"creation": "2013-01-08 15:50:01",
"docstatus": 0,
"creation": "2012-12-20 17:16:48",
"modified": "2013-02-19 10:42:13",
"modified_by": "Administrator",
"modified": "2013-01-07 17:09:53"
"owner": "Administrator"
},
{
"istable": 0,
"allow_print": 0,
"module": "Core",
"autoname": "field:role_name",
"read_only": 0,
"allow_copy": 0,
"allow_email": 0,
"hide_heading": 0,
"issingle": 0,
"name": "__common__",
"allow_print": 0,
"allow_rename": 1,
"autoname": "field:role_name",
"doctype": "DocType",
"hide_heading": 0,
"hide_toolbar": 0,
"allow_copy": 0
"issingle": 0,
"istable": 0,
"module": "Core",
"name": "__common__",
"read_only": 0
},
{
"doctype": "DocField",
"name": "__common__",
"parent": "Role",
"doctype": "DocField",
"parentfield": "fields",
"parenttype": "DocType",
"permlevel": 0,
"parentfield": "fields"
},
{
"parent": "Role",
"read": 1,
"cancel": 0,
"name": "__common__",
"amend": 0,
"create": 1,
"doctype": "DocPerm",
"submit": 0,
"write": 1,
"parenttype": "DocType",
"role": "System Manager",
"permlevel": 0,
"parentfield": "permissions"
},
{
"name": "Role",
"doctype": "DocType"
},
{
"oldfieldtype": "Select",
"doctype": "DocField",
"label": "Module",
"oldfieldname": "module",
"fieldname": "module",
"fieldtype": "Select",
"reqd": 1,
"options": "link:Module Def"
},
{
"oldfieldtype": "Data",
"doctype": "DocField",
"label": "Role Name",
"oldfieldname": "role_name",
"fieldname": "role_name",
"fieldtype": "Data",
"reqd": 1
},
{
"description": "Default values are set across the role and can be over-ridden by user permissions.",
"oldfieldtype": "Table",
"doctype": "DocField",
"label": "Defaults",
"oldfieldname": "defaults",
"fieldname": "defaults",
"fieldtype": "Table",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "DefaultValue"
"cancel": 0,
"create": 1,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Role",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 1,
"submit": 0,
"write": 1
},
{
"doctype": "DocPerm"
"doctype": "DocType",
"name": "Role"
},
{
"doctype": "DocField",
"fieldname": "module",
"fieldtype": "Select",
"label": "Module",
"oldfieldname": "module",
"oldfieldtype": "Select",
"options": "link:Module Def"
},
{
"doctype": "DocField",
"fieldname": "role_name",
"fieldtype": "Data",
"label": "Role Name",
"oldfieldname": "role_name",
"oldfieldtype": "Data"
},
{
"amend": 0,
"doctype": "DocPerm",
"role": "System Manager"
},
{
"doctype": "DocPerm",
"role": "Administrator"
}
]

View file

@ -37,7 +37,7 @@ class DocType:
"fieldname":self.doc.workflow_state_field})):
# create custom field
webnotes.model_wrapper([{
webnotes.bean([{
"doctype":"Custom Field",
"dt": self.doc.document_type,
"__islocal": 1,

View file

@ -141,15 +141,23 @@ wn.pages['data-import-tool'].onload = function(wrapper) {
});
// add overwrite option
var $submit_btn = $('#dit-upload-area form input[type="submit"]');
$('<input type="checkbox" name="overwrite" style="margin-top: -3px">\
<span> Overwrite</span>\
<p class="help">If you are uploading a child table (for example Item Price), the all the entries of that table will be deleted (for that parent record) and new entries will be made.</p><br>')
.insertBefore('#dit-upload-area form input[type="submit"]')
.insertBefore($submit_btn);
// add submit option
$('<input type="checkbox" name="_submit" style="margin-top: -3px">\
<span> Submit</span>\
<p class="help">If you are inserting new records (overwrite not checked) \
and if you have submit permission, the record will be submitted.</p><br>')
.insertBefore($submit_btn);
// add ignore option
$('<input type="checkbox" name="ignore_encoding_errors" style="margin-top: -3px">\
<span> Ignore Encoding Errors</span><br><br>')
.insertBefore('#dit-upload-area form input[type="submit"]')
.insertBefore($submit_btn);
// rename button
$('#dit-upload-area form input[type="submit"]')

View file

@ -4,7 +4,7 @@ import webnotes
import webnotes.model.doc
import webnotes.model.doctype
from webnotes.model.doc import Document
from webnotes.utils import cstr
from webnotes.utils import cstr, cint, flt
from webnotes.utils.datautils import UnicodeWriter
data_keys = webnotes._dict({
@ -19,7 +19,7 @@ doctype_dl = None
@webnotes.whitelist()
def get_doctypes():
return [r[0] for r in webnotes.conn.sql("""select name from `tabDocType`
where document_type = 'Master'""")]
where document_type = 'Master' or allow_import = 1""")]
@webnotes.whitelist()
def get_doctype_options():
@ -137,6 +137,9 @@ def getdocfield(fieldname):
def upload():
"""upload data"""
global doctype_dl
webnotes.mute_emails = True
from webnotes.utils.datautils import read_csv_content_from_uploaded_file
def bad_template():
@ -223,6 +226,8 @@ def upload():
webnotes.conn.rollback()
else:
webnotes.conn.commit()
webnotes.mute_emails = False
return {"messages": ret, "error": error}
@ -271,6 +276,10 @@ def check_record(d, parenttype):
if val and docfield.fieldtype=='Date':
d[key] = parse_date(val)
elif val and docfield.fieldtype in ["Int", "Check"]:
d[key] = cint(val)
elif val and docfield.fieldtype in ["Currency", "Float"]:
d[key] = flt(val)
def getlink(doctype, name):
return '<a href="#Form/%(doctype)s/%(name)s">%(name)s</a>' % locals()
@ -282,21 +291,25 @@ def delete_child_rows(rows, doctype):
def import_doc(d, doctype, overwrite, row_idx):
"""import main (non child) document"""
from webnotes.model.wrapper import ModelWrapper
from webnotes.model.bean import Bean
if webnotes.conn.exists(doctype, d['name']):
if overwrite:
doclist = webnotes.model.doc.get(doctype, d['name'])
doclist[0].fields.update(d)
model_wrapper = ModelWrapper(doclist)
model_wrapper.save()
bean = Bean(doclist)
bean.save()
return 'Updated row (#%d) %s' % (row_idx, getlink(doctype, d['name']))
else:
return 'Ignored row (#%d) %s (exists)' % (row_idx,
getlink(doctype, d['name']))
else:
d['__islocal'] = 1
dl = ModelWrapper([webnotes.model.doc.Document(fielddata = d)])
dl = Bean([webnotes.model.doc.Document(fielddata = d)])
dl.save()
if webnotes.form_dict.get("_submit")=="on":
dl.submit()
return 'Inserted row (#%d) %s' % (row_idx, getlink(doctype,
dl.doc.fields['name']))

View file

@ -9,7 +9,7 @@ def get_roles_and_doctypes():
ifnull(issingle,0)=0 and
name not in ('DocType')""")],
"roles": [d[0] for d in webnotes.conn.sql("""select name from tabRole where name not in
('All', 'Guest', 'Administrator')""")]
('Guest', 'Administrator')""")]
}
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])

View file

@ -1,5 +1,6 @@
from __future__ import unicode_literals
import webnotes
import webnotes.defaults
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def get_users_and_links():
@ -39,9 +40,8 @@ def get_properties(user=None, key=None):
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def remove(user, name):
webnotes.conn.sql("""delete from tabDefaultValue where name=%s""", name)
webnotes.clear_cache(user=user)
webnotes.defaults.clear_default(name=name)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def add(parent, defkey, defvalue):
webnotes.conn.add_default(defkey, defvalue, parent)
webnotes.defaults.add_user_default(defkey, defvalue, parent)

View file

@ -13,10 +13,8 @@
{
"public/css/all-web.css": [
"lib/public/css/bootstrap.css",
"lib/public/css/bootstrap-responsive.css",
"lib/public/css/font-awesome.css",
"lib/public/css/legacy/body.css",
"lib/public/css/ui/common.css",
"lib/public/css/ui/layout.css"
]
},
@ -76,6 +74,7 @@
"lib/public/js/wn/request.js",
"lib/public/js/wn/router.js",
"lib/public/js/wn/app.js",
"lib/public/js/wn/defaults.js",
"lib/public/js/legacy/globals.js",
"lib/public/js/legacy/utils/datatype.js",

1092
public/css/bootstrap-responsive.css vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -12,17 +12,12 @@ body {
}
footer {
text-align: center;
color: inherit;
padding: 10px;
font-size: 12px;
line-height: 1.7;
}
footer, footer a {
color: #999;
}
label {
padding-top: 15px;
color: #404040;

View file

@ -165,7 +165,7 @@ wn.datetime = {
+ d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds();
},
user_to_str: function(d) {
user_to_str: function(d, no_time_str) {
var user_fmt = this.get_user_fmt();
var time_str = '';
@ -193,6 +193,9 @@ wn.datetime = {
var d = d.split('-');
var val = d[2]+'-'+d[0]+'-'+d[1];
}
if(no_time_str)time_str = '';
return val + time_str;
},

View file

@ -276,3 +276,16 @@ _f.Frm.prototype.call = function(opts) {
_f.Frm.prototype.get_field = function(field) {
return cur_frm.fields_dict[field];
}
_f.Frm.prototype.map = function(from_to_list) {
var doctype = from_to_list[0][1];
console.log("Making " + doctype);
var new_docname = wn.model.make_new_doc_and_get_name(doctype);
$c("dt_map", {
"docs": wn.model.compress([locals[doctype][new_docname]]),
"from_doctype": cur_frm.doc.doctype,
"to_doctype": doctype,
"from_docname": cur_frm.doc.name,
"from_to_list": JSON.stringify(from_to_list),
}, function(r, rt) { if(!r.exc) loaddoc(doctype, new_docname); });
}

View file

@ -629,6 +629,10 @@ LinkField.prototype.make_input = function() {
me.get_value = function() { return me.txt.value; }
// increasing zindex of input to increase zindex of autosuggest
// because of the increase in zindex of dialog_wrapper
$(me.txt).css({"z-index": 10});
$(me.txt).autocomplete({
source: function(request, response) {
var args = {

View file

@ -53,7 +53,7 @@ _f.Frm = function(doctype, parent, in_form) {
this.docname = '';
this.doctype = doctype;
this.display = 0;
this.refresh_if_stale_for = 600;
this.refresh_if_stale_for = 120;
var me = this;
this.last_view_is_edit = {};
@ -881,16 +881,31 @@ _f.Frm.prototype.reload_doc = function() {
var me = this;
var onsave = function(r, rtxt) {
// n tweets and last comment
me.runclientscript('setup', me.doctype, me.docname);
//me.runclientscript('setup', me.doctype, me.docname);
me.refresh();
}
if(me.doc.__islocal) {
// reload only doctype
$c('webnotes.widgets.form.load.getdoctype', {'doctype':me.doctype }, onsave, null, null, 'Refreshing ' + me.doctype + '...');
wn.call({
method: "webnotes.widgets.form.load.getdoctype",
args: {
doctype: me.doctype
},
callback: function(r) {
me.refresh();
}
})
} else {
// reload doc and docytpe
$c('webnotes.widgets.form.load.getdoc', {'name':me.docname, 'doctype':me.doctype, 'getdoctype':1, 'user':user}, onsave, null, null, 'Refreshing ' + me.docname + '...');
wn.call({
method: "webnotes.widgets.form.load.getdoc",
args: {
doctype: me.doctype,
name: me.docname
},
callback: function(r) {
me.refresh();
}
});
}
}

View file

@ -113,38 +113,6 @@ _f.SectionBreak.prototype.make_body = function() {
}
}
_f.SectionBreak.prototype.has_data = function() {
// return true if
// 1. any field in the section is mandatory & not set as default
// 2. any field in the section has data that is not default
// 3. if table, table has rows
var me = this;
for(var i in me.fields) {
var f = me.fields[i];
var v = f.get_value ? f.get_value() : null;
// value that is not default
defaultval = f.df['default'] || sys_defaults[f.fieldname] || user_defaults[f.fieldname];
if(v && v != defaultval) {
return true;
}
// unfilled mandatory field
if(f.df.reqd && !v) {
return true;
}
// filled table
if(f.df.fieldtype=='Table') {
if(f.grid.get_children().length || f.df.reqd) {
return true;
}
}
}
return false;
}
_f.SectionBreak.prototype.refresh = function(from_form) {
var hidden = 0;
// we generate section breaks, but hide it based on perms/hidden value

46
public/js/wn/defaults.js Normal file
View file

@ -0,0 +1,46 @@
wn.defaults = {
get_user_default: function(key) {
var d = wn.boot.profile.defaults[key];
if($.isArray(d)) d = d[0];
return d;
},
get_user_defaults: function(key) {
var d = wn.boot.profile.defaults[key];
if(!$.isArray(d)) d = [d];
return d;
},
get_global_default: function(key) {
var d = sys_defaults[key];
if($.isArray(d)) d = d[0];
return d;
},
get_global_defaults: function(key) {
var d = sys_defaults[key];
if(!$.isArray(d)) d = [d];
return d;
},
set_default: function(key, value, callback) {
if(typeof value=="string")
value = JSON.stringify(value);
wn.boot.profile.defaults[key] = value;
wn.call({
method: "webnotes.client.set_default",
args: {
key: key,
value: value
},
callback: callback || function(r) {}
});
},
get_default: function(key) {
var value = wn.boot.profile.defaults[key];
if(value) {
try {
return JSON.parse(value)
} catch(e) {
return value;
}
}
},
}

View file

@ -40,6 +40,7 @@ $.extend(wn.datetime, {
return [double_digit(d.getHours()), double_digit(d.getMinutes()), double_digit(d.getSeconds())].join(":")
},
get_datetime_as_string: function(d) {
if(!d) return null;
return [d.getFullYear(), double_digit(d.getMonth()+1), double_digit(d.getDate())].join("-") + " "
+ [double_digit(d.getHours()), double_digit(d.getMinutes()), double_digit(d.getSeconds())].join(":");
}

View file

@ -40,33 +40,9 @@ $.extend(wn.user, {
return true;
}
},
set_default: function(key, value, callback) {
if(typeof value=="string")
value = JSON.stringify(value);
wn.boot.profile.defaults[key] = value;
wn.call({
method: "webnotes.client.set_default",
args: {
key: key,
value: value
},
callback: callback || function(r) {}
});
},
get_default: function(key) {
var value = wn.boot.profile.defaults[key];
if(value) {
try {
return JSON.parse(value)
} catch(e) {
return value;
}
}
},
get_desktop_items: function() {
// get user sequence preference
var user_list = wn.user.get_default("_desktop_items");
var user_list = wn.defaults.get_default("_desktop_items");
if(user_list && user_list.length)
var modules_list = user_list;

View file

@ -40,6 +40,11 @@ $.extend(wn.model, {
if(!in_list(no_value_fields, f.fieldtype) && doc[f.fieldname]==null) {
var v = wn.model.get_default_value(f);
if(v) {
if(in_list(["Int", "Check"], f.fieldtype))
v = cint(v);
else if(in_list(["Currency", "Float"], f.fieldtype))
v = flt(v);
doc[f.fieldname] = v;
updated.push(f.fieldname);
}
@ -63,10 +68,8 @@ $.extend(wn.model, {
return dateutil.get_cur_time()
else if(df["default"])
return df["default"];
else if(user_defaults[df.fieldname])
return user_defaults[df.fieldname][0];
else if(sys_defaults[df.fieldname])
return sys_defaults[df.fieldname];
else if(wn.defaults.get_user_default(df.fieldname))
return wn.defaults.get_user_default(df.fieldname);
},
add_child: function(doc, childtype, parentfield) {

View file

@ -65,7 +65,11 @@ $.extend(wn.meta, {
},
get_label: function(dt, fn, dn) {
return this.get_docfield(dt, fn, dn).label || fn;
if(fn==="owner") {
return "Owner";
} else {
return this.get_docfield(dt, fn, dn).label || fn;
}
},
get_print_formats: function(doctype) {

View file

@ -92,7 +92,7 @@ $.extend(wn.perm, {
$.each(wn.model.get("DocPerm", {parent:doctype}), function(i, p) {
if(p.permlevel==0 && p.match && in_list(user_roles, p.role)) {
match_keys = wn.perm.get_match_keys(p.match);
match_rules[match_keys[0]] = user_defaults[match_keys[1]];
match_rules[match_keys[0]] = wn.defaults.get_user_defaults(match_keys[1]);
}
});
return match_rules;
@ -115,10 +115,11 @@ $.extend(wn.perm, {
var document_key = key_list[0];
var default_key = key_list[1];
if(user_defaults[default_key]) {
for(var i=0;i<user_defaults[default_key].length;i++) {
var match_values = wn.defaults.get_user_defaults(key)
if(match_values) {
for(var i=0 ; i<match_values.length;i++) {
// user must have match field in defaults
if(user_defaults[default_key][i]==locals[doctype][name][document_key]) {
if(match_values[i]==locals[doctype][name][document_key]) {
// must match document
return true;
}

View file

@ -63,7 +63,7 @@ wn.ui.Dialog = wn.ui.FieldGroup.extend({
this.appframe.$titlebar.find('.appframe-title').html(t || '');
},
set_postion: function() {
this.zindex = 1;
this.zindex = 10;
if(cur_dialog) {
this.zindex = cur_dialog.zindex + 1;
}

View file

@ -20,7 +20,7 @@ wn.ui.toolbar.Bookmarks = Class.extend({
setup: function() {
var me = this;
this.bookmarks = wn.user.get_default("_bookmarks") || [];
this.bookmarks = wn.defaults.get_default("_bookmarks") || [];
for(var i=this.bookmarks.length-1; i>=0; i--) {
var bookmark = this.bookmarks[i];
this.add_item(bookmark.route, bookmark.title)
@ -72,7 +72,7 @@ wn.ui.toolbar.Bookmarks = Class.extend({
return wn.utils.filter_dict(this.bookmarks, {"route": route}).length;
},
save: function() {
wn.user.set_default("_bookmarks", this.bookmarks);
wn.defaults.set_default("_bookmarks", this.bookmarks);
},
remove: function(route) {
this.bookmarks = $.map(this.bookmarks, function(d) {

View file

@ -115,14 +115,16 @@ wn.views.Calendar = Class.extend({
},
eventClick: function(event, jsEvent, view) {
// edit event description or delete
if(wn.model.can_read(me.doctype))
wn.set_route("Form", me.doctype, event.name);
var doctype = event.doctype || me.doctype;
if(wn.model.can_read(doctype)) {
wn.set_route("Form", doctype, event.name);
}
},
eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
me.update_event(event);
me.update_event(event, revertFunc);
},
eventResize: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
me.update_event(event);
me.update_event(event, revertFunc);
},
select: function(startDate, endDate, allDay, jsEvent, view) {
if(jsEvent.day_clicked && view.name=="month")
@ -160,15 +162,20 @@ wn.views.Calendar = Class.extend({
var me = this;
$.each(events, function(i, d) {
d.id = d.name;
d.editable = wn.model.can_write(d.doctype || this.doctype);
d.editable = wn.model.can_write(d.doctype || me.doctype);
// do not allow submitted/cancelled events to be moved / extended
if(d.docstatus && d.docstatus > 0) {
d.editable = false;
}
$.each(me.field_map, function(target, source) {
d[target] = d[source];
});
if(!me.field_map.allDay)
d.allDay = 1;
if(d.status) {
if(me.style_map) {
$.extend(d, me.styles[me.style_map[d.status]] || {});
@ -180,7 +187,7 @@ wn.views.Calendar = Class.extend({
}
})
},
update_event: function(event) {
update_event: function(event, revertFunc) {
var me = this;
wn.model.remove_from_locals(me.doctype, event.name);
wn.call({
@ -189,6 +196,7 @@ wn.views.Calendar = Class.extend({
callback: function(r) {
if(r.exc) {
show_alert("Unable to update event.")
revertFunc();
}
}
});

View file

@ -92,7 +92,11 @@ wn.views.DocListView = wn.ui.Listing.extend({
if(keys(match_rules).length) {
var match_text = []
$.each(match_rules, function(key, values) {
match_text.push(wn._(wn.meta.get_label(me.doctype, key)) + " = " + wn.utils.comma_or(values));
if(values.length==0) {
match_text.push(wn._(wn.meta.get_label(me.doctype, key)) + wn._(" is not set"));
} else if(values.length) {
match_text.push(wn._(wn.meta.get_label(me.doctype, key)) + " = " + wn.utils.comma_or(values));
}
});
wn.utils.set_footnote(this, this.$page.find(".layout-main-section"),
wn._("Showing only for") + ": " + match_text.join(" & "));

View file

@ -98,7 +98,7 @@ wn.views.ReportView = wn.ui.Listing.extend({
set_init_columns: function() {
// pre-select mandatory columns
var columns = wn.user.get_default("_list_settings:" + this.doctype);
var columns = wn.defaults.get_default("_list_settings:" + this.doctype);
if(!columns) {
var columns = [['name', this.doctype],];
$.each(wn.meta.docfield_list[this.doctype], function(i, df) {
@ -465,7 +465,7 @@ wn.ui.ColumnPicker = Class.extend({
columns.push([$selected.attr('fieldname'),
$selected.attr('table')]);
});
wn.user.set_default("_list_settings:" + me.doctype, columns);
wn.defaults.set_default("_list_settings:" + me.doctype, columns);
me.list.columns = columns;
me.list.run();
});

View file

@ -258,6 +258,7 @@ def get_roles(user=None, with_standard=True):
def has_permission(doctype, ptype="read", doc=None):
"""check if user has permission"""
from webnotes.defaults import get_user_default_as_list
if session.user=="Administrator":
return True
if conn.get_value("DocType", doctype, "istable"):
@ -279,7 +280,7 @@ def has_permission(doctype, ptype="read", doc=None):
keys = [p.match, p.match]
if doc.fields.get(keys[0],"[No Value]") \
in conn.get_defaults_as_list(keys[1], session.user):
in get_user_default_as_list(keys[1]):
return True
else:
match_failed[keys[0]] = doc.fields.get(keys[0],"[No Value]")
@ -312,12 +313,15 @@ def doclist(lst=None):
from webnotes.model.doclist import DocList
return DocList(lst)
def model_wrapper(doctype=None, name=None):
from webnotes.model.wrapper import ModelWrapper
return ModelWrapper(doctype, name)
def bean(doctype=None, name=None, copy=None):
from webnotes.model.bean import Bean
if copy:
return Bean(copy_doclist(copy))
else:
return Bean(doctype, name)
def get_doclist(doctype, name=None):
return model_wrapper(doctype, name).doclist
return bean(doctype, name).doclist
def get_doctype(doctype, processed=False):
import webnotes.model.doctype
@ -357,7 +361,7 @@ def get_method(method_string):
def make_property_setter(args):
args = _dict(args)
model_wrapper([{
bean([{
'doctype': "Property Setter",
'doctype_or_field': args.doctype_or_field or "DocField",
'doc_type': args.doctype,
@ -389,4 +393,15 @@ def copy_doclist(in_doclist):
new_doclist.append(doc(d.fields.copy()))
return doclist(new_doclist)
def map_doclist(from_to_list, from_docname, to_doclist=None):
from_doctype, to_doctype = from_to_list[0][0], from_to_list[0][1]
if to_doclist:
to_doclist = bean(to_doclist).doclist
else:
to_doclist = bean({"doctype": to_doctype}).doclist
mapper = get_obj("DocType Mapper", "-".join(from_to_list[0]))
to_doclist = mapper.dt_map(from_doctype, to_doctype, from_docname, to_doclist[0], to_doclist, from_to_list)
return to_doclist

View file

@ -26,6 +26,7 @@ bootstrap client session
"""
import webnotes
import webnotes.defaults
import webnotes.model.doc
import webnotes.widgets.page
@ -43,7 +44,7 @@ def get_bootinfo():
# system info
bootinfo['control_panel'] = webnotes._dict(cp.copy())
bootinfo['sysdefaults'] = webnotes.utils.get_defaults()
bootinfo['sysdefaults'] = webnotes.defaults.get_defaults()
bootinfo['server_date'] = webnotes.utils.nowdate()
if webnotes.session['user'] != 'Guest':

View file

@ -30,7 +30,7 @@ def get(doctype, name=None, filters=None):
name = webnotes.conn.get_value(doctype, json.loads(filters))
if not name:
raise Exception, "No document found for given filters"
return [d.fields for d in webnotes.model_wrapper(doctype, name).doclist]
return [d.fields for d in webnotes.bean(doctype, name).doclist]
@webnotes.whitelist()
def insert(doclist):
@ -45,7 +45,7 @@ def save(doclist):
if isinstance(doclist, basestring):
doclist = json.loads(doclist)
doclistobj = webnotes.model_wrapper(doclist)
doclistobj = webnotes.bean(doclist)
doclistobj.save()
return [d.fields for d in doclist]
@ -55,14 +55,14 @@ def submit(doclist):
if isinstance(doclist, basestring):
doclist = json.loads(doclist)
doclistobj = webnotes.model_wrapper(doclist)
doclistobj = webnotes.bean(doclist)
doclistobj.submit()
return [d.fields for d in doclist]
@webnotes.whitelist()
def cancel(doctype, name):
wrapper = webnotes.model_wrapper(doctype, name)
wrapper = webnotes.bean(doctype, name)
wrapper.cancel()
return [d.fields for d in wrapper.doclist]
@ -77,4 +77,4 @@ def set_default(key, value, parent=None):
def make_width_property_setter():
doclist = json.loads(webnotes.form_dict.doclist)
if doclist[0]["doctype"]=="Property Setter" and doclist[0]["property"]=="width":
webnotes.model_wrapper(doclist).save()
webnotes.bean(doclist).save()

View file

@ -243,7 +243,7 @@ class Database:
return " and ".join(conditions), filters
def get(self, doctype, filters=None, as_dict=False):
def get(self, doctype, filters=None, as_dict=True):
return self.get_value(doctype, filters, "*", as_dict=as_dict)
def get_value(self, doctype, filters=None, fieldname="name", ignore=None, as_dict=False):
@ -299,72 +299,38 @@ class Database:
doc.fields[field] = val
def set_global(self, key, val, user='__global'):
res = self.sql('select defkey from `tabDefaultValue` where defkey=%s and parent=%s', (key, user))
if res:
self.sql('update `tabDefaultValue` set defvalue=%s where parent=%s and defkey=%s', (str(val), user, key))
else:
self.sql('insert into `tabDefaultValue` (name, defkey, defvalue, parent) values (%s,%s,%s,%s)', (user+'_'+key, key, str(val), user))
self.set_default(key, val, user)
def get_global(self, key, user='__global'):
g = self.sql("select defvalue from tabDefaultValue where defkey=%s and parent=%s", (key, user))
return g and g[0][0] or None
def get_globals_like(self, key):
return [g[0] for g in self.sql("""select defvalue from tabDefaultValue
where defkey like %s and parent='__global'""", key)]
return self.get_default(key, user)
def set_default(self, key, val, parent="Control Panel"):
"""set control panel default (tabDefaultVal)"""
if self.sql("""select defkey from `tabDefaultValue` where
defkey=%s and parent=%s """, (key, parent)):
# update
self.sql("""update `tabDefaultValue` set defvalue=%s
where parent=%s and defkey=%s""", (val, parent, key))
webnotes.clear_cache()
else:
self.add_default(key, val, parent)
import webnotes.defaults
webnotes.defaults.set_default(key, val, parent)
def add_default(self, key, val, parent="Control Panel"):
d = webnotes.doc('DefaultValue')
d.parent = parent
d.parenttype = 'Control Panel' # does not matter
d.parentfield = 'system_defaults'
d.defkey = key
d.defvalue = val
d.save(1)
webnotes.clear_cache()
import webnotes.defaults
webnotes.defaults.add_default(key, val, parent)
def get_default(self, key, parent="Control Panel"):
"""get default value"""
ret = self.get_defaults_as_list(key, parent)
return ret and ret[0] or None
import webnotes.defaults
d = webnotes.defaults.get_defaults(parent).get(key)
return isinstance(d, list) and d[0] or d
def get_defaults_as_list(self, key, parent="Control Panel"):
ret = [r[0] for r in self.sql("""select defvalue from \
tabDefaultValue where defkey=%s and parent=%s""", (key, parent))]
if key in ["owner", "user"] and webnotes.session:
ret.append(webnotes.session.user)
return ret
import webnotes.defaults
d = webnotes.defaults.get_default(key, parent)
return isinstance(d, basestring) and [d] or d
def get_defaults(self, key=None, parent="Control Panel"):
"""get all defaults"""
import webnotes.defaults
if key:
return self.get_default(key, parent)
return webnotes.defaults.get_defaults(parent).get(key)
else:
res = self.sql("""select defkey, defvalue from `tabDefaultValue`
where parent = %s""", parent, as_dict=1)
defaults = webnotes._dict({})
for d in res:
if d.defkey in defaults:
# listify
if isinstance(defaults[d.defkey], basestring):
defaults[d.defkey] = [defaults[d.defkey]]
defaults[d.defkey].append(d.defvalue)
else:
defaults[d.defkey] = d.defvalue
return defaults
return webnotes.defaults.get_defaults(parent)
def begin(self):
return # not required

128
webnotes/defaults.py Normal file
View file

@ -0,0 +1,128 @@
from __future__ import unicode_literals
import webnotes
import memc
# User
def set_user_default(key, value, user=None):
set_default(key, value, user or webnotes.session.user)
def add_user_default(key, value, user=None):
add_default(key, value, user or webnotes.session.user)
def get_user_default(key, user=None):
d = get_defaults(user or webnotes.session.user).get(key, None)
return isinstance(d, list) and d[0] or d
def get_user_default_as_list(key, user=None):
d = get_defaults(user or webnotes.session.user).get(key, None)
return isinstance(d, basestring) and [d] or d
def get_defaults(user=None):
userd = get_defaults_for(user or webnotes.session.user)
globald = get_defaults_for()
globald.update(userd)
return globald
def clear_user_default(key, user=None):
clear_default(key, parent=user or webnotes.session.user)
# Global
def set_global_default(key, value):
set_default(key, value, "Control Panel")
def add_global_default(key, value):
add_default(key, value, "Control Panel")
def get_global_default(key):
d = get_defaults().get(key, None)
return isinstance(d, list) and d[0] or d
# Common
def set_default(key, value, parent):
if webnotes.conn.sql("""select defkey from `tabDefaultValue` where
defkey=%s and parent=%s """, (key, parent)):
# update
webnotes.conn.sql("""update `tabDefaultValue` set defvalue=%s
where parent=%s and defkey=%s""", (value, parent, key))
clear_cache(parent)
else:
add_default(key, value, parent)
def add_default(key, value, parent):
d = webnotes.doc({
"doctype": "DefaultValue",
"parent": parent,
"parenttype": "Control Panel",
"parentfield": "system_defaults",
"defkey": key,
"defvalue": value
})
d.insert()
clear_cache(parent)
def clear_default(key=None, value=None, parent=None, name=None):
conditions = []
values = []
if key:
conditions.append("defkey=%s")
values.append(key)
if value:
conditions.append("defvalue=%s")
values.append(value)
if name:
conditions.append("name=%s")
values.append(name)
if parent:
conditions.append("parent=%s")
values.append(parent)
if not conditions:
raise Exception, "[clear_default] No key specified."
webnotes.conn.sql("""delete from tabDefaultValue where %s""" % " and ".join(conditions), values)
clear_cache()
def get_defaults_for(parent="Control Panel"):
"""get all defaults"""
defaults = webnotes.cache().get_value("__defaults:" + parent)
if not defaults:
res = webnotes.conn.sql("""select defkey, defvalue from `tabDefaultValue`
where parent = %s order by creation""", parent, as_dict=1)
defaults = webnotes._dict({})
for d in res:
if d.defkey in defaults:
# listify
if isinstance(defaults[d.defkey], basestring) and defaults[d.defkey] != d.defvalue:
defaults[d.defkey] = [defaults[d.defkey]]
if d.defvalue not in defaults[d.defkey]:
defaults[d.defkey].append(d.defvalue)
else:
defaults[d.defkey] = d.defvalue
webnotes.cache().set_value("__defaults:" + parent, defaults)
return defaults
def clear_cache(parent=None):
def all_profiles():
return webnotes.conn.sql_list("select name from tabProfile") + ["Control Panel"]
if parent=="Control Panel" or not parent:
parent = all_profiles()
elif isinstance(parent, basestring):
parent = [parent]
for p in parent:
webnotes.cache().delete_value("__defaults:" + p)
webnotes.clear_cache()

View file

@ -73,7 +73,7 @@ def dt_map():
import webnotes.model.utils
from webnotes.model.code import get_obj
from webnotes.model.doc import Document
from webnotes.model.wrapper import ModelWrapper
from webnotes.model.bean import Bean
form_dict = webnotes.form_dict
@ -84,7 +84,7 @@ def dt_map():
from_to_list = form_dict.get('from_to_list')
dm = get_obj('DocType Mapper', from_doctype +'-' + to_doctype)
dl = dm.dt_map(from_doctype, to_doctype, from_docname, Document(fielddata = dt_list[0]), (len(dt_list) > 1) and ModelWrapper(dt_list).doclist or [], from_to_list)
dl = dm.dt_map(from_doctype, to_doctype, from_docname, Document(fielddata = dt_list[0]), (len(dt_list) > 1) and Bean(dt_list).doclist or [], from_to_list)
webnotes.response['docs'] = dl

View file

@ -37,7 +37,7 @@ def insert(doclist):
else:
d.fields["__islocal"] = 1
wrapper = webnotes.model_wrapper(doclist)
wrapper = webnotes.bean(doclist)
wrapper.save()
return wrapper

View file

@ -22,7 +22,7 @@
from __future__ import unicode_literals
"""
Transactions are defined as collection of classes, a ModelWrapper represents collection of Document
Transactions are defined as collection of classes, a Bean represents collection of Document
objects for a transaction with main and children.
Group actions like save, etc are performed on doclists
@ -33,7 +33,7 @@ from webnotes import _
from webnotes.utils import cint
from webnotes.model.doc import Document
class ModelWrapper:
class Bean:
"""
Collection of Documents with one parent and multiple children
"""
@ -247,6 +247,9 @@ class ModelWrapper:
def save(self, check_links=1):
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "write", self.doc):
if self.doc.docstatus == 1:
self.no_permission_to("Save submitted document")
self.prepare_for_save(check_links)
self.run_method('validate')
self.save_main()
@ -306,9 +309,9 @@ class ModelWrapper:
def clone(source_wrapper):
""" Copy previous invoice and change dates"""
if isinstance(source_wrapper, list):
source_wrapper = ModelWrapper(source_wrapper)
source_wrapper = Bean(source_wrapper)
new_wrapper = ModelWrapper(source_wrapper.doclist.copy())
new_wrapper = Bean(source_wrapper.doclist.copy())
new_wrapper.doc.fields.update({
"amended_from": None,
"amendment_date": None,

View file

@ -32,7 +32,7 @@ methods in following modules are imported for backward compatibility
* webnotes.*
* webnotes.utils.*
* webnotes.model.doc.*
* webnotes.model.wrapper.*
* webnotes.model.bean.*
"""
custom_class = '''
import webnotes

View file

@ -111,8 +111,17 @@ class Document:
def __str__(self):
return str(self.fields)
def __repr__(self):
return repr(self.fields)
def __unicode__(self):
return unicode(self.fields)
def __eq__(self, other):
return self.fields == other.fields
if isinstance(other, Document):
return self.fields == other.fields
else:
return False
def __getstate__(self):
return self.fields
@ -660,4 +669,15 @@ def get(dt, dn='', with_children = 1, from_controller = 0, prefix = 'tab'):
def getsingle(doctype):
"""get single doc as dict"""
dataset = webnotes.conn.sql("select field, value from tabSingles where doctype=%s", doctype)
return dict(dataset)
return dict(dataset)
def copy_common_fields(from_doc, to_doc):
from webnotes.model import default_fields
doctype_list = webnotes.get_doctype(to_doc.doctype)
for fieldname, value in from_doc.fields.items():
if fieldname in default_fields:
continue
if doctype_list.get_field(fieldname) and to_doc.fields[fieldname] != value:
to_doc.fields[fieldname] = value

View file

@ -132,11 +132,11 @@ def sort_fields(doclist):
else:
newlist.append(d)
pending.remove(d)
# recurring at end
if pending:
newlist += pending
# renum
idx = 1
for d in newlist:

View file

@ -72,7 +72,9 @@ def get_table_fields(doctype):
return child_tables + custom_child_tables
def has_field(doctype, fieldname):
doclist = webnotes.model.doctype.get(doctype)
return doclist.get({"parent":doctype, "doctype":"DocField", "fieldname":fieldname})
def has_field(doctype, fieldname, parent=None, parentfield=None):
return get_field(doctype, fieldname, parent=None, parentfield=None) and True or False
def get_field(doctype, fieldname, parent=None, parentfield=None):
doclist = webnotes.get_doctype(doctype)
return doclist.get_field(fieldname, parent, parentfield)

View file

@ -60,7 +60,7 @@ def sync_doctype(module_name, docname, force=0):
def merge_doctype(doclist, force=False):
modified = doclist[0]['modified']
if not doclist:
raise Exception('ModelWrapper could not be evaluated')
raise Exception('Bean could not be evaluated')
db_modified = str(webnotes.conn.get_value(doclist[0].get('doctype'),
doclist[0].get('name'), 'modified'))

View file

@ -91,7 +91,6 @@ class Profile:
quirks:
read_only => Not in Search
in_create => Not in create
"""
self.build_doctype_map()
self.build_perm_map()
@ -133,18 +132,8 @@ class Profile:
self.all_read += self.can_read
def get_defaults(self):
if not self.defaults:
roles = self.get_roles() + [self.name]
res = webnotes.conn.sql("""select defkey, defvalue
from `tabDefaultValue` where parent in ("%s") order by idx""" % '", "'.join(roles))
self.defaults = {'owner': [self.name], "user": [self.name]}
for rec in res:
if not self.defaults.has_key(rec[0]):
self.defaults[rec[0]] = []
self.defaults[rec[0]].append(rec[1] or '')
import webnotes.defaults
self.defaults = webnotes.defaults.get_defaults(self.name)
return self.defaults
# update recent documents
@ -208,7 +197,7 @@ def get_system_managers():
return [p[0] for p in system_managers]
def add_role(profile, role):
profile_wrapper = webnotes.model_wrapper("Profile", profile)
profile_wrapper = webnotes.bean("Profile", profile)
profile_wrapper.doclist.append({
"doctype": "UserRole",
"parentfield": "user_roles",

View file

@ -53,7 +53,7 @@ def clear_cache(user=None):
for sess in webnotes.conn.sql("""select user, sid from tabSessions""", as_dict=1):
cache.delete_value("sesssion:" + sess.sid)
cache.delete_value("bootinfo:" + sess.user)
def clear_sessions(user=None, keep_current=False):
if not user:
user = webnotes.session.user

View file

@ -69,7 +69,7 @@ def make_test_objects(doctype, test_records):
for doclist in test_records:
if not "doctype" in doclist[0]:
doclist[0]["doctype"] = doctype
d = webnotes.model_wrapper((webnotes.doclist(doclist)).copy())
d = webnotes.bean((webnotes.doclist(doclist)).copy())
if webnotes.test_objects.get(d.doc.doctype):
# do not create test records, if already exists
return []
@ -77,7 +77,15 @@ def make_test_objects(doctype, test_records):
if not d.doc.naming_series:
d.doc.naming_series = "_T-" + d.doc.doctype + "-"
# submit if docstatus is set to 1 for test record
docstatus = d.doc.docstatus
d.doc.docstatus = 0
d.insert()
if docstatus == 1:
d.submit()
records.append(d.doc.name)
return records
@ -100,7 +108,7 @@ def export_doc(doctype, docname):
make_test_records(doctype)
meta = webnotes.get_doctype(doctype)
for d in webnotes.model_wrapper(doctype, docname):
for d in webnotes.bean(doctype, docname):
new_doc = {}
for key, val in d.fields.iteritems():
if val and key not in ignore_list:
@ -157,6 +165,7 @@ if __name__=="__main__":
parser.add_argument('-v', '--verbose', default=False, action="store_true")
parser.add_argument('-e', '--export', nargs=2, metavar="DOCTYPE DOCNAME")
parser.add_argument('-a', '--all', default=False, action="store_true")
parser.add_argument('-m', '--module', default=1, metavar="MODULE")
args = parser.parse_args()
webnotes.print_messages = args.verbose
@ -170,5 +179,10 @@ if __name__=="__main__":
run_all_tests(args.verbose)
elif args.export:
export_doc(args.export[0], args.export[1])
elif args.module:
test_suite = unittest.TestSuite()
__import__(args.module)
test_suite.addTest(unittest.TestLoader().loadTestsFromModule(sys.modules[args.module]))
unittest.TextTestRunner(verbosity=1+(args.verbose and 1 or 0)).run(test_suite)

View file

@ -0,0 +1,44 @@
import webnotes, unittest
from webnotes.defaults import *
class TestDefaults(unittest.TestCase):
def test_global(self):
set_global_default("key1", "value1")
self.assertEquals(get_global_default("key1"), "value1")
set_global_default("key1", "value2")
self.assertEquals(get_global_default("key1"), "value2")
add_global_default("key1", "value3")
self.assertEquals(get_global_default("key1"), "value2")
self.assertEquals(get_defaults()["key1"], ["value2", "value3"])
self.assertEquals(get_user_default_as_list("key1"), ["value2", "value3"])
def test_user(self):
set_user_default("key1", "2value1")
self.assertEquals(get_user_default_as_list("key1"), ["2value1"])
set_user_default("key1", "2value2")
self.assertEquals(get_user_default("key1"), "2value2")
add_user_default("key1", "3value3")
self.assertEquals(get_user_default("key1"), "2value2")
self.assertEquals(get_user_default_as_list("key1"), ["2value2", "3value3"])
def test_global_if_not_user(self):
set_global_default("key4", "value4")
self.assertEquals(get_user_default("key4"), "value4")
def test_clear(self):
set_user_default("key5", "value5")
self.assertEquals(get_user_default("key5"), "value5")
clear_user_default("key5")
self.assertEquals(get_user_default("key5"), None)
def test_clear_global(self):
set_global_default("key6", "value6")
self.assertEquals(get_user_default("key6"), "value6")
clear_default("key6", value="value6")
self.assertEquals(get_user_default("key6"), None)

View file

@ -109,7 +109,7 @@ def build_for_doc_from_database(fields):
for item in webnotes.conn.sql("""select name from `tab%s`""" % fields.doctype, as_dict=1):
messages = []
doclist = webnotes.model_wrapper(fields.doctype, item.name).doclist
doclist = webnotes.bean(fields.doctype, item.name).doclist
for doc in doclist:
if doc.doctype in fields:

View file

@ -86,12 +86,13 @@ def sendmail(recipients, sender='', msg='', subject='[No Subject]'):
import webnotes.utils.email_lib
return email_lib.sendmail(recipients, sender, msg, subject)
def get_request_site_address():
def get_request_site_address(full_address=False):
"""get app url from request"""
import os
try:
return 'HTTPS' in os.environ.get('SERVER_PROTOCOL') and 'https://' or 'http://' \
+ os.environ.get('HTTP_HOST')
+ os.environ.get('HTTP_HOST')\
+ (full_address and (os.environ.get("REQUEST_URI")) or "")
except TypeError, e:
return 'http://localhost'
@ -265,7 +266,7 @@ def formatdate(string_date=None):
if string_date:
string_date = getdate(string_date)
else:
string_date = nowdate()
string_date = now_datetime().date()
global user_format
if not user_format:

View file

@ -33,7 +33,7 @@ from __future__ import unicode_literals
import webnotes, unittest
from webnotes import msgprint
from webnotes.model.wrapper import ModelWrapper
from webnotes.model.bean import Bean
from webnotes.model.doc import Document
class TestNSM(unittest.TestCase):
@ -53,7 +53,7 @@ class TestNSM(unittest.TestCase):
]
for d in self.data:
self.__dict__[d[0]] = ModelWrapper([Document(fielddata = {
self.__dict__[d[0]] = Bean([Document(fielddata = {
"doctype": "Item Group", "item_group_name": d[0], "parent_item_group": d[1],
"__islocal": 1
})])

View file

@ -29,8 +29,7 @@ import json
def update_event(args, field_map):
args = webnotes._dict(json.loads(args))
field_map = webnotes._dict(json.loads(field_map))
w = webnotes.model_wrapper(args.doctype, args.name)
w = webnotes.bean(args.doctype, args.name)
w.doc.fields[field_map.start] = args[field_map.start]
w.doc.fields[field_map.end] = args[field_map.end]
w.save()

View file

@ -58,6 +58,11 @@ def add(args=None):
d.date = args.get('date', nowdate())
d.assigned_by = args.get('assigned_by', webnotes.user.name)
d.save(1)
# set assigned_to if field exists
from webnotes.model.meta import has_field
if has_field(args['doctype'], "assigned_to"):
webnotes.conn.set_value(args['doctype'], args['name'], "assigned_to", args['assign_to'])
# notify
if not args.get("no_notification"):

View file

@ -26,7 +26,7 @@ import webnotes.model.doc
import webnotes.utils
@webnotes.whitelist()
def getdoc():
def getdoc(doctype, name, user=None):
"""
Loads a doclist for a given document. This method is called directly from the client.
Requries "doctype", "name" as form variables.
@ -35,18 +35,15 @@ def getdoc():
import webnotes
form = webnotes.form_dict
doctype, docname = form.get('doctype'), form.get('name')
if not (doctype and docname):
if not (doctype and name):
raise Exception, 'doctype and name required!'
doclist = []
# single
doclist = load_single_doc(doctype, docname, (form.get('user') or webnotes.session['user']))
doclist = load_single_doc(doctype, name, user or webnotes.session.user)
# load doctype along with the doc
if form.get('getdoctype'):
if webnotes.form_dict.get('getdoctype'):
import webnotes.model.doctype
doclist += webnotes.model.doctype.get(doctype, processed=True)
@ -92,7 +89,7 @@ def load_single_doc(dt, dn, user):
return None
try:
dl = webnotes.model_wrapper(dt, dn).doclist
dl = webnotes.bean(dt, dn).doclist
except Exception, e:
webnotes.errprint(webnotes.utils.getTraceback())
webnotes.msgprint('Error in script while loading')

View file

@ -30,7 +30,7 @@ def runserverobj():
Run server objects
"""
import webnotes.model.code
from webnotes.model.wrapper import ModelWrapper
from webnotes.model.bean import Bean
from webnotes.utils import cint
wrapper = None
@ -44,7 +44,7 @@ def runserverobj():
so = webnotes.model.code.get_obj(dt, dn)
else:
wrapper = ModelWrapper()
wrapper = Bean()
wrapper.from_compressed(webnotes.form_dict.get('docs'), dn)
if not wrapper.has_read_perm():
webnotes.msgprint(_("No Permission"), raise_exception = True)

View file

@ -27,7 +27,7 @@ import webnotes
def savedocs():
"""save / submit / update doclist"""
try:
wrapper = webnotes.model_wrapper()
wrapper = webnotes.bean()
wrapper.from_compressed(webnotes.form_dict.docs, webnotes.form_dict.docname)
# action
@ -48,7 +48,7 @@ def savedocs():
def cancel(doctype=None, name=None):
"""cancel a doclist"""
try:
wrapper = webnotes.model_wrapper(doctype, name)
wrapper = webnotes.bean(doctype, name)
wrapper.cancel()
send_updated_docs(wrapper)

View file

@ -28,6 +28,7 @@ sql = webnotes.conn.sql
out = webnotes.response
from webnotes.utils import cint
import webnotes.defaults
def get_sql_tables(q):
if q.find('WHERE') != -1:
@ -74,31 +75,17 @@ def get_sql_meta(tl):
return meta
def getmatchcondition(dt, ud, ur):
res = sql("SELECT `role`, `match` FROM tabDocPerm WHERE parent = '%s' AND (`read`=1) AND permlevel = 0" % dt)
cond = []
for r in res:
if r[0] in ur: # role applicable to user
if r[1]:
defvalues = ud.get(r[1],['_NA'])
for d in defvalues:
cond.append('`tab%s`.`%s`="%s"' % (dt, r[1], d))
else: # nomatch i.e. full read rights
return ''
return ' OR '.join(cond)
def add_match_conditions(q, tl, ur, ud):
def add_match_conditions(q, tl):
sl = []
ur = webnotes.user.get_roles()
for dt in tl:
s = getmatchcondition(dt, ud, ur)
s = getmatchcondition(dt, ur)
if s:
sl.append(s)
# insert the conditions
if sl:
condition_st = q.find('WHERE')!=-1 and ' AND ' or ' WHERE '
condition_end = q.find('ORDER BY')!=-1 and 'ORDER BY' or 'LIMIT'
condition_end = q.find('GROUP BY')!=-1 and 'GROUP BY' or condition_end
@ -110,6 +97,19 @@ def add_match_conditions(q, tl, ur, ud):
return q
def getmatchcondition(dt, ur):
res = sql("SELECT `role`, `match` FROM tabDocPerm WHERE parent = '%s' AND (`read`=1) AND permlevel = 0" % dt)
cond = []
for r in res:
if r[0] in ur: # role applicable to user
if r[1]:
for d in webnotes.defaults.get_user_default_as_list(default_key) or ["** No Match **"]:
cond.append('`tab%s`.`%s`="%s"' % (dt, r[1], d))
else:
return ''
return ' OR '.join(cond)
def exec_report(code, res, colnames=[], colwidths=[], coltypes=[], coloptions=[], filter_values={}, query='', from_export=0):
col_idx, i, out, style, header_html, footer_html, page_template = {}, 0, None, [], '', '', ''
for c in colnames:
@ -231,7 +231,7 @@ def runquery(q='', ret=0, from_export=0):
tl = get_sql_tables(q)
meta = get_sql_meta(tl)
q = add_match_conditions(q, tl, webnotes.user.get_roles(), webnotes.user.get_defaults())
q = add_match_conditions(q, tl)
webnotes
# replace special variables
q = q.replace('__user', session['user'])
@ -280,7 +280,7 @@ def runquery(q='', ret=0, from_export=0):
if qm.split()[0].lower() != 'select':
raise Exception, 'Query (Max) must be a SELECT'
if not webnotes.form_dict.get('simple_query'):
qm = add_match_conditions(qm, tl, webnotes.user.get_roles(), webnotes.user.get_defaults())
qm = add_match_conditions(qm, tl)
out['n_values'] = webnotes.utils.cint(sql(qm)[0][0])

View file

@ -24,6 +24,7 @@ from __future__ import unicode_literals
"""build query for doclistview and return results"""
import webnotes, json
import webnotes.defaults
tables = None
doctypes = {}
@ -41,25 +42,41 @@ def build_query(arg=None):
gets doctype, subject, filters
limit_start, limit_page_length
"""
data = webnotes.form_dict
global tables
data = prepare_data(arg)
if 'query' in data:
return run_custom_query(data)
filters = json.loads(data['filters'])
fields = json.loads(data['fields'])
tables = get_tables()
load_doctypes()
query = """select %(fields)s from %(tables)s where %(conditions)s
%(group_by)s order by %(order_by)s %(limit)s""" % data
return query
remove_user_tags(fields)
# conditions
conditions = build_conditions(filters)
def prepare_data(arg=None):
global tables
if arg:
data = webnotes._dict(arg)
else:
data = webnotes._dict(webnotes.form_dict)
if 'query' in data:
return data
if isinstance(data.get("filters"), basestring):
data["filters"] = json.loads(data["filters"])
if isinstance(data.get("fields"), basestring):
data["fields"] = json.loads(data["fields"])
tables = get_tables(data)
load_doctypes()
remove_user_tags(data)
conditions = build_conditions(data)
# query dict
data['tables'] = ', '.join(tables)
data['conditions'] = ' and '.join(conditions)
data['fields'] = ', '.join(fields)
data['fields'] = ', '.join(data.fields)
if not data.get('order_by'):
data['order_by'] = tables[0] + '.modified desc'
@ -73,10 +90,7 @@ def build_query(arg=None):
add_limit(data)
query = """select %(fields)s from %(tables)s where %(conditions)s
%(group_by)s order by %(order_by)s %(limit)s""" % data
return query
return data
def compress(data):
"""separate keys and values"""
@ -125,12 +139,12 @@ def load_doctypes():
raise webnotes.PermissionError, doctype
doctypes[doctype] = webnotes.model.doctype.get(doctype)
def remove_user_tags(fields):
def remove_user_tags(data):
"""remove column _user_tags if not in table"""
for fld in fields:
for fld in data.fields:
if '_user_tags' in fld:
if not '_user_tags' in get_table_columns(webnotes.form_dict['doctype']):
del fields[fields.index(fld)]
if not '_user_tags' in get_table_columns(data.doctype):
del data.fields[data.fields.index(fld)]
break
def add_limit(data):
@ -139,35 +153,37 @@ def add_limit(data):
else:
data['limit'] = ''
def build_conditions(filters):
def build_conditions(data):
"""build conditions"""
data = webnotes.form_dict
# docstatus condition
docstatus = json.loads(data['docstatus'])
if docstatus:
conditions = [tables[0] + '.docstatus in (' + ','.join(docstatus) + ')']
if isinstance(data.docstatus, basestring):
data.docstatus = json.loads(data.docstatus)
if data.docstatus:
conditions = [tables[0] + '.docstatus in (' + ','.join(data.docstatus) + ')']
else:
# default condition
conditions = [tables[0] + '.docstatus < 2']
# make conditions from filters
build_filter_conditions(data, filters, conditions)
build_filter_conditions(data, conditions)
# join parent, child tables
for tname in tables[1:]:
conditions.append(tname + '.parent = ' + tables[0] + '.name')
# match conditions
build_match_conditions(data, conditions)
match_conditions = build_match_conditions(data)
if match_conditions:
conditions.append(match_conditions)
return conditions
def build_filter_conditions(data, filters, conditions):
def build_filter_conditions(data, conditions):
"""build conditions from user filters"""
from webnotes.utils import cstr
for f in filters:
for f in data.filters:
tname = ('`tab' + f[0] + '`')
if not tname in tables:
tables.append(tname)
@ -185,10 +201,16 @@ def build_filter_conditions(data, filters, conditions):
conditions.append('ifnull(' + tname + '.' + f[1] + ",0) " + f[2] \
+ " " + cstr(f[3]))
def build_match_conditions(data, conditions):
def build_match_conditions(data):
"""add match conditions if applicable"""
match_conditions = []
match = True
if not tables or not doctypes:
global tables
tables = get_tables(data)
load_doctypes()
for d in doctypes[data['doctype']]:
if d.doctype == 'DocPerm' and d.parent == data['doctype']:
if d.role in roles:
@ -198,7 +220,7 @@ def build_match_conditions(data, conditions):
else:
default_key = document_key = d.match
for v in webnotes.user.get_defaults().get(default_key, ['**No Match**']):
for v in webnotes.defaults.get_user_default_as_list(default_key) or ["** No Match **"]:
match_conditions.append('`tab%s`.%s="%s"' % (data['doctype'],
document_key, v))
@ -208,15 +230,16 @@ def build_match_conditions(data, conditions):
match = False
if match_conditions and match:
conditions.append('('+ ' or '.join(match_conditions) +')')
return '('+ ' or '.join(match_conditions) +')'
def get_tables():
def get_tables(data):
"""extract tables from fields"""
data = webnotes.form_dict
tables = ['`tab' + data['doctype'] + '`']
# add tables from fields
for f in json.loads(data['fields']):
for f in data.get('fields') or []:
if "." not in f: continue
table_name = f.split('.')[0]
if table_name.lower().startswith('group_concat('):
table_name = table_name[13:]
@ -243,7 +266,7 @@ def save_report():
d.ref_doctype = data['doctype']
d.json = data['json']
webnotes.model_wrapper([d]).save()
webnotes.bean([d]).save()
webnotes.msgprint("%s saved." % d.name)
return d.name