@@ -93,6 +93,7 @@ wn.datetime = { | |||||
add_months: function(d, months) { | add_months: function(d, months) { | ||||
dt = dateutil.str_to_obj(d) | dt = dateutil.str_to_obj(d) | ||||
months = cint(months); | |||||
new_dt = new Date(dt.getFullYear(), dt.getMonth()+months, dt.getDate()) | new_dt = new Date(dt.getFullYear(), dt.getMonth()+months, dt.getDate()) | ||||
if(new_dt.getDate() != dt.getDate()) { | if(new_dt.getDate() != dt.getDate()) { | ||||
// month has changed, go the last date of prev month | // month has changed, go the last date of prev month | ||||
@@ -5216,5 +5216,5 @@ function HorizontalPositionCache(getElement) { | |||||
}; | }; | ||||
} | } | ||||
})(jQuery); | })(jQuery); |
@@ -51,6 +51,7 @@ wn.views.Calendar = Class.extend({ | |||||
// $('<div class="help"></div>') | // $('<div class="help"></div>') | ||||
// .html(wn._("Select dates to create a new ") + wn._(me.doctype)) | // .html(wn._("Select dates to create a new ") + wn._(me.doctype)) | ||||
// .appendTo(this.$wrapper); | // .appendTo(this.$wrapper); | ||||
this.$cal.fullCalendar(this.cal_options); | this.$cal.fullCalendar(this.cal_options); | ||||
}, | }, | ||||
field_map: { | field_map: { | ||||
@@ -39,7 +39,7 @@ wn.views.moduleview.ModuleView = Class.extend({ | |||||
wn.ui.make_app_page({ | wn.ui.make_app_page({ | ||||
parent: wrapper, | parent: wrapper, | ||||
single_column: true, | single_column: true, | ||||
title: wn._(wn.modules[module].label || module) | |||||
title: wn._(wn.modules[module] && wn.modules[module].label || module) | |||||
}); | }); | ||||
wrapper.appframe.add_module_icon(module); | wrapper.appframe.add_module_icon(module); | ||||
this.wrapper = wrapper; | this.wrapper = wrapper; | ||||
@@ -325,7 +325,11 @@ class DocTypeNestedSet(object): | |||||
update_nsm(self) | update_nsm(self) | ||||
def on_trash(self): | def on_trash(self): | ||||
self.doc.fields[self.nsm_parent_field] = "" | |||||
parent = self.doc.fields[self.nsm_parent_field] | |||||
if not parent: | |||||
msgprint(_("Root ") + self.doc.doctype + _(" cannot be deleted."), raise_exception=1) | |||||
parent = "" | |||||
update_nsm(self) | update_nsm(self) | ||||
def on_rename(self, newdn, olddn, merge=False, group_fname="is_group"): | def on_rename(self, newdn, olddn, merge=False, group_fname="is_group"): | ||||
@@ -24,10 +24,12 @@ from __future__ import unicode_literals | |||||
import webnotes | import webnotes | ||||
import os, json | import os, json | ||||
import types | |||||
from webnotes import _ | from webnotes import _ | ||||
from webnotes.modules import scrub, get_module_path | from webnotes.modules import scrub, get_module_path | ||||
from webnotes.utils import flt, cint | from webnotes.utils import flt, cint | ||||
import webnotes.widgets.reportview | |||||
@webnotes.whitelist() | @webnotes.whitelist() | ||||
def get_script(report_name): | def get_script(report_name): | ||||
@@ -67,6 +69,8 @@ def run(report_name, filters=None): | |||||
method_name = scrub(webnotes.conn.get_value("DocType", report.ref_doctype, "module")) \ | method_name = scrub(webnotes.conn.get_value("DocType", report.ref_doctype, "module")) \ | ||||
+ ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute" | + ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute" | ||||
columns, result = webnotes.get_method(method_name)(filters or {}) | columns, result = webnotes.get_method(method_name)(filters or {}) | ||||
result = get_filtered_data(report.ref_doctype, columns, result) | |||||
if cint(report.add_total_row) and result: | if cint(report.add_total_row) and result: | ||||
result = add_total_row(result, columns) | result = add_total_row(result, columns) | ||||
@@ -88,4 +92,64 @@ def add_total_row(result, columns): | |||||
total_row[0] = "Total" | total_row[0] = "Total" | ||||
result.append(total_row) | result.append(total_row) | ||||
return result | |||||
return result | |||||
def get_filtered_data(ref_doctype, columns, data): | |||||
result = [] | |||||
linked_doctypes = get_linked_doctypes(columns) | |||||
match_filters = get_user_match_filters(linked_doctypes, ref_doctype) | |||||
if match_filters: | |||||
matched_columns = get_matched_columns(linked_doctypes, match_filters) | |||||
for row in data: | |||||
match = True | |||||
for col, idx in matched_columns.items(): | |||||
if row[idx] not in match_filters[col]: | |||||
match = False | |||||
if match: | |||||
result.append(row) | |||||
else: | |||||
for row in data: | |||||
result.append(row) | |||||
return result | |||||
def get_linked_doctypes(columns): | |||||
linked_doctypes = {} | |||||
for idx, col in enumerate(columns): | |||||
if "Link" in col: | |||||
link_dt = col.split(":")[1].split("/")[1] | |||||
linked_doctypes[link_dt] = idx | |||||
return linked_doctypes | |||||
def get_user_match_filters(doctypes, ref_doctype): | |||||
match_filters = {} | |||||
doctypes_meta = {} | |||||
tables = [] | |||||
doctypes[ref_doctype] = None | |||||
for dt in doctypes: | |||||
tables.append("`tab" + dt + "`") | |||||
doctypes_meta[dt] = webnotes.model.doctype.get(dt) | |||||
webnotes.widgets.reportview.tables = tables | |||||
webnotes.widgets.reportview.doctypes = doctypes_meta | |||||
for dt in doctypes: | |||||
match_filters = webnotes.widgets.reportview.build_match_conditions(dt, | |||||
None, False, match_filters) | |||||
return match_filters | |||||
def get_matched_columns(linked_doctypes, match_filters): | |||||
col_idx_map = {} | |||||
for dt, idx in linked_doctypes.items(): | |||||
link_field = dt.lower().replace(" ", "_") | |||||
if link_field in match_filters: | |||||
col_idx_map[link_field] = idx | |||||
return col_idx_map |
@@ -124,7 +124,7 @@ def load_doctypes(): | |||||
import webnotes.model.doctype | import webnotes.model.doctype | ||||
roles = webnotes.get_roles() | roles = webnotes.get_roles() | ||||
for t in tables: | for t in tables: | ||||
if t.startswith('`'): | if t.startswith('`'): | ||||
doctype = t[4:-1] | doctype = t[4:-1] | ||||
@@ -194,16 +194,20 @@ def build_filter_conditions(filters, conditions): | |||||
conditions.append('ifnull(' + tname + '.' + f[1] + ",0) " + f[2] \ | conditions.append('ifnull(' + tname + '.' + f[1] + ",0) " + f[2] \ | ||||
+ " " + cstr(f[3])) | + " " + cstr(f[3])) | ||||
def build_match_conditions(doctype, fields=None): | |||||
def build_match_conditions(doctype, fields=None, as_condition=True, match_filters={}): | |||||
"""add match conditions if applicable""" | """add match conditions if applicable""" | ||||
global tables | |||||
global tables, roles | |||||
match_conditions = [] | match_conditions = [] | ||||
match = True | match = True | ||||
if not tables or not doctypes: | if not tables or not doctypes: | ||||
tables = get_tables(doctype, fields) | tables = get_tables(doctype, fields) | ||||
load_doctypes() | load_doctypes() | ||||
if not roles: | |||||
roles = webnotes.get_roles() | |||||
for d in doctypes[doctype]: | for d in doctypes[doctype]: | ||||
if d.doctype == 'DocPerm' and d.parent == doctype: | if d.doctype == 'DocPerm' and d.parent == doctype: | ||||
if d.role in roles: | if d.role in roles: | ||||
@@ -212,20 +216,30 @@ def build_match_conditions(doctype, fields=None): | |||||
document_key, default_key = d.match.split(":") | document_key, default_key = d.match.split(":") | ||||
else: | else: | ||||
default_key = document_key = d.match | default_key = document_key = d.match | ||||
for v in webnotes.defaults.get_user_default_as_list(default_key) or ["** No Match **"]: | |||||
match_conditions.append('`tab%s`.%s="%s"' % (doctype, | |||||
document_key, v)) | |||||
for v in webnotes.defaults.get_user_default_as_list(default_key, \ | |||||
webnotes.session.user) or ["** No Match **"]: | |||||
if as_condition: | |||||
match_conditions.append('`tab%s`.%s="%s"' % (doctype, | |||||
document_key, v)) | |||||
else: | |||||
if v: | |||||
match_filters.setdefault(document_key, []) | |||||
if v not in match_filters[document_key]: | |||||
match_filters[document_key].append(v) | |||||
elif d.read == 1 and d.permlevel == 0: | elif d.read == 1 and d.permlevel == 0: | ||||
# don't restrict if another read permission at level 0 | # don't restrict if another read permission at level 0 | ||||
# exists without a match restriction | # exists without a match restriction | ||||
match = False | match = False | ||||
if match_conditions and match: | |||||
return '('+ ' or '.join(match_conditions) +')' | |||||
if as_condition: | |||||
if match_conditions and match: | |||||
return '('+ ' or '.join(match_conditions) +')' | |||||
else: | |||||
return "" | |||||
else: | else: | ||||
return "" | |||||
return match_filters | |||||
def get_tables(doctype, fields): | def get_tables(doctype, fields): | ||||
"""extract tables from fields""" | """extract tables from fields""" | ||||
@@ -292,7 +306,6 @@ def export_query(): | |||||
f = StringIO() | f = StringIO() | ||||
writer = csv.writer(f) | writer = csv.writer(f) | ||||
from webnotes.utils import cstr | |||||
for r in data: | for r in data: | ||||
# encode only unicode type strings and not int, floats etc. | # encode only unicode type strings and not int, floats etc. | ||||
writer.writerow(map(lambda v: isinstance(v, unicode) and v.encode('utf-8') or v, r)) | writer.writerow(map(lambda v: isinstance(v, unicode) and v.encode('utf-8') or v, r)) | ||||