feat: Allow user to save custom reports

This commit is contained in:
deepeshgarg007 2019-04-12 16:17:25 +05:30
parent 80f2865885
commit af0c373c8a
4 changed files with 174 additions and 14 deletions

View file

@ -17,6 +17,9 @@ frappe.ui.form.on('Report', {
case "Script Report":
frappe.set_route("query-report", doc.name);
break;
case "Custom Report":
frappe.set_route("query-report", doc.name);
break;
}
}, "fa fa-table");

View file

@ -79,6 +79,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "reference_report",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Reference Report",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -228,7 +261,7 @@
"label": "Report Type",
"length": 0,
"no_copy": 0,
"options": "Report Builder\nQuery Report\nScript Report",
"options": "Report Builder\nQuery Report\nScript Report\nCustom Report",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -479,7 +512,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.report_type==\"Report Builder\"",
"depends_on": "eval:doc.report_type==\"Report Builder\" || \"Custom Report\"",
"fetch_if_empty": 0,
"fieldname": "json",
"fieldtype": "Code",
@ -642,17 +675,15 @@
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-04-07 20:32:30.943582",
"modified": "2019-04-12 15:53:14.194591",
"modified_by": "Administrator",
"module": "Core",
"name": "Report",
@ -737,7 +768,6 @@
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",

View file

