This commit is contained in:
Akhilesh Darjee 2013-05-15 11:50:17 +05:30
commit 5760d094f0
23 changed files with 179 additions and 149 deletions

View file

@ -25,9 +25,6 @@ import webnotes
from webnotes import form, msgprint
class DocType:
def __init__(self, doc, doclist):
self.doc = doc

View file

@ -111,7 +111,7 @@ class DocType:
webnotes.conn.sql("delete from `tabProperty Setter` where doc_type = %s", self.doc.name)
webnotes.conn.sql("delete from `tabSearch Criteria` where doc_type = %s", self.doc.name)
def on_rename(self, new, old):
def on_rename(self, new, old, merge=False):
if self.doc.issingle:
webnotes.conn.sql("""\
update tabSingles set doctype=%s

View file

@ -22,7 +22,7 @@
from __future__ import unicode_literals
import webnotes, json
from webnotes.utils import cint, now
from webnotes.utils import cint, now, cstr
from webnotes import _
class DocType:
@ -32,19 +32,14 @@ class DocType:
def autoname(self):
"""set name as email id"""
import re
from webnotes.utils import validate_email_add
if self.doc.name not in ('Guest','Administrator'):
self.doc.email = self.doc.email.strip()
if not validate_email_add(self.doc.email):
webnotes.msgprint("%s is not a valid email id" % self.doc.email)
raise Exception
self.doc.email = self.doc.email.strip()
self.doc.name = self.doc.email
def validate(self):
self.in_insert = self.doc.fields.get("__islocal")
if self.doc.name not in ('Guest','Administrator'):
self.validate_email_type(self.doc.email)
self.validate_max_users()
self.check_one_system_manager()
self.check_enable_disable()
@ -67,9 +62,11 @@ class DocType:
import conf
# check only when enabling a user
if hasattr(conf, 'max_users') and self.doc.enabled and \
self.doc.name not in ["Administrator", "Guest"]:
self.doc.name not in ["Administrator", "Guest"] and \
cstr(self.doc.user_type).strip() in ("", "System User"):
active_users = webnotes.conn.sql("""select count(*) from tabProfile
where ifnull(enabled, 0)=1 and docstatus<2
and ifnull(user_type, "System User") = "System User"
and name not in ('Administrator', 'Guest', %s)""", (self.doc.name,))[0][0]
if active_users >= conf.max_users and conf.max_users:
webnotes.msgprint("""
@ -188,7 +185,7 @@ Thank you,<br>
'user_fullname': get_user_fullname(webnotes.session['user'])
}
sender = webnotes.session.user != "Administrator" and webnotes.session.user or None
sender = webnotes.session.user not in ("Administrator", "Guest") and webnotes.session.user or None
sendmail_md(recipients=self.doc.email, sender=sender, subject=subject, msg=txt % args)
@ -219,11 +216,8 @@ Thank you,<br>
webnotes.conn.sql("""delete from `tabComment` where comment_doctype='Message'
and (comment_docname=%s or owner=%s)""", (self.doc.name, self.doc.name))
def on_rename(self,newdn,olddn):
# do not allow renaming administrator and guest
if olddn in ["Administrator", "Guest"]:
webnotes.msgprint("""Hey! You are restricted from renaming the user: %s""" % \
(olddn, ), raise_exception=1)
def on_rename(self,newdn,olddn, merge=False):
self.validate_rename(newdn, olddn)
tables = webnotes.conn.sql("show tables")
for tab in tables:
@ -244,7 +238,24 @@ Thank you,<br>
where name=%s""", (newdn, newdn))
# update __Auth table
webnotes.conn.sql("""update __Auth set user=%s where user=%s""", (newdn, olddn))
if not merge:
webnotes.conn.sql("""update __Auth set user=%s where user=%s""", (newdn, olddn))
def validate_rename(self, newdn, olddn):
# do not allow renaming administrator and guest
if olddn in ["Administrator", "Guest"]:
webnotes.msgprint("""Hey! You are restricted from renaming the user: %s""" % \
(olddn, ), raise_exception=1)
self.validate_email_type(newdn)
def validate_email_type(self, email):
from webnotes.utils import validate_email_add
email = email.strip()
if not validate_email_add(email):
webnotes.msgprint("%s is not a valid email id" % email)
raise Exception
@webnotes.whitelist()
def get_all_roles(arg=None):

View file

@ -4,8 +4,8 @@ import webnotes
import webnotes.model.doc
import webnotes.model.doctype
from webnotes.model.doc import Document
from webnotes.utils import cstr, cint, flt
from webnotes.utils.datautils import UnicodeWriter
from webnotes.utils import cstr
from webnotes.utils.datautils import UnicodeWriter, check_record, import_doc, getlink
from webnotes import _
data_keys = webnotes._dict({
@ -15,8 +15,6 @@ data_keys = webnotes._dict({
"columns": "Column Name:"
})
doctype_dl = None
@webnotes.whitelist()
def get_doctypes():
return [r[0] for r in webnotes.conn.sql("""select name from `tabDocType`
@ -31,8 +29,6 @@ def get_doctype_options():
@webnotes.whitelist(allow_roles=['System Manager', 'Administrator'])
def get_template():
global doctype_dl
doctype = webnotes.form_dict['doctype']
parenttype = webnotes.form_dict.get('parent_doctype')
@ -133,8 +129,6 @@ def get_template():
@webnotes.whitelist(allow_roles=['System Manager', 'Administrator'])
def upload():
"""upload data"""
global doctype_dl
webnotes.mute_emails = True
from webnotes.utils.datautils import read_csv_content_from_uploaded_file
@ -214,11 +208,11 @@ def upload():
row_idx = (i + 1) + start_row
d = dict(zip(columns, row[1:]))
d = webnotes._dict(zip(columns, row[1:]))
d['doctype'] = doctype
try:
check_record(d, parenttype)
check_record(d, parenttype, doctype_dl)
if parenttype:
# child doc
doc = Document(doctype)
@ -262,72 +256,8 @@ def get_parent_field(doctype, parenttype):
raise Exception
return parentfield
def check_record(d, parenttype=None):
"""check for mandatory, select options, dates. these should ideally be in doclist"""
from webnotes.utils.dateutils import parse_date
if parenttype and not d.get('parent'):
raise Exception, "parent is required."
global doctype_dl
if not doctype_dl:
doctype_dl = webnotes.model.doctype.get(d.doctype)
for key in d:
docfield = doctype_dl.get_field(key)
val = d[key]
if docfield:
if docfield.reqd and (val=='' or val==None):
raise Exception, "%s is mandatory." % key
if docfield.fieldtype=='Select' and val and docfield.options:
if docfield.options.startswith('link:'):
link_doctype = docfield.options.split(':')[1]
if not webnotes.conn.exists(link_doctype, val):
raise Exception, "%s must be a valid %s" % (key, link_doctype)
elif docfield.options == "attach_files:":
pass
elif val not in docfield.options.split('\n'):
raise Exception, "%s must be one of: %s" % (key,
", ".join(filter(None, docfield.options.split("\n"))))
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()
def delete_child_rows(rows, doctype):
"""delete child rows for all parents"""
for p in list(set([r[1] for r in rows])):
webnotes.conn.sql("""delete from `tab%s` where parent=%s""" % (doctype, '%s'), p)
def import_doc(d, doctype, overwrite, row_idx, submit=False):
"""import main (non child) document"""
if webnotes.conn.exists(doctype, d['name']):
if overwrite:
bean = webnotes.bean(doctype, d['name'])
bean.doc.fields.update(d)
if d.get("docstatus") == 1:
bean.update_after_submit()
else:
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:
bean = webnotes.bean([d])
bean.insert()
if submit:
bean.submit()
return 'Inserted row (#%d) %s' % (row_idx, getlink(doctype,
bean.doc.fields['name']))

View file

@ -24,7 +24,7 @@ wn.modules_setup = {
if(m!="Setup") {
var $chk = $("<input type='checkbox' data-module='"+m+"' style='margin-top: -2px'>")
.prependTo($('<p><span> '+m+'</span></p>').appendTo("#modules-list"));
if(wn.boot.hidden_modules.indexOf(m)==-1) {
if(!wn.boot.hidden_modules || wn.boot.hidden_modules.indexOf(m)==-1) {
$chk.attr("checked", true);
}
}

View file

@ -73,7 +73,7 @@ function cint(v, def) {
v=v+'';
v=lstrip(v, ['0']);
v=parseInt(v);
if(isNaN(v))v=def?def:0;
if(isNaN(v))v=def===undefined?0:def;
return v;
}
function validate_email(txt) {

View file

@ -942,9 +942,9 @@ CurrencyField.prototype.get_field_currency = function() {
};
CurrencyField.prototype.get_formatted = function(val) {
if(this.not_in_form)
if(!this.doctype)
return val;
return format_currency(val, this.get_field_currency());
}
CurrencyField.prototype.set_disp = function(val) {
@ -1088,7 +1088,7 @@ SelectField.prototype.make_input = function() {
padding-left: 6px; padding-right: 6px; margin-left: 6px;'>\
<i class='icon-plus'></i></button>")
.click(function() {
cur_frm.attachments.new_attachment();
cur_frm.attachments.new_attachment(me.df.fieldname);
})
.appendTo(this.input_area);
}

View file

@ -696,11 +696,15 @@ _f.Frm.prototype.refresh_dependency = function() {
// show / hide
if(f.guardian_has_value) {
f.df.hidden = 0;
f.refresh();
if(f.df.hidden != 0) {
f.df.hidden = 0;
f.refresh();
}
} else {
f.df.hidden = 1;
f.refresh();
if(f.df.hidden != 1) {
f.df.hidden = 1;
f.refresh();
}
}
}
}

View file

@ -247,7 +247,8 @@ _f.Grid.prototype.set_cell_value = function(cell) {
// variations
if(cell.cellIndex) {
$(cell.div).html(wn.format(v, hc.df, {for_print:
((doc && doc.docstatus==0 && !cint(hc.df ? hc.df.read_only : 1)) ? true : false)}));
((doc && doc.docstatus==0 && !cint(hc.df ? hc.df.read_only : 1))
? true : false)}, doc));
} else {
// Index column
cell.div.style.padding = '2px';

View file

@ -62,11 +62,14 @@ wn.ui.form.Attachments = Class.extend({
var file_list = this.get_file_list();
var file_names = keys(file_list).sort();
// add attachment objects
for(var i=0; i<file_names.length; i++) {
this.add_attachment(file_names[i], file_list);
}
// refresh select fields with options attach_files:
this.refresh_attachment_select_fields();
},
get_file_list: function() {
return this.frm.doc.file_list ? JSON.parse(this.frm.doc.file_list) : {};
@ -104,16 +107,13 @@ wn.ui.form.Attachments = Class.extend({
return;
}
me.remove_fileid(data);
me.frm && me.frm.cscript.on_remove_attachment
&& me.frm.cscript.on_remove_attachment(me.frm.doc);
me.frm.refresh();
}
});
});
return false;
});
},
new_attachment: function() {
new_attachment: function(fieldname) {
var me = this;
if(!this.dialog) {
this.dialog = new wn.ui.Dialog({
@ -125,7 +125,7 @@ wn.ui.form.Attachments = Class.extend({
}
this.dialog.body.innerHTML = '';
this.dialog.show();
wn.upload.make({
parent: this.dialog.body,
args: {
@ -134,15 +134,19 @@ wn.ui.form.Attachments = Class.extend({
docname: this.frm.docname
},
callback: function(fileid, filename, r) {
me.update_attachment(fileid, filename, r);
me.update_attachment(fileid, filename, fieldname, r);
}
});
},
update_attachment: function(fileid, filename, r) {
update_attachment: function(fileid, filename, fieldname, r) {
this.dialog && this.dialog.hide();
if(fileid) {
this.add_to_file_list(fileid, filename);
this.refresh();
if(fieldname) {
this.frm.set_value(fieldname, "files/"+filename);
this.frm.cscript[fieldname] && this.frm.cscript[fieldname](this.frm.doc);
}
}
},
add_to_file_list: function(fileid, filename) {
@ -159,5 +163,18 @@ wn.ui.form.Attachments = Class.extend({
new_file_list[key] = value;
});
this.frm.doc.file_list = JSON.stringify(new_file_list);
this.refresh();
},
refresh_attachment_select_fields: function() {
for(var i=0; i<this.frm.fields.length; i++) {
if(this.frm.fields[i].attach_files) {
var fieldname = this.frm.fields[i].df.fieldname;
refresh_field(fieldname);
if(this.frm.doc[fieldname]!=undefined && !inList(this.frm.fields[i].df.options.split("\n"), this.frm.doc[fieldname])) {
this.frm.cscript.on_remove_attachment && this.frm.cscript.on_remove_attachment(this.frm.doc);
this.frm.set_value(fieldname, "");
}
}
}
}
});

View file

@ -7,15 +7,14 @@ wn.form.formatters = {
return value==null ? "" : value
},
Float: function(value, docfield) {
var decimals = wn.boot.sysdefaults.float_precision ?
parseInt(wn.boot.sysdefaults.float_precision) : null;
var decimals = cint(docfield.options, null) || cint(wn.boot.sysdefaults.float_precision, null);
return "<div style='text-align: right'>" +
((value==null || value==="") ? "" :
format_number(value, null, decimals)) + "</div>";
},
Int: function(value) {
return cint(value);
return value==null ? "": cint(value);
},
Percent: function(value) {
return flt(value, 2) + "%";

View file

@ -127,7 +127,6 @@ $.extend(wn.meta, {
get_field_currency: function(df, doc) {
var currency = wn.boot.sysdefaults.currency;
if(!doc && cur_frm)
doc = cur_frm.doc;
@ -138,10 +137,9 @@ $.extend(wn.meta, {
// get reference record e.g. Company
var docname = doc[options[1]];
if(!docname && cur_frm) {
docname = cur_frm.doc[options[1]]
docname = cur_frm.doc[options[1]];
}
currency = wn.model.get_value(options[0], doc[options[1]],
options[2]) || currency;
currency = wn.model.get_value(options[0], docname, options[2]) || currency;
}
} else if(doc && doc[df.options]) {
currency = doc[df.options];

View file

@ -277,8 +277,8 @@ $.extend(wn.model, {
map_info = map_info[args.source[0].doctype];
if(!map_info) {
map_info = {
table_map: {},
field_map: {}
table_map: args.table_map || {},
field_map: args.field_map || {}
}
}

View file

@ -196,6 +196,7 @@ wn.views.CommunicationComposer = Class.extend({
$(fields.send_email.input).attr("checked", "checked")
$(fields.send.input).click(function() {
var btn = this;
var form_values = me.dialog.get_values();
if(!form_values) return;
@ -233,6 +234,7 @@ wn.views.CommunicationComposer = Class.extend({
print_html: print_html,
attachments: selected_attachments
},
btn: btn,
callback: function(r) {
if(!r.exc) {
if(form_values.send_email)

View file

@ -165,12 +165,12 @@ wn.views.ListView = Class.extend({
}
else if(opts.content=='name') {
$("<a>")
.attr("href", "#Form/" + data.doctype + "/" + data.name)
.attr("href", "#Form/" + data.doctype + "/" + encodeURIComponent(data.name))
.html(data.name)
.appendTo(parent);
}
else if(opts.content=='avatar' || opts.content=='avatar_modified') {
$(parent).append(wn.avatar(data.owner, false, wn._("Modified by")+": "
$(parent).append(wn.avatar(data.modified_by, false, wn._("Modified by")+": "
+ wn.user_info(data.modified_by).fullname));
}
else if(opts.content=='check') {

View file

@ -57,7 +57,6 @@ login.do_login = function(){
data: args,
dataType: "json",
success: function(data) {
$("input").val("");
$("#login-spinner").toggle(false);
$('#login_btn').attr("disabled", false);
if(data.message=="Logged In") {

View file

@ -220,7 +220,7 @@ def whitelist(allow_guest=False, allow_roles=None):
raise PermissionError, "Method not allowed"
return fn
return innerfn
def clear_cache(user=None, doctype=None):
@ -342,9 +342,9 @@ def reload_doc(module, dt=None, dn=None):
import webnotes.modules
return webnotes.modules.reload_doc(module, dt, dn)
def rename_doc(doctype, old, new, debug=0, force=False):
def rename_doc(doctype, old, new, debug=0, force=False, merge=False):
from webnotes.model.rename_doc import rename_doc
rename_doc(doctype, old, new, force=force)
rename_doc(doctype, old, new, force=force, merge=merge)
def insert(doclist):
import webnotes.model

View file

@ -109,11 +109,12 @@ def get_defaults_for(parent="Control Panel"):
for d in res:
if d.defkey in defaults:
# listify
if isinstance(defaults[d.defkey], basestring) and defaults[d.defkey] != d.defvalue:
if not isinstance(defaults[d.defkey], list) 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:
elif d.defvalue is not None:
defaults[d.defkey] = d.defvalue
if webnotes.session and parent == webnotes.session.user:

View file

@ -258,7 +258,7 @@ class Document:
self._set_name(autoname, istable)
# validate name
validate_name(self.doctype, self.name, case)
self.name = validate_name(self.doctype, self.name, case)
# insert!
if not keep_timestamps:
@ -670,9 +670,10 @@ def copy_common_fields(from_doc, to_doc):
if doctype_list.get_field(fieldname) and to_doc.fields[fieldname] != value:
to_doc.fields[fieldname] = value
def validate_name(doctype, name, case=None):
if webnotes.conn.sql('select name from `tab%s` where name=%s' % (doctype,'%s'), name):
raise NameError, 'Name %s already exists' % name
def validate_name(doctype, name, case=None, merge=False):
if not merge:
if webnotes.conn.sql('select name from `tab%s` where name=%s' % (doctype,'%s'), name):
raise NameError, 'Name %s already exists' % name
# no name
if not name: return 'No Name Specified for %s' % doctype

View file

@ -1,7 +1,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _
import webnotes.utils
from webnotes.utils import cint
import webnotes.model.doctype
from webnotes.model.doc import validate_name
@ -13,16 +13,19 @@ def rename_doc(doctype, old, new, force=False, merge=False):
"""
if not webnotes.conn.exists(doctype, old):
return
force = cint(force)
merge = cint(merge)
# get doclist of given doctype
doclist = webnotes.model.doctype.get(doctype)
new = validate_rename(doctype, new, doclist, merge, force)
# call on_rename
obj = webnotes.get_obj(doctype, old)
if hasattr(obj, 'on_rename'):
new = obj.on_rename(new, old) or new
new = obj.on_rename(new, old, merge) or new
new = validate_rename(doctype, new, doclist, merge, force)
if not merge:
rename_parent_and_child(doctype, old, new, doclist)
@ -61,8 +64,8 @@ def validate_rename(doctype, new, doclist, merge, force):
if merge and not exists:
webnotes.msgprint("%s: %s does not exist, select a new target to merge." % (doctype, new), raise_exception=1)
if not merge and exists:
if (not merge) and exists:
webnotes.msgprint("%s: %s exists, select a new, new name." % (doctype, new), raise_exception=1)
if not webnotes.has_permission(doctype, "write"):
@ -72,7 +75,7 @@ def validate_rename(doctype, new, doclist, merge, force):
webnotes.msgprint("%s cannot be renamed" % doctype, raise_exception=1)
# validate naming like it's done in doc.py
new = validate_name(doctype, new)
new = validate_name(doctype, new, merge=merge)
return new

View file

@ -22,9 +22,10 @@
from __future__ import unicode_literals
import webnotes
from webnotes import msgprint
import json
import csv, cStringIO
from webnotes.utils import encode, cstr
from webnotes.utils import encode, cstr, cint, flt
def read_csv_content_from_uploaded_file(ignore_encoding=False):
from webnotes.utils.file_manager import get_uploaded_content
@ -47,8 +48,6 @@ def read_csv_content_from_attached_file(doc):
raise Exception
def read_csv_content(fcontent, ignore_encoding=False):
import csv
from webnotes.utils import cstr
rows = []
try:
reader = csv.reader(fcontent.splitlines())
@ -93,6 +92,7 @@ def to_csv(data):
writer.writerow(row)
return writer.getvalue()
class UnicodeWriter:
def __init__(self, encoding="utf-8"):
@ -105,4 +105,67 @@ class UnicodeWriter:
self.writer.writerow(row)
def getvalue(self):
return self.queue.getvalue()
return self.queue.getvalue()
def check_record(d, parenttype=None, doctype_dl=None):
"""check for mandatory, select options, dates. these should ideally be in doclist"""
from webnotes.utils.dateutils import parse_date
if parenttype and not d.get('parent'):
raise Exception, "parent is required."
if not doctype_dl:
doctype_dl = webnotes.model.doctype.get(d.doctype)
for key in d:
docfield = doctype_dl.get_field(key)
val = d[key]
if docfield:
if docfield.reqd and (val=='' or val==None):
raise Exception, "%s is mandatory." % key
if docfield.fieldtype=='Select' and val and docfield.options:
if docfield.options.startswith('link:'):
link_doctype = docfield.options.split(':')[1]
if not webnotes.conn.exists(link_doctype, val):
raise Exception, "%s must be a valid %s" % (key, link_doctype)
elif docfield.options == "attach_files:":
pass
elif val not in docfield.options.split('\n'):
raise Exception, "%s must be one of: %s" % (key,
", ".join(filter(None, docfield.options.split("\n"))))
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 import_doc(d, doctype, overwrite, row_idx, submit=False):
"""import main (non child) document"""
if webnotes.conn.exists(doctype, d['name']):
if overwrite:
bean = webnotes.bean(doctype, d['name'])
bean.doc.fields.update(d)
if d.get("docstatus") == 1:
bean.update_after_submit()
else:
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:
bean = webnotes.bean([d])
bean.insert()
if submit:
bean.submit()
return 'Inserted row (#%d) %s' % (row_idx, getlink(doctype,
bean.doc.fields['name']))
def getlink(doctype, name):
return '<a href="#Form/%(doctype)s/%(name)s">%(name)s</a>' % locals()

View file

@ -64,6 +64,9 @@ def runserverobj():
else:
webnotes.response['message'] = r
from webnotes.widgets.form.load import add_file_list
add_file_list(so.doc.doctype, so.doc.name, so.doclist)
webnotes.response['docs'] += so.doclist
def check_guest_access(doc):

View file

@ -80,10 +80,11 @@ def add_total_row(result, columns):
total_row = [""]*len(columns)
for row in result:
for i, col in enumerate(columns):
if col.split(":")[1] in ["Currency", "Int", "Float"] and flt(row[i]):
col = col.split(":")
if len(col) > 1 and col[1] in ["Currency", "Int", "Float"] and flt(row[i]):
total_row[i] = flt(total_row[i]) + flt(row[i])
if columns[0].split(":")[1] not in ["Currency", "Int", "Float"]:
first_col = columns[0].split(":")
if len(first_col) > 1 and first_col[1] not in ["Currency", "Int", "Float"]:
total_row[0] = "Total"
result.append(total_row)