diff --git a/frappe/__init__.py b/frappe/__init__.py index 513c444ab9..ac1472de75 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -236,7 +236,7 @@ def errprint(msg): :param msg: Message.""" msg = as_unicode(msg) - if not request or (not "cmd" in local.form_dict): + if not request or (not "cmd" in local.form_dict) or conf.developer_mode: print msg.encode('utf-8') error_log.append(msg) diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index 3ed44a24a0..4aeae4503d 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -59,27 +59,38 @@ class Report(Document): make_boilerplate("controller.py", self, {"name": self.name}) make_boilerplate("controller.js", self, {"name": self.name}) - def get_data(self, filters=None, limit=None, user=None): - + def get_data(self, filters=None, limit=None, user=None, as_dict=False): + columns = [] out = [] if self.report_type in ('Query Report', 'Script Report'): # query and script reports data = frappe.desk.query_report.run(self.name, filters=filters, user=user) - columns_list = [] for d in data.get('columns'): if isinstance(d, dict): - columns_list.append(d.get('label')) + columns.append(frappe._dict(d)) else: - columns_list.append(d.split(':')[0]) + parts = d.split(':') + fieldtype, options = parts[1], None + if fieldtype and '/' in fieldtype: + fieldtype, options = fieldtype.split('/') + + columns.append(frappe._dict(label=parts[0], fieldtype=fieldtype, fieldname=parts[0])) - out.append(columns_list) out += data.get('result') else: # standard report params = json.loads(self.json) columns = params.get('columns') - filters = params.get('filters') + _filters = params.get('filters') or [] + + if filters: + print filters + for key, value in filters.iteritems(): + condition, _value = '=', value + if isinstance(value, (list, tuple)): + condition, _value = value + _filters.append([key, condition, _value]) def _format(parts): # sort by is saved as DocType.fieldname, covert it to sql @@ -90,14 +101,26 @@ class Report(Document): order_by += ', ' + _format(params.get('sort_by_next').split('.')) + ' ' + params.get('sort_order_next') result = frappe.get_list(self.ref_doctype, fields = [_format([c[1], c[0]]) for c in columns], - filters=filters, order_by = order_by, as_list=True, limit=limit, user=user) + filters=_filters, order_by = order_by, as_list=True, limit=limit, user=user, debug=True) meta = frappe.get_meta(self.ref_doctype) - out.append([meta.get_label(c[0]) for c in columns]) + columns = [meta.get_field(c[0]) or frappe._dict(label=meta.get_label(c[0]), fieldname=c[0]) + for c in columns] + out = out + [list(d) for d in result] - return out + if as_dict: + data = [] + for row in out: + _row = frappe._dict() + data.append(_row) + for i, val in enumerate(row): + _row[columns[i].get('fieldname')] = val + else: + data = out + + return columns, data @Document.whitelist diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index 6168672733..68d48e5bf6 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -16,14 +16,14 @@ class TestReport(unittest.TestCase): frappe.get_doc(json.loads(f.read())).insert() report = frappe.get_doc('Report', 'User Activity Report') - data = report.get_data() + columns, data = report.get_data() self.assertEquals(data[0][0], 'ID') self.assertEquals(data[0][1], 'User Type') self.assertTrue('Administrator' in [d[0] for d in data]) def test_query_report(self): report = frappe.get_doc('Report', 'Permitted Documents For User') - data = report.get_data(filters={'user': 'Administrator', 'doctype': 'DocType'}) + columns, data = report.get_data(filters={'user': 'Administrator', 'doctype': 'DocType'}) self.assertEquals(data[0][0], 'Name') self.assertEquals(data[0][1], 'Module') self.assertTrue('User' in [d[0] for d in data]) diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.js b/frappe/email/doctype/auto_email_report/auto_email_report.js index 019cdc6a52..c565490193 100644 --- a/frappe/email/doctype/auto_email_report/auto_email_report.js +++ b/frappe/email/doctype/auto_email_report/auto_email_report.js @@ -48,6 +48,9 @@ frappe.ui.form.on('Auto Email Report', { } } }, + report: function(frm) { + frm.set_value('filters', ''); + }, show_filters: function(frm) { var wrapper = $(frm.get_field('filters_display').wrapper); wrapper.empty(); diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.json b/frappe/email/doctype/auto_email_report/auto_email_report.json index 03a28175bd..113ade1c3a 100644 --- a/frappe/email/doctype/auto_email_report/auto_email_report.json +++ b/frappe/email/doctype/auto_email_report/auto_email_report.json @@ -185,6 +185,36 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "24", + "depends_on": "eval:doc.report_type=='Report Builder'", + "fieldname": "data_modified_till", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Send Records Updated in Last X Hours", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -539,7 +569,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-11-07 05:50:31.903959", + "modified": "2016-12-26 12:46:41.193379", "modified_by": "Administrator", "module": "Email", "name": "Auto Email Report", diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.py b/frappe/email/doctype/auto_email_report/auto_email_report.py index 710d6ddc3f..f4a9413c2e 100644 --- a/frappe/email/doctype/auto_email_report/auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/auto_email_report.py @@ -3,9 +3,10 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe +import frappe, json from frappe import _ from frappe.model.document import Document +from datetime import timedelta import frappe.utils from frappe.utils.xlsutils import get_xls from frappe.utils.csvutils import to_csv @@ -42,29 +43,45 @@ class AutoEmailReport(Document): def get_report_content(self): '''Returns file in for the report in given format''' report = frappe.get_doc('Report', self.report) - raw = report.get_data(limit=self.no_of_rows or 100, user = self.user, filters = self.filters) - if len(raw)==1 and self.send_if_data: + if self.report_type=='Report Builder' and self.data_modified_till: + self.filters = json.loads(self.filters) if self.filters else {} + self.filters['modified'] = ('>', frappe.utils.now_datetime() - timedelta(hours=self.data_modified_till)) + + columns, data = report.get_data(limit=self.no_of_rows or 100, user = self.user, + filters = self.filters, as_dict=True) + + if len(data)==1 and self.send_if_data: return None if self.format == 'HTML': - return self.get_html_table(raw) + return self.get_html_table(columns, data) elif self.format == 'XLS': - return get_xls(raw) + return get_xls(columns, data) elif self.format == 'CSV': - return to_csv(raw) + return self.get_csv(columns, data) else: frappe.throw(_('Invalid Output Format')) - def get_html_table(self, data): + def get_html_table(self, columns, data): return frappe.render_template('frappe/templates/includes/print_table.html', { - 'headings': data[0], + 'columns': columns, 'data': data[1:] }) + def get_csv(self, columns, data): + out = [[df.label for df in columns], ] + for row in data: + new_row = [] + out.append(new_row) + for df in columns: + new_row.append(frappe.format(row[df.fieldname], df, row)) + + return to_csv(out) + def get_file_name(self): return "{0}.{1}".format(self.report.replace(" ", "-").replace("/", "-"), self.format.lower()) diff --git a/frappe/email/doctype/auto_email_report/test_auto_email_report.py b/frappe/email/doctype/auto_email_report/test_auto_email_report.py index 72da43098b..1436626430 100644 --- a/frappe/email/doctype/auto_email_report/test_auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/test_auto_email_report.py @@ -9,4 +9,31 @@ import unittest, json # test_records = frappe.get_test_records('Auto Email Report') class TestAutoEmailReport(unittest.TestCase): - pass \ No newline at end of file + def test_auto_email(self): + frappe.delete_doc('Auto Email Report', 'Permitted Documents For User') + + auto_email_report = frappe.get_doc(dict( + doctype='Auto Email Report', + report='Permitted Documents For User', + report_type='Script Report', + user='Administrator', + enabled=1, + email_to='test@example.com', + format='HTML', + frequency='Daily', + filters=json.dumps(dict(user='Administrator', doctype='DocType')) + )).insert() + + data = auto_email_report.get_report_content() + self.assertTrue('
- {{ col }} + {% for col in columns %} + | + {{- col.label -}} | {% endfor %}
---|---|
- {{ frappe.format(val) }} + {% for col in columns %} + | + {{- frappe.format(row[col.fieldname], col, row) -}} | {% endfor %} diff --git a/frappe/utils/xlsutils.py b/frappe/utils/xlsutils.py index 643aadef3a..bff7807308 100644 --- a/frappe/utils/xlsutils.py +++ b/frappe/utils/xlsutils.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe, xlwt, StringIO, datetime from frappe import _ -def get_xls(data): +def get_xls(columns, data): '''Convert data to xls''' stream = StringIO.StringIO() workbook = xlwt.Workbook() @@ -14,18 +14,22 @@ def get_xls(data): (frappe.defaults.get_global_default("date_format") or "yyyy-mm-dd")) bold = xlwt.easyxf('font: bold 1') + # header + for i, col in enumerate(columns): + sheet.write(0, i, col.label, bold) + for i, row in enumerate(data): - for j, val in enumerate(row): + for j, df in enumerate(columns): f = None + + val = row[columns[j].fieldname] if isinstance(val, (datetime.datetime, datetime.date)): f = dateformat - if i==0: - f = bold if f: - sheet.write(i, j, val, f) + sheet.write(i+1, j, val, f) else: - sheet.write(i, j, val) + sheet.write(i+1, j, frappe.format(val, df, row)) workbook.save(stream) stream.seek(0) diff --git a/frappe/www/login.html b/frappe/www/login.html index 69da9034bf..ab0ba62ad8 100644 --- a/frappe/www/login.html +++ b/frappe/www/login.html @@ -9,10 +9,10 @@ {% block page_content %} -