diff --git a/core/doctype/control_panel/control_panel.py b/core/doctype/control_panel/control_panel.py index cad9748815..c487e2a97d 100644 --- a/core/doctype/control_panel/control_panel.py +++ b/core/doctype/control_panel/control_panel.py @@ -25,9 +25,6 @@ import webnotes from webnotes import form, msgprint - - - class DocType: def __init__(self, doc, doclist): self.doc = doc diff --git a/core/doctype/doctype/doctype.py b/core/doctype/doctype/doctype.py index b0a1aebfbd..9ce5b630b2 100644 --- a/core/doctype/doctype/doctype.py +++ b/core/doctype/doctype/doctype.py @@ -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 diff --git a/core/doctype/profile/profile.py b/core/doctype/profile/profile.py index 10bdd86a8b..af96bf2b9b 100644 --- a/core/doctype/profile/profile.py +++ b/core/doctype/profile/profile.py @@ -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,
'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,
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,
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): diff --git a/core/page/data_import_tool/data_import_tool.py b/core/page/data_import_tool/data_import_tool.py index 7aeff6672d..83a79c5281 100644 --- a/core/page/data_import_tool/data_import_tool.py +++ b/core/page/data_import_tool/data_import_tool.py @@ -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 '%(name)s' % 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'])) diff --git a/core/page/modules_setup/modules_setup.js b/core/page/modules_setup/modules_setup.js index e5de902520..856bb63d10 100644 --- a/core/page/modules_setup/modules_setup.js +++ b/core/page/modules_setup/modules_setup.js @@ -24,7 +24,7 @@ wn.modules_setup = { if(m!="Setup") { var $chk = $("") .prependTo($('

'+m+'

').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); } } diff --git a/public/js/legacy/utils/datatype.js b/public/js/legacy/utils/datatype.js index 1494aaa04e..56a568c934 100644 --- a/public/js/legacy/utils/datatype.js +++ b/public/js/legacy/utils/datatype.js @@ -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) { diff --git a/public/js/legacy/widgets/form/fields.js b/public/js/legacy/widgets/form/fields.js index 48c98b6fc2..4f801d7e77 100644 --- a/public/js/legacy/widgets/form/fields.js +++ b/public/js/legacy/widgets/form/fields.js @@ -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;'>\ ") .click(function() { - cur_frm.attachments.new_attachment(); + cur_frm.attachments.new_attachment(me.df.fieldname); }) .appendTo(this.input_area); } diff --git a/public/js/legacy/widgets/form/form.js b/public/js/legacy/widgets/form/form.js index d1b9a7b569..c31c09a8fa 100644 --- a/public/js/legacy/widgets/form/form.js +++ b/public/js/legacy/widgets/form/form.js @@ -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(); + } } } } diff --git a/public/js/legacy/widgets/form/grid.js b/public/js/legacy/widgets/form/grid.js index 26db9cdde7..9c3db75182 100644 --- a/public/js/legacy/widgets/form/grid.js +++ b/public/js/legacy/widgets/form/grid.js @@ -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'; diff --git a/public/js/wn/form/attachments.js b/public/js/wn/form/attachments.js index cb9788ac82..7c43151c70 100644 --- a/public/js/wn/form/attachments.js +++ b/public/js/wn/form/attachments.js @@ -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" + ((value==null || value==="") ? "" : format_number(value, null, decimals)) + ""; }, Int: function(value) { - return cint(value); + return value==null ? "": cint(value); }, Percent: function(value) { return flt(value, 2) + "%"; diff --git a/public/js/wn/model/meta.js b/public/js/wn/model/meta.js index 202a1e30df..2e64625094 100644 --- a/public/js/wn/model/meta.js +++ b/public/js/wn/model/meta.js @@ -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]; diff --git a/public/js/wn/model/model.js b/public/js/wn/model/model.js index d5313b8952..2b85fb33d2 100644 --- a/public/js/wn/model/model.js +++ b/public/js/wn/model/model.js @@ -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 || {} } } diff --git a/public/js/wn/views/communication.js b/public/js/wn/views/communication.js index aac4f66b7b..401900aab0 100644 --- a/public/js/wn/views/communication.js +++ b/public/js/wn/views/communication.js @@ -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) diff --git a/public/js/wn/views/listview.js b/public/js/wn/views/listview.js index 490c0a4fda..d3b581fbbc 100644 --- a/public/js/wn/views/listview.js +++ b/public/js/wn/views/listview.js @@ -165,12 +165,12 @@ wn.views.ListView = Class.extend({ } else if(opts.content=='name') { $("") - .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') { diff --git a/templates/js/login.js b/templates/js/login.js index 06ea4c5242..ff2b8fd0b1 100644 --- a/templates/js/login.js +++ b/templates/js/login.js @@ -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") { diff --git a/webnotes/__init__.py b/webnotes/__init__.py index 2d765d95dc..7c2c2c9bcc 100644 --- a/webnotes/__init__.py +++ b/webnotes/__init__.py @@ -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 diff --git a/webnotes/defaults.py b/webnotes/defaults.py index 223d01803c..065110aa22 100644 --- a/webnotes/defaults.py +++ b/webnotes/defaults.py @@ -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: diff --git a/webnotes/model/doc.py b/webnotes/model/doc.py index 3b2313ddbb..665a0731a8 100755 --- a/webnotes/model/doc.py +++ b/webnotes/model/doc.py @@ -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 diff --git a/webnotes/model/rename_doc.py b/webnotes/model/rename_doc.py index 3f5da9d311..b2c4e8c3e8 100644 --- a/webnotes/model/rename_doc.py +++ b/webnotes/model/rename_doc.py @@ -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 diff --git a/webnotes/utils/datautils.py b/webnotes/utils/datautils.py index 0155d73abf..df27058957 100644 --- a/webnotes/utils/datautils.py +++ b/webnotes/utils/datautils.py @@ -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() \ No newline at end of file + 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 '%(name)s' % locals() \ No newline at end of file diff --git a/webnotes/widgets/form/run_method.py b/webnotes/widgets/form/run_method.py index b40cb91e64..6d8134567f 100644 --- a/webnotes/widgets/form/run_method.py +++ b/webnotes/widgets/form/run_method.py @@ -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): diff --git a/webnotes/widgets/query_report.py b/webnotes/widgets/query_report.py index 7b58a07b16..4f22353e38 100644 --- a/webnotes/widgets/query_report.py +++ b/webnotes/widgets/query_report.py @@ -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)