@ -18,6 +18,15 @@ from datetime import timedelta
from frappe.utils import gzip_decompress
def get_report_doc(report_name):
custom_report = custom_columns = frappe.db.get_value("Report",
{'report_name':report_name, 'is_standard': 'No', 'report_type': 'Custom Report'},
['reference_report', 'json']
)
if custom_report:
report_name, custom_columns = custom_report[0], custom_report[1]
doc = frappe.get_doc("Report", report_name)
if not doc.is_permitted():
frappe.throw(_("You don't have access to Report: {0}").format(report_name), frappe.PermissionError)
@ -29,10 +38,10 @@ def get_report_doc(report_name):
if doc.disabled:
frappe.throw(_("Report {0} is disabled").format(report_name))
return doc
return doc, custom_columns
def generate_report_result(report, filters=None, user=None):
def generate_report_result(report, filters=None, user=None, custom_columns=None):
status = None
if not user:
user = frappe.session.user
@ -81,6 +90,11 @@ def generate_report_result(report, filters=None, user=None):
if len(res) > 4:
data_to_be_printed = res[4]
if custom_columns:
columns = json.loads(custom_columns)
result = add_data_to_custom_columns(columns, result)
if result:
result = get_filtered_data(report.ref_doctype, columns, result, user)
@ -102,7 +116,7 @@ def background_enqueue_run(report_name, filters=None, user=None):
"""run reports in background"""
if not user:
user = frappe.session.user
report = get_report_doc(report_name)
report, _ = get_report_doc(report_name)
track_instance = \
frappe.get_doc({
"doctype": "Prepared Report",
@ -125,8 +139,7 @@ def background_enqueue_run(report_name, filters=None, user=None):
@frappe.whitelist()
def get_script(report_name):
report = get_report_doc(report_name)
report, _ = get_report_doc(report_name)
module = report.module or frappe.db.get_value("DocType", report.ref_doctype, "module")
module_path = get_module_path(module)
report_folder = os.path.join(module_path, "report", scrub(report.name))
@ -161,7 +174,7 @@ def get_script(report_name):
@frappe.read_only()
def run(report_name, filters=None, user=None):
report = get_report_doc(report_name)
report, custom_columns = get_report_doc(report_name)
if not user:
user = frappe.session.user
if not frappe.has_permission(report.ref_doctype, "report"):
@ -181,12 +194,37 @@ def run(report_name, filters=None, user=None):
dn = ""
result = get_prepared_report_result(report, filters, dn, user)
else:
result = generate_report_result(report, filters, user)
result = generate_report_result(report, filters, user, custom_columns)
result["add_total_row"] = report.add_total_row
return result
def add_data_to_custom_columns(columns, result):
custom_fields_data = get_data_for_custom_report(columns)
data = []
for row in result:
row_obj = {}
if isinstance(row, list):
for idx, column in enumerate(columns):
if column.get('link_field'):
row_obj[column['fieldname']] = None
row.insert(idx,None)
else:
row_obj[column['fieldname']] = row[idx]
data.append(row_obj)
else:
data.append(row)
for row in data:
for column in columns:
if column.get('link_field'):
row[column['fieldname']] = \
custom_fields_data.get((column['doctype'], column['fieldname']), {}).get(row[column['link_field']])
return data
def get_prepared_report_result(report, filters, dn="", user=None):
latest_report_data = {}
@ -362,6 +400,44 @@ def get_data_for_custom_field(doctype, field):
return value_map
def get_data_for_custom_report(columns):
doc_field_value_map = {}
for column in columns:
if column.get('link_field'):
fieldname = column.get('fieldname')
doctype = column.get('doctype')
doc_field_value_map[(doctype, fieldname)] = get_data_for_custom_field(doctype, fieldname)
return doc_field_value_map
@frappe.whitelist()
def save_report(reference_report, report_name, columns):
report_doc, _ = get_report_doc(reference_report)
docname = frappe.db.exists("Report", report_name)
if docname:
report = frappe.get_doc("Report", {'report_name':docname, 'is_standard': 'No', 'report_type': 'Custom Report'})
report.update({"json": columns})
report.save()
frappe.msgprint("Report updated successfully")
return docname
else:
new_report = frappe.get_doc({
'doctype': 'Report',
'report_name': report_name,
'json': columns,
'ref_doctype': report_doc.ref_doctype,
'is_standard': 'No',
'report_type': 'Custom Report',
'reference_report': reference_report
}).insert(ignore_permissions = True)
frappe.msgprint("{0} saved successfully".format(new_report.name))
return new_report.name
def get_filtered_data(ref_doctype, columns, data, user):
result = []
linked_doctypes = get_linked_doctypes(columns, data)

View file

@ -110,9 +110,21 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
this.page_name = frappe.get_route_str();
this.report_name = this.route[1];
this.page_title = __(this.report_name);
this.show_save = false;
this.menu_items = this.get_menu_items();
this.datatable = null;
this.prepared_report_action = "New";
this.custom_report = null;
frappe.db.get_value("Report",
{"report_name": this.report_name},
'reference_report', (r) => {
if (r.reference_report){
this.custom_report = this.report_name;
this.report_name = r.reference_report;
}
}
)
frappe.run_serially([
() => this.get_report_doc(),
@ -289,7 +301,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
method: 'frappe.desk.query_report.run',
type: 'GET',
args: {
report_name: this.report_name,
report_name: this.custom_report || this.report_name,
filters: filters,
},
callback: resolve,
@ -1003,8 +1015,11 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
fieldname: df.fieldname,
fieldtype: df.fieldtype,
label: df.label,
link_field: this.doctype_field_map[values.doctype],
doctype: values.doctype,
width: 100
});
frappe.call({
method: 'frappe.desk.query_report.get_data_for_custom_field',
args: {
@ -1018,6 +1033,8 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
d.hide();
}
});
this.show_save = true;
this.set_menu_items()
}
})
@ -1025,6 +1042,40 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
},
standard: true
},
{
label: __('Save'),
action: () => {
let d = new frappe.ui.Dialog({
title: __('Save Reports'),
fields: [
{
fieldtype: 'Data',
fieldname: 'report_name',
label: __("Report Name"),
default: this.report_doc.is_standard == 'No' ? this.custom_report : "",
}
],
primary_action: (values) => {
frappe.call({
method: "frappe.desk.query_report.save_report",
args: {
reference_report: this.report_name,
report_name: values.report_name,
columns: this.columns
},
callback: function(r) {
this.show_save = false;
d.hide();
frappe.set_route('query-report', r.message);
}
});
}
});
d.show()
},
condition: () => this.show_save,
standard: true
},
{
label: __('User Permissions'),
action: () => frappe.set_route('List', 'User Permission', {