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 // Contributed by Case Solved and sponsored by Nulight Studios
/* eslint-disable */ /* eslint-disable */
frappe.provide('frappe.query_reports');
frappe.query_reports["Tax Detail"] = { frappe.query_reports["Tax Detail"] = {
filters: [ filters: [
{ {
@ -50,83 +52,124 @@ frappe.query_reports["Tax Detail"] = {
// Remove Add Column and Save from menu // Remove Add Column and Save from menu
report.page.add_inner_button(__("New Report"), () => new_report(), __("Custom Report")); report.page.add_inner_button(__("New Report"), () => new_report(), __("Custom Report"));
report.page.add_inner_button(__("Load Report"), () => load_report(), __("Custom Report")); report.page.add_inner_button(__("Load Report"), () => load_report(), __("Custom Report"));
hide_filters(); hide_filters(report);
},
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();
}
} }
}; };
function hide_filters() { function hide_filters(report) {
frappe.query_report.page.page_form[0].querySelectorAll('.form-group.frappe-control').forEach(function setHidden(field) { report.page.page_form[0].querySelectorAll('.form-group.frappe-control').forEach(function setHidden(field) {
if (field.dataset.fieldtype == "Read Only") { if (field.dataset.fieldtype == "Read Only") {
field.classList.add("hidden"); field.classList.add("hidden");
} }
}); });
} }
class TaxReport { erpnext.TaxDetail = class TaxDetail {
// construct after datatable is loaded
constructor() { constructor() {
this.qr = frappe.query_report; this.patch();
this.page = frappe.query_report.page;
this.create_controls();
this.load_report(); this.load_report();
} }
load_report() { // Monkey patch the QueryReport class
if (this.loaded) { patch() {
return; 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.qr.refresh_report = () => this.refresh_report();
this.report_name.value = report_name; this.qr.show_footer_message = () => this.show_footer_message();
frappe.call({ }
method: 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports', show_footer_message() {
args: {name: report_name}, // The last thing to run after datatable_render in refresh()
freeze: true console.log('show_footer_message');
}).then((r) => { this.super.show_footer_message.apply(this.qr);
const data = JSON.parse(r.message[report_name]['json']); if (this.qr.report_name !== 'Tax Detail') {
this.sections = data.sections || {}; this.set_value_options();
this.controls['show_detail'].set_input(data.show_detail); this.show_help();
this.set_section(); if (this.loading) {
}) this.set_section('');
this.loaded = 1; }
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: this.qr.report_name}
}).then((r) => {
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);
});
}
}
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() { save_report() {
frappe.call({ if (this.qr.report_name !== 'Tax Detail') {
method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report', frappe.call({
args: { method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report',
reference_report: 'Tax Detail', args: {
report_name: this.qr.report_name, reference_report: 'Tax Detail',
data: { report_name: this.qr.report_name,
columns: this.qr.get_visible_columns(), data: {
sections: this.sections, columns: this.qr.get_visible_columns(),
show_detail: this.controls['show_detail'].get_input_value() sections: this.sections,
} show_detail: this.controls['show_detail'].get_input_value()
}, }
freeze: true },
}).then((r) => { freeze: true
this.reload(); }).then((r) => {
}); this.set_section('');
});
}
} }
set_value_options() { set_value_options() {
this.fieldname_lookup = {}; // May be run with no columns or data
this.label_lookup = {}; if (this.qr.columns) {
this.qr.columns.forEach((col, index) => { this.fieldname_lookup = {};
if (col['fieldtype'] == "Currency") { this.label_lookup = {};
this.fieldname_lookup[col['label']] = col['fieldname']; this.qr.columns.forEach((col, index) => {
this.label_lookup[col['fieldname']] = col['label']; if (col['fieldtype'] == "Currency") {
} this.fieldname_lookup[col['label']] = col['fieldname'];
}); this.label_lookup[col['fieldname']] = col['label'];
const options = Object.keys(this.fieldname_lookup); }
this.controls['value_field'].$wrapper.find("select").empty().add_options(options); });
this.controls['value_field'].set_input(options[0]); const options = Object.keys(this.fieldname_lookup);
this.controls['value_field'].$wrapper.find("select").empty().add_options(options);
this.controls['value_field'].set_input(options[0]);
}
} }
set_value_label_from_filter() { set_value_label_from_filter() {
const section_name = this.controls['section_name'].value; const section_name = this.controls['section_name'].value;
@ -158,46 +201,38 @@ class TaxReport {
}); });
dialog.show(); 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) { set_section(name) {
// Sets the given section name and then reloads the data
if (name && !this.sections[name]) { if (name && !this.sections[name]) {
this.sections[name] = {}; this.sections[name] = {};
} }
let options = Object.keys(this.sections); let options = Object.keys(this.sections);
options.unshift(''); options.unshift('');
this.controls['section_name'].$wrapper.find("select").empty().add_options(options); 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) { if (name) {
this.controls['section_name'].set_input(name); this.controls['section_name'].set_input(name);
this.qr.set_filter_value('mode', 'edit');
if (org_mode === 'run') {
refresh = true;
}
} else { } else {
this.controls['section_name'].set_input(''); 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.reload_filter();
this.set_mode('edit'); if (refresh) {
} else { this.qr.refresh();
this.set_mode('run');
} }
this.controls['filter_index'].set_input('');
this.reload();
} }
reload_filter() { reload_filter() {
const section_name = this.controls['section_name'].value; const section_name = this.controls['section_name'].get_input_value();
if (section_name) { 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 section = this.sections[section_name];
let fidxs = Object.keys(section); let fidxs = Object.keys(section);
fidxs.unshift(''); fidxs.unshift('');
@ -207,17 +242,16 @@ class TaxReport {
this.controls['filter_index'].$wrapper.find("select").empty(); this.controls['filter_index'].$wrapper.find("select").empty();
this.controls['filter_index'].set_input(''); this.controls['filter_index'].set_input('');
} }
this.set_filters(); this.set_table_filters();
} }
set_filters() { set_table_filters() {
let filters = {}; let filters = {};
const section_name = this.controls['section_name'].value; const section_name = this.controls['section_name'].get_input_value();
const fidx = this.controls['filter_index'].value; const fidx = this.controls['filter_index'].get_input_value();
if (section_name && fidx) { if (section_name && fidx) {
filters = this.sections[section_name][fidx]['filters']; filters = this.sections[section_name][fidx]['filters'];
} }
this.setAppliedFilters(filters); this.setAppliedFilters(filters);
this.qr.datatable.columnmanager.applyFilter(filters);
this.set_value_label_from_filter(); this.set_value_label_from_filter();
} }
setAppliedFilters(filters) { setAppliedFilters(filters) {
@ -229,32 +263,20 @@ class TaxReport {
input.value = null; input.value = null;
} }
}); });
} this.qr.datatable.columnmanager.applyFilter(filters);
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();
}
} }
delete(name, type) { delete(name, type) {
if (type === 'section') { if (type === 'section') {
delete this.sections[name]; delete this.sections[name];
this.controls['section_name'].$wrapper.find("select").empty().add_options(Object.keys(this.sections)); const new_section = Object.keys(this.sections)[0] || '';
this.controls['section_name'].set_input(Object.keys(this.sections)[0] || ''); this.set_section(new_section);
this.controls['filter_index'].set_input('');
} }
if (type === 'filter') { 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]; delete this.sections[cur_section][name];
this.controls['filter_index'].set_input(''); this.controls['filter_index'].set_input('');
this.reload_filter();
} }
this.reload();
} }
create_controls() { create_controls() {
if (this.controls) { if (this.controls) {
@ -262,7 +284,7 @@ class TaxReport {
} }
let controls = {}; let controls = {};
// SELECT in data.js // SELECT in data.js
controls['section_name'] = this.page.add_field({ controls['section_name'] = this.qr.page.add_field({
label: __('Section'), label: __('Section'),
fieldtype: 'Select', fieldtype: 'Select',
fieldname: 'section_name', fieldname: 'section_name',
@ -271,7 +293,7 @@ class TaxReport {
} }
}); });
// BUTTON in button.js // BUTTON in button.js
controls['new_section'] = this.page.add_field({ controls['new_section'] = this.qr.page.add_field({
label: __('New Section'), label: __('New Section'),
fieldtype: 'Button', fieldtype: 'Button',
fieldname: 'new_section', fieldname: 'new_section',
@ -279,33 +301,33 @@ class TaxReport {
this.new_section(__('New Section')); this.new_section(__('New Section'));
} }
}); });
controls['delete_section'] = this.page.add_field({ controls['delete_section'] = this.qr.page.add_field({
label: __('Delete Section'), label: __('Delete Section'),
fieldtype: 'Button', fieldtype: 'Button',
fieldname: 'delete_section', fieldname: 'delete_section',
click: () => { click: () => {
let cur_section = this.controls['section_name'].value; let cur_section = this.controls['section_name'].get_input_value();
if (cur_section) { if (cur_section) {
frappe.confirm(__('Are you sure you want to delete section ') + cur_section + '?', frappe.confirm(__('Are you sure you want to delete section ') + cur_section + '?',
() => {this.delete(cur_section, 'section')}); () => {this.delete(cur_section, 'section')});
} }
} }
}); });
controls['filter_index'] = this.page.add_field({ controls['filter_index'] = this.qr.page.add_field({
label: __('Filter'), label: __('Filter'),
fieldtype: 'Select', fieldtype: 'Select',
fieldname: 'filter_index', fieldname: 'filter_index',
change: (e) => { change: (e) => {
this.controls['filter_index'].set_input(this.controls['filter_index'].get_input_value()); 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'), label: __('Add Filter'),
fieldtype: 'Button', fieldtype: 'Button',
fieldname: 'add_filter', fieldname: 'add_filter',
click: () => { click: () => {
let section_name = this.controls['section_name'].value; let section_name = this.controls['section_name'].get_input_value();
if (section_name) { if (section_name) {
let prefix = 'Filter'; let prefix = 'Filter';
let data = { 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'), label: __('Delete Filter'),
fieldtype: 'Button', fieldtype: 'Button',
fieldname: 'delete_filter', fieldname: 'delete_filter',
click: () => { click: () => {
let cur_filter = this.controls['filter_index'].value; let cur_filter = this.controls['filter_index'].get_input_value();
if (cur_filter) { if (cur_filter) {
frappe.confirm(__('Are you sure you want to delete filter ') + cur_filter + '?', frappe.confirm(__('Are you sure you want to delete filter ') + cur_filter + '?',
() => {this.delete(cur_filter, 'filter')}); () => {this.delete(cur_filter, 'filter')});
} }
} }
}); });
controls['value_field'] = this.page.add_field({ controls['value_field'] = this.qr.page.add_field({
label: __('Value Column'), label: __('Value Column'),
fieldtype: 'Select', fieldtype: 'Select',
fieldname: 'value_field', fieldname: 'value_field',
@ -346,37 +368,35 @@ class TaxReport {
this.controls['value_field'].set_input(this.controls['value_field'].get_input_value()); 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'), label: __('Save & Run'),
fieldtype: 'Button', fieldtype: 'Button',
fieldname: 'save', fieldname: 'save',
click: () => { click: () => {
this.controls['section_name'].set_input('');
this.set_mode('run');
this.save_report(); this.save_report();
} }
}); });
controls['show_detail'] = this.page.add_field({ controls['show_detail'] = this.qr.page.add_field({
label: __('Show Detail'), label: __('Show Detail'),
fieldtype: 'Check', fieldtype: 'Check',
fieldname: 'show_detail', fieldname: 'show_detail',
default: 1 default: 1
}); });
this.controls = controls; this.controls = controls;
this.set_value_options();
this.get_filter_controls();
this.show_help();
} }
show_help() { show_help() {
const help = __(`You can add multiple sections to your custom report using the New Section button above. 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. 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. 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. You can specify which Currency column will be summed for each filter in the final report with the Value Column
Once you're done, hit Save & Run.`); select box. Once you're done, hit Save & Run.`);
this.qr.show_status(help); this.qr.$report_footer.append(`<div class="col-md-12">${help}</div>`);
} }
} }
if (!window.taxdetail) {
window.taxdetail = new erpnext.TaxDetail();
}
function get_reports(cb) { function get_reports(cb) {
frappe.call({ 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() { function new_report() {
const dialog = new frappe.ui.Dialog({ const dialog = new frappe.ui.Dialog({
title: __("New Report"), title: __('New Report'),
fields: [ fields: [
{ {
fieldname: 'report_name', fieldname: 'report_name',
@ -424,7 +430,7 @@ function new_report() {
}, },
freeze: true freeze: true
}).then((r) => { }).then((r) => {
frappe.set_route("query-report", values.report_name); frappe.set_route('query-report', values.report_name);
}); });
dialog.hide(); dialog.hide();
} }
@ -435,7 +441,7 @@ function new_report() {
function load_report() { function load_report() {
get_reports(function load_report_cb(reports) { get_reports(function load_report_cb(reports) {
const dialog = new frappe.ui.Dialog({ const dialog = new frappe.ui.Dialog({
title: __("Load Report"), title: __('Load Report'),
fields: [ fields: [
{ {
fieldname: 'report_name', fieldname: 'report_name',
@ -447,7 +453,7 @@ function load_report() {
primary_action_label: __('Load'), primary_action_label: __('Load'),
primary_action: function load_report_pa(values) { primary_action: function load_report_pa(values) {
dialog.hide(); dialog.hide();
frappe.set_route("query-report", values.report_name); frappe.set_route('query-report', values.report_name);
} }
}); });
dialog.show(); dialog.show();