Merge branch 'master' into edge
This commit is contained in:
commit
e29aa3eddf
25 changed files with 227 additions and 186 deletions
|
|
@ -160,8 +160,9 @@ class DocType:
|
|||
new.label = 'Amended From'
|
||||
new.fieldtype = 'Link'
|
||||
new.fieldname = 'amended_from'
|
||||
new.options = "Sales Invoice"
|
||||
new.permlevel = 1
|
||||
new.options = self.doc.name
|
||||
new.permlevel = 0
|
||||
new.read_only = 1
|
||||
new.print_hide = 1
|
||||
new.no_copy = 1
|
||||
new.idx = max_idx + 1
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"creation": "2013-02-14 17:37:36",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-02-26 10:45:10",
|
||||
"modified": "2013-03-01 10:18:03",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
|
|
@ -131,7 +131,7 @@
|
|||
"fieldname": "language",
|
||||
"fieldtype": "Select",
|
||||
"label": "Language",
|
||||
"options": "\n\u0627\u0644\u0639\u0631\u0628\u064a\u0629\nenglish\nespa\u00f1ol\nfran\u00e7ais\n\u0939\u093f\u0902\u0926\u0940\nHrvatski\nnederlands\nportugu\u00eas\nportugu\u00eas brasileiro\n\u0441\u0440\u043f\u0441\u043a\u0438\n\u0ba4\u0bae\u0bbf\u0bb4\u0bcd\n\u0e44\u0e17\u0e22"
|
||||
"options": "\n\u0627\u0644\u0639\u0631\u0628\u064a\u0629\nDeutsch\nenglish\nespa\u00f1ol\nfran\u00e7ais\n\u0939\u093f\u0902\u0926\u0940\nHrvatski\nnederlands\nportugu\u00eas\nportugu\u00eas brasileiro\n\u0441\u0440\u043f\u0441\u043a\u0438\n\u0ba4\u0bae\u0bbf\u0bb4\u0bcd\n\u0e44\u0e17\u0e22"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
|
|
|
|||
|
|
@ -133,15 +133,15 @@ _f.Frm.prototype.setup_print_layout = function() {
|
|||
});
|
||||
|
||||
var appframe = this.print_wrapper.appframe;
|
||||
appframe.add_button("View Details", function() {
|
||||
appframe.add_button(wn._("View Details"), function() {
|
||||
me.edit_doc();
|
||||
}).addClass("btn-success");
|
||||
|
||||
appframe.add_button("Print", function() {
|
||||
appframe.add_button(wn._("Print"), function() {
|
||||
me.print_doc();
|
||||
}, 'icon-print');
|
||||
|
||||
this.$print_view_select = appframe.add_select("Select Preview", this.print_formats)
|
||||
this.$print_view_select = appframe.add_select(wn._("Select Preview"), this.print_formats)
|
||||
.css({"float":"right"})
|
||||
.val(this.print_formats[0])
|
||||
.change(function() {
|
||||
|
|
@ -652,6 +652,10 @@ _f.Frm.prototype.cleanup_refresh = function() {
|
|||
var fn = me.meta.autoname.substr(6);
|
||||
cur_frm.toggle_display(fn, false);
|
||||
}
|
||||
|
||||
if(me.meta.autoname=="naming_series:" && !me.doc.__islocal) {
|
||||
cur_frm.toggle_display("naming_series", false);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve "depends_on" and show / hide accordingly
|
||||
|
|
|
|||
|
|
@ -64,6 +64,18 @@ $.extend(wn.meta, {
|
|||
}
|
||||
},
|
||||
|
||||
has_field: function(dt, fn) {
|
||||
return wn.meta.docfield_map[dt][fn];
|
||||
},
|
||||
|
||||
get_parentfield: function(parent_dt, child_dt) {
|
||||
var df = wn.model.get("DocField", {parent:parent_dt, fieldtype:"Table",
|
||||
options:child_dt})
|
||||
if(!df.length)
|
||||
throw "parentfield not found for " + parent_dt + ", " + child_dt;
|
||||
return df[0].fieldname;
|
||||
},
|
||||
|
||||
get_label: function(dt, fn, dn) {
|
||||
if(fn==="owner") {
|
||||
return "Owner";
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
//
|
||||
|
||||
wn.provide('wn.model');
|
||||
wn.provide("wn.model.map_info");
|
||||
|
||||
$.extend(wn.model, {
|
||||
no_value_type: ['Section Break', 'Column Break', 'HTML', 'Table',
|
||||
|
|
@ -75,6 +76,9 @@ $.extend(wn.model, {
|
|||
if(meta.__calendar_js) {
|
||||
eval(meta.__calendar_js);
|
||||
}
|
||||
if(meta.__map_js) {
|
||||
eval(meta.__map_js);
|
||||
}
|
||||
callback(r);
|
||||
}
|
||||
});
|
||||
|
|
@ -228,23 +232,90 @@ $.extend(wn.model, {
|
|||
delete locals[doctype][name];
|
||||
},
|
||||
|
||||
copy_doc: function(dt, dn, from_amend) {
|
||||
get_no_copy_list: function(doctype) {
|
||||
var no_copy_list = ['name','amended_from','amendment_date','cancel_reason'];
|
||||
$.each(wn.model.get("DocField", {parent:doctype}), function(i, df) {
|
||||
if(cint(df.no_copy)) no_copy_list.push(df.fieldname);
|
||||
})
|
||||
return no_copy_list;
|
||||
},
|
||||
|
||||
copy_doc: function(dt, dn, from_amend) {
|
||||
var no_copy_list = wn.model.get_no_copy_list(dt);
|
||||
var newdoc = wn.model.get_new_doc(dt);
|
||||
|
||||
for(var key in locals[dt][dn]) {
|
||||
// dont copy name and blank fields
|
||||
var df = wn.meta.get_docfield(dt, key);
|
||||
|
||||
// dont copy name and blank fields
|
||||
if(key.substr(0,2)!='__'
|
||||
&& !in_list(no_copy_list, key)
|
||||
&& !(df && (!from_amend && cint(df.no_copy)==1))) {
|
||||
&& !in_list(no_copy_list, key)) {
|
||||
newdoc[key] = locals[dt][dn][key];
|
||||
}
|
||||
}
|
||||
return newdoc;
|
||||
},
|
||||
|
||||
// args: source (doclist), target (doctype), table_map, field_map, callback
|
||||
map: function(args) {
|
||||
wn.model.with_doctype(args.target, function() {
|
||||
var map_info = wn.model.map_info[args.target]
|
||||
if(map_info)
|
||||
map_info = map_info[args.source[0].doctype];
|
||||
if(!map_info) {
|
||||
map_info = {
|
||||
table_map: {},
|
||||
field_map: {}
|
||||
}
|
||||
}
|
||||
|
||||
// main
|
||||
var target = wn.model.map_doc(args.source[0], args.target, map_info.field_map[args.target]);
|
||||
|
||||
// children
|
||||
$.each(map_info.table_map, function(child_target, child_source) {
|
||||
$.each($.map(args.source, function(d)
|
||||
{ if(d.doctype==child_source) return d; else return null; }), function(i, d) {
|
||||
var child = wn.model.map_doc(d, child_target, map_info.field_map[child_target]);
|
||||
$.extend(child, {
|
||||
parent: target.name,
|
||||
parenttype: target.doctype,
|
||||
parentfield: wn.meta.get_parentfield(target.doctype, child.doctype),
|
||||
idx: i+1
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if(args.callback) {
|
||||
args.callback(target);
|
||||
} else {
|
||||
wn.set_route("Form", target.doctype, target.name);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// map a single doc to a new doc of given DocType and field_map
|
||||
map_doc: function(source, doctype, field_map) {
|
||||
var new_doc = wn.model.get_new_doc(doctype);
|
||||
var no_copy_list = wn.model.get_no_copy_list(doctype);
|
||||
if(!field_map) field_map = {};
|
||||
delete no_copy_list[no_copy_list.indexOf("name")];
|
||||
|
||||
for(fieldname in wn.meta.docfield_map[doctype]) {
|
||||
var df = wn.meta.docfield_map[doctype][fieldname];
|
||||
if(!df.no_copy) {
|
||||
var source_key = field_map[df.fieldname] || df.fieldname;
|
||||
if(source_key.substr(0,1)=="=") {
|
||||
var value = source_key.substr(1);
|
||||
} else {
|
||||
var value = source[source_key];
|
||||
}
|
||||
if(value!==undefined) {
|
||||
new_doc[df.fieldname] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new_doc;
|
||||
},
|
||||
|
||||
delete_doc: function(doctype, docname, callback) {
|
||||
wn.confirm("Permanently delete "+ docname + "?", function() {
|
||||
wn.call({
|
||||
|
|
|
|||
|
|
@ -89,13 +89,18 @@ $.extend(wn.perm, {
|
|||
|
||||
get_match_rule: function(doctype) {
|
||||
var match_rules = {};
|
||||
var match = true;
|
||||
$.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]] = wn.defaults.get_user_defaults(match_keys[1]);
|
||||
if(p.permlevel==0 && in_list(user_roles, p.role)) {
|
||||
if(p.match) {
|
||||
match_keys = wn.perm.get_match_keys(p.match);
|
||||
match_rules[match_keys[0]] = wn.defaults.get_user_defaults(match_keys[1]);
|
||||
} else {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return match_rules;
|
||||
return match ? match_rules : {};
|
||||
},
|
||||
|
||||
get_match_keys: function(match) {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ wn.views.Calendar = Class.extend({
|
|||
var me = this;
|
||||
this.$wrapper = $(this.page).find(".layout-main");
|
||||
this.$cal = $("<div>").appendTo(this.$wrapper);
|
||||
wn.utils.set_footnote(this, this.$wrapper, wn._("Select or drag across dates to create a new event."));
|
||||
wn.utils.set_footnote(this, this.$wrapper, wn._("Select or drag across time slots to create a new event."));
|
||||
//
|
||||
// $('<div class="help"></div>')
|
||||
// .html(wn._("Select dates to create a new ") + wn._(me.doctype))
|
||||
|
|
|
|||
|
|
@ -78,13 +78,16 @@ wn.views.DocListView = wn.ui.Listing.extend({
|
|||
me.can_delete = wn.model.can_delete(me.doctype);
|
||||
me.meta = locals.DocType[me.doctype];
|
||||
me.$page.find('.wnlist-area').empty(),
|
||||
me.setup_docstatus_filter();
|
||||
me.setup_listview();
|
||||
me.setup_docstatus_filter();
|
||||
me.init_list();
|
||||
me.init_stats();
|
||||
me.add_delete_option();
|
||||
me.make_help();
|
||||
me.show_match_help();
|
||||
if(me.listview.settings.onload) {
|
||||
me.listview.settings.onload(me);
|
||||
}
|
||||
me.make_help();
|
||||
},
|
||||
show_match_help: function() {
|
||||
var me = this;
|
||||
|
|
@ -213,7 +216,7 @@ wn.views.DocListView = wn.ui.Listing.extend({
|
|||
},
|
||||
add_delete_option: function() {
|
||||
var me = this;
|
||||
if(this.can_delete) {
|
||||
if(this.can_delete || this.listview.settings.selectable) {
|
||||
this.add_button(wn._('Delete'), function() { me.delete_items(); }, 'icon-remove');
|
||||
this.add_button(wn._('Select All'), function() {
|
||||
var checks = me.$page.find('.list-delete');
|
||||
|
|
@ -221,11 +224,14 @@ wn.views.DocListView = wn.ui.Listing.extend({
|
|||
}, 'icon-ok');
|
||||
}
|
||||
},
|
||||
get_checked_items: function() {
|
||||
return $.map(this.$page.find('.list-delete:checked'), function(e) {
|
||||
return $(e).data('data');
|
||||
});
|
||||
},
|
||||
delete_items: function() {
|
||||
var me = this;
|
||||
var dl = $.map(me.$page.find('.list-delete:checked'), function(e) {
|
||||
return $(e).data('name');
|
||||
});
|
||||
var dl = this.get_checked_items();
|
||||
if(!dl.length)
|
||||
return;
|
||||
|
||||
|
|
@ -235,7 +241,7 @@ wn.views.DocListView = wn.ui.Listing.extend({
|
|||
wn.call({
|
||||
method: 'webnotes.widgets.reportview.delete_items',
|
||||
args: {
|
||||
items: dl,
|
||||
items: $.map(dl, function(d, i) { return d.name }),
|
||||
doctype: me.doctype
|
||||
},
|
||||
callback: function() {
|
||||
|
|
|
|||
|
|
@ -57,17 +57,18 @@ wn.views.ListView = Class.extend({
|
|||
// additional fields
|
||||
if(this.settings.add_fields) {
|
||||
$.each(this.settings.add_fields, function(i, d) {
|
||||
me.fields.push(d);
|
||||
if(me.fields.indexOf(d)==-1)
|
||||
me.fields.push(d);
|
||||
});
|
||||
}
|
||||
},
|
||||
set_columns: function() {
|
||||
this.columns = [];
|
||||
var me = this;
|
||||
if(wn.model.can_delete(this.doctype)) {
|
||||
this.columns.push({width: '3%', content:'check'})
|
||||
if(wn.model.can_delete(this.doctype) || this.settings.selectable) {
|
||||
this.columns.push({width: '4%', content:'check'})
|
||||
}
|
||||
this.columns.push({width: '4%', content:'avatar'});
|
||||
this.columns.push({width: '7%', content:'avatar'});
|
||||
if(wn.model.is_submittable(this.doctype)) {
|
||||
this.columns.push({width: '3%', content:'docstatus',
|
||||
css: {"text-align": "center"}});
|
||||
|
|
@ -173,8 +174,10 @@ wn.views.ListView = Class.extend({
|
|||
+ wn.user_info(data.modified_by).fullname));
|
||||
}
|
||||
else if(opts.content=='check') {
|
||||
$(parent).append('<input class="list-delete" type="checkbox">');
|
||||
$(parent).find('input').data('name', data.name);
|
||||
$('<input class="list-delete" type="checkbox">')
|
||||
.data('name', data.name)
|
||||
.data('data', data)
|
||||
.appendTo(parent)
|
||||
}
|
||||
else if(opts.content=='docstatus') {
|
||||
$(parent).append(repl('<span class="docstatus"> \
|
||||
|
|
@ -266,7 +269,7 @@ wn.views.ListView = Class.extend({
|
|||
}
|
||||
|
||||
// title
|
||||
if(!in_list(["avatar"], opts.content)) {
|
||||
if(!in_list(["avatar", "_user_tags", "check"], opts.content)) {
|
||||
$(parent).attr("title", (opts.title || opts.content) + ": "
|
||||
+ (data[opts.content] || "Not Set"))
|
||||
.tooltip();
|
||||
|
|
|
|||
|
|
@ -209,6 +209,11 @@ wn.views.QueryReport = Class.extend({
|
|||
if(df.width) {
|
||||
col.width=parseInt(df.width);
|
||||
}
|
||||
} else {
|
||||
col.df = {
|
||||
label: c,
|
||||
fieldtype: "Data"
|
||||
}
|
||||
}
|
||||
col.name = toTitle(col.name.replace(/ /g, " "))
|
||||
return col
|
||||
|
|
@ -277,8 +282,7 @@ wn.views.QueryReport = Class.extend({
|
|||
} else if(filter[0]=="<") {
|
||||
filter = filter.substr(1);
|
||||
cond = "<"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(in_list(['Float', 'Currency', 'Int', 'Date'], columnDef.df.fieldtype)) {
|
||||
// non strings
|
||||
|
|
@ -291,7 +295,7 @@ wn.views.QueryReport = Class.extend({
|
|||
value = flt(value);
|
||||
filter = flt(filter);
|
||||
}
|
||||
|
||||
|
||||
out = eval("value" + cond + "filter");
|
||||
} else {
|
||||
// range
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ wn.views.ReportView = wn.ui.Listing.extend({
|
|||
sort_by: me.sort_by_select.val(),
|
||||
sort_order: me.sort_order_select.val(),
|
||||
sort_by_next: me.sort_by_next_select.val(),
|
||||
sort_order_next: me.sort_order_next_select.val()
|
||||
sort_order_next: me.sort_order_next_select.val()
|
||||
})
|
||||
},
|
||||
callback: function(r) {
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ def generate_hash():
|
|||
import hashlib, time
|
||||
return hashlib.sha224(str(time.time())).hexdigest()
|
||||
|
||||
def get_obj(dt = None, dn = None, doc=None, doclist=[], with_children = 0):
|
||||
def get_obj(dt = None, dn = None, doc=None, doclist=[], with_children = True):
|
||||
from webnotes.model.code import get_obj
|
||||
return get_obj(dt, dn, doc, doclist, with_children)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,10 +33,13 @@ def get(doctype, name=None, filters=None):
|
|||
return [d.fields for d in webnotes.bean(doctype, name).doclist]
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_value(doctype, fieldname, filters=None):
|
||||
def get_value(doctype, fieldname, filters=None, as_dict=True):
|
||||
if not webnotes.has_permission(doctype):
|
||||
webnotes.msgprint("No Permission", raise_exception=True)
|
||||
|
||||
if fieldname and fieldname.startswith("["):
|
||||
fieldname = json.loads(fieldname)
|
||||
return webnotes.conn.get_value(doctype, json.loads(filters), fieldname)
|
||||
return webnotes.conn.get_value(doctype, json.loads(filters), fieldname, as_dict=as_dict)
|
||||
|
||||
@webnotes.whitelist()
|
||||
def insert(doclist):
|
||||
|
|
|
|||
|
|
@ -245,11 +245,15 @@ class Database:
|
|||
|
||||
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):
|
||||
|
||||
def get_value(self, doctype, filters=None, fieldname="name", ignore=None, as_dict=False, debug=False):
|
||||
"""Get a single / multiple value from a record.
|
||||
For Single DocType, let filters be = None"""
|
||||
|
||||
ret = self.get_values(doctype, filters, fieldname, ignore, as_dict, debug)
|
||||
return ret and (len(ret[0]) > 1 and ret[0] or ret[0][0]) or None
|
||||
|
||||
def get_values(self, doctype, filters=None, fieldname="name", ignore=None, as_dict=False, debug=False):
|
||||
if filters is not None and (filters!=doctype or filters=='DocType'):
|
||||
if fieldname!="*" and isinstance(fieldname, basestring):
|
||||
fieldname = "`" + fieldname + "`"
|
||||
|
|
@ -260,24 +264,27 @@ class Database:
|
|||
|
||||
try:
|
||||
r = self.sql("select %s from `tab%s` where %s" % (fl, doctype,
|
||||
conditions), filters, as_dict)
|
||||
conditions), filters, as_dict, debug=debug)
|
||||
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
|
||||
return r
|
||||
|
||||
else:
|
||||
fieldname = isinstance(fieldname, basestring) and [fieldname] or fieldname
|
||||
|
||||
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)
|
||||
doctype=%s" % (', '.join(['%s']*len(fieldname)), '%s'), tuple(fieldname) + (doctype,), as_dict=False, debug=debug)
|
||||
if as_dict:
|
||||
return r and webnotes._dict(r) or None
|
||||
return r and [webnotes._dict(r)] or []
|
||||
else:
|
||||
return r and (len(r) > 1 and [i[0] for i in r] or r[0][1]) or None
|
||||
if r:
|
||||
return [[i[1] for i in r]]
|
||||
else:
|
||||
return []
|
||||
|
||||
def set_value(self, dt, dn, field, val, modified=None, modified_by=None):
|
||||
from webnotes.utils import now
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class Installer:
|
|||
root_password = getpass.getpass("MySQL root password: ")
|
||||
|
||||
self.root_password = root_password
|
||||
|
||||
|
||||
self.conn = webnotes.db.Database(user=root_login, password=root_password)
|
||||
webnotes.conn=self.conn
|
||||
webnotes.session= webnotes._dict({'user':'Administrator'})
|
||||
|
|
@ -55,8 +55,7 @@ class Installer:
|
|||
self.dbman.delete_user(target)
|
||||
|
||||
# create user and db
|
||||
self.dbman.create_user(target,
|
||||
hasattr(conf, 'db_password') and conf.db_password or password)
|
||||
self.dbman.create_user(target, conf.db_password)
|
||||
|
||||
if verbose: print "Created user %s" % target
|
||||
|
||||
|
|
@ -82,7 +81,7 @@ class Installer:
|
|||
source_given = False
|
||||
source_path = os.path.join(os.path.sep.join(os.path.abspath(webnotes.__file__).split(os.path.sep)[:-3]), 'data', 'Framework.sql')
|
||||
|
||||
self.dbman.restore_database(target, source_path, self.root_password)
|
||||
self.dbman.restore_database(target, source_path, target, conf.db_password)
|
||||
if verbose: print "Imported from database %s" % source_path
|
||||
|
||||
# fresh app
|
||||
|
|
@ -91,8 +90,8 @@ class Installer:
|
|||
self.install_app()
|
||||
|
||||
# update admin password
|
||||
self.update_admin_password(password)
|
||||
self.create_auth_table()
|
||||
self.update_admin_password(password)
|
||||
return target
|
||||
|
||||
def install_app(self):
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ from webnotes import _
|
|||
from webnotes.utils import cint
|
||||
from webnotes.model.doc import Document
|
||||
|
||||
class DocstatusTransitionError(webnotes.ValidationError): pass
|
||||
|
||||
class Bean:
|
||||
"""
|
||||
Collection of Documents with one parent and multiple children
|
||||
|
|
@ -40,7 +42,6 @@ class Bean:
|
|||
def __init__(self, dt=None, dn=None):
|
||||
self.docs = []
|
||||
self.obj = None
|
||||
self.to_docstatus = 0
|
||||
self.ignore_permissions = 0
|
||||
if isinstance(dt, basestring) and not dn:
|
||||
dn = dt
|
||||
|
|
@ -115,7 +116,7 @@ class Bean:
|
|||
"""
|
||||
return [d.fields for d in self.docs]
|
||||
|
||||
def check_if_latest(self):
|
||||
def check_if_latest(self, method="save"):
|
||||
"""
|
||||
Raises exception if the modified time is not the same as in the database
|
||||
"""
|
||||
|
|
@ -123,17 +124,37 @@ class Bean:
|
|||
|
||||
if (not is_single(self.doc.doctype)) and (not cint(self.doc.fields.get('__islocal'))):
|
||||
tmp = webnotes.conn.sql("""
|
||||
SELECT modified FROM `tab%s` WHERE name="%s" for update"""
|
||||
% (self.doc.doctype, self.doc.name))
|
||||
SELECT modified, docstatus FROM `tab%s` WHERE name="%s" for update"""
|
||||
% (self.doc.doctype, self.doc.name), as_dict=True)
|
||||
|
||||
if not tmp:
|
||||
webnotes.msgprint("""This record does not exist. Please refresh.""", raise_exception=1)
|
||||
|
||||
if tmp and str(tmp[0][0]) != str(self.doc.modified):
|
||||
if tmp and str(tmp[0].modified) != str(self.doc.modified):
|
||||
webnotes.msgprint("""
|
||||
Document has been modified after you have opened it.
|
||||
To maintain the integrity of the data, you will not be able to save your changes.
|
||||
Please refresh this document. [%s/%s]""" % (tmp[0][0], self.doc.modified), raise_exception=1)
|
||||
Please refresh this document. [%s/%s]""" % (tmp[0].modified, self.doc.modified), raise_exception=1)
|
||||
|
||||
self.check_docstatus_transition(tmp[0].docstatus, method)
|
||||
|
||||
def check_docstatus_transition(self, db_docstatus, method):
|
||||
valid = {
|
||||
"save": [0,0],
|
||||
"submit": [0,1],
|
||||
"cancel": [1,2],
|
||||
"update_after_submit": [1,1]
|
||||
}
|
||||
|
||||
labels = {
|
||||
0: _("Draft"),
|
||||
1: _("Submitted"),
|
||||
2: _("Cancelled")
|
||||
}
|
||||
|
||||
if [db_docstatus, self.to_docstatus] != valid[method]:
|
||||
webnotes.msgprint(_("Cannot change from") + ": " + labels[db_docstatus] + " > " + \
|
||||
labels[self.to_docstatus], raise_exception=DocstatusTransitionError)
|
||||
|
||||
def check_links(self):
|
||||
ref, err_list = {}, []
|
||||
|
|
@ -162,13 +183,13 @@ class Bean:
|
|||
if d.docstatus != 2 and self.to_docstatus >= d.docstatus: # don't update deleted
|
||||
d.docstatus = self.to_docstatus
|
||||
|
||||
def prepare_for_save(self, check_links):
|
||||
self.check_if_latest()
|
||||
if check_links:
|
||||
def prepare_for_save(self, method):
|
||||
self.check_if_latest(method)
|
||||
if method != "cancel":
|
||||
self.check_links()
|
||||
self.update_timestamps_and_docstatus()
|
||||
self.update_parent_info()
|
||||
|
||||
|
||||
def update_parent_info(self):
|
||||
idx_map = {}
|
||||
is_local = cint(self.doc.fields.get("__islocal"))
|
||||
|
|
@ -247,10 +268,8 @@ class Bean:
|
|||
|
||||
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.to_docstatus = 0
|
||||
self.prepare_for_save("save")
|
||||
self.run_method('validate')
|
||||
self.save_main()
|
||||
self.save_children()
|
||||
|
|
@ -262,10 +281,12 @@ class Bean:
|
|||
|
||||
def submit(self):
|
||||
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "submit", self.doc):
|
||||
if self.doc.docstatus != 0:
|
||||
webnotes.msgprint("Only draft can be submitted", raise_exception=1)
|
||||
self.to_docstatus = 1
|
||||
self.save()
|
||||
self.prepare_for_save("submit")
|
||||
self.run_method('validate')
|
||||
self.save_main()
|
||||
self.save_children()
|
||||
self.run_method('on_update')
|
||||
self.run_method('on_submit')
|
||||
else:
|
||||
self.no_permission_to(_("Submit"))
|
||||
|
|
@ -274,10 +295,9 @@ class Bean:
|
|||
|
||||
def cancel(self):
|
||||
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "cancel", self.doc):
|
||||
if self.doc.docstatus != 1:
|
||||
webnotes.msgprint("Only submitted can be cancelled", raise_exception=1)
|
||||
self.to_docstatus = 2
|
||||
self.prepare_for_save(1)
|
||||
self.prepare_for_save("cancel")
|
||||
self.run_method('before_cancel')
|
||||
self.save_main()
|
||||
self.save_children()
|
||||
self.run_method('on_cancel')
|
||||
|
|
@ -291,7 +311,8 @@ class Bean:
|
|||
webnotes.msgprint("Only to called after submit", raise_exception=1)
|
||||
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "write", self.doc):
|
||||
self.to_docstatus = 1
|
||||
self.prepare_for_save(1)
|
||||
self.prepare_for_save("update_after_submit")
|
||||
self.run_method('before_update_after_submit')
|
||||
self.save_main()
|
||||
self.save_children()
|
||||
self.run_method('on_update_after_submit')
|
||||
|
|
|
|||
|
|
@ -373,13 +373,13 @@ class DbManager:
|
|||
"""get list of databases"""
|
||||
return [d[0] for d in self.conn.sql("SHOW DATABASES")]
|
||||
|
||||
def restore_database(self,target,source,root_password):
|
||||
def restore_database(self,target,source,user,password):
|
||||
from webnotes.utils import make_esc
|
||||
esc = make_esc('$ ')
|
||||
|
||||
try:
|
||||
ret = os.system("mysql -u root -p%s %s < %s" % \
|
||||
(esc(root_password), esc(target), source))
|
||||
ret = os.system("mysql -u %s -p%s %s < %s" % \
|
||||
(esc(user), esc(password), esc(target), source))
|
||||
except Exception,e:
|
||||
raise e
|
||||
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ def add_code(doctype, doclist):
|
|||
_add_code(scrub(doc.name) + '.css', '__css')
|
||||
_add_code('%s_list.js' % scrub(doc.name), '__list_js')
|
||||
_add_code('%s_calendar.js' % scrub(doc.name), '__calendar_js')
|
||||
_add_code('%s_map.js' % scrub(doc.name), '__map_js')
|
||||
add_embedded_js(doc)
|
||||
|
||||
def add_embedded_js(doc):
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ def delete_doc(doctype=None, name=None, doclist = None, force=0):
|
|||
|
||||
return 'okay'
|
||||
|
||||
def check_if_doc_is_linked(dt, dn):
|
||||
def check_if_doc_is_linked(dt, dn, method="Delete"):
|
||||
"""
|
||||
Raises excption if the given doc(dt, dn) is linked in another record.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class Session:
|
|||
data = self.get_session_record()
|
||||
if data:
|
||||
# set language
|
||||
if data.lang:
|
||||
if data.lang and self.user!="demo@erpnext.com":
|
||||
webnotes.lang = data.lang
|
||||
self.data = webnotes._dict({'data': data,
|
||||
'user':data.user, 'sid': self.sid})
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
# Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
|
||||
#
|
||||
# MIT License (MIT)
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
"""
|
||||
Tests for modules:
|
||||
|
||||
To execute webnotes/tests.py webnotes.tests.modules
|
||||
|
||||
Uses Sandbox DocType for testing
|
||||
"""
|
||||
import unittest
|
||||
import webnotes
|
||||
|
||||
from webnotes.modules import Module
|
||||
|
||||
class ModuleTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
webnotes.conn.begin()
|
||||
|
||||
def update_timestamp(self, path):
|
||||
"""
|
||||
Just open a file for write and save it so that the timetamp changes
|
||||
"""
|
||||
import os
|
||||
path = os.path.join(Module('core').get_path(), path)
|
||||
c = file(path,'r').read()
|
||||
file(path,'w').write(c)
|
||||
|
||||
def test_module_import(self):
|
||||
"""
|
||||
Import a txt file into the database and check if a new column has been added
|
||||
"""
|
||||
webnotes.conn.rollback()
|
||||
webnotes.conn.sql("alter table tabSandbox drop column `to_be_dropped`", ignore_ddl=1)
|
||||
webnotes.conn.begin()
|
||||
|
||||
# delete from table
|
||||
webnotes.conn.sql("delete from tabDocField where parent='Sandbox' and fieldname='to_be_dropped'")
|
||||
|
||||
self.update_timestamp('doctype/sandbox/sandbox.txt')
|
||||
|
||||
# reload
|
||||
Module('core').reload('DocType','Sandbox')
|
||||
|
||||
# commit re-adding
|
||||
webnotes.conn.commit()
|
||||
|
||||
# check if column created
|
||||
self.assertTrue('to_be_dropped' in [r[0] for r in webnotes.conn.sql("desc tabSandbox")])
|
||||
|
||||
# check if imported in table
|
||||
self.assertTrue(len(webnotes.conn.sql("select name from tabDocField where parent='Sandbox' and fieldname='to_be_dropped'"))==1)
|
||||
|
||||
|
||||
def test_read_js_code(self):
|
||||
"""
|
||||
Read a js code file
|
||||
"""
|
||||
data = Module('core').get_doc_file('DocType','Sandbox','.js').read()
|
||||
self.assertTrue('//test3456' in data)
|
||||
self.assertTrue('//import3456' in data)
|
||||
|
||||
def test_sql_file(self):
|
||||
"""
|
||||
Test an sql file
|
||||
"""
|
||||
webnotes.conn.rollback()
|
||||
webnotes.conn.sql("drop trigger if exists sandbox_trigger")
|
||||
self.update_timestamp('doctype/sandbox/my_trigger.sql')
|
||||
Module('core').get_file('doctype','sandbox','my_trigger.sql').sync()
|
||||
self.assertTrue(webnotes.conn.sql("show triggers like 'tabSandbox'")[0][0]=='sandbox_trigger')
|
||||
|
||||
def test_sync_all(self):
|
||||
"""
|
||||
Test sync all (rerun the sql file test calling sync_all)
|
||||
"""
|
||||
|
||||
webnotes.conn.rollback()
|
||||
webnotes.conn.sql("drop trigger if exists sandbox_trigger")
|
||||
self.update_timestamp('doctype/sandbox/my_trigger.sql')
|
||||
Module('core').sync_all()
|
||||
self.assertTrue(webnotes.conn.sql("show triggers like 'tabSandbox'")[0][0]=='sandbox_trigger')
|
||||
|
||||
def tearDown(self):
|
||||
webnotes.conn.rollback()
|
||||
|
|
@ -52,7 +52,7 @@ def build_message_files():
|
|||
build_for_framework('lib/public/js/wn', 'js')
|
||||
build_for_framework('app/public/js', 'js', with_doctype_names=True)
|
||||
|
||||
build_for_modules()
|
||||
#build_for_modules()
|
||||
|
||||
def build_for_pages(path):
|
||||
"""make locale files for framework py and js (all)"""
|
||||
|
|
|
|||
|
|
@ -182,9 +182,15 @@ def add_years(date, years):
|
|||
|
||||
def date_diff(string_ed_date, string_st_date):
|
||||
return (getdate(string_ed_date) - getdate(string_st_date)).days
|
||||
|
||||
def time_diff(string_ed_date, string_st_date):
|
||||
return get_datetime(string_ed_date) - get_datetime(string_st_date)
|
||||
|
||||
def time_diff_in_seconds(string_ed_date, string_st_date):
|
||||
return (get_datetime(string_ed_date) - get_datetime(string_st_date)).seconds
|
||||
return time_diff(string_ed_date, string_st_date).seconds
|
||||
|
||||
def time_diff_in_hours(string_ed_date, string_st_date):
|
||||
return round(float(time_diff(string_ed_date, string_st_date).seconds) / 3600, 6)
|
||||
|
||||
def now_datetime():
|
||||
from datetime import datetime
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ def get_open_count(doctypes):
|
|||
if d in queries:
|
||||
condition = queries[d]
|
||||
key = condition.keys()[0]
|
||||
query = "select count(*) from `tab%s` where `%s`=%s" % (d, key, '%s')
|
||||
query = "select count(*) from `tab%s` where `%s`=%s and docstatus<2" % (d, key, '%s')
|
||||
count[d] = webnotes.conn.sql(query, condition[key])[0][0] or ""
|
||||
conditions[d] = condition
|
||||
|
||||
|
|
|
|||
|
|
@ -220,6 +220,8 @@ def build_match_conditions(doctype, fields=None):
|
|||
|
||||
if match_conditions and match:
|
||||
return '('+ ' or '.join(match_conditions) +')'
|
||||
else:
|
||||
return ""
|
||||
|
||||
def get_tables(doctype, fields):
|
||||
"""extract tables from fields"""
|
||||
|
|
@ -253,7 +255,8 @@ def save_report():
|
|||
d = Document('Report')
|
||||
d.report_name = data['name']
|
||||
d.ref_doctype = data['doctype']
|
||||
|
||||
|
||||
d.report_type = "Report Builder"
|
||||
d.json = data['json']
|
||||
webnotes.bean([d]).save()
|
||||
webnotes.msgprint("%s saved." % d.name)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue