feat: Allow users to customize their own reports
This commit is contained in:
parent
71ceb496d1
commit
ddd45a71bc
3 changed files with 129 additions and 18 deletions
|
|
@ -4,6 +4,7 @@
|
|||
import frappe, json, os
|
||||
import unittest
|
||||
from frappe.desk.query_report import run, save_report
|
||||
from frappe.desk.reportview import delete_report, save_report as save_as_report
|
||||
from frappe.custom.doctype.customize_form.customize_form import reset_customization
|
||||
|
||||
test_records = frappe.get_test_records('Report')
|
||||
|
|
@ -30,6 +31,57 @@ class TestReport(unittest.TestCase):
|
|||
self.assertEqual(columns[1].get('label'), 'Module')
|
||||
self.assertTrue('User' in [d.get('name') for d in data])
|
||||
|
||||
def test_can_save_or_delete_report(self):
|
||||
'''Test case to test if if users can create, save or delete their own report of type Report Builder'''
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
report = frappe.get_doc({
|
||||
'doctype': 'Report',
|
||||
'ref_doctype': 'User',
|
||||
'report_name': 'Test Delete Report',
|
||||
'report_type': 'Report Builder',
|
||||
'is_standard': 'No',
|
||||
}).insert()
|
||||
|
||||
frappe.set_user("test@example.com")
|
||||
self.assertRaisesRegex(frappe.exceptions.ValidationError, "Only Report owner or Report Manager can delete the reports", delete_report, report.name)
|
||||
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
report.report_type = 'Custom Report' # change report type to validate
|
||||
report.save()
|
||||
|
||||
self.assertRaisesRegex(frappe.exceptions.ValidationError, "Only reports of type Report Builder can be deleted", delete_report, report.name)
|
||||
|
||||
report.is_standard = 'Yes' # change is_standard to validate
|
||||
report.save()
|
||||
|
||||
self.assertRaisesRegex(frappe.exceptions.ValidationError, "Standard Reports can not be deleted", delete_report, report.name)
|
||||
|
||||
frappe.set_user("test@example.com")
|
||||
|
||||
report_name = save_as_report(
|
||||
'Dummy Report',
|
||||
'User',
|
||||
json.dumps([{
|
||||
'fieldname': 'email',
|
||||
'fieldtype': 'Data',
|
||||
'label': 'Email',
|
||||
'insert_after_index': 0,
|
||||
'link_field': 'name',
|
||||
'doctype': 'User',
|
||||
'options': 'Email',
|
||||
'width': 100,
|
||||
'id':'email',
|
||||
'name': 'Email'
|
||||
}])
|
||||
)
|
||||
|
||||
doc = frappe.get_doc("Report", report_name)
|
||||
|
||||
delete_report(doc.name)
|
||||
|
||||
|
||||
def test_custom_report(self):
|
||||
reset_customization('User')
|
||||
custom_report_name = save_report(
|
||||
|
|
|
|||
|
|
@ -262,23 +262,47 @@ def compress(data, args=None):
|
|||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
def save_report():
|
||||
"""save report"""
|
||||
def save_report(name, doctype, report_settings):
|
||||
"""save report if report type is report builder"""
|
||||
|
||||
data = frappe.local.form_dict
|
||||
if frappe.db.exists('Report', data['name']):
|
||||
d = frappe.get_doc('Report', data['name'])
|
||||
if frappe.db.exists('Report', name):
|
||||
d = frappe.get_doc('Report', name)
|
||||
if d.is_standard == "Yes":
|
||||
frappe.throw(_("Standard Reports can not be edited"))
|
||||
|
||||
if d.report_type != "Report Builder":
|
||||
frappe.throw(_("Only reports of type Report Builder can be created"))
|
||||
|
||||
if d.owner != frappe.session.user:
|
||||
frappe.throw(_("Only Report owner or Report Manager can save the reports"))
|
||||
else:
|
||||
d = frappe.new_doc('Report')
|
||||
d.report_name = data['name']
|
||||
d.ref_doctype = data['doctype']
|
||||
d.report_name = name
|
||||
d.ref_doctype = doctype
|
||||
|
||||
d.report_type = "Report Builder"
|
||||
d.json = data['json']
|
||||
frappe.get_doc(d).save()
|
||||
d.json = report_settings
|
||||
frappe.get_doc(d).save(ignore_permissions=True)
|
||||
frappe.msgprint(_("{0} is saved").format(d.name), alert=True)
|
||||
return d.name
|
||||
|
||||
@frappe.whitelist()
|
||||
def delete_report(name):
|
||||
"""delete report type of report builder if user is report owner or has role Report Manager"""
|
||||
|
||||
report_doc = frappe.get_doc("Report", name)
|
||||
if report_doc.is_standard == "Yes":
|
||||
frappe.throw(_("Standard Reports can not be deleted"))
|
||||
|
||||
if report_doc.report_type != "Report Builder":
|
||||
frappe.throw(_("Only reports of type Report Builder can be deleted"))
|
||||
|
||||
if report_doc.owner != frappe.session.user:
|
||||
frappe.throw(_("Only Report owner or Report Manager can delete the reports"))
|
||||
|
||||
report_doc.delete(ignore_permissions=True)
|
||||
frappe.msgprint(_("{0} is Deleted").format(report_doc.name), alert=True)
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.read_only()
|
||||
def export_query():
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.page_title = __('Report:') + ' ' + this.page_title;
|
||||
this.menu_items = this.report_menu_items();
|
||||
this.view = 'Report';
|
||||
|
||||
const route = frappe.get_route();
|
||||
if (route.length === 4) {
|
||||
this.report_name = route[3];
|
||||
}
|
||||
|
||||
this.view = 'Report';
|
||||
|
||||
if (this.report_name) {
|
||||
return this.get_report_doc()
|
||||
.then(doc => {
|
||||
|
|
@ -39,6 +39,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
this.page_length = this.report_doc.json.page_length || 20;
|
||||
this.order_by = this.report_doc.json.order_by || 'modified desc';
|
||||
this.chart_args = this.report_doc.json.chart_args;
|
||||
this.menu_items = this.report_menu_items();
|
||||
});
|
||||
} else {
|
||||
this.add_totals_row = this.view_user_settings.add_totals_row || 0;
|
||||
|
|
@ -1207,7 +1208,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
args: {
|
||||
name: name,
|
||||
doctype: this.doctype,
|
||||
json: JSON.stringify(report_settings)
|
||||
report_settings: JSON.stringify(report_settings)
|
||||
},
|
||||
callback:(r) => {
|
||||
if(r.exc) {
|
||||
|
|
@ -1244,6 +1245,25 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
}
|
||||
}
|
||||
|
||||
delete_report() {
|
||||
const _delete_report = (name) => {
|
||||
return frappe.call({
|
||||
method: 'frappe.desk.reportview.delete_report',
|
||||
args: { name },
|
||||
callback: (r) => {
|
||||
if (r.exc) {
|
||||
frappe.msgprint(__("Report was not deleted (there were errors)"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this.report_name) {
|
||||
_delete_report(this.report_name);
|
||||
}
|
||||
}
|
||||
|
||||
get_column_widths() {
|
||||
if (this.datatable) {
|
||||
return this.datatable
|
||||
|
|
@ -1465,12 +1485,27 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
}
|
||||
});
|
||||
|
||||
// save buttons
|
||||
if(frappe.user.is_report_manager()) {
|
||||
items = items.concat([
|
||||
{ label: __('Save'), action: () => this.save_report('save') },
|
||||
{ label: __('Save As'), action: () => this.save_report('save_as') }
|
||||
]);
|
||||
const can_save_or_delete = this.report_doc.owner === frappe.session.user || frappe.user.is_report_manager()
|
||||
// A user with role Report Manager or Report Owner can save
|
||||
if (can_save_or_delete) {
|
||||
items.push({
|
||||
label: __("Save"),
|
||||
action: () => this.save_report('save')
|
||||
});
|
||||
}
|
||||
|
||||
// anyone can save as
|
||||
items.push({
|
||||
label: __('Save As'),
|
||||
action: () => this.save_report('save_as')
|
||||
});
|
||||
|
||||
// A user with role Report Manager or Report Owner can delete
|
||||
if (can_save_or_delete) {
|
||||
items.push({
|
||||
label: __("Delete"),
|
||||
action: () => this.delete_report()
|
||||
});
|
||||
}
|
||||
|
||||
// user permissions
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue