2021-02-23 18:57:52 +00:00
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// Contributed by Case Solved and sponsored by Nulight Studios
/* eslint-disable */
2021-03-24 02:56:30 +00:00
frappe . provide ( 'frappe.query_reports' ) ;
2021-02-23 18:57:52 +00:00
frappe . query _reports [ "Tax Detail" ] = {
2021-03-05 06:46:38 +00:00
filters : [
2021-02-23 18:57:52 +00:00
{
2021-03-05 06:46:38 +00:00
fieldname : "company" ,
label : _ _ ( "Company" ) ,
fieldtype : "Link" ,
options : "Company" ,
default : frappe . defaults . get _user _default ( "company" ) ,
reqd : 1
2021-02-23 18:57:52 +00:00
} ,
{
2021-03-05 06:46:38 +00:00
fieldname : "from_date" ,
label : _ _ ( "From Date" ) ,
fieldtype : "Date" ,
default : frappe . datetime . month _start ( frappe . datetime . get _today ( ) ) ,
reqd : 1 ,
width : "60px"
2021-02-23 18:57:52 +00:00
} ,
{
2021-03-05 06:46:38 +00:00
fieldname : "to_date" ,
label : _ _ ( "To Date" ) ,
fieldtype : "Date" ,
default : frappe . datetime . month _end ( frappe . datetime . get _today ( ) ) ,
reqd : 1 ,
width : "60px"
2021-02-23 18:57:52 +00:00
} ,
2021-03-14 06:05:02 +00:00
{
fieldname : "report_name" ,
label : _ _ ( "Report Name" ) ,
fieldtype : "Read Only" ,
default : frappe . query _report . report _name ,
hidden : 1 ,
reqd : 1
} ,
{
fieldname : "mode" ,
label : _ _ ( "Mode" ) ,
fieldtype : "Read Only" ,
2021-04-01 22:31:24 +00:00
default : "edit" ,
2021-03-14 06:05:02 +00:00
hidden : 1 ,
reqd : 1
}
2021-02-23 18:57:52 +00:00
] ,
2021-03-05 06:46:38 +00:00
onload : function onload ( report ) {
// Remove Add Column and Save from menu
2021-03-14 06:05:02 +00:00
report . page . add _inner _button ( _ _ ( "New Report" ) , ( ) => new _report ( ) , _ _ ( "Custom Report" ) ) ;
report . page . add _inner _button ( _ _ ( "Load Report" ) , ( ) => load _report ( ) , _ _ ( "Custom Report" ) ) ;
2021-03-24 02:56:30 +00:00
hide _filters ( report ) ;
2021-02-23 18:57:52 +00:00
}
} ;
2021-03-24 02:56:30 +00:00
function hide _filters ( report ) {
report . page . page _form [ 0 ] . querySelectorAll ( '.form-group.frappe-control' ) . forEach ( function setHidden ( field ) {
2021-03-14 06:05:02 +00:00
if ( field . dataset . fieldtype == "Read Only" ) {
field . classList . add ( "hidden" ) ;
}
} ) ;
}
2021-03-24 02:56:30 +00:00
erpnext . TaxDetail = class TaxDetail {
2021-02-23 18:57:52 +00:00
constructor ( ) {
2021-03-24 02:56:30 +00:00
this . patch ( ) ;
2021-03-05 06:46:38 +00:00
this . load _report ( ) ;
}
2021-03-24 02:56:30 +00:00
// 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
}
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()
this . super . show _footer _message . apply ( this . qr ) ;
if ( this . qr . report _name !== 'Tax Detail' ) {
this . show _help ( ) ;
if ( this . loading ) {
this . set _section ( '' ) ;
2021-04-01 22:31:24 +00:00
} else {
this . reload _component ( '' ) ;
2021-03-24 02:56:30 +00:00
}
}
this . loading = false ;
}
refresh _report ( ) {
// Infrequent report build (onload), load filters & data
// super function runs a refresh() serially
// already run within frappe.run_serially
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 ) ;
} ) ;
}
}
2021-03-05 06:46:38 +00:00
load _report ( ) {
2021-03-24 02:56:30 +00:00
// One-off report build like titles, menu, etc
// Run when this object is created which happens in qr.load_report
this . qr . menu _items = this . get _menu _items ( ) ;
}
get _menu _items ( ) {
2021-03-27 04:02:59 +00:00
// Replace Save action
2021-03-24 02:56:30 +00:00
let new _items = [ ] ;
2021-03-24 04:01:18 +00:00
const save = _ _ ( 'Save' ) ;
2021-03-24 02:56:30 +00:00
for ( let item of this . qr . menu _items ) {
2021-03-24 04:01:18 +00:00
if ( item . label === save ) {
2021-03-24 02:56:30 +00:00
new _items . push ( {
2021-03-24 04:01:18 +00:00
label : save ,
action : ( ) => this . save _report ( ) ,
2021-03-24 02:56:30 +00:00
standard : false
} ) ;
} else {
new _items . push ( item ) ;
}
2021-03-14 06:05:02 +00:00
}
2021-03-24 02:56:30 +00:00
return new _items ;
2021-02-23 18:57:52 +00:00
}
save _report ( ) {
2021-04-01 22:31:24 +00:00
this . check _datatable ( ) ;
2021-03-24 02:56:30 +00:00
if ( this . qr . report _name !== 'Tax Detail' ) {
frappe . call ( {
method : 'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report' ,
args : {
reference _report : 'Tax Detail' ,
report _name : this . qr . report _name ,
data : {
columns : this . qr . get _visible _columns ( ) ,
sections : this . sections ,
show _detail : this . controls [ 'show_detail' ] . get _input _value ( )
}
} ,
freeze : true
} ) . then ( ( r ) => {
this . set _section ( '' ) ;
} ) ;
}
2021-02-23 18:57:52 +00:00
}
2021-04-01 22:31:24 +00:00
check _datatable ( ) {
if ( ! this . qr . datatable ) {
frappe . throw ( _ _ ( 'Please change the date range to load data first' ) ) ;
2021-03-14 06:05:02 +00:00
}
}
2021-03-05 06:46:38 +00:00
set _section ( name ) {
2021-03-24 02:56:30 +00:00
// Sets the given section name and then reloads the data
2021-03-05 06:46:38 +00:00
if ( name && ! this . sections [ name ] ) {
this . sections [ name ] = { } ;
}
2021-03-14 06:05:02 +00:00
let options = Object . keys ( this . sections ) ;
options . unshift ( '' ) ;
this . controls [ 'section_name' ] . $wrapper . find ( "select" ) . empty ( ) . add _options ( options ) ;
2021-03-24 02:56:30 +00:00
const org _mode = this . qr . get _filter _value ( 'mode' ) ;
let refresh = false ;
2021-03-05 06:46:38 +00:00
if ( name ) {
this . controls [ 'section_name' ] . set _input ( name ) ;
2021-03-24 02:56:30 +00:00
this . qr . set _filter _value ( 'mode' , 'edit' ) ;
if ( org _mode === 'run' ) {
refresh = true ;
}
2021-03-14 06:05:02 +00:00
} else {
this . controls [ 'section_name' ] . set _input ( '' ) ;
2021-03-24 02:56:30 +00:00
this . qr . set _filter _value ( 'mode' , 'run' ) ;
if ( org _mode === 'edit' ) {
refresh = true ;
}
2021-03-05 06:46:38 +00:00
}
2021-03-24 02:56:30 +00:00
if ( refresh ) {
this . qr . refresh ( ) ;
2021-03-14 06:05:02 +00:00
}
2021-04-01 22:31:24 +00:00
this . reload _component ( '' ) ;
2021-03-05 06:46:38 +00:00
}
2021-04-01 22:31:24 +00:00
reload _component ( component _name ) {
2021-03-24 02:56:30 +00:00
const section _name = this . controls [ 'section_name' ] . get _input _value ( ) ;
2021-03-14 06:05:02 +00:00
if ( section _name ) {
2021-04-01 22:31:24 +00:00
const section = this . sections [ section _name ] ;
const component _names = Object . keys ( section ) ;
component _names . unshift ( '' ) ;
this . controls [ 'component' ] . $wrapper . find ( "select" ) . empty ( ) . add _options ( component _names ) ;
this . controls [ 'component' ] . set _input ( component _name ) ;
if ( component _name ) {
this . controls [ 'component_type' ] . set _input ( section [ component _name ] . type ) ;
}
2021-03-05 06:46:38 +00:00
} else {
2021-04-01 22:31:24 +00:00
this . controls [ 'component' ] . $wrapper . find ( "select" ) . empty ( ) ;
this . controls [ 'component' ] . set _input ( '' ) ;
2021-03-05 06:46:38 +00:00
}
2021-03-24 02:56:30 +00:00
this . set _table _filters ( ) ;
2021-03-05 06:46:38 +00:00
}
2021-03-24 02:56:30 +00:00
set _table _filters ( ) {
2021-03-14 06:05:02 +00:00
let filters = { } ;
2021-03-24 02:56:30 +00:00
const section _name = this . controls [ 'section_name' ] . get _input _value ( ) ;
2021-04-01 22:31:24 +00:00
const component _name = this . controls [ 'component' ] . get _input _value ( ) ;
if ( section _name && component _name ) {
const component _type = this . sections [ section _name ] [ component _name ] . type ;
if ( component _type === 'filter' ) {
filters = this . sections [ section _name ] [ component _name ] [ 'filters' ] ;
}
2021-03-14 06:05:02 +00:00
}
this . setAppliedFilters ( filters ) ;
}
setAppliedFilters ( filters ) {
2021-04-01 22:31:24 +00:00
if ( this . qr . datatable ) {
Array . from ( this . qr . datatable . header . querySelectorAll ( '.dt-filter' ) ) . map ( function setFilters ( input ) {
let idx = input . dataset . colIndex ;
if ( filters [ idx ] ) {
input . value = filters [ idx ] ;
} else {
input . value = null ;
}
} ) ;
this . qr . datatable . columnmanager . applyFilter ( filters ) ;
}
2021-03-05 06:46:38 +00:00
}
delete ( name , type ) {
if ( type === 'section' ) {
delete this . sections [ name ] ;
2021-03-24 02:56:30 +00:00
const new _section = Object . keys ( this . sections ) [ 0 ] || '' ;
this . set _section ( new _section ) ;
2021-03-05 06:46:38 +00:00
}
2021-04-01 22:31:24 +00:00
if ( type === 'component' ) {
2021-03-24 02:56:30 +00:00
const cur _section = this . controls [ 'section_name' ] . get _input _value ( ) ;
2021-03-05 06:46:38 +00:00
delete this . sections [ cur _section ] [ name ] ;
2021-04-01 22:31:24 +00:00
this . reload _component ( '' ) ;
2021-03-05 06:46:38 +00:00
}
}
2021-02-23 18:57:52 +00:00
create _controls ( ) {
2021-03-05 06:46:38 +00:00
let controls = { } ;
// SELECT in data.js
2021-03-24 02:56:30 +00:00
controls [ 'section_name' ] = this . qr . page . add _field ( {
2021-03-05 06:46:38 +00:00
label : _ _ ( 'Section' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Select' ,
fieldname : 'section_name' ,
2021-03-05 06:46:38 +00:00
change : ( e ) => {
2021-03-14 06:05:02 +00:00
this . set _section ( this . controls [ 'section_name' ] . get _input _value ( ) ) ;
2021-02-23 18:57:52 +00:00
}
} ) ;
2021-03-05 06:46:38 +00:00
// BUTTON in button.js
2021-03-24 02:56:30 +00:00
controls [ 'new_section' ] = this . qr . page . add _field ( {
2021-03-05 06:46:38 +00:00
label : _ _ ( 'New Section' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Button' ,
2021-03-05 06:46:38 +00:00
fieldname : 'new_section' ,
click : ( ) => {
2021-04-01 22:31:24 +00:00
frappe . prompt ( {
label : _ _ ( 'Section Name' ) ,
fieldname : 'name' ,
fieldtype : 'Data'
} , ( values ) => {
this . set _section ( values . name ) ;
} ) ;
2021-03-05 06:46:38 +00:00
}
2021-02-23 18:57:52 +00:00
} ) ;
2021-03-24 02:56:30 +00:00
controls [ 'delete_section' ] = this . qr . page . add _field ( {
2021-03-05 06:46:38 +00:00
label : _ _ ( 'Delete Section' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Button' ,
2021-03-05 06:46:38 +00:00
fieldname : 'delete_section' ,
click : ( ) => {
2021-03-24 02:56:30 +00:00
let cur _section = this . controls [ 'section_name' ] . get _input _value ( ) ;
2021-03-05 06:46:38 +00:00
if ( cur _section ) {
2021-04-18 22:13:39 +00:00
frappe . confirm ( _ _ ( 'Are you sure you want to delete section' ) + ' ' + cur _section + '?' ,
2021-03-05 06:46:38 +00:00
( ) => { this . delete ( cur _section , 'section' ) } ) ;
}
}
2021-02-23 18:57:52 +00:00
} ) ;
2021-04-01 22:31:24 +00:00
controls [ 'component' ] = this . qr . page . add _field ( {
label : _ _ ( 'Component' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Select' ,
2021-04-01 22:31:24 +00:00
fieldname : 'component' ,
2021-03-05 06:46:38 +00:00
change : ( e ) => {
2021-04-01 22:31:24 +00:00
this . reload _component ( this . controls [ 'component' ] . get _input _value ( ) ) ;
2021-03-05 06:46:38 +00:00
}
2021-02-23 18:57:52 +00:00
} ) ;
2021-04-01 22:31:24 +00:00
controls [ 'component_type' ] = this . qr . page . add _field ( {
label : _ _ ( 'Component Type' ) ,
fieldtype : 'Select' ,
fieldname : 'component_type' ,
default : 'filter' ,
options : [
{ label : _ _ ( 'Filtered Row Subtotal' ) , value : 'filter' } ,
{ label : _ _ ( 'Section Subtotal' ) , value : 'section' }
]
} ) ;
controls [ 'add_component' ] = this . qr . page . add _field ( {
label : _ _ ( 'Add Component' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Button' ,
2021-04-01 22:31:24 +00:00
fieldname : 'add_component' ,
2021-03-05 06:46:38 +00:00
click : ( ) => {
2021-04-01 22:31:24 +00:00
this . check _datatable ( ) ;
2021-03-24 02:56:30 +00:00
let section _name = this . controls [ 'section_name' ] . get _input _value ( ) ;
2021-03-05 06:46:38 +00:00
if ( section _name ) {
2021-04-01 22:31:24 +00:00
const component _type = this . controls [ 'component_type' ] . get _input _value ( ) ;
let idx = 0 ;
const names = Object . keys ( this . sections [ section _name ] ) ;
if ( names . length > 0 ) {
const idxs = names . map ( ( key ) => parseInt ( key . match ( /\d+$/ ) ) || 0 ) ;
idx = Math . max ( ... idxs ) + 1 ;
2021-03-14 06:05:02 +00:00
}
2021-04-01 22:31:24 +00:00
const filters = this . qr . datatable . columnmanager . getAppliedFilters ( ) ;
if ( component _type === 'filter' ) {
const name = 'Filter' + idx . toString ( ) ;
let data = {
type : component _type ,
filters : filters
}
this . sections [ section _name ] [ name ] = data ;
this . reload _component ( name ) ;
} else if ( component _type === 'section' ) {
if ( filters && Object . keys ( filters ) . length !== 0 ) {
frappe . show _alert ( {
message : _ _ ( 'Column filters ignored' ) ,
indicator : 'yellow'
} ) ;
}
let data = {
type : component _type
}
frappe . prompt ( {
label : _ _ ( 'Section' ) ,
fieldname : 'section' ,
fieldtype : 'Select' ,
options : Object . keys ( this . sections )
} , ( values ) => {
this . sections [ section _name ] [ values . section ] = data ;
this . reload _component ( values . section ) ;
} ) ;
} else {
frappe . throw ( _ _ ( 'Please select the Component Type first' ) ) ;
2021-03-05 06:46:38 +00:00
}
} else {
2021-04-01 22:31:24 +00:00
frappe . throw ( _ _ ( 'Please select the Section first' ) ) ;
2021-03-05 06:46:38 +00:00
}
}
2021-02-23 18:57:52 +00:00
} ) ;
2021-04-01 22:31:24 +00:00
controls [ 'delete_component' ] = this . qr . page . add _field ( {
label : _ _ ( 'Delete Component' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Button' ,
2021-04-01 22:31:24 +00:00
fieldname : 'delete_component' ,
2021-03-05 06:46:38 +00:00
click : ( ) => {
2021-04-01 22:31:24 +00:00
const component = this . controls [ 'component' ] . get _input _value ( ) ;
if ( component ) {
2021-04-18 22:13:39 +00:00
frappe . confirm ( _ _ ( 'Are you sure you want to delete component' ) + ' ' + component + '?' ,
2021-04-01 22:31:24 +00:00
( ) => { this . delete ( component , 'component' ) } ) ;
2021-03-05 06:46:38 +00:00
}
}
2021-02-23 18:57:52 +00:00
} ) ;
2021-03-24 02:56:30 +00:00
controls [ 'save' ] = this . qr . page . add _field ( {
2021-03-05 06:46:38 +00:00
label : _ _ ( 'Save & Run' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Button' ,
2021-03-05 06:46:38 +00:00
fieldname : 'save' ,
click : ( ) => {
2021-03-14 06:05:02 +00:00
this . save _report ( ) ;
2021-03-05 06:46:38 +00:00
}
2021-02-23 18:57:52 +00:00
} ) ;
2021-03-24 02:56:30 +00:00
controls [ 'show_detail' ] = this . qr . page . add _field ( {
2021-03-19 23:05:19 +00:00
label : _ _ ( 'Show Detail' ) ,
fieldtype : 'Check' ,
fieldname : 'show_detail' ,
default : 1
} ) ;
2021-03-05 06:46:38 +00:00
this . controls = controls ;
}
show _help ( ) {
2021-04-08 23:54:34 +00:00
const help = _ _ ( 'Your custom report is built from General Ledger Entries within the date range. You can add multiple sections to the report using the New Section button. Each component added to a section adds a subset of the data into the specified section. Beware of duplicated data rows. The Filtered Row component type saves the datatable column filters to specify the added data. The Section component type refers to the data in a previously defined section, but it cannot refer to its parent section. The Amount column is summed to give the section subtotal. Use the Show Detail box to see the data rows included in each section in the final report. Once finished, hit Save & Run. Report contributed by' ) ;
this . qr . $report _footer . append ( '<div class="col-md-12"><strong>' + _ _ ( 'Help' ) + ` : </strong> ${ help } <a href="https://www.casesolved.co.uk"> Case Solved</a></div> ` ) ;
2021-02-23 18:57:52 +00:00
}
}
2021-03-24 02:56:30 +00:00
if ( ! window . taxdetail ) {
window . taxdetail = new erpnext . TaxDetail ( ) ;
}
2021-03-05 06:46:38 +00:00
2021-02-23 18:57:52 +00:00
function get _reports ( cb ) {
frappe . call ( {
method : 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports' ,
freeze : true
} ) . then ( ( r ) => {
cb ( r . message ) ;
} )
}
function new _report ( ) {
const dialog = new frappe . ui . Dialog ( {
2021-03-24 02:56:30 +00:00
title : _ _ ( 'New Report' ) ,
2021-02-23 18:57:52 +00:00
fields : [
{
fieldname : 'report_name' ,
2021-03-05 06:46:38 +00:00
label : _ _ ( 'Report Name' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Data' ,
default : 'VAT Return'
}
] ,
primary _action _label : _ _ ( 'Create' ) ,
primary _action : function new _report _pa ( values ) {
frappe . call ( {
2021-03-14 06:05:02 +00:00
method : 'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report' ,
args : {
reference _report : 'Tax Detail' ,
report _name : values . report _name ,
2021-03-27 04:02:59 +00:00
data : {
columns : [ ] ,
sections : { } ,
show _detail : 1
}
2021-03-14 06:05:02 +00:00
} ,
2021-02-23 18:57:52 +00:00
freeze : true
} ) . then ( ( r ) => {
2021-03-24 02:56:30 +00:00
frappe . set _route ( 'query-report' , values . report _name ) ;
2021-02-23 18:57:52 +00:00
} ) ;
dialog . hide ( ) ;
}
} ) ;
dialog . show ( ) ;
}
function load _report ( ) {
get _reports ( function load _report _cb ( reports ) {
const dialog = new frappe . ui . Dialog ( {
2021-03-24 02:56:30 +00:00
title : _ _ ( 'Load Report' ) ,
2021-02-23 18:57:52 +00:00
fields : [
{
fieldname : 'report_name' ,
2021-03-05 06:46:38 +00:00
label : _ _ ( 'Report Name' ) ,
2021-02-23 18:57:52 +00:00
fieldtype : 'Select' ,
options : Object . keys ( reports )
}
] ,
primary _action _label : _ _ ( 'Load' ) ,
primary _action : function load _report _pa ( values ) {
dialog . hide ( ) ;
2021-03-24 02:56:30 +00:00
frappe . set _route ( 'query-report' , values . report _name ) ;
2021-02-23 18:57:52 +00:00
}
} ) ;
dialog . show ( ) ;
} ) ;
}