fix: major refactor to monkey-patch into the QueryReport class

This commit is contained in:
casesolved-co-uk 2021-03-24 02:56:30 +00:00
parent dba4b3cd13
commit 8e413651c2

View File

@ -3,6 +3,8 @@
// Contributed by Case Solved and sponsored by Nulight Studios
/* eslint-disable */
frappe.provide('frappe.query_reports');
frappe.query_reports["Tax Detail"] = {
filters: [
{
@ -50,55 +52,92 @@ frappe.query_reports["Tax Detail"] = {
// Remove Add Column and Save from menu
report.page.add_inner_button(__("New Report"), () => new_report(), __("Custom Report"));
report.page.add_inner_button(__("Load Report"), () => load_report(), __("Custom Report"));
hide_filters();
},
after_datatable_render: (datatable) => {
if (frappe.query_report.report_name == 'Tax Detail') {
return;
}
if (this.taxreport) {
this.taxreport.load_report();
} else {
this.taxreport = new TaxReport();
}
hide_filters(report);
}
};
function hide_filters() {
frappe.query_report.page.page_form[0].querySelectorAll('.form-group.frappe-control').forEach(function setHidden(field) {
function hide_filters(report) {
report.page.page_form[0].querySelectorAll('.form-group.frappe-control').forEach(function setHidden(field) {
if (field.dataset.fieldtype == "Read Only") {
field.classList.add("hidden");
}
});
}
class TaxReport {
// construct after datatable is loaded
erpnext.TaxDetail = class TaxDetail {
constructor() {
this.qr = frappe.query_report;
this.page = frappe.query_report.page;
this.create_controls();
this.patch();
this.load_report();
}
load_report() {
if (this.loaded) {
return;
// Monkey patch the QueryReport class
patch() {
this.qr = frappe.query_report;
this.super = {
refresh_report: this.qr.refresh_report,
show_footer_message: this.qr.show_footer_message
}
const report_name = this.qr.report_name;
this.report_name.value = report_name;
this.qr.refresh_report = () => this.refresh_report();
this.qr.show_footer_message = () => this.show_footer_message();
}
show_footer_message() {
// The last thing to run after datatable_render in refresh()
console.log('show_footer_message');
this.super.show_footer_message.apply(this.qr);
if (this.qr.report_name !== 'Tax Detail') {
this.set_value_options();
this.show_help();
if (this.loading) {
this.set_section('');
}
this.reload_filter();
}
this.loading = false;
}
refresh_report() {
// Infrequent report build (onload), load filters & data
// super function runs a refresh() serially
// already run within frappe.run_serially
console.log('refresh_report');
this.loading = true;
this.super.refresh_report.apply(this.qr);
if (this.qr.report_name !== 'Tax Detail') {
frappe.call({
method: 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports',
args: {name: report_name},
freeze: true
args: {name: this.qr.report_name}
}).then((r) => {
const data = JSON.parse(r.message[report_name]['json']);
const data = JSON.parse(r.message[this.qr.report_name]['json']);
this.create_controls();
this.sections = data.sections || {};
this.controls['show_detail'].set_input(data.show_detail);
this.set_section();
})
this.loaded = 1;
});
}
}
load_report() {
// One-off report build like titles, menu, etc
// Run when this object is created which happens in qr.load_report
console.log('load_report');
this.qr.menu_items = this.get_menu_items();
}
get_menu_items() {
// Replace save button
let new_items = [];
const label = __('Save');
for (let item of this.qr.menu_items) {
if (item.label === label) {
new_items.push({
label: label,
action: this.save_report,
standard: false
});
} else {
new_items.push(item);
}
}
return new_items;
}
save_report() {
if (this.qr.report_name !== 'Tax Detail') {
frappe.call({
method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report',
args: {
@ -112,10 +151,13 @@ class TaxReport {
},
freeze: true
}).then((r) => {
this.reload();
this.set_section('');
});
}
}
set_value_options() {
// May be run with no columns or data
if (this.qr.columns) {
this.fieldname_lookup = {};
this.label_lookup = {};
this.qr.columns.forEach((col, index) => {
@ -128,6 +170,7 @@ class TaxReport {
this.controls['value_field'].$wrapper.find("select").empty().add_options(options);
this.controls['value_field'].set_input(options[0]);
}
}
set_value_label_from_filter() {
const section_name = this.controls['section_name'].value;
const fidx = this.controls['filter_index'].value;
@ -158,46 +201,38 @@ class TaxReport {
});
dialog.show();
}
get_filter_controls() {
this.qr.filters.forEach(filter => {
if (filter['fieldname'] == 'mode') {
this.mode = filter;
}
if (filter['fieldname'] == 'report_name') {
this.report_name = filter;
}
});
}
set_mode(mode) {
this.mode.value = mode;
}
edit_mode() {
return this.mode.value == 'edit';
}
set_section(name) {
// Sets the given section name and then reloads the data
if (name && !this.sections[name]) {
this.sections[name] = {};
}
let options = Object.keys(this.sections);
options.unshift('');
this.controls['section_name'].$wrapper.find("select").empty().add_options(options);
const org_mode = this.qr.get_filter_value('mode');
let refresh = false;
if (name) {
this.controls['section_name'].set_input(name);
this.qr.set_filter_value('mode', 'edit');
if (org_mode === 'run') {
refresh = true;
}
} else {
this.controls['section_name'].set_input('');
this.qr.set_filter_value('mode', 'run');
if (org_mode === 'edit') {
refresh = true;
}
if (this.controls['section_name'].value) {
this.set_mode('edit');
} else {
this.set_mode('run');
}
this.controls['filter_index'].set_input('');
this.reload();
this.reload_filter();
if (refresh) {
this.qr.refresh();
}
}
reload_filter() {
const section_name = this.controls['section_name'].value;
const section_name = this.controls['section_name'].get_input_value();
if (section_name) {
let fidx = this.controls['filter_index'].value;
let fidx = this.controls['filter_index'].get_input_value();
let section = this.sections[section_name];
let fidxs = Object.keys(section);
fidxs.unshift('');
@ -207,17 +242,16 @@ class TaxReport {
this.controls['filter_index'].$wrapper.find("select").empty();
this.controls['filter_index'].set_input('');
}
this.set_filters();
this.set_table_filters();
}
set_filters() {
set_table_filters() {
let filters = {};
const section_name = this.controls['section_name'].value;
const fidx = this.controls['filter_index'].value;
const section_name = this.controls['section_name'].get_input_value();
const fidx = this.controls['filter_index'].get_input_value();
if (section_name && fidx) {
filters = this.sections[section_name][fidx]['filters'];
}
this.setAppliedFilters(filters);
this.qr.datatable.columnmanager.applyFilter(filters);
this.set_value_label_from_filter();
}
setAppliedFilters(filters) {
@ -229,32 +263,20 @@ class TaxReport {
input.value = null;
}
});
}
reload() {
// Reloads the data. When the datatable is reloaded, load_report()
// will be run by the after_datatable_render event.
// TODO: why does this trigger multiple reloads?
this.qr.refresh();
this.show_help();
if (this.edit_mode()) {
this.reload_filter();
} else {
this.controls['filter_index'].$wrapper.find("select").empty();
}
this.qr.datatable.columnmanager.applyFilter(filters);
}
delete(name, type) {
if (type === 'section') {
delete this.sections[name];
this.controls['section_name'].$wrapper.find("select").empty().add_options(Object.keys(this.sections));
this.controls['section_name'].set_input(Object.keys(this.sections)[0] || '');
this.controls['filter_index'].set_input('');
const new_section = Object.keys(this.sections)[0] || '';
this.set_section(new_section);
}
if (type === 'filter') {
let cur_section = this.controls['section_name'].value;
const cur_section = this.controls['section_name'].get_input_value();
delete this.sections[cur_section][name];
this.controls['filter_index'].set_input('');
this.reload_filter();
}
this.reload();
}
create_controls() {
if (this.controls) {
@ -262,7 +284,7 @@ class TaxReport {
}
let controls = {};
// SELECT in data.js
controls['section_name'] = this.page.add_field({
controls['section_name'] = this.qr.page.add_field({
label: __('Section'),
fieldtype: 'Select',
fieldname: 'section_name',
@ -271,7 +293,7 @@ class TaxReport {
}
});
// BUTTON in button.js
controls['new_section'] = this.page.add_field({
controls['new_section'] = this.qr.page.add_field({
label: __('New Section'),
fieldtype: 'Button',
fieldname: 'new_section',
@ -279,33 +301,33 @@ class TaxReport {
this.new_section(__('New Section'));
}
});
controls['delete_section'] = this.page.add_field({
controls['delete_section'] = this.qr.page.add_field({
label: __('Delete Section'),
fieldtype: 'Button',
fieldname: 'delete_section',
click: () => {
let cur_section = this.controls['section_name'].value;
let cur_section = this.controls['section_name'].get_input_value();
if (cur_section) {
frappe.confirm(__('Are you sure you want to delete section ') + cur_section + '?',
() => {this.delete(cur_section, 'section')});
}
}
});
controls['filter_index'] = this.page.add_field({
controls['filter_index'] = this.qr.page.add_field({
label: __('Filter'),
fieldtype: 'Select',
fieldname: 'filter_index',
change: (e) => {
this.controls['filter_index'].set_input(this.controls['filter_index'].get_input_value());
this.set_filters();
this.set_table_filters();
}
});
controls['add_filter'] = this.page.add_field({
controls['add_filter'] = this.qr.page.add_field({
label: __('Add Filter'),
fieldtype: 'Button',
fieldname: 'add_filter',
click: () => {
let section_name = this.controls['section_name'].value;
let section_name = this.controls['section_name'].get_input_value();
if (section_name) {
let prefix = 'Filter';
let data = {
@ -326,19 +348,19 @@ class TaxReport {
}
}
});
controls['delete_filter'] = this.page.add_field({
controls['delete_filter'] = this.qr.page.add_field({
label: __('Delete Filter'),
fieldtype: 'Button',
fieldname: 'delete_filter',
click: () => {
let cur_filter = this.controls['filter_index'].value;
let cur_filter = this.controls['filter_index'].get_input_value();
if (cur_filter) {
frappe.confirm(__('Are you sure you want to delete filter ') + cur_filter + '?',
() => {this.delete(cur_filter, 'filter')});
}
}
});
controls['value_field'] = this.page.add_field({
controls['value_field'] = this.qr.page.add_field({
label: __('Value Column'),
fieldtype: 'Select',
fieldname: 'value_field',
@ -346,37 +368,35 @@ class TaxReport {
this.controls['value_field'].set_input(this.controls['value_field'].get_input_value());
}
});
controls['save'] = this.page.add_field({
controls['save'] = this.qr.page.add_field({
label: __('Save & Run'),
fieldtype: 'Button',
fieldname: 'save',
click: () => {
this.controls['section_name'].set_input('');
this.set_mode('run');
this.save_report();
}
});
controls['show_detail'] = this.page.add_field({
controls['show_detail'] = this.qr.page.add_field({
label: __('Show Detail'),
fieldtype: 'Check',
fieldname: 'show_detail',
default: 1
});
this.controls = controls;
this.set_value_options();
this.get_filter_controls();
this.show_help();
}
show_help() {
const help = __(`You can add multiple sections to your custom report using the New Section button above.
To specify what data goes in each section, specify column filters below, then save with Add Filter.
Each section can have multiple filters added.
You can specify which Currency column will be summed for each filter in the final report with the Value Column select box.
Once you're done, hit Save & Run.`);
this.qr.show_status(help);
To specify what data goes in each section, specify column filters in the data table, then save with Add Filter.
Each section can have multiple filters added but be careful with the duplicated data rows.
You can specify which Currency column will be summed for each filter in the final report with the Value Column
select box. Once you're done, hit Save & Run.`);
this.qr.$report_footer.append(`<div class="col-md-12">${help}</div>`);
}
}
if (!window.taxdetail) {
window.taxdetail = new erpnext.TaxDetail();
}
function get_reports(cb) {
frappe.call({
@ -387,23 +407,9 @@ function get_reports(cb) {
})
}
function override_menu() {
//TODO: Replace save button
this.qr.menu_items.forEach((item, idx) => {
if (item['label'] == __('Save')) {
delete this.qr.menu_items[idx];
}
})
this.qr.menu_items.push({
label: __('Save'),
action: this.save_report
})
this.qr.set_menu_items();
}
function new_report() {
const dialog = new frappe.ui.Dialog({
title: __("New Report"),
title: __('New Report'),
fields: [
{
fieldname: 'report_name',
@ -424,7 +430,7 @@ function new_report() {
},
freeze: true
}).then((r) => {
frappe.set_route("query-report", values.report_name);
frappe.set_route('query-report', values.report_name);
});
dialog.hide();
}
@ -435,7 +441,7 @@ function new_report() {
function load_report() {
get_reports(function load_report_cb(reports) {
const dialog = new frappe.ui.Dialog({
title: __("Load Report"),
title: __('Load Report'),
fields: [
{
fieldname: 'report_name',
@ -447,7 +453,7 @@ function load_report() {
primary_action_label: __('Load'),
primary_action: function load_report_pa(values) {
dialog.hide();
frappe.set_route("query-report", values.report_name);
frappe.set_route('query-report', values.report_name);
}
});
dialog.show();