From ea78f7b1260e5708efbe019a244fea20fe5c043e Mon Sep 17 00:00:00 2001 From: John Woodlock Date: Sat, 16 Mar 2013 15:28:58 +0000 Subject: [PATCH] add expect payments by date pentaho rpt to core reports script + other minor changes --- mifosng-db/0003-mifosx-core-reports-utf8.sql | 4 +-- .../service/ReadReportingServiceImpl.java | 19 +++++++-------- .../Branch Expected Cash Flow.prpt | Bin 34905 -> 34940 bytes ...Expected Payments By Date - Formatted.prpt | Bin 0 -> 35457 bytes .../expectedPaymentsByDate.properties | 23 ++++++++++++++++++ 5 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 mifosng-provider/src/main/pentahoReports/Expected Payments By Date - Formatted.prpt create mode 100644 mifosng-provider/src/main/pentahoReports/expectedPaymentsByDate.properties diff --git a/mifosng-db/0003-mifosx-core-reports-utf8.sql b/mifosng-db/0003-mifosx-core-reports-utf8.sql index c918f4090..b6a728bd3 100644 --- a/mifosng-db/0003-mifosx-core-reports-utf8.sql +++ b/mifosng-db/0003-mifosx-core-reports-utf8.sql @@ -2,9 +2,9 @@ truncate table stretchy_parameter; truncate table stretchy_report_parameter; -INSERT INTO `stretchy_report` VALUES (1,'Client Listing','Table',NULL,'Client','select \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\n c.account_no as \"Client Account No.\", \r\nc.display_name as \"Name\", \n\nc.joined_date as \"Joined\", c.external_id as \"External Id\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand \n\nounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\nwhere o.id = ${officeId}\r\nand c.is_deleted=0\r\n\n\norder by ounder.hierarchy, c.account_no','Individual Client Report\r\n\r\nLists the small number of defined fields on the client table. Would expect to copy this \n\nreport and add any \'one to one\' additional data for specific tenant needs.\r\n\r\nCan be run for any size MFI but you\'d expect it only to be run within a branch for \n\nlarger ones. Depending on how many columns are displayed, there is probably is a limit of about 20/50k clients returned for html display (export to excel doesn\'t \n\nhave that client browser/memory impact).',1,1),(2,'Client Loans Listing','Table',NULL,'Client','select \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nc.account_no as \"Client \n\nAccount No.\", \r\nc.display_name as \"Name\", \r\nlo.display_name as \"Loan Officer\", l.account_no as \"Loan Account No.\", l.external_id as \"External Id\", \r\n\n\np.name as Loan, st.enum_message_property as \"Status\", \r\nf.`name` as Fund, purp.code_value as \"Loan Purpose\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency, \r\nl.principal_amount,\n\n\r\nl.arrearstolerance_amount as \"Arrears Tolerance Amount\",\r\nl.number_of_repayments as \"Expected No. Repayments\",\r\nl.annual_nominal_interest_rate as \" Annual \n\nNominal Interest Rate\", \r\nl.nominal_interest_rate_per_period as \"Nominal Interest Rate Per Period\",\r\n\r\nipf.enum_message_property as \"Interest Rate Frequency\n\n\",\r\nim.enum_message_property as \"Interest Method\",\r\nicp.enum_message_property as \"Interest Calculated in Period\",\r\nl.term_frequency as \"Term Frequency\",\n\n\r\ntf.enum_message_property as \"Term Frequency Period\",\r\nl.repay_every as \"Repayment Frequency\",\r\nrf.enum_message_property as \"Repayment Frequency Period\",\n\n\r\nam.enum_message_property as \"Amortization\",\r\n\r\nl.total_charges_due_at_disbursement_derived as \"Total Charges Due At Disbursement\",\r\n\r\ndate( \n\nl.submittedon_date) as Submitted, date(l.approvedon_date) Approved, l.expected_disbursedon_date As \"Expected Disbursal\",\r\ndate(l.expected_firstrepaymenton_date) as \n\n\"Expected First Repayment\", date(l.interest_calculated_from_date) as \"Interest Calculated From\" ,\r\ndate(l.disbursedon_date) as Disbursed, date\n\n(l.expected_maturedon_date) \"Expected Maturity\",\r\ndate(l.maturedon_date) as \"Matured On\", date(l.closedon_date) as Closed,\r\ndate(l.rejectedon_date) as \n\nRejected, date(l.rescheduledon_date) as Rescheduled, \r\ndate(l.withdrawnon_date) as Withdrawn, date(l.writtenoffon_date) \"Written Off\"\r\nfrom m_office o \r\njoin \n\nm_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on \n\nc.office_id = ounder.id\r\nleft join m_loan l on l.client_id = c.id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_product_loan p on p.id = \n\nl.product_id\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join r_enum_value st on st.enum_name = \"loan_status_id\" and st.enum_id = l.loan_status_id\r\nleft join \n\nr_enum_value ipf on ipf.enum_name = \"interest_period_frequency_enum\" and ipf.enum_id = l.interest_period_frequency_enum\r\nleft join r_enum_value im on im.enum_name \n\n= \"interest_method_enum\" and im.enum_id = l.interest_method_enum\r\nleft join r_enum_value tf on tf.enum_name = \"term_period_frequency_enum\" and tf.enum_id = \n\nl.term_period_frequency_enum\r\nleft join r_enum_value icp on icp.enum_name = \"interest_calculated_in_period_enum\" and icp.enum_id = \n\nl.interest_calculated_in_period_enum\r\nleft join r_enum_value rf on rf.enum_name = \"repayment_period_frequency_enum\" and rf.enum_id = \n\nl.repayment_period_frequency_enum\r\nleft join r_enum_value am on am.enum_name = \"amortization_method_enum\" and am.enum_id = l.amortization_method_enum\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\n\r\nleft \n\njoin m_currency cur on cur.code = l.currency_code\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand \n\n(l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \n\n\"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\norder by ounder.hierarchy, 2 , l.id','Individual Client Report\r\n\r\nPretty \n\nwide report that lists the basic details of client loans. \r\n\r\nCan be run for any size MFI but you\'d expect it only to be run within a branch for larger ones. \n\nThere is probably is a limit of about 20/50k clients returned for html display (export to excel doesn\'t have that client browser/memory impact).',1,1),(5,'Loans Awaiting Disbursal','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nc.account_no as \"Client Account No\", c.display_name as \"Name\", l.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, ifnull(cur.display_symbol, l.currency_code) as Currency, \r\nl.principal_amount as Principal, \r\nl.term_frequency as \"Term Frequency\",\n\n\r\ntf.enum_message_property as \"Term Frequency Period\",\r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\",\r\ndate(l.approvedon_date) \"Approved\",\r\ndatediff(l.expected_disbursedon_date, curdate()) as \"Days to Disbursal\",\r\ndate(l.expected_disbursedon_date) \"Expected Disbursal\",\r\npurp.code_value as \"Loan Purpose\",\r\n lo.display_name as \"Loan Officer\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join r_enum_value tf on tf.enum_name = \"term_period_frequency_enum\" and tf.enum_id = l.term_period_frequency_enum\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 200\r\norder by ounder.hierarchy, datediff(l.expected_disbursedon_date, curdate()), c.account_no','Individual Client Report',1,1),(6,'Loans Awaiting Disbursal Summary','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\npl.`name` as \"Product\", \r\nifnull(cur.display_symbol, l.currency_code) as Currency, f.`name` as Fund,\r\nsum(l.principal_amount) as Principal\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 200\r\ngroup by ounder.hierarchy, pl.`name`, l.currency_code, f.`name`\r\norder by ounder.hierarchy, pl.`name`, l.currency_code, f.`name`','Individual Client Report',1,1),(7,'Loans Awaiting Disbursal Summary by Month','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\npl.`name` as \"Product\", \r\nifnull(cur.display_symbol, l.currency_code) as Currency, \r\nyear(l.expected_disbursedon_date) as \"Year\", \r\nmonthname(l.expected_disbursedon_date) as \"Month\",\r\nsum(l.principal_amount) as Principal\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 200\r\ngroup by ounder.hierarchy, pl.`name`, l.currency_code, year(l.expected_disbursedon_date), month(l.expected_disbursedon_date)\r\norder by ounder.hierarchy, pl.`name`, l.currency_code, year(l.expected_disbursedon_date), month(l.expected_disbursedon_date)','Individual Client Report',1,1),(8,'Loans Pending Approval','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nc.account_no as \"Client Account No.\", c.display_name as \"Client Name\", \r\nifnull(cur.display_symbol, l.currency_code) as Currency, pl.`name` as \"Product\", \r\nl.account_no as \"Loan Account No.\", \r\nl.principal_amount as \"Loan Amount\", \r\nl.term_frequency as \"Term Frequency\",\n\n\r\ntf.enum_message_property as \"Term Frequency Period\",\r\nl.annual_nominal_interest_rate as \" Annual \n\nNominal Interest Rate\", \r\ndatediff(curdate(), l.submittedon_date) \"Days Pending Approval\", \r\npurp.code_value as \"Loan Purpose\",\r\nlo.display_name as \"Loan Officer\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join r_enum_value tf on tf.enum_name = \"term_period_frequency_enum\" and tf.enum_id = l.term_period_frequency_enum\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 100 /*Submitted and awaiting approval */\r\norder by ounder.hierarchy, l.submittedon_date, l.account_no','Individual Client Report',1,1),(11,'Active Loans - Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\", x.currency as Currency,\r\n x.client_count as \"No. of Clients\", x.active_loan_count as \"No. Active Loans\", x. loans_in_arrears_count as \"No. of Loans in Arrears\",\r\nx.principal as \"Total Loans Disbursed\", x.principal_repaid as \"Principal Repaid\", x.principal_outstanding as \"Principal Outstanding\", x.principal_overdue as \"Principal Overdue\",\r\nx.interest as \"Total Interest\", x.interest_repaid as \"Interest Repaid\", x.interest_outstanding as \"Interest Outstanding\", x.interest_overdue as \"Interest Overdue\",\r\nx.fees as \"Total Fees\", x.fees_repaid as \"Fees Repaid\", x.fees_outstanding as \"Fees Outstanding\", x.fees_overdue as \"Fees Overdue\",\r\nx.penalties as \"Total Penalties\", x.penalties_repaid as \"Penalties Repaid\", x.penalties_outstanding as \"Penalties Outstanding\", x.penalties_overdue as \"Penalties Overdue\",\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.principal_overdue * 100) / x.principal_outstanding, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.principal_overdue + x.interest_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue + x.penalties_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding + x.penalties_overdue), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select ounder.id as branch,\r\nifnull(cur.display_symbol, l.currency_code) as currency,\r\ncount(distinct(c.id)) as client_count, \r\ncount(distinct(l.id)) as active_loan_count,\r\ncount(distinct(if(laa.loan_id is not null, l.id, null) )) as loans_in_arrears_count,\r\n\r\nsum(l.principal_disbursed_derived) as principal,\r\nsum(l.principal_repaid_derived) as principal_repaid,\r\nsum(l.principal_outstanding_derived) as principal_outstanding,\r\nsum(laa.principal_overdue_derived) as principal_overdue,\r\n\r\nsum(l.interest_charged_derived) as interest,\r\nsum(l.interest_repaid_derived) as interest_repaid,\r\nsum(l.interest_outstanding_derived) as interest_outstanding,\r\nsum(laa.interest_overdue_derived) as interest_overdue,\r\n\r\nsum(l.fee_charges_charged_derived) as fees,\r\nsum(l.fee_charges_repaid_derived) as fees_repaid,\r\nsum(l.fee_charges_outstanding_derived) as fees_outstanding,\r\nsum(laa.fee_charges_overdue_derived) as fees_overdue,\r\n\r\nsum(l.penalty_charges_charged_derived) as penalties,\r\nsum(l.penalty_charges_repaid_derived) as penalties_repaid,\r\nsum(l.penalty_charges_outstanding_derived) as penalties_outstanding,\r\nsum(laa.penalty_charges_overdue_derived) as penalties_overdue\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nleft join m_currency cur on cur.code = l.currency_code\r\n\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by ounder.id, l.currency_code) x on x.branch = mo.id\r\norder by mo.hierarchy, x.Currency',NULL,1,1),(12,'Active Loans - Details','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", \r\nc.display_name as \"Client\", l.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed Date\", \r\ndate(l.expected_maturedon_date) as \"Expected Matured On\",\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.principal_outstanding_derived as \"Principal Outstanding\",\r\nlaa.principal_overdue_derived as \"Principal Overdue\",\r\n\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.interest_outstanding_derived as \"Interest Outstanding\",\r\nlaa.interest_overdue_derived as \"Interest Overdue\",\r\n\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.fee_charges_outstanding_derived as \"Fees Outstanding\",\r\nlaa.fee_charges_overdue_derived as \"Fees Overdue\",\r\n\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nl.penalty_charges_outstanding_derived as \"Penalties Outstanding\",\r\npenalty_charges_overdue_derived as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(13,'Obligation Met Loans Details','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nc.account_no as \"Client Account No.\", c.display_name as \"Client\",\r\nl.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Amount\", \r\nl.total_repayment_derived as \"Total Repaid\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed\", \r\ndate(l.closedon_date) as \"Closed\",\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nlo.display_name as \"Loan Officer\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand (case\r\n when ${obligDateType} = 1 then\r\n l.closedon_date between \'${startDate}\' and \'${endDate}\'\r\n when ${obligDateType} = 2 then\r\n l.disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\n else 1 = 1\r\n end)\r\nand l.loan_status_id = 600\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(14,'Obligation Met Loans Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\ncount(distinct(c.id)) as \"No. of Clients\",\r\ncount(distinct(l.id)) as \"No. of Loans\",\r\nsum(l.principal_amount) as \"Total Loan Amount\", \r\nsum(l.principal_repaid_derived) as \"Total Principal Repaid\",\r\nsum(l.interest_repaid_derived) as \"Total Interest Repaid\",\r\nsum(l.fee_charges_repaid_derived) as \"Total Fees Repaid\",\r\nsum(l.penalty_charges_repaid_derived) as \"Total Penalties Repaid\",\r\nsum(l.interest_waived_derived) as \"Total Interest Waived\",\r\nsum(l.fee_charges_waived_derived) as \"Total Fees Waived\",\r\nsum(l.penalty_charges_waived_derived) as \"Total Penalties Waived\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand (case\r\n when ${obligDateType} = 1 then\r\n l.closedon_date between \'${startDate}\' and \'${endDate}\'\r\n when ${obligDateType} = 2 then\r\n l.disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\n else 1 = 1\r\n end)\r\nand l.loan_status_id = 600\r\ngroup by ounder.hierarchy, l.currency_code\r\norder by ounder.hierarchy, l.currency_code','Individual Client \n\nReport',1,1),(15,'Portfolio at Risk','Table',NULL,'Loan','select x.Currency, x.`Principal Outstanding`, x.`Principal Overdue`, x.`Interest Outstanding`, x.`Interest Overdue`, \r\nx.`Fees Outstanding`, x.`Fees Overdue`, x.`Penalties Outstanding`, x.`Penalties Overdue`,\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.`Principal Overdue` * 100) / x.`Principal Outstanding`, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding`), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding`), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue` + x.`Penalties Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding` + x.`Penalties Overdue`), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from \r\n(select ifnull(cur.display_symbol, l.currency_code) as Currency, \r\nsum(l.principal_outstanding_derived) as \"Principal Outstanding\",\r\nsum(laa.principal_overdue_derived) as \"Principal Overdue\",\r\n\r\nsum(l.interest_outstanding_derived) as \"Interest Outstanding\",\r\nsum(laa.interest_overdue_derived) as \"Interest Overdue\",\r\n\r\nsum(l.fee_charges_outstanding_derived) as \"Fees Outstanding\",\r\nsum(laa.fee_charges_overdue_derived) as \"Fees Overdue\",\r\n\r\nsum(penalty_charges_outstanding_derived) as \"Penalties Outstanding\",\r\nsum(laa.penalty_charges_overdue_derived) as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join m_product_loan p on p.id = l.product_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by l.currency_code\r\norder by l.currency_code) x','Covers all loans.\r\n\r\nFor larger MFIs … we should add some derived fields on loan (or a 1:1 loan related table like mifos 2.x does)\r\nPrinciple, Interest, Fees, Penalties Outstanding and Overdue (possibly waived and written off too)',1,1),(16,'Portfolio at Risk by Branch','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\",\r\nx.Currency, x.`Principal Outstanding`, x.`Principal Overdue`, x.`Interest Outstanding`, x.`Interest Overdue`, \r\nx.`Fees Outstanding`, x.`Fees Overdue`, x.`Penalties Outstanding`, x.`Penalties Overdue`,\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.`Principal Overdue` * 100) / x.`Principal Outstanding`, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding`), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding`), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue` + x.`Penalties Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding` + x.`Penalties Overdue`), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select ounder.id as \"branch\", ifnull(cur.display_symbol, l.currency_code) as Currency, \r\n\r\nsum(l.principal_outstanding_derived) as \"Principal Outstanding\",\r\nsum(laa.principal_overdue_derived) as \"Principal Overdue\",\r\n\r\nsum(l.interest_outstanding_derived) as \"Interest Outstanding\",\r\nsum(laa.interest_overdue_derived) as \"Interest Overdue\",\r\n\r\nsum(l.fee_charges_outstanding_derived) as \"Fees Outstanding\",\r\nsum(laa.fee_charges_overdue_derived) as \"Fees Overdue\",\r\n\r\nsum(penalty_charges_outstanding_derived) as \"Penalties Outstanding\",\r\nsum(laa.penalty_charges_overdue_derived) as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join m_product_loan p on p.id = l.product_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by ounder.id, l.currency_code) x on x.branch = mo.id\r\norder by mo.hierarchy, x.Currency','Covers all loans.\r\n\r\nFor larger MFIs … we should add some derived fields on loan (or a 1:1 loan related table like mifos 2.x does)\r\nPrinciple, Interest, Fees, Penalties Outstanding and Overdue (possibly waived and written off too)',1,1),(20,'Funds Disbursed Between Dates Summary','Table',NULL,'Fund','select ifnull(f.`name`, \'-\') as Fund, ifnull(cur.display_symbol, l.currency_code) as Currency, \r\nround(sum(l.principal_amount), 4) as disbursed_amount\r\nfrom m_office ounder \r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_currency cur on cur.`code` = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nwhere disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (l.currency_code = \'${currencyId}\' or \'-1\' = \'${currencyId}\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\ngroup by ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, l.currency_code)\r\norder by ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, l.currency_code)',NULL,1,1),(21,'Funds Disbursed Between Dates Summary by Office','Table',NULL,'Fund','select \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\n \n\nifnull(f.`name`, \'-\') as Fund, ifnull(cur.display_symbol, l.currency_code) as Currency, round(sum(l.principal_amount), 4) as disbursed_amount\r\nfrom m_office o\r\n\n\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c \n\non c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_currency cur on cur.`code` = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\n\n\nwhere disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\nand o.id = ${officeId}\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand \n\n(l.currency_code = \'${currencyId}\' or \'-1\' = \'${currencyId}\')\r\ngroup by ounder.`name`, ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, \n\nl.currency_code)\r\norder by ounder.`name`, ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, l.currency_code)',NULL,1,1),(48,'Balance Sheet','Pentaho',NULL,'Accounting',NULL,'Balance Sheet',1,1),(49,'Income Statement','Pentaho',NULL,'Accounting',NULL,'Profit and Loss Statement',1,1),(50,'Trial Balance','Pentaho',NULL,'Accounting',NULL,'Trial Balance Report',1,1),(51,'Written-Off Loans','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, ml.currency_code) as Currency, \r\nc.account_no as \"Client Account No.\",\r\nc.display_name AS \'Client Name\',\r\nml.account_no AS \'Loan Account No.\',\r\nmpl.name AS \'Product Name\',\r\nml.disbursedon_date AS \'Disbursed Date\',\r\nlt.transaction_date AS \'Written Off date\',\r\nml.principal_amount as \"Loan Amount\",\r\nifnull(lt.principal_portion_derived, 0) AS \'Written-Off Principal\',\r\nifnull(lt.interest_portion_derived, 0) AS \'Written-Off Interest\',\r\nifnull(lt.fee_charges_portion_derived,0) AS \'Written-Off Fees\',\r\nifnull(lt.penalty_charges_portion_derived,0) AS \'Written-Off Penalties\',\r\nn.note AS \'Reason For Write-Off\',\r\nIFNULL(ms.display_name,\'-\') AS \'Loan Officer Name\'\r\nFROM m_office o\r\nJOIN m_office ounder ON ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\nJOIN m_client c ON c.office_id = ounder.id\r\nJOIN m_loan ml ON ml.client_id = c.id\r\nJOIN m_product_loan mpl ON mpl.id=ml.product_id\r\nLEFT JOIN m_staff ms ON ms.id=ml.loan_officer_id\r\nJOIN m_loan_transaction lt ON lt.loan_id = ml.id\r\nLEFT JOIN m_note n ON n.loan_transaction_id = lt.id\r\nLEFT JOIN m_currency cur on cur.code = ml.currency_code\r\nWHERE lt.transaction_type_enum = 6 /*write-off */\r\nAND lt.is_reversed is false \r\nAND ml.loan_status_id=601\r\nAND o.id=${officeId}\r\nAND (mpl.id=${loanProductId} OR ${loanProductId}=-1)\r\nAND lt.transaction_date BETWEEN \'${startDate}\' AND \'${endDate}\'\r\nAND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\") \r\nORDER BY ounder.hierarchy, ifnull(cur.display_symbol, ml.currency_code), ml.account_no','Individual Lending Report. Written Off Loans',1,1),(52,'Aging Detail','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, ml.currency_code) as Currency, \r\nmc.account_no as \"Client Account No.\",\r\n mc.display_name AS \"Client Name\",\r\n ml.account_no AS \"Account Number\",\r\n ml.principal_amount AS \"Loan Amount\",\r\n ml.principal_disbursed_derived AS \"Original Principal\",\r\n ml.interest_charged_derived AS \"Original Interest\",\r\n ml.principal_repaid_derived AS \"Principal Paid\",\r\n ml.interest_repaid_derived AS \"Interest Paid\",\r\n laa.principal_overdue_derived AS \"Principal Overdue\",\r\n laa.interest_overdue_derived AS \"Interest Overdue\",\r\nDATEDIFF(CURDATE(), laa.overdue_since_date_derived) as \"Days in Arrears\",\r\n\r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<7, \'<1\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<8, \' 1\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<15, \'2\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<22, \' 3\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<29, \' 4\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<36, \' 5\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<43, \' 6\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<50, \' 7\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<57, \' 8\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<64, \' 9\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<71, \'10\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<78, \'11\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<85, \'12\', \'12+\')))))))))))) )AS \"Weeks In Arrears Band\",\r\n\r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<31, \'0 - 30\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<61, \'30 - 60\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<91, \'60 - 90\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<181, \'90 - 180\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<361, \'180 - 360\', \r\n \'> 360\'))))) AS \"Days in Arrears Band\"\r\n\r\n FROM m_office mo \r\n JOIN m_office ounder ON ounder.hierarchy like concat(mo.hierarchy, \'%\')\r\n AND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc ON mc.office_id=ounder.id\r\n INNER JOIN m_loan ml ON ml.client_id = mc.id\r\n INNER JOIN r_enum_value rev ON rev.enum_id=ml.loan_status_id\r\n INNER JOIN m_loan_arrears_aging laa ON laa.loan_id=ml.id\r\n left join m_currency cur on cur.code = ml.currency_code\r\n WHERE ml.loan_status_id=300\r\n AND mo.id=${officeId}\r\nORDER BY ounder.hierarchy, ifnull(cur.display_symbol, ml.currency_code), ml.account_no','Loan arrears aging (Weeks)',1,1),(53,'Aging Summary (Arrears in Weeks)','Table',NULL,'Loan','SELECT \r\n IFNULL(periods.currencyName, periods.currency) as currency, \r\n periods.period_no \'Weeks In Arrears (Up To)\', \r\n IFNULL(ars.loanId, 0) \'No Of Loans\', \r\n IFNULL(ars.principal,0.0) \'Original Principal\', \r\n IFNULL(ars.interest,0.0) \'Original Interest\', \r\n IFNULL(ars.prinPaid,0.0) \'Principal Paid\', \r\n IFNULL(ars.intPaid,0.0) \'Interest Paid\', \r\n IFNULL(ars.prinOverdue,0.0) \'Principal Overdue\', \r\n IFNULL(ars.intOverdue,0.0)\'Interest Overdue\'\r\nFROM \r\n /* full table of aging periods/currencies used combo to ensure each line represented */\r\n (SELECT curs.code as currency, curs.name as currencyName, pers.* from\r\n (SELECT \'On Schedule\' period_no,1 pid UNION\r\n SELECT \'1\',2 UNION\r\n SELECT \'2\',3 UNION\r\n SELECT \'3\',4 UNION\r\n SELECT \'4\',5 UNION\r\n SELECT \'5\',6 UNION\r\n SELECT \'6\',7 UNION\r\n SELECT \'7\',8 UNION\r\n SELECT \'8\',9 UNION\r\n SELECT \'9\',10 UNION\r\n SELECT \'10\',11 UNION\r\n SELECT \'11\',12 UNION\r\n SELECT \'12\',13 UNION\r\n SELECT \'12+\',14) pers,\r\n (SELECT distinctrow moc.code, moc.name\r\n FROM m_office mo2\r\n INNER JOIN m_office ounder2 ON ounder2.hierarchy \r\n LIKE CONCAT(mo2.hierarchy, \'%\')\r\nAND ounder2.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc2 ON mc2.office_id=ounder2.id\r\n INNER JOIN m_loan ml2 ON ml2.client_id = mc2.id\r\n INNER JOIN m_organisation_currency moc ON moc.code = ml2.currency_code\r\n WHERE ml2.loan_status_id=300 /* active */\r\n AND mo2.id=${officeId}\r\nAND (ml2.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")) curs) periods\r\n\r\n\r\nLEFT JOIN /* table of aging periods per currency with gaps if no applicable loans */\r\n(SELECT \r\n z.currency, z.arrPeriod, \r\n COUNT(z.loanId) as loanId, SUM(z.principal) as principal, SUM(z.interest) as interest, \r\n SUM(z.prinPaid) as prinPaid, SUM(z.intPaid) as intPaid, \r\n SUM(z.prinOverdue) as prinOverdue, SUM(z.intOverdue) as intOverdue\r\nFROM\r\n /*derived table just used to get arrPeriod value (was much slower to\r\n duplicate calc of minOverdueDate in inner query)\r\nmight not be now with derived fields but didn’t check */\r\n (SELECT x.loanId, x.currency, x.principal, x.interest, x.prinPaid, x.intPaid, x.prinOverdue, x.intOverdue,\r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<1, \'On Schedule\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<8, \'1\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<15, \'2\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<22, \'3\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<29, \'4\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<36, \'5\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<43, \'6\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<50, \'7\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<57, \'8\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<64, \'9\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<71, \'10\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<78, \'11\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<85, \'12\',\r\n \'12+\'))))))))))))) AS arrPeriod\r\n\r\n FROM /* get the individual loan details */\r\n (SELECT ml.id AS loanId, ml.currency_code as currency,\r\n ml.principal_disbursed_derived as principal, \r\n ml.interest_charged_derived as interest, \r\n ml.principal_repaid_derived as prinPaid, \r\n ml.interest_repaid_derived intPaid,\r\n\r\n laa.principal_overdue_derived as prinOverdue,\r\n laa.interest_overdue_derived as intOverdue,\r\n\r\n IFNULL(laa.overdue_since_date_derived, curdate()) as minOverdueDate\r\n \r\n FROM m_office mo\r\n INNER JOIN m_office ounder ON ounder.hierarchy \r\n LIKE CONCAT(mo.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc ON mc.office_id=ounder.id\r\n INNER JOIN m_loan ml ON ml.client_id = mc.id\r\n LEFT JOIN m_loan_arrears_aging laa on laa.loan_id = ml.id\r\n WHERE ml.loan_status_id=300 /* active */\r\n AND mo.id=${officeId}\r\n AND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\n GROUP BY ml.id) x\r\n ) z \r\nGROUP BY z.currency, z.arrPeriod ) ars ON ars.arrPeriod=periods.period_no and ars.currency = periods.currency\r\nORDER BY periods.currency, periods.pid','Loan amount in arrears by branch',1,1),(54,'Rescheduled Loans','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, ml.currency_code) as Currency, \r\nc.account_no as \"Client Account No.\",\r\nc.display_name AS \'Client Name\',\r\nml.account_no AS \'Loan Account No.\',\r\nmpl.name AS \'Product Name\',\r\nml.disbursedon_date AS \'Disbursed Date\',\r\nlt.transaction_date AS \'Written Off date\',\r\nml.principal_amount as \"Loan Amount\",\r\nifnull(lt.principal_portion_derived, 0) AS \'Rescheduled Principal\',\r\nifnull(lt.interest_portion_derived, 0) AS \'Rescheduled Interest\',\r\nifnull(lt.fee_charges_portion_derived,0) AS \'Rescheduled Fees\',\r\nifnull(lt.penalty_charges_portion_derived,0) AS \'Rescheduled Penalties\',\r\nn.note AS \'Reason For Rescheduling\',\r\nIFNULL(ms.display_name,\'-\') AS \'Loan Officer Name\'\r\nFROM m_office o\r\nJOIN m_office ounder ON ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\nJOIN m_client c ON c.office_id = ounder.id\r\nJOIN m_loan ml ON ml.client_id = c.id\r\nJOIN m_product_loan mpl ON mpl.id=ml.product_id\r\nLEFT JOIN m_staff ms ON ms.id=ml.loan_officer_id\r\nJOIN m_loan_transaction lt ON lt.loan_id = ml.id\r\nLEFT JOIN m_note n ON n.loan_transaction_id = lt.id\r\nLEFT JOIN m_currency cur on cur.code = ml.currency_code\r\nWHERE lt.transaction_type_enum = 7 /*marked for rescheduling */\r\nAND lt.is_reversed is false \r\nAND ml.loan_status_id=602\r\nAND o.id=${officeId}\r\nAND (mpl.id=${loanProductId} OR ${loanProductId}=-1)\r\nAND lt.transaction_date BETWEEN \'${startDate}\' AND \'${endDate}\'\r\nAND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nORDER BY ounder.hierarchy, ifnull(cur.display_symbol, ml.currency_code), ml.account_no','Individual Lending Report. Rescheduled Loans. The ability to reschedule (or mark that you have rescheduled the loan elsewhere) is a legacy of the older Mifos product. Needed for migration.',1,1),(55,'Active Loans Passed Final Maturity','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", \r\nc.display_name as \"Client\", l.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed Date\", \r\ndate(l.expected_maturedon_date) as \"Expected Matured On\",\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.principal_outstanding_derived as \"Principal Outstanding\",\r\nlaa.principal_overdue_derived as \"Principal Overdue\",\r\n\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.interest_outstanding_derived as \"Interest Outstanding\",\r\nlaa.interest_overdue_derived as \"Interest Overdue\",\r\n\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.fee_charges_outstanding_derived as \"Fees Outstanding\",\r\nlaa.fee_charges_overdue_derived as \"Fees Overdue\",\r\n\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nl.penalty_charges_outstanding_derived as \"Penalties Outstanding\",\r\nlaa.penalty_charges_overdue_derived as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand l.expected_maturedon_date < curdate()\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(56,'Active Loans Passed Final Maturity Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\", x.currency as Currency,\r\n x.client_count as \"No. of Clients\", x.active_loan_count as \"No. Active Loans\", x. arrears_loan_count as \"No. of Loans in Arrears\",\r\nx.principal as \"Total Loans Disbursed\", x.principal_repaid as \"Principal Repaid\", x.principal_outstanding as \"Principal Outstanding\", x.principal_overdue as \"Principal Overdue\",\r\nx.interest as \"Total Interest\", x.interest_repaid as \"Interest Repaid\", x.interest_outstanding as \"Interest Outstanding\", x.interest_overdue as \"Interest Overdue\",\r\nx.fees as \"Total Fees\", x.fees_repaid as \"Fees Repaid\", x.fees_outstanding as \"Fees Outstanding\", x.fees_overdue as \"Fees Overdue\",\r\nx.penalties as \"Total Penalties\", x.penalties_repaid as \"Penalties Repaid\", x.penalties_outstanding as \"Penalties Outstanding\", x.penalties_overdue as \"Penalties Overdue\",\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.principal_overdue * 100) / x.principal_outstanding, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.principal_overdue + x.interest_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue + x.penalties_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding + x.penalties_overdue), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select ounder.id as branch,\r\nifnull(cur.display_symbol, l.currency_code) as currency,\r\ncount(distinct(c.id)) as client_count, \r\ncount(distinct(l.id)) as active_loan_count,\r\ncount(distinct(laa.loan_id) ) as arrears_loan_count,\r\n\r\nsum(l.principal_disbursed_derived) as principal,\r\nsum(l.principal_repaid_derived) as principal_repaid,\r\nsum(l.principal_outstanding_derived) as principal_outstanding,\r\nsum(ifnull(laa.principal_overdue_derived,0)) as principal_overdue,\r\n\r\nsum(l.interest_charged_derived) as interest,\r\nsum(l.interest_repaid_derived) as interest_repaid,\r\nsum(l.interest_outstanding_derived) as interest_outstanding,\r\nsum(ifnull(laa.interest_overdue_derived,0)) as interest_overdue,\r\n\r\nsum(l.fee_charges_charged_derived) as fees,\r\nsum(l.fee_charges_repaid_derived) as fees_repaid,\r\nsum(l.fee_charges_outstanding_derived) as fees_outstanding,\r\nsum(ifnull(laa.fee_charges_overdue_derived,0)) as fees_overdue,\r\n\r\nsum(l.penalty_charges_charged_derived) as penalties,\r\nsum(l.penalty_charges_repaid_derived) as penalties_repaid,\r\nsum(l.penalty_charges_outstanding_derived) as penalties_outstanding,\r\nsum(ifnull(laa.penalty_charges_overdue_derived,0)) as penalties_overdue\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\n\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand l.expected_maturedon_date < curdate()\r\ngroup by ounder.id, l.currency_code) x on x.branch = mo.id\r\norder by mo.hierarchy, x.Currency',NULL,1,1),(57,'Active Loans in last installment','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(lastInstallment.`hierarchy`) - LENGTH(REPLACE(lastInstallment.`hierarchy`, \'.\', \'\')) - 1))), lastInstallment.branch) as \"Office/Branch\",\r\nlastInstallment.Currency,\r\nlastInstallment.`Loan Officer`, \r\nlastInstallment.`Client Account No`, lastInstallment.`Client`, \r\nlastInstallment.`Loan Account No`, lastInstallment.`Product`, \r\nlastInstallment.`Fund`, lastInstallment.`Loan Amount`, \r\nlastInstallment.`Annual Nominal Interest Rate`, \r\nlastInstallment.`Disbursed`, lastInstallment.`Expected Matured On` ,\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.principal_outstanding_derived as \"Principal Outstanding\",\r\nlaa.principal_overdue_derived as \"Principal Overdue\",\r\n\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.interest_outstanding_derived as \"Interest Outstanding\",\r\nlaa.interest_overdue_derived as \"Interest Overdue\",\r\n\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.fee_charges_outstanding_derived as \"Fees Outstanding\",\r\nlaa.fee_charges_overdue_derived as \"Fees Overdue\",\r\n\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nl.penalty_charges_outstanding_derived as \"Penalties Outstanding\",\r\nlaa.penalty_charges_overdue_derived as \"Penalties Overdue\"\r\n\r\nfrom \r\n(select l.id as loanId, l.number_of_repayments, min(r.installment), \r\nounder.id, ounder.hierarchy, ounder.`name` as branch, \r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", c.account_no as \"Client Account No\",\r\nc.display_name as \"Client\", l.account_no as \"Loan Account No\", pl.`name` as \"Product\", \r\nf.`name` as Fund, l.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \"Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed\", date(l.expected_maturedon_date) as \"Expected Matured On\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_repayment_schedule r on r.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand r.completed_derived is false\r\nand r.duedate >= curdate()\r\ngroup by l.id\r\nhaving l.number_of_repayments = min(r.installment)) lastInstallment\r\njoin m_loan l on l.id = lastInstallment.loanId\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\norder by lastInstallment.hierarchy, lastInstallment.Currency, lastInstallment.`Client Account No`, lastInstallment.`Loan Account No`','Individual Client \n\nReport',1,1),(58,'Active Loans in last installment Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\", x.currency as Currency,\r\n x.client_count as \"No. of Clients\", x.active_loan_count as \"No. Active Loans\", x. arrears_loan_count as \"No. of Loans in Arrears\",\r\nx.principal as \"Total Loans Disbursed\", x.principal_repaid as \"Principal Repaid\", x.principal_outstanding as \"Principal Outstanding\", x.principal_overdue as \"Principal Overdue\",\r\nx.interest as \"Total Interest\", x.interest_repaid as \"Interest Repaid\", x.interest_outstanding as \"Interest Outstanding\", x.interest_overdue as \"Interest Overdue\",\r\nx.fees as \"Total Fees\", x.fees_repaid as \"Fees Repaid\", x.fees_outstanding as \"Fees Outstanding\", x.fees_overdue as \"Fees Overdue\",\r\nx.penalties as \"Total Penalties\", x.penalties_repaid as \"Penalties Repaid\", x.penalties_outstanding as \"Penalties Outstanding\", x.penalties_overdue as \"Penalties Overdue\",\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.principal_overdue * 100) / x.principal_outstanding, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.principal_overdue + x.interest_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue + x.penalties_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding + x.penalties_overdue), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select lastInstallment.branchId as branchId,\r\nlastInstallment.Currency,\r\ncount(distinct(lastInstallment.clientId)) as client_count, \r\ncount(distinct(lastInstallment.loanId)) as active_loan_count,\r\ncount(distinct(laa.loan_id) ) as arrears_loan_count,\r\n\r\nsum(l.principal_disbursed_derived) as principal,\r\nsum(l.principal_repaid_derived) as principal_repaid,\r\nsum(l.principal_outstanding_derived) as principal_outstanding,\r\nsum(ifnull(laa.principal_overdue_derived,0)) as principal_overdue,\r\n\r\nsum(l.interest_charged_derived) as interest,\r\nsum(l.interest_repaid_derived) as interest_repaid,\r\nsum(l.interest_outstanding_derived) as interest_outstanding,\r\nsum(ifnull(laa.interest_overdue_derived,0)) as interest_overdue,\r\n\r\nsum(l.fee_charges_charged_derived) as fees,\r\nsum(l.fee_charges_repaid_derived) as fees_repaid,\r\nsum(l.fee_charges_outstanding_derived) as fees_outstanding,\r\nsum(ifnull(laa.fee_charges_overdue_derived,0)) as fees_overdue,\r\n\r\nsum(l.penalty_charges_charged_derived) as penalties,\r\nsum(l.penalty_charges_repaid_derived) as penalties_repaid,\r\nsum(l.penalty_charges_outstanding_derived) as penalties_outstanding,\r\nsum(ifnull(laa.penalty_charges_overdue_derived,0)) as penalties_overdue\r\n\r\nfrom \r\n(select l.id as loanId, l.number_of_repayments, min(r.installment), \r\nounder.id as branchId, ounder.hierarchy, ounder.`name` as branch, \r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", c.id as clientId, c.account_no as \"Client Account No\",\r\nc.display_name as \"Client\", l.account_no as \"Loan Account No\", pl.`name` as \"Product\", \r\nf.`name` as Fund, l.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \"Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed\", date(l.expected_maturedon_date) as \"Expected Matured On\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_repayment_schedule r on r.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand r.completed_derived is false\r\nand r.duedate >= curdate()\r\ngroup by l.id\r\nhaving l.number_of_repayments = min(r.installment)) lastInstallment\r\njoin m_loan l on l.id = lastInstallment.loanId\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\ngroup by lastInstallment.branchId) x on x.branchId = mo.id\r\norder by mo.hierarchy, x.Currency','Individual Client \n\nReport',1,1),(59,'Active Loans by Disbursal Period','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nc.account_no as \"Client Account No\", c.display_name as \"Client\", l.account_no as \"Loan Account No\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Principal Amount\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed Date\", \r\n\r\nl.total_expected_repayment_derived as \"Total Loan (P+I+F+Pen)\",\r\nl.total_repayment_derived as \"Total Repaid (P+I+F+Pen)\",\r\nlo.display_name as \"Loan Officer\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\nand l.loan_status_id = 300\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(61,'Aging Summary (Arrears in Months)','Table',NULL,'Loan','SELECT \r\n IFNULL(periods.currencyName, periods.currency) as currency, \r\n periods.period_no \'Days In Arrears\', \r\n IFNULL(ars.loanId, 0) \'No Of Loans\', \r\n IFNULL(ars.principal,0.0) \'Original Principal\', \r\n IFNULL(ars.interest,0.0) \'Original Interest\', \r\n IFNULL(ars.prinPaid,0.0) \'Principal Paid\', \r\n IFNULL(ars.intPaid,0.0) \'Interest Paid\', \r\n IFNULL(ars.prinOverdue,0.0) \'Principal Overdue\', \r\n IFNULL(ars.intOverdue,0.0)\'Interest Overdue\'\r\nFROM \r\n /* full table of aging periods/currencies used combo to ensure each line represented */\r\n (SELECT curs.code as currency, curs.name as currencyName, pers.* from\r\n (SELECT \'On Schedule\' period_no,1 pid UNION\r\n SELECT \'0 - 30\',2 UNION\r\n SELECT \'30 - 60\',3 UNION\r\n SELECT \'60 - 90\',4 UNION\r\n SELECT \'90 - 180\',5 UNION\r\n SELECT \'180 - 360\',6 UNION\r\n SELECT \'> 360\',7 ) pers,\r\n (SELECT distinctrow moc.code, moc.name\r\n FROM m_office mo2\r\n INNER JOIN m_office ounder2 ON ounder2.hierarchy \r\n LIKE CONCAT(mo2.hierarchy, \'%\')\r\nAND ounder2.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc2 ON mc2.office_id=ounder2.id\r\n INNER JOIN m_loan ml2 ON ml2.client_id = mc2.id\r\n INNER JOIN m_organisation_currency moc ON moc.code = ml2.currency_code\r\n WHERE ml2.loan_status_id=300 /* active */\r\n AND mo2.id=${officeId}\r\nAND (ml2.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")) curs) periods\r\n\r\n\r\nLEFT JOIN /* table of aging periods per currency with gaps if no applicable loans */\r\n(SELECT \r\n z.currency, z.arrPeriod, \r\n COUNT(z.loanId) as loanId, SUM(z.principal) as principal, SUM(z.interest) as interest, \r\n SUM(z.prinPaid) as prinPaid, SUM(z.intPaid) as intPaid, \r\n SUM(z.prinOverdue) as prinOverdue, SUM(z.intOverdue) as intOverdue\r\nFROM\r\n /*derived table just used to get arrPeriod value (was much slower to\r\n duplicate calc of minOverdueDate in inner query)\r\nmight not be now with derived fields but didn’t check */\r\n (SELECT x.loanId, x.currency, x.principal, x.interest, x.prinPaid, x.intPaid, x.prinOverdue, x.intOverdue,\r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<1, \'On Schedule\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<31, \'0 - 30\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<61, \'30 - 60\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<91, \'60 - 90\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<181, \'90 - 180\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<361, \'180 - 360\', \r\n \'> 360\')))))) AS arrPeriod\r\n\r\n FROM /* get the individual loan details */\r\n (SELECT ml.id AS loanId, ml.currency_code as currency,\r\n ml.principal_disbursed_derived as principal, \r\n ml.interest_charged_derived as interest, \r\n ml.principal_repaid_derived as prinPaid, \r\n ml.interest_repaid_derived intPaid,\r\n\r\n laa.principal_overdue_derived as prinOverdue,\r\n laa.interest_overdue_derived as intOverdue,\r\n\r\n IFNULL(laa.overdue_since_date_derived, curdate()) as minOverdueDate\r\n \r\n FROM m_office mo\r\n INNER JOIN m_office ounder ON ounder.hierarchy \r\n LIKE CONCAT(mo.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc ON mc.office_id=ounder.id\r\n INNER JOIN m_loan ml ON ml.client_id = mc.id\r\n LEFT JOIN m_loan_arrears_aging laa on laa.loan_id = ml.id\r\n WHERE ml.loan_status_id=300 /* active */\r\n AND mo.id=${officeId}\r\n AND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\n GROUP BY ml.id) x\r\n ) z \r\nGROUP BY z.currency, z.arrPeriod ) ars ON ars.arrPeriod=periods.period_no and ars.currency = periods.currency\r\nORDER BY periods.currency, periods.pid','Loan amount in arrears by branch',1,1),(91,'Loan Account Schedule','Pentaho',NULL,'Loan',NULL,NULL,1,0),(92,'Branch Expected Cash Flow','Pentaho',NULL,'Loan',NULL,NULL,1,1),(93,'Expected Payments By Date - Basic','Table',NULL,'Loan','SELECT \r\n ounder.name \'Office\', \r\n IFNULL(ms.display_name,\'-\') \'Loan Officer\',\r\n mc.account_no \'Client Account Number\',\r\n mc.display_name \'Name\',\r\n mp.name \'Product\',\r\n ml.account_no \'Loan Account Number\',\r\n mr.duedate \'Due Date\',\r\n mr.installment \'Installment\',\r\n cu.display_symbol \'Currency\',\r\n mr.principal_amount- IFNULL(mr.principal_completed_derived,0) \'Principal Due\',\r\n mr.interest_amount- IFNULL(IFNULL(mr.interest_completed_derived,mr.interest_waived_derived),0) \'Interest Due\', \r\n IFNULL(mr.fee_charges_amount,0)- IFNULL(IFNULL(mr.fee_charges_completed_derived,mr.fee_charges_waived_derived),0) \'Fees Due\', \r\n IFNULL(mr.penalty_charges_amount,0)- IFNULL(IFNULL(mr.penalty_charges_completed_derived,mr.penalty_charges_waived_derived),0) \'Penalty Due\',\r\n (mr.principal_amount- IFNULL(mr.principal_completed_derived,0)) +\r\n (mr.interest_amount- IFNULL(IFNULL(mr.interest_completed_derived,mr.interest_waived_derived),0)) + \r\n (IFNULL(mr.fee_charges_amount,0)- IFNULL(IFNULL(mr.fee_charges_completed_derived,mr.fee_charges_waived_derived),0)) + \r\n (IFNULL(mr.penalty_charges_amount,0)- IFNULL(IFNULL(mr.penalty_charges_completed_derived,mr.penalty_charges_waived_derived),0)) \'Total Due\', \r\n mlaa.total_overdue_derived \'Total Overdue\'\r\n \r\n FROM m_office mo\r\n JOIN m_office ounder ON ounder.hierarchy LIKE CONCAT(mo.hierarchy, \'%\')\r\n \r\n AND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n \r\n LEFT JOIN m_client mc ON mc.office_id=ounder.id\r\n LEFT JOIN m_loan ml ON ml.client_id=mc.id AND ml.loan_status_id=300\r\n LEFT JOIN m_loan_arrears_aging mlaa ON mlaa.loan_id=ml.id\r\n LEFT JOIN m_loan_repayment_schedule mr ON mr.loan_id=ml.id AND mr.completed_derived=0\r\n LEFT JOIN m_product_loan mp ON mp.id=ml.product_id\r\n LEFT JOIN m_staff ms ON ms.id=ml.loan_officer_id\r\n LEFT JOIN m_currency cu ON cu.code=ml.currency_code\r\n WHERE mo.id=${officeId}\r\n AND (IFNULL(ml.loan_officer_id, -10) = \"${loanOfficerId}\" OR \"-1\" = \"${loanOfficerId}\")\r\n AND mr.duedate BETWEEN \'${startDate}\' AND \'${endDate}\'\r\n ORDER BY ounder.id,mr.duedate,ml.account_no','Test',1,1); +INSERT INTO `stretchy_report` VALUES (1,'Client Listing','Table',NULL,'Client','select \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\n c.account_no as \"Client Account No.\", \r\nc.display_name as \"Name\", \n\nc.joined_date as \"Joined\", c.external_id as \"External Id\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand \n\nounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\nwhere o.id = ${officeId}\r\nand c.is_deleted=0\r\n\n\norder by ounder.hierarchy, c.account_no','Individual Client Report\r\n\r\nLists the small number of defined fields on the client table. Would expect to copy this \n\nreport and add any \'one to one\' additional data for specific tenant needs.\r\n\r\nCan be run for any size MFI but you\'d expect it only to be run within a branch for \n\nlarger ones. Depending on how many columns are displayed, there is probably is a limit of about 20/50k clients returned for html display (export to excel doesn\'t \n\nhave that client browser/memory impact).',1,1),(2,'Client Loans Listing','Table',NULL,'Client','select \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nc.account_no as \"Client \n\nAccount No.\", \r\nc.display_name as \"Name\", \r\nlo.display_name as \"Loan Officer\", l.account_no as \"Loan Account No.\", l.external_id as \"External Id\", \r\n\n\np.name as Loan, st.enum_message_property as \"Status\", \r\nf.`name` as Fund, purp.code_value as \"Loan Purpose\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency, \r\nl.principal_amount,\n\n\r\nl.arrearstolerance_amount as \"Arrears Tolerance Amount\",\r\nl.number_of_repayments as \"Expected No. Repayments\",\r\nl.annual_nominal_interest_rate as \" Annual \n\nNominal Interest Rate\", \r\nl.nominal_interest_rate_per_period as \"Nominal Interest Rate Per Period\",\r\n\r\nipf.enum_message_property as \"Interest Rate Frequency\n\n\",\r\nim.enum_message_property as \"Interest Method\",\r\nicp.enum_message_property as \"Interest Calculated in Period\",\r\nl.term_frequency as \"Term Frequency\",\n\n\r\ntf.enum_message_property as \"Term Frequency Period\",\r\nl.repay_every as \"Repayment Frequency\",\r\nrf.enum_message_property as \"Repayment Frequency Period\",\n\n\r\nam.enum_message_property as \"Amortization\",\r\n\r\nl.total_charges_due_at_disbursement_derived as \"Total Charges Due At Disbursement\",\r\n\r\ndate( \n\nl.submittedon_date) as Submitted, date(l.approvedon_date) Approved, l.expected_disbursedon_date As \"Expected Disbursal\",\r\ndate(l.expected_firstrepaymenton_date) as \n\n\"Expected First Repayment\", date(l.interest_calculated_from_date) as \"Interest Calculated From\" ,\r\ndate(l.disbursedon_date) as Disbursed, date\n\n(l.expected_maturedon_date) \"Expected Maturity\",\r\ndate(l.maturedon_date) as \"Matured On\", date(l.closedon_date) as Closed,\r\ndate(l.rejectedon_date) as \n\nRejected, date(l.rescheduledon_date) as Rescheduled, \r\ndate(l.withdrawnon_date) as Withdrawn, date(l.writtenoffon_date) \"Written Off\"\r\nfrom m_office o \r\njoin \n\nm_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on \n\nc.office_id = ounder.id\r\nleft join m_loan l on l.client_id = c.id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_product_loan p on p.id = \n\nl.product_id\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join r_enum_value st on st.enum_name = \"loan_status_id\" and st.enum_id = l.loan_status_id\r\nleft join \n\nr_enum_value ipf on ipf.enum_name = \"interest_period_frequency_enum\" and ipf.enum_id = l.interest_period_frequency_enum\r\nleft join r_enum_value im on im.enum_name \n\n= \"interest_method_enum\" and im.enum_id = l.interest_method_enum\r\nleft join r_enum_value tf on tf.enum_name = \"term_period_frequency_enum\" and tf.enum_id = \n\nl.term_period_frequency_enum\r\nleft join r_enum_value icp on icp.enum_name = \"interest_calculated_in_period_enum\" and icp.enum_id = \n\nl.interest_calculated_in_period_enum\r\nleft join r_enum_value rf on rf.enum_name = \"repayment_period_frequency_enum\" and rf.enum_id = \n\nl.repayment_period_frequency_enum\r\nleft join r_enum_value am on am.enum_name = \"amortization_method_enum\" and am.enum_id = l.amortization_method_enum\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\n\r\nleft \n\njoin m_currency cur on cur.code = l.currency_code\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand \n\n(l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \n\n\"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\norder by ounder.hierarchy, 2 , l.id','Individual Client Report\r\n\r\nPretty \n\nwide report that lists the basic details of client loans. \r\n\r\nCan be run for any size MFI but you\'d expect it only to be run within a branch for larger ones. \n\nThere is probably is a limit of about 20/50k clients returned for html display (export to excel doesn\'t have that client browser/memory impact).',1,1),(5,'Loans Awaiting Disbursal','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nc.account_no as \"Client Account No\", c.display_name as \"Name\", l.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, ifnull(cur.display_symbol, l.currency_code) as Currency, \r\nl.principal_amount as Principal, \r\nl.term_frequency as \"Term Frequency\",\n\n\r\ntf.enum_message_property as \"Term Frequency Period\",\r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\",\r\ndate(l.approvedon_date) \"Approved\",\r\ndatediff(l.expected_disbursedon_date, curdate()) as \"Days to Disbursal\",\r\ndate(l.expected_disbursedon_date) \"Expected Disbursal\",\r\npurp.code_value as \"Loan Purpose\",\r\n lo.display_name as \"Loan Officer\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join r_enum_value tf on tf.enum_name = \"term_period_frequency_enum\" and tf.enum_id = l.term_period_frequency_enum\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 200\r\norder by ounder.hierarchy, datediff(l.expected_disbursedon_date, curdate()), c.account_no','Individual Client Report',1,1),(6,'Loans Awaiting Disbursal Summary','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\npl.`name` as \"Product\", \r\nifnull(cur.display_symbol, l.currency_code) as Currency, f.`name` as Fund,\r\nsum(l.principal_amount) as Principal\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 200\r\ngroup by ounder.hierarchy, pl.`name`, l.currency_code, f.`name`\r\norder by ounder.hierarchy, pl.`name`, l.currency_code, f.`name`','Individual Client Report',1,1),(7,'Loans Awaiting Disbursal Summary by Month','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\npl.`name` as \"Product\", \r\nifnull(cur.display_symbol, l.currency_code) as Currency, \r\nyear(l.expected_disbursedon_date) as \"Year\", \r\nmonthname(l.expected_disbursedon_date) as \"Month\",\r\nsum(l.principal_amount) as Principal\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 200\r\ngroup by ounder.hierarchy, pl.`name`, l.currency_code, year(l.expected_disbursedon_date), month(l.expected_disbursedon_date)\r\norder by ounder.hierarchy, pl.`name`, l.currency_code, year(l.expected_disbursedon_date), month(l.expected_disbursedon_date)','Individual Client Report',1,1),(8,'Loans Pending Approval','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nc.account_no as \"Client Account No.\", c.display_name as \"Client Name\", \r\nifnull(cur.display_symbol, l.currency_code) as Currency, pl.`name` as \"Product\", \r\nl.account_no as \"Loan Account No.\", \r\nl.principal_amount as \"Loan Amount\", \r\nl.term_frequency as \"Term Frequency\",\n\n\r\ntf.enum_message_property as \"Term Frequency Period\",\r\nl.annual_nominal_interest_rate as \" Annual \n\nNominal Interest Rate\", \r\ndatediff(curdate(), l.submittedon_date) \"Days Pending Approval\", \r\npurp.code_value as \"Loan Purpose\",\r\nlo.display_name as \"Loan Officer\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join r_enum_value tf on tf.enum_name = \"term_period_frequency_enum\" and tf.enum_id = l.term_period_frequency_enum\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 100 /*Submitted and awaiting approval */\r\norder by ounder.hierarchy, l.submittedon_date, l.account_no','Individual Client Report',1,1),(11,'Active Loans - Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\", x.currency as Currency,\r\n x.client_count as \"No. of Clients\", x.active_loan_count as \"No. Active Loans\", x. loans_in_arrears_count as \"No. of Loans in Arrears\",\r\nx.principal as \"Total Loans Disbursed\", x.principal_repaid as \"Principal Repaid\", x.principal_outstanding as \"Principal Outstanding\", x.principal_overdue as \"Principal Overdue\",\r\nx.interest as \"Total Interest\", x.interest_repaid as \"Interest Repaid\", x.interest_outstanding as \"Interest Outstanding\", x.interest_overdue as \"Interest Overdue\",\r\nx.fees as \"Total Fees\", x.fees_repaid as \"Fees Repaid\", x.fees_outstanding as \"Fees Outstanding\", x.fees_overdue as \"Fees Overdue\",\r\nx.penalties as \"Total Penalties\", x.penalties_repaid as \"Penalties Repaid\", x.penalties_outstanding as \"Penalties Outstanding\", x.penalties_overdue as \"Penalties Overdue\",\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.principal_overdue * 100) / x.principal_outstanding, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.principal_overdue + x.interest_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue + x.penalties_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding + x.penalties_overdue), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select ounder.id as branch,\r\nifnull(cur.display_symbol, l.currency_code) as currency,\r\ncount(distinct(c.id)) as client_count, \r\ncount(distinct(l.id)) as active_loan_count,\r\ncount(distinct(if(laa.loan_id is not null, l.id, null) )) as loans_in_arrears_count,\r\n\r\nsum(l.principal_disbursed_derived) as principal,\r\nsum(l.principal_repaid_derived) as principal_repaid,\r\nsum(l.principal_outstanding_derived) as principal_outstanding,\r\nsum(laa.principal_overdue_derived) as principal_overdue,\r\n\r\nsum(l.interest_charged_derived) as interest,\r\nsum(l.interest_repaid_derived) as interest_repaid,\r\nsum(l.interest_outstanding_derived) as interest_outstanding,\r\nsum(laa.interest_overdue_derived) as interest_overdue,\r\n\r\nsum(l.fee_charges_charged_derived) as fees,\r\nsum(l.fee_charges_repaid_derived) as fees_repaid,\r\nsum(l.fee_charges_outstanding_derived) as fees_outstanding,\r\nsum(laa.fee_charges_overdue_derived) as fees_overdue,\r\n\r\nsum(l.penalty_charges_charged_derived) as penalties,\r\nsum(l.penalty_charges_repaid_derived) as penalties_repaid,\r\nsum(l.penalty_charges_outstanding_derived) as penalties_outstanding,\r\nsum(laa.penalty_charges_overdue_derived) as penalties_overdue\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nleft join m_currency cur on cur.code = l.currency_code\r\n\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by ounder.id, l.currency_code) x on x.branch = mo.id\r\norder by mo.hierarchy, x.Currency',NULL,1,1),(12,'Active Loans - Details','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", \r\nc.display_name as \"Client\", l.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed Date\", \r\ndate(l.expected_maturedon_date) as \"Expected Matured On\",\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.principal_outstanding_derived as \"Principal Outstanding\",\r\nlaa.principal_overdue_derived as \"Principal Overdue\",\r\n\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.interest_outstanding_derived as \"Interest Outstanding\",\r\nlaa.interest_overdue_derived as \"Interest Overdue\",\r\n\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.fee_charges_outstanding_derived as \"Fees Outstanding\",\r\nlaa.fee_charges_overdue_derived as \"Fees Overdue\",\r\n\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nl.penalty_charges_outstanding_derived as \"Penalties Outstanding\",\r\npenalty_charges_overdue_derived as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(13,'Obligation Met Loans Details','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nc.account_no as \"Client Account No.\", c.display_name as \"Client\",\r\nl.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Amount\", \r\nl.total_repayment_derived as \"Total Repaid\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed\", \r\ndate(l.closedon_date) as \"Closed\",\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nlo.display_name as \"Loan Officer\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand (case\r\n when ${obligDateType} = 1 then\r\n l.closedon_date between \'${startDate}\' and \'${endDate}\'\r\n when ${obligDateType} = 2 then\r\n l.disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\n else 1 = 1\r\n end)\r\nand l.loan_status_id = 600\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(14,'Obligation Met Loans Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\ncount(distinct(c.id)) as \"No. of Clients\",\r\ncount(distinct(l.id)) as \"No. of Loans\",\r\nsum(l.principal_amount) as \"Total Loan Amount\", \r\nsum(l.principal_repaid_derived) as \"Total Principal Repaid\",\r\nsum(l.interest_repaid_derived) as \"Total Interest Repaid\",\r\nsum(l.fee_charges_repaid_derived) as \"Total Fees Repaid\",\r\nsum(l.penalty_charges_repaid_derived) as \"Total Penalties Repaid\",\r\nsum(l.interest_waived_derived) as \"Total Interest Waived\",\r\nsum(l.fee_charges_waived_derived) as \"Total Fees Waived\",\r\nsum(l.penalty_charges_waived_derived) as \"Total Penalties Waived\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand (case\r\n when ${obligDateType} = 1 then\r\n l.closedon_date between \'${startDate}\' and \'${endDate}\'\r\n when ${obligDateType} = 2 then\r\n l.disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\n else 1 = 1\r\n end)\r\nand l.loan_status_id = 600\r\ngroup by ounder.hierarchy, l.currency_code\r\norder by ounder.hierarchy, l.currency_code','Individual Client \n\nReport',1,1),(15,'Portfolio at Risk','Table',NULL,'Loan','select x.Currency, x.`Principal Outstanding`, x.`Principal Overdue`, x.`Interest Outstanding`, x.`Interest Overdue`, \r\nx.`Fees Outstanding`, x.`Fees Overdue`, x.`Penalties Outstanding`, x.`Penalties Overdue`,\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.`Principal Overdue` * 100) / x.`Principal Outstanding`, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding`), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding`), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue` + x.`Penalties Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding` + x.`Penalties Overdue`), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from \r\n(select ifnull(cur.display_symbol, l.currency_code) as Currency, \r\nsum(l.principal_outstanding_derived) as \"Principal Outstanding\",\r\nsum(laa.principal_overdue_derived) as \"Principal Overdue\",\r\n\r\nsum(l.interest_outstanding_derived) as \"Interest Outstanding\",\r\nsum(laa.interest_overdue_derived) as \"Interest Overdue\",\r\n\r\nsum(l.fee_charges_outstanding_derived) as \"Fees Outstanding\",\r\nsum(laa.fee_charges_overdue_derived) as \"Fees Overdue\",\r\n\r\nsum(penalty_charges_outstanding_derived) as \"Penalties Outstanding\",\r\nsum(laa.penalty_charges_overdue_derived) as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join m_product_loan p on p.id = l.product_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by l.currency_code\r\norder by l.currency_code) x','Covers all loans.\r\n\r\nFor larger MFIs … we should add some derived fields on loan (or a 1:1 loan related table like mifos 2.x does)\r\nPrinciple, Interest, Fees, Penalties Outstanding and Overdue (possibly waived and written off too)',1,1),(16,'Portfolio at Risk by Branch','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\",\r\nx.Currency, x.`Principal Outstanding`, x.`Principal Overdue`, x.`Interest Outstanding`, x.`Interest Overdue`, \r\nx.`Fees Outstanding`, x.`Fees Overdue`, x.`Penalties Outstanding`, x.`Penalties Overdue`,\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.`Principal Overdue` * 100) / x.`Principal Outstanding`, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding`), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding`), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.`Principal Overdue` + x.`Interest Overdue` + x.`Fees Overdue` + x.`Penalties Overdue`) * 100) / (x.`Principal Outstanding` + x.`Interest Outstanding` + x.`Fees Outstanding` + x.`Penalties Overdue`), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select ounder.id as \"branch\", ifnull(cur.display_symbol, l.currency_code) as Currency, \r\n\r\nsum(l.principal_outstanding_derived) as \"Principal Outstanding\",\r\nsum(laa.principal_overdue_derived) as \"Principal Overdue\",\r\n\r\nsum(l.interest_outstanding_derived) as \"Interest Outstanding\",\r\nsum(laa.interest_overdue_derived) as \"Interest Overdue\",\r\n\r\nsum(l.fee_charges_outstanding_derived) as \"Fees Outstanding\",\r\nsum(laa.fee_charges_overdue_derived) as \"Fees Overdue\",\r\n\r\nsum(penalty_charges_outstanding_derived) as \"Penalties Outstanding\",\r\nsum(laa.penalty_charges_overdue_derived) as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_code_value purp on purp.id = l.loanpurpose_cv_id\r\nleft join m_product_loan p on p.id = l.product_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\ngroup by ounder.id, l.currency_code) x on x.branch = mo.id\r\norder by mo.hierarchy, x.Currency','Covers all loans.\r\n\r\nFor larger MFIs … we should add some derived fields on loan (or a 1:1 loan related table like mifos 2.x does)\r\nPrinciple, Interest, Fees, Penalties Outstanding and Overdue (possibly waived and written off too)',1,1),(20,'Funds Disbursed Between Dates Summary','Table',NULL,'Fund','select ifnull(f.`name`, \'-\') as Fund, ifnull(cur.display_symbol, l.currency_code) as Currency, \r\nround(sum(l.principal_amount), 4) as disbursed_amount\r\nfrom m_office ounder \r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_currency cur on cur.`code` = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nwhere disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (l.currency_code = \'${currencyId}\' or \'-1\' = \'${currencyId}\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\ngroup by ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, l.currency_code)\r\norder by ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, l.currency_code)',NULL,1,1),(21,'Funds Disbursed Between Dates Summary by Office','Table',NULL,'Fund','select \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\n \n\nifnull(f.`name`, \'-\') as Fund, ifnull(cur.display_symbol, l.currency_code) as Currency, round(sum(l.principal_amount), 4) as disbursed_amount\r\nfrom m_office o\r\n\n\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c \n\non c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_currency cur on cur.`code` = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\n\n\nwhere disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\nand o.id = ${officeId}\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand \n\n(l.currency_code = \'${currencyId}\' or \'-1\' = \'${currencyId}\')\r\ngroup by ounder.`name`, ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, \n\nl.currency_code)\r\norder by ounder.`name`, ifnull(f.`name`, \'-\') , ifnull(cur.display_symbol, l.currency_code)',NULL,1,1),(48,'Balance Sheet','Pentaho',NULL,'Accounting',NULL,'Balance Sheet',1,1),(49,'Income Statement','Pentaho',NULL,'Accounting',NULL,'Profit and Loss Statement',1,1),(50,'Trial Balance','Pentaho',NULL,'Accounting',NULL,'Trial Balance Report',1,1),(51,'Written-Off Loans','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, ml.currency_code) as Currency, \r\nc.account_no as \"Client Account No.\",\r\nc.display_name AS \'Client Name\',\r\nml.account_no AS \'Loan Account No.\',\r\nmpl.name AS \'Product Name\',\r\nml.disbursedon_date AS \'Disbursed Date\',\r\nlt.transaction_date AS \'Written Off date\',\r\nml.principal_amount as \"Loan Amount\",\r\nifnull(lt.principal_portion_derived, 0) AS \'Written-Off Principal\',\r\nifnull(lt.interest_portion_derived, 0) AS \'Written-Off Interest\',\r\nifnull(lt.fee_charges_portion_derived,0) AS \'Written-Off Fees\',\r\nifnull(lt.penalty_charges_portion_derived,0) AS \'Written-Off Penalties\',\r\nn.note AS \'Reason For Write-Off\',\r\nIFNULL(ms.display_name,\'-\') AS \'Loan Officer Name\'\r\nFROM m_office o\r\nJOIN m_office ounder ON ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\nJOIN m_client c ON c.office_id = ounder.id\r\nJOIN m_loan ml ON ml.client_id = c.id\r\nJOIN m_product_loan mpl ON mpl.id=ml.product_id\r\nLEFT JOIN m_staff ms ON ms.id=ml.loan_officer_id\r\nJOIN m_loan_transaction lt ON lt.loan_id = ml.id\r\nLEFT JOIN m_note n ON n.loan_transaction_id = lt.id\r\nLEFT JOIN m_currency cur on cur.code = ml.currency_code\r\nWHERE lt.transaction_type_enum = 6 /*write-off */\r\nAND lt.is_reversed is false \r\nAND ml.loan_status_id=601\r\nAND o.id=${officeId}\r\nAND (mpl.id=${loanProductId} OR ${loanProductId}=-1)\r\nAND lt.transaction_date BETWEEN \'${startDate}\' AND \'${endDate}\'\r\nAND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\") \r\nORDER BY ounder.hierarchy, ifnull(cur.display_symbol, ml.currency_code), ml.account_no','Individual Lending Report. Written Off Loans',1,1),(52,'Aging Detail','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, ml.currency_code) as Currency, \r\nmc.account_no as \"Client Account No.\",\r\n mc.display_name AS \"Client Name\",\r\n ml.account_no AS \"Account Number\",\r\n ml.principal_amount AS \"Loan Amount\",\r\n ml.principal_disbursed_derived AS \"Original Principal\",\r\n ml.interest_charged_derived AS \"Original Interest\",\r\n ml.principal_repaid_derived AS \"Principal Paid\",\r\n ml.interest_repaid_derived AS \"Interest Paid\",\r\n laa.principal_overdue_derived AS \"Principal Overdue\",\r\n laa.interest_overdue_derived AS \"Interest Overdue\",\r\nDATEDIFF(CURDATE(), laa.overdue_since_date_derived) as \"Days in Arrears\",\r\n\r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<7, \'<1\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<8, \' 1\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<15, \'2\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<22, \' 3\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<29, \' 4\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<36, \' 5\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<43, \' 6\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<50, \' 7\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<57, \' 8\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<64, \' 9\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<71, \'10\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<78, \'11\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<85, \'12\', \'12+\')))))))))))) )AS \"Weeks In Arrears Band\",\r\n\r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<31, \'0 - 30\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<61, \'30 - 60\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<91, \'60 - 90\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<181, \'90 - 180\', \r\n IF(DATEDIFF(CURDATE(), laa.overdue_since_date_derived)<361, \'180 - 360\', \r\n \'> 360\'))))) AS \"Days in Arrears Band\"\r\n\r\n FROM m_office mo \r\n JOIN m_office ounder ON ounder.hierarchy like concat(mo.hierarchy, \'%\')\r\n AND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc ON mc.office_id=ounder.id\r\n INNER JOIN m_loan ml ON ml.client_id = mc.id\r\n INNER JOIN r_enum_value rev ON rev.enum_id=ml.loan_status_id\r\n INNER JOIN m_loan_arrears_aging laa ON laa.loan_id=ml.id\r\n left join m_currency cur on cur.code = ml.currency_code\r\n WHERE ml.loan_status_id=300\r\n AND mo.id=${officeId}\r\nORDER BY ounder.hierarchy, ifnull(cur.display_symbol, ml.currency_code), ml.account_no','Loan arrears aging (Weeks)',1,1),(53,'Aging Summary (Arrears in Weeks)','Table',NULL,'Loan','SELECT \r\n IFNULL(periods.currencyName, periods.currency) as currency, \r\n periods.period_no \'Weeks In Arrears (Up To)\', \r\n IFNULL(ars.loanId, 0) \'No Of Loans\', \r\n IFNULL(ars.principal,0.0) \'Original Principal\', \r\n IFNULL(ars.interest,0.0) \'Original Interest\', \r\n IFNULL(ars.prinPaid,0.0) \'Principal Paid\', \r\n IFNULL(ars.intPaid,0.0) \'Interest Paid\', \r\n IFNULL(ars.prinOverdue,0.0) \'Principal Overdue\', \r\n IFNULL(ars.intOverdue,0.0)\'Interest Overdue\'\r\nFROM \r\n /* full table of aging periods/currencies used combo to ensure each line represented */\r\n (SELECT curs.code as currency, curs.name as currencyName, pers.* from\r\n (SELECT \'On Schedule\' period_no,1 pid UNION\r\n SELECT \'1\',2 UNION\r\n SELECT \'2\',3 UNION\r\n SELECT \'3\',4 UNION\r\n SELECT \'4\',5 UNION\r\n SELECT \'5\',6 UNION\r\n SELECT \'6\',7 UNION\r\n SELECT \'7\',8 UNION\r\n SELECT \'8\',9 UNION\r\n SELECT \'9\',10 UNION\r\n SELECT \'10\',11 UNION\r\n SELECT \'11\',12 UNION\r\n SELECT \'12\',13 UNION\r\n SELECT \'12+\',14) pers,\r\n (SELECT distinctrow moc.code, moc.name\r\n FROM m_office mo2\r\n INNER JOIN m_office ounder2 ON ounder2.hierarchy \r\n LIKE CONCAT(mo2.hierarchy, \'%\')\r\nAND ounder2.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc2 ON mc2.office_id=ounder2.id\r\n INNER JOIN m_loan ml2 ON ml2.client_id = mc2.id\r\n INNER JOIN m_organisation_currency moc ON moc.code = ml2.currency_code\r\n WHERE ml2.loan_status_id=300 /* active */\r\n AND mo2.id=${officeId}\r\nAND (ml2.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")) curs) periods\r\n\r\n\r\nLEFT JOIN /* table of aging periods per currency with gaps if no applicable loans */\r\n(SELECT \r\n z.currency, z.arrPeriod, \r\n COUNT(z.loanId) as loanId, SUM(z.principal) as principal, SUM(z.interest) as interest, \r\n SUM(z.prinPaid) as prinPaid, SUM(z.intPaid) as intPaid, \r\n SUM(z.prinOverdue) as prinOverdue, SUM(z.intOverdue) as intOverdue\r\nFROM\r\n /*derived table just used to get arrPeriod value (was much slower to\r\n duplicate calc of minOverdueDate in inner query)\r\nmight not be now with derived fields but didn’t check */\r\n (SELECT x.loanId, x.currency, x.principal, x.interest, x.prinPaid, x.intPaid, x.prinOverdue, x.intOverdue,\r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<1, \'On Schedule\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<8, \'1\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<15, \'2\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<22, \'3\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<29, \'4\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<36, \'5\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<43, \'6\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<50, \'7\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<57, \'8\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<64, \'9\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<71, \'10\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<78, \'11\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<85, \'12\',\r\n \'12+\'))))))))))))) AS arrPeriod\r\n\r\n FROM /* get the individual loan details */\r\n (SELECT ml.id AS loanId, ml.currency_code as currency,\r\n ml.principal_disbursed_derived as principal, \r\n ml.interest_charged_derived as interest, \r\n ml.principal_repaid_derived as prinPaid, \r\n ml.interest_repaid_derived intPaid,\r\n\r\n laa.principal_overdue_derived as prinOverdue,\r\n laa.interest_overdue_derived as intOverdue,\r\n\r\n IFNULL(laa.overdue_since_date_derived, curdate()) as minOverdueDate\r\n \r\n FROM m_office mo\r\n INNER JOIN m_office ounder ON ounder.hierarchy \r\n LIKE CONCAT(mo.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc ON mc.office_id=ounder.id\r\n INNER JOIN m_loan ml ON ml.client_id = mc.id\r\n LEFT JOIN m_loan_arrears_aging laa on laa.loan_id = ml.id\r\n WHERE ml.loan_status_id=300 /* active */\r\n AND mo.id=${officeId}\r\n AND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\n GROUP BY ml.id) x\r\n ) z \r\nGROUP BY z.currency, z.arrPeriod ) ars ON ars.arrPeriod=periods.period_no and ars.currency = periods.currency\r\nORDER BY periods.currency, periods.pid','Loan amount in arrears by branch',1,1),(54,'Rescheduled Loans','Table',NULL,'Loan','SELECT \r\nconcat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, ml.currency_code) as Currency, \r\nc.account_no as \"Client Account No.\",\r\nc.display_name AS \'Client Name\',\r\nml.account_no AS \'Loan Account No.\',\r\nmpl.name AS \'Product Name\',\r\nml.disbursedon_date AS \'Disbursed Date\',\r\nlt.transaction_date AS \'Written Off date\',\r\nml.principal_amount as \"Loan Amount\",\r\nifnull(lt.principal_portion_derived, 0) AS \'Rescheduled Principal\',\r\nifnull(lt.interest_portion_derived, 0) AS \'Rescheduled Interest\',\r\nifnull(lt.fee_charges_portion_derived,0) AS \'Rescheduled Fees\',\r\nifnull(lt.penalty_charges_portion_derived,0) AS \'Rescheduled Penalties\',\r\nn.note AS \'Reason For Rescheduling\',\r\nIFNULL(ms.display_name,\'-\') AS \'Loan Officer Name\'\r\nFROM m_office o\r\nJOIN m_office ounder ON ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\nJOIN m_client c ON c.office_id = ounder.id\r\nJOIN m_loan ml ON ml.client_id = c.id\r\nJOIN m_product_loan mpl ON mpl.id=ml.product_id\r\nLEFT JOIN m_staff ms ON ms.id=ml.loan_officer_id\r\nJOIN m_loan_transaction lt ON lt.loan_id = ml.id\r\nLEFT JOIN m_note n ON n.loan_transaction_id = lt.id\r\nLEFT JOIN m_currency cur on cur.code = ml.currency_code\r\nWHERE lt.transaction_type_enum = 7 /*marked for rescheduling */\r\nAND lt.is_reversed is false \r\nAND ml.loan_status_id=602\r\nAND o.id=${officeId}\r\nAND (mpl.id=${loanProductId} OR ${loanProductId}=-1)\r\nAND lt.transaction_date BETWEEN \'${startDate}\' AND \'${endDate}\'\r\nAND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nORDER BY ounder.hierarchy, ifnull(cur.display_symbol, ml.currency_code), ml.account_no','Individual Lending Report. Rescheduled Loans. The ability to reschedule (or mark that you have rescheduled the loan elsewhere) is a legacy of the older Mifos product. Needed for migration.',1,1),(55,'Active Loans Passed Final Maturity','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", \r\nc.display_name as \"Client\", l.account_no as \"Loan Account No.\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed Date\", \r\ndate(l.expected_maturedon_date) as \"Expected Matured On\",\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.principal_outstanding_derived as \"Principal Outstanding\",\r\nlaa.principal_overdue_derived as \"Principal Overdue\",\r\n\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.interest_outstanding_derived as \"Interest Outstanding\",\r\nlaa.interest_overdue_derived as \"Interest Overdue\",\r\n\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.fee_charges_outstanding_derived as \"Fees Outstanding\",\r\nlaa.fee_charges_overdue_derived as \"Fees Overdue\",\r\n\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nl.penalty_charges_outstanding_derived as \"Penalties Outstanding\",\r\nlaa.penalty_charges_overdue_derived as \"Penalties Overdue\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand l.expected_maturedon_date < curdate()\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(56,'Active Loans Passed Final Maturity Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\", x.currency as Currency,\r\n x.client_count as \"No. of Clients\", x.active_loan_count as \"No. Active Loans\", x. arrears_loan_count as \"No. of Loans in Arrears\",\r\nx.principal as \"Total Loans Disbursed\", x.principal_repaid as \"Principal Repaid\", x.principal_outstanding as \"Principal Outstanding\", x.principal_overdue as \"Principal Overdue\",\r\nx.interest as \"Total Interest\", x.interest_repaid as \"Interest Repaid\", x.interest_outstanding as \"Interest Outstanding\", x.interest_overdue as \"Interest Overdue\",\r\nx.fees as \"Total Fees\", x.fees_repaid as \"Fees Repaid\", x.fees_outstanding as \"Fees Outstanding\", x.fees_overdue as \"Fees Overdue\",\r\nx.penalties as \"Total Penalties\", x.penalties_repaid as \"Penalties Repaid\", x.penalties_outstanding as \"Penalties Outstanding\", x.penalties_overdue as \"Penalties Overdue\",\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.principal_overdue * 100) / x.principal_outstanding, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.principal_overdue + x.interest_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue + x.penalties_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding + x.penalties_overdue), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select ounder.id as branch,\r\nifnull(cur.display_symbol, l.currency_code) as currency,\r\ncount(distinct(c.id)) as client_count, \r\ncount(distinct(l.id)) as active_loan_count,\r\ncount(distinct(laa.loan_id) ) as arrears_loan_count,\r\n\r\nsum(l.principal_disbursed_derived) as principal,\r\nsum(l.principal_repaid_derived) as principal_repaid,\r\nsum(l.principal_outstanding_derived) as principal_outstanding,\r\nsum(ifnull(laa.principal_overdue_derived,0)) as principal_overdue,\r\n\r\nsum(l.interest_charged_derived) as interest,\r\nsum(l.interest_repaid_derived) as interest_repaid,\r\nsum(l.interest_outstanding_derived) as interest_outstanding,\r\nsum(ifnull(laa.interest_overdue_derived,0)) as interest_overdue,\r\n\r\nsum(l.fee_charges_charged_derived) as fees,\r\nsum(l.fee_charges_repaid_derived) as fees_repaid,\r\nsum(l.fee_charges_outstanding_derived) as fees_outstanding,\r\nsum(ifnull(laa.fee_charges_overdue_derived,0)) as fees_overdue,\r\n\r\nsum(l.penalty_charges_charged_derived) as penalties,\r\nsum(l.penalty_charges_repaid_derived) as penalties_repaid,\r\nsum(l.penalty_charges_outstanding_derived) as penalties_outstanding,\r\nsum(ifnull(laa.penalty_charges_overdue_derived,0)) as penalties_overdue\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\n\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand l.expected_maturedon_date < curdate()\r\ngroup by ounder.id, l.currency_code) x on x.branch = mo.id\r\norder by mo.hierarchy, x.Currency',NULL,1,1),(57,'Active Loans in last installment','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(lastInstallment.`hierarchy`) - LENGTH(REPLACE(lastInstallment.`hierarchy`, \'.\', \'\')) - 1))), lastInstallment.branch) as \"Office/Branch\",\r\nlastInstallment.Currency,\r\nlastInstallment.`Loan Officer`, \r\nlastInstallment.`Client Account No`, lastInstallment.`Client`, \r\nlastInstallment.`Loan Account No`, lastInstallment.`Product`, \r\nlastInstallment.`Fund`, lastInstallment.`Loan Amount`, \r\nlastInstallment.`Annual Nominal Interest Rate`, \r\nlastInstallment.`Disbursed`, lastInstallment.`Expected Matured On` ,\r\n\r\nl.principal_repaid_derived as \"Principal Repaid\",\r\nl.principal_outstanding_derived as \"Principal Outstanding\",\r\nlaa.principal_overdue_derived as \"Principal Overdue\",\r\n\r\nl.interest_repaid_derived as \"Interest Repaid\",\r\nl.interest_outstanding_derived as \"Interest Outstanding\",\r\nlaa.interest_overdue_derived as \"Interest Overdue\",\r\n\r\nl.fee_charges_repaid_derived as \"Fees Repaid\",\r\nl.fee_charges_outstanding_derived as \"Fees Outstanding\",\r\nlaa.fee_charges_overdue_derived as \"Fees Overdue\",\r\n\r\nl.penalty_charges_repaid_derived as \"Penalties Repaid\",\r\nl.penalty_charges_outstanding_derived as \"Penalties Outstanding\",\r\nlaa.penalty_charges_overdue_derived as \"Penalties Overdue\"\r\n\r\nfrom \r\n(select l.id as loanId, l.number_of_repayments, min(r.installment), \r\nounder.id, ounder.hierarchy, ounder.`name` as branch, \r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", c.account_no as \"Client Account No\",\r\nc.display_name as \"Client\", l.account_no as \"Loan Account No\", pl.`name` as \"Product\", \r\nf.`name` as Fund, l.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \"Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed\", date(l.expected_maturedon_date) as \"Expected Matured On\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_repayment_schedule r on r.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand r.completed_derived is false\r\nand r.duedate >= curdate()\r\ngroup by l.id\r\nhaving l.number_of_repayments = min(r.installment)) lastInstallment\r\njoin m_loan l on l.id = lastInstallment.loanId\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\norder by lastInstallment.hierarchy, lastInstallment.Currency, lastInstallment.`Client Account No`, lastInstallment.`Loan Account No`','Individual Client \n\nReport',1,1),(58,'Active Loans in last installment Summary','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(mo.`hierarchy`) - LENGTH(REPLACE(mo.`hierarchy`, \'.\', \'\')) - 1))), mo.`name`) as \"Office/Branch\", x.currency as Currency,\r\n x.client_count as \"No. of Clients\", x.active_loan_count as \"No. Active Loans\", x. arrears_loan_count as \"No. of Loans in Arrears\",\r\nx.principal as \"Total Loans Disbursed\", x.principal_repaid as \"Principal Repaid\", x.principal_outstanding as \"Principal Outstanding\", x.principal_overdue as \"Principal Overdue\",\r\nx.interest as \"Total Interest\", x.interest_repaid as \"Interest Repaid\", x.interest_outstanding as \"Interest Outstanding\", x.interest_overdue as \"Interest Overdue\",\r\nx.fees as \"Total Fees\", x.fees_repaid as \"Fees Repaid\", x.fees_outstanding as \"Fees Outstanding\", x.fees_overdue as \"Fees Overdue\",\r\nx.penalties as \"Total Penalties\", x.penalties_repaid as \"Penalties Repaid\", x.penalties_outstanding as \"Penalties Outstanding\", x.penalties_overdue as \"Penalties Overdue\",\r\n\r\n (case\r\n when ${parType} = 1 then\r\n cast(round((x.principal_overdue * 100) / x.principal_outstanding, 2) as char)\r\n when ${parType} = 2 then\r\n cast(round(((x.principal_overdue + x.interest_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding), 2) as char)\r\n when ${parType} = 3 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding), 2) as char)\r\n when ${parType} = 4 then\r\n cast(round(((x.principal_overdue + x.interest_overdue + x.fees_overdue + x.penalties_overdue) * 100) / (x.principal_outstanding + x.interest_outstanding + x.fees_outstanding + x.penalties_overdue), 2) as char)\r\n else \"invalid PAR Type\"\r\n end) as \"Portfolio at Risk %\"\r\n from m_office mo\r\njoin \r\n(select lastInstallment.branchId as branchId,\r\nlastInstallment.Currency,\r\ncount(distinct(lastInstallment.clientId)) as client_count, \r\ncount(distinct(lastInstallment.loanId)) as active_loan_count,\r\ncount(distinct(laa.loan_id) ) as arrears_loan_count,\r\n\r\nsum(l.principal_disbursed_derived) as principal,\r\nsum(l.principal_repaid_derived) as principal_repaid,\r\nsum(l.principal_outstanding_derived) as principal_outstanding,\r\nsum(ifnull(laa.principal_overdue_derived,0)) as principal_overdue,\r\n\r\nsum(l.interest_charged_derived) as interest,\r\nsum(l.interest_repaid_derived) as interest_repaid,\r\nsum(l.interest_outstanding_derived) as interest_outstanding,\r\nsum(ifnull(laa.interest_overdue_derived,0)) as interest_overdue,\r\n\r\nsum(l.fee_charges_charged_derived) as fees,\r\nsum(l.fee_charges_repaid_derived) as fees_repaid,\r\nsum(l.fee_charges_outstanding_derived) as fees_outstanding,\r\nsum(ifnull(laa.fee_charges_overdue_derived,0)) as fees_overdue,\r\n\r\nsum(l.penalty_charges_charged_derived) as penalties,\r\nsum(l.penalty_charges_repaid_derived) as penalties_repaid,\r\nsum(l.penalty_charges_outstanding_derived) as penalties_outstanding,\r\nsum(ifnull(laa.penalty_charges_overdue_derived,0)) as penalties_overdue\r\n\r\nfrom \r\n(select l.id as loanId, l.number_of_repayments, min(r.installment), \r\nounder.id as branchId, ounder.hierarchy, ounder.`name` as branch, \r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nlo.display_name as \"Loan Officer\", c.id as clientId, c.account_no as \"Client Account No\",\r\nc.display_name as \"Client\", l.account_no as \"Loan Account No\", pl.`name` as \"Product\", \r\nf.`name` as Fund, l.principal_amount as \"Loan Amount\", \r\nl.annual_nominal_interest_rate as \"Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed\", date(l.expected_maturedon_date) as \"Expected Matured On\"\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_repayment_schedule r on r.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.loan_status_id = 300\r\nand r.completed_derived is false\r\nand r.duedate >= curdate()\r\ngroup by l.id\r\nhaving l.number_of_repayments = min(r.installment)) lastInstallment\r\njoin m_loan l on l.id = lastInstallment.loanId\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\ngroup by lastInstallment.branchId) x on x.branchId = mo.id\r\norder by mo.hierarchy, x.Currency','Individual Client \n\nReport',1,1),(59,'Active Loans by Disbursal Period','Table',NULL,'Loan','select concat(repeat(\"..\", \r\n ((LENGTH(ounder.`hierarchy`) - LENGTH(REPLACE(ounder.`hierarchy`, \'.\', \'\')) - 1))), ounder.`name`) as \"Office/Branch\",\r\nifnull(cur.display_symbol, l.currency_code) as Currency,\r\nc.account_no as \"Client Account No\", c.display_name as \"Client\", l.account_no as \"Loan Account No\", pl.`name` as \"Product\", \r\nf.`name` as Fund, \r\nl.principal_amount as \"Loan Principal Amount\", \r\nl.annual_nominal_interest_rate as \" Annual Nominal Interest Rate\", \r\ndate(l.disbursedon_date) as \"Disbursed Date\", \r\n\r\nl.total_expected_repayment_derived as \"Total Loan (P+I+F+Pen)\",\r\nl.total_repayment_derived as \"Total Repaid (P+I+F+Pen)\",\r\nlo.display_name as \"Loan Officer\"\r\n\r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\nand ounder.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\r\njoin m_client c on c.office_id = ounder.id\r\njoin m_loan l on l.client_id = c.id\r\njoin m_product_loan pl on pl.id = l.product_id\r\nleft join m_staff lo on lo.id = l.loan_officer_id\r\nleft join m_currency cur on cur.code = l.currency_code\r\nleft join m_fund f on f.id = l.fund_id\r\nleft join m_loan_arrears_aging laa on laa.loan_id = l.id\r\nwhere o.id = ${officeId}\r\nand (l.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\nand (l.product_id = \"${loanProductId}\" or \"-1\" = \"${loanProductId}\")\r\nand (ifnull(l.loan_officer_id, -10) = \"${loanOfficerId}\" or \"-1\" = \"${loanOfficerId}\")\r\nand (ifnull(l.fund_id, -10) = ${fundId} or -1 = ${fundId})\r\nand (ifnull(l.loanpurpose_cv_id, -10) = ${loanPurposeId} or -1 = ${loanPurposeId})\r\nand l.disbursedon_date between \'${startDate}\' and \'${endDate}\'\r\nand l.loan_status_id = 300\r\ngroup by l.id\r\norder by ounder.hierarchy, l.currency_code, c.account_no, l.account_no','Individual Client \n\nReport',1,1),(61,'Aging Summary (Arrears in Months)','Table',NULL,'Loan','SELECT \r\n IFNULL(periods.currencyName, periods.currency) as currency, \r\n periods.period_no \'Days In Arrears\', \r\n IFNULL(ars.loanId, 0) \'No Of Loans\', \r\n IFNULL(ars.principal,0.0) \'Original Principal\', \r\n IFNULL(ars.interest,0.0) \'Original Interest\', \r\n IFNULL(ars.prinPaid,0.0) \'Principal Paid\', \r\n IFNULL(ars.intPaid,0.0) \'Interest Paid\', \r\n IFNULL(ars.prinOverdue,0.0) \'Principal Overdue\', \r\n IFNULL(ars.intOverdue,0.0)\'Interest Overdue\'\r\nFROM \r\n /* full table of aging periods/currencies used combo to ensure each line represented */\r\n (SELECT curs.code as currency, curs.name as currencyName, pers.* from\r\n (SELECT \'On Schedule\' period_no,1 pid UNION\r\n SELECT \'0 - 30\',2 UNION\r\n SELECT \'30 - 60\',3 UNION\r\n SELECT \'60 - 90\',4 UNION\r\n SELECT \'90 - 180\',5 UNION\r\n SELECT \'180 - 360\',6 UNION\r\n SELECT \'> 360\',7 ) pers,\r\n (SELECT distinctrow moc.code, moc.name\r\n FROM m_office mo2\r\n INNER JOIN m_office ounder2 ON ounder2.hierarchy \r\n LIKE CONCAT(mo2.hierarchy, \'%\')\r\nAND ounder2.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc2 ON mc2.office_id=ounder2.id\r\n INNER JOIN m_loan ml2 ON ml2.client_id = mc2.id\r\n INNER JOIN m_organisation_currency moc ON moc.code = ml2.currency_code\r\n WHERE ml2.loan_status_id=300 /* active */\r\n AND mo2.id=${officeId}\r\nAND (ml2.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")) curs) periods\r\n\r\n\r\nLEFT JOIN /* table of aging periods per currency with gaps if no applicable loans */\r\n(SELECT \r\n z.currency, z.arrPeriod, \r\n COUNT(z.loanId) as loanId, SUM(z.principal) as principal, SUM(z.interest) as interest, \r\n SUM(z.prinPaid) as prinPaid, SUM(z.intPaid) as intPaid, \r\n SUM(z.prinOverdue) as prinOverdue, SUM(z.intOverdue) as intOverdue\r\nFROM\r\n /*derived table just used to get arrPeriod value (was much slower to\r\n duplicate calc of minOverdueDate in inner query)\r\nmight not be now with derived fields but didn’t check */\r\n (SELECT x.loanId, x.currency, x.principal, x.interest, x.prinPaid, x.intPaid, x.prinOverdue, x.intOverdue,\r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<1, \'On Schedule\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<31, \'0 - 30\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<61, \'30 - 60\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<91, \'60 - 90\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<181, \'90 - 180\', \r\n IF(DATEDIFF(CURDATE(), minOverdueDate)<361, \'180 - 360\', \r\n \'> 360\')))))) AS arrPeriod\r\n\r\n FROM /* get the individual loan details */\r\n (SELECT ml.id AS loanId, ml.currency_code as currency,\r\n ml.principal_disbursed_derived as principal, \r\n ml.interest_charged_derived as interest, \r\n ml.principal_repaid_derived as prinPaid, \r\n ml.interest_repaid_derived intPaid,\r\n\r\n laa.principal_overdue_derived as prinOverdue,\r\n laa.interest_overdue_derived as intOverdue,\r\n\r\n IFNULL(laa.overdue_since_date_derived, curdate()) as minOverdueDate\r\n \r\n FROM m_office mo\r\n INNER JOIN m_office ounder ON ounder.hierarchy \r\n LIKE CONCAT(mo.hierarchy, \'%\')\r\nAND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n INNER JOIN m_client mc ON mc.office_id=ounder.id\r\n INNER JOIN m_loan ml ON ml.client_id = mc.id\r\n LEFT JOIN m_loan_arrears_aging laa on laa.loan_id = ml.id\r\n WHERE ml.loan_status_id=300 /* active */\r\n AND mo.id=${officeId}\r\n AND (ml.currency_code = \"${currencyId}\" or \"-1\" = \"${currencyId}\")\r\n GROUP BY ml.id) x\r\n ) z \r\nGROUP BY z.currency, z.arrPeriod ) ars ON ars.arrPeriod=periods.period_no and ars.currency = periods.currency\r\nORDER BY periods.currency, periods.pid','Loan amount in arrears by branch',1,1),(91,'Loan Account Schedule','Pentaho',NULL,'Loan',NULL,NULL,1,0),(92,'Branch Expected Cash Flow','Pentaho',NULL,'Loan',NULL,NULL,1,1),(93,'Expected Payments By Date - Basic','Table',NULL,'Loan','SELECT \r\n ounder.name \'Office\', \r\n IFNULL(ms.display_name,\'-\') \'Loan Officer\',\r\n mc.account_no \'Client Account Number\',\r\n mc.display_name \'Name\',\r\n mp.name \'Product\',\r\n ml.account_no \'Loan Account Number\',\r\n mr.duedate \'Due Date\',\r\n mr.installment \'Installment\',\r\n cu.display_symbol \'Currency\',\r\n mr.principal_amount- IFNULL(mr.principal_completed_derived,0) \'Principal Due\',\r\n mr.interest_amount- IFNULL(IFNULL(mr.interest_completed_derived,mr.interest_waived_derived),0) \'Interest Due\', \r\n IFNULL(mr.fee_charges_amount,0)- IFNULL(IFNULL(mr.fee_charges_completed_derived,mr.fee_charges_waived_derived),0) \'Fees Due\', \r\n IFNULL(mr.penalty_charges_amount,0)- IFNULL(IFNULL(mr.penalty_charges_completed_derived,mr.penalty_charges_waived_derived),0) \'Penalty Due\',\r\n (mr.principal_amount- IFNULL(mr.principal_completed_derived,0)) +\r\n (mr.interest_amount- IFNULL(IFNULL(mr.interest_completed_derived,mr.interest_waived_derived),0)) + \r\n (IFNULL(mr.fee_charges_amount,0)- IFNULL(IFNULL(mr.fee_charges_completed_derived,mr.fee_charges_waived_derived),0)) + \r\n (IFNULL(mr.penalty_charges_amount,0)- IFNULL(IFNULL(mr.penalty_charges_completed_derived,mr.penalty_charges_waived_derived),0)) \'Total Due\', \r\n mlaa.total_overdue_derived \'Total Overdue\'\r\n \r\n FROM m_office mo\r\n JOIN m_office ounder ON ounder.hierarchy LIKE CONCAT(mo.hierarchy, \'%\')\r\n \r\n AND ounder.hierarchy like CONCAT(\'${currentUserHierarchy}\', \'%\')\r\n \r\n LEFT JOIN m_client mc ON mc.office_id=ounder.id\r\n LEFT JOIN m_loan ml ON ml.client_id=mc.id AND ml.loan_status_id=300\r\n LEFT JOIN m_loan_arrears_aging mlaa ON mlaa.loan_id=ml.id\r\n LEFT JOIN m_loan_repayment_schedule mr ON mr.loan_id=ml.id AND mr.completed_derived=0\r\n LEFT JOIN m_product_loan mp ON mp.id=ml.product_id\r\n LEFT JOIN m_staff ms ON ms.id=ml.loan_officer_id\r\n LEFT JOIN m_currency cu ON cu.code=ml.currency_code\r\n WHERE mo.id=${officeId}\r\n AND (IFNULL(ml.loan_officer_id, -10) = \"${loanOfficerId}\" OR \"-1\" = \"${loanOfficerId}\")\r\n AND mr.duedate BETWEEN \'${startDate}\' AND \'${endDate}\'\r\n ORDER BY ounder.id,mr.duedate,ml.account_no','Test',1,1),(94,'Expected Payments By Date - Formatted','Pentaho',NULL,'Loan',NULL,NULL,1,1); INSERT INTO `stretchy_parameter` VALUES (1,'startDateSelect','startDate','startDate','date','date','today',NULL,NULL,NULL,NULL,NULL),(2,'endDateSelect','endDate','endDate','date','date','today',NULL,NULL,NULL,NULL,NULL),(3,'obligDateTypeSelect','obligDateType','obligDateType','select','number','0',NULL,NULL,NULL,'select * from\r\n(select 1 as id, \"Closed\" as `name` union all\r\nselect 2, \"Disbursal\" ) x\r\norder by x.`id`',NULL),(5,'OfficeIdSelectOne','officeId','Office','select','number','0',NULL,'Y',NULL,'select id, \r\nconcat(substring(\"........................................\", 1, \r\n \n\n((LENGTH(`hierarchy`) - LENGTH(REPLACE(`hierarchy`, \'.\', \'\')) - 1) * 4)), \r\n `name`) as tc\r\nfrom m_office\r\nwhere hierarchy like concat\n\n(\'${currentUserHierarchy}\', \'%\')\r\norder by hierarchy',NULL),(6,'loanOfficerIdSelectAll','loanOfficerId','Loan Officer','select','number','0',NULL,NULL,'Y','(select lo.id, lo.display_name as `Name` \r\nfrom m_office o \r\njoin m_office ounder on ounder.hierarchy like concat(o.hierarchy, \'%\')\r\njoin m_staff lo on lo.office_id = ounder.id\r\nwhere lo.is_loan_officer = true\r\nand o.id = ${officeId})\r\nunion all\r\n(select -10, \'-\')\r\norder by 2',5),(10,'currencyIdSelectAll','currencyId','Currency','select','number','0',NULL,NULL,'Y','select `code`, `name`\r\nfrom m_organisation_currency\r\norder by `code`',NULL),(20,'fundIdSelectAll','fundId','Fund','select','number','0',NULL,NULL,'Y','(select id, `name`\r\nfrom m_fund)\r\nunion all\r\n(select -10, \'-\')\r\norder by 2',NULL),(25,'loanProductIdSelectAll','loanProductId','Product','select','number','0',NULL,NULL,'Y','select p.id, p.`name`\r\nfrom m_product_loan p\r\nwhere p.currency_code = \'${currencyId}\'\r\norder by 2',10),(26,'loanPurposeIdSelectAll','loanPurposeId','Loan Purpose','select','number','0',NULL,NULL,'Y','select -10 as id, \'-\' as code_value\r\nunion all\r\nselect * from (select v.id, v.code_value\r\nfrom m_code c\r\njoin m_code_value v on v.code_id = c.id\r\nwhere c.code_name = \"loanPurpose\"\r\norder by v.order_position) x',NULL),(100,'parTypeSelect','parType','parType','select','number','0',NULL,NULL,NULL,'select * from\r\n(select 1 as id, \"Principal Only\" as `name` union all\r\nselect 2, \"Principal + Interest\" union all\r\nselect 3, \"Principal + Interest + Fees\" union all\r\nselect 4, \"Principal + Interest + Fees + Penalties\") x\r\norder by x.`id`',NULL),(1001,'FullReportList',NULL,'n/a','n/a','n/a','n/a','Y',NULL,NULL,'select r.report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,\r\n \n\nrp.parameter_id, rp.report_parameter_name, p.parameter_name\r\n from stretchy_report r\r\n left join stretchy_report_parameter rp on rp.report_id = r.report_id\r\n \n\nleft join stretchy_parameter p on p.parameter_id = rp.parameter_id\r\n where r.use_report is true\r\n and exists\r\n (\r\n select \'f\'\r\n from m_appuser_role ur \n\n\r\n join m_role r on r.id = ur.role_id\r\n join m_role_permission rp on rp.role_id = r.id\r\n join m_permission p on p.id = rp.permission_id\r\n where \n\nur.appuser_id = ${currentUserId}\r\n and (p.code in (\'ALL_FUNCTIONS_READ\', \'ALL_FUNCTIONS\') or p.code = concat(\"READ_\", r.report_name))\r\n )\r\n order by \n\nr.report_category, r.report_name, rp.parameter_id',NULL),(1002,'FullParameterList',NULL,'n/a','n/a','n/a','n/a','Y',NULL,NULL,'select sp.parameter_name, sp.parameter_variable, sp.parameter_label, sp.parameter_displayType, \r\nsp.parameter_FormatType, sp.parameter_default, sp.selectOne, sp.selectAll, spp.parameter_name as parentParameterName\r\nfrom stretchy_parameter sp\r\nleft join stretchy_parameter spp on spp.parameter_id = sp.parent_parameter_id\r\nwhere sp.special is null\r\nand exists \r\n (select \'f\' \r\n from stretchy_report sr\r\n join stretchy_report_parameter srp on srp.report_id = sr.report_id\r\n where sr.report_name in(${reportListing})\r\n and srp.parameter_id = sp.parameter_id\r\n )\r\norder by sp.parameter_id',NULL),(1003,'reportCategoryList',NULL,'n/a','n/a','n/a','n/a','Y',NULL,NULL,'select r.report_id, r.report_name, r.report_type, r.report_subtype, \n\nr.report_category,\r\n rp.parameter_id, rp.report_parameter_name, p.parameter_name\r\n from stretchy_report r\r\n left join stretchy_report_parameter rp on \n\nrp.report_id = r.report_id\r\n left join stretchy_parameter p on p.parameter_id = rp.parameter_id\r\n where r.report_category = \'${reportCategory}\'\r\n and \n\nr.use_report is true\r\n and exists\r\n (\r\n select \'f\'\r\n from m_appuser_role ur \r\n join m_role r on r.id = ur.role_id\r\n join m_role_permission rp on \n\nrp.role_id = r.id\r\n join m_permission p on p.id = rp.permission_id\r\n where ur.appuser_id = ${currentUserId}\r\n and (p.code in (\'ALL_FUNCTIONS_READ\', \n\n\'ALL_FUNCTIONS\') or p.code = concat(\"READ_\", r.report_name))\r\n )\r\n order by r.report_category, r.report_name, rp.parameter_id',NULL); -INSERT INTO `stretchy_report_parameter` VALUES (1,5,NULL),(2,5,NULL),(2,6,NULL),(2,10,NULL),(2,20,NULL),(2,25,NULL),(2,26,NULL),(5,5,NULL),(5,6,NULL),(5,10,NULL),(5,20,NULL),(5,25,NULL),(5,26,NULL),(6,5,NULL),(6,6,NULL),(6,10,NULL),(6,20,NULL),(6,25,NULL),(6,26,NULL),(7,5,NULL),(7,6,NULL),(7,10,NULL),(7,20,NULL),(7,25,NULL),(7,26,NULL),(8,5,NULL),(8,6,NULL),(8,10,NULL),(8,25,NULL),(8,26,NULL),(11,5,NULL),(11,6,NULL),(11,10,NULL),(11,20,NULL),(11,25,NULL),(11,26,NULL),(11,100,NULL),(12,5,NULL),(12,6,NULL),(12,10,NULL),(12,20,NULL),(12,25,NULL),(12,26,NULL),(13,1,NULL),(13,2,NULL),(13,3,NULL),(13,5,NULL),(13,6,NULL),(13,10,NULL),(13,20,NULL),(13,25,NULL),(13,26,NULL),(14,1,NULL),(14,2,NULL),(14,3,NULL),(14,5,NULL),(14,6,NULL),(14,10,NULL),(14,20,NULL),(14,25,NULL),(14,26,NULL),(15,5,NULL),(15,6,NULL),(15,10,NULL),(15,20,NULL),(15,25,NULL),(15,26,NULL),(15,100,NULL),(16,5,NULL),(16,6,NULL),(16,10,NULL),(16,20,NULL),(16,25,NULL),(16,26,NULL),(16,100,NULL),(20,1,NULL),(20,2,NULL),(20,10,NULL),(20,20,NULL),(21,1,NULL),(21,2,NULL),(21,5,NULL),(21,10,NULL),(21,20,NULL),(48,5,'branch'),(48,2,'date'),(49,5,'branch'),(49,1,'fromDate'),(49,2,'toDate'),(50,5,'branch'),(50,1,'fromDate'),(50,2,'toDate'),(51,1,NULL),(51,2,NULL),(51,5,NULL),(51,10,NULL),(51,25,NULL),(52,5,NULL),(53,5,NULL),(53,10,NULL),(54,1,NULL),(54,2,NULL),(54,5,NULL),(54,10,NULL),(54,25,NULL),(55,5,NULL),(55,6,NULL),(55,10,NULL),(55,20,NULL),(55,25,NULL),(55,26,NULL),(56,5,NULL),(56,6,NULL),(56,10,NULL),(56,20,NULL),(56,25,NULL),(56,26,NULL),(56,100,NULL),(57,5,NULL),(57,6,NULL),(57,10,NULL),(57,20,NULL),(57,25,NULL),(57,26,NULL),(58,5,NULL),(58,6,NULL),(58,10,NULL),(58,20,NULL),(58,25,NULL),(58,26,NULL),(58,100,NULL),(59,1,NULL),(59,2,NULL),(59,5,NULL),(59,6,NULL),(59,10,NULL),(59,20,NULL),(59,25,NULL),(59,26,NULL),(61,5,NULL),(61,10,NULL),(92,1,'fromDate'),(92,5,'selectOffice'),(92,2,'toDate'),(93,1,NULL),(93,2,NULL),(93,5,NULL),(93,6,NULL); +INSERT INTO `stretchy_report_parameter` VALUES (1,5,NULL),(2,5,NULL),(2,6,NULL),(2,10,NULL),(2,20,NULL),(2,25,NULL),(2,26,NULL),(5,5,NULL),(5,6,NULL),(5,10,NULL),(5,20,NULL),(5,25,NULL),(5,26,NULL),(6,5,NULL),(6,6,NULL),(6,10,NULL),(6,20,NULL),(6,25,NULL),(6,26,NULL),(7,5,NULL),(7,6,NULL),(7,10,NULL),(7,20,NULL),(7,25,NULL),(7,26,NULL),(8,5,NULL),(8,6,NULL),(8,10,NULL),(8,25,NULL),(8,26,NULL),(11,5,NULL),(11,6,NULL),(11,10,NULL),(11,20,NULL),(11,25,NULL),(11,26,NULL),(11,100,NULL),(12,5,NULL),(12,6,NULL),(12,10,NULL),(12,20,NULL),(12,25,NULL),(12,26,NULL),(13,1,NULL),(13,2,NULL),(13,3,NULL),(13,5,NULL),(13,6,NULL),(13,10,NULL),(13,20,NULL),(13,25,NULL),(13,26,NULL),(14,1,NULL),(14,2,NULL),(14,3,NULL),(14,5,NULL),(14,6,NULL),(14,10,NULL),(14,20,NULL),(14,25,NULL),(14,26,NULL),(15,5,NULL),(15,6,NULL),(15,10,NULL),(15,20,NULL),(15,25,NULL),(15,26,NULL),(15,100,NULL),(16,5,NULL),(16,6,NULL),(16,10,NULL),(16,20,NULL),(16,25,NULL),(16,26,NULL),(16,100,NULL),(20,1,NULL),(20,2,NULL),(20,10,NULL),(20,20,NULL),(21,1,NULL),(21,2,NULL),(21,5,NULL),(21,10,NULL),(21,20,NULL),(48,5,'branch'),(48,2,'date'),(49,5,'branch'),(49,1,'fromDate'),(49,2,'toDate'),(50,5,'branch'),(50,1,'fromDate'),(50,2,'toDate'),(51,1,NULL),(51,2,NULL),(51,5,NULL),(51,10,NULL),(51,25,NULL),(52,5,NULL),(53,5,NULL),(53,10,NULL),(54,1,NULL),(54,2,NULL),(54,5,NULL),(54,10,NULL),(54,25,NULL),(55,5,NULL),(55,6,NULL),(55,10,NULL),(55,20,NULL),(55,25,NULL),(55,26,NULL),(56,5,NULL),(56,6,NULL),(56,10,NULL),(56,20,NULL),(56,25,NULL),(56,26,NULL),(56,100,NULL),(57,5,NULL),(57,6,NULL),(57,10,NULL),(57,20,NULL),(57,25,NULL),(57,26,NULL),(58,5,NULL),(58,6,NULL),(58,10,NULL),(58,20,NULL),(58,25,NULL),(58,26,NULL),(58,100,NULL),(59,1,NULL),(59,2,NULL),(59,5,NULL),(59,6,NULL),(59,10,NULL),(59,20,NULL),(59,25,NULL),(59,26,NULL),(61,5,NULL),(61,10,NULL),(92,1,'fromDate'),(92,5,'selectOffice'),(92,2,'toDate'),(93,1,NULL),(93,2,NULL),(93,5,NULL),(93,6,NULL),(94,2,'endDate'),(94,6,'loanOfficerId'),(94,5,'officeId'),(94,1,'startDate'); insert into m_permission(grouping, `code`, entity_name, action_name, can_maker_checker) select 'report', concat('READ_', r.report_name), r.report_name, 'READ', false diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadReportingServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadReportingServiceImpl.java index 8c19aa614..130c70a12 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadReportingServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadReportingServiceImpl.java @@ -314,7 +314,6 @@ public class ReadReportingServiceImpl implements ReadReportingService { try { - logger.info("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); ReportParameterValues rptParamValues = report.getParameterValues(); ReportParameterDefinition paramsDefinition = report.getParameterDefinition(); @@ -346,17 +345,17 @@ public class ReadReportingServiceImpl implements ReadReportingService { rptParamValues.put(paramName, pValue); } - // tenant database name and current user's office hierarchy - // passed as parameters to allow multitenant penaho reporting - // and - // data scoping - String tenantdb = dataSource.getConnection().getCatalog(); - String userhierarchy = currentUser.getOffice().getHierarchy(); - logger.info("db name:" + tenantdb + " userhierarchy:" + userhierarchy); - rptParamValues.put("tenantdb", tenantdb); - rptParamValues.put("userhierarchy", userhierarchy); } + // tenant database name and current user's office hierarchy + // passed as parameters to allow multitenant penaho reporting + // and + // data scoping + String tenantdb = dataSource.getConnection().getCatalog(); + String userhierarchy = currentUser.getOffice().getHierarchy(); + logger.info("db name:" + tenantdb + " userhierarchy:" + userhierarchy); + rptParamValues.put("tenantdb", tenantdb); + rptParamValues.put("userhierarchy", userhierarchy); } catch (Exception e) { logger.error("error.msg.reporting.error:" + e.getMessage()); throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage()); diff --git a/mifosng-provider/src/main/pentahoReports/Branch Expected Cash Flow.prpt b/mifosng-provider/src/main/pentahoReports/Branch Expected Cash Flow.prpt index 93a4afd3843c7e0bb98704460d990382514377dd..ce1596ff977aac6c9b019e0c3f298379f1abb938 100644 GIT binary patch delta 3688 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≷muM3cJseVFB0%Mec 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 QffVurp&~F%d9{Oh08St6Gynhq literal 0 HcmV?d00001 diff --git a/mifosng-provider/src/main/pentahoReports/expectedPaymentsByDate.properties b/mifosng-provider/src/main/pentahoReports/expectedPaymentsByDate.properties new file mode 100644 index 000000000..b28c368b1 --- /dev/null +++ b/mifosng-provider/src/main/pentahoReports/expectedPaymentsByDate.properties @@ -0,0 +1,23 @@ +ExpectedPaymentsByDate=Expected Payments By Date +From=From : +To=To: +Office=Office : +DueDate=Due Date : +ClientName=Client Name +LoanAccountNo=Loan Account No: +Product=Product +Installment=Installment +Date=Date +Principal=Principal +LoanOfficer=Loan Officer +Interest=Interest +FeesDue=Fees Due +PenaltyDue=Penalty Due +TotalDue=Total Due +TotalOverDue=Total Over Due +Total=Total : +PrintedBy\:=Printed by: +On\:=On: +MFIName\:=MFI Name: +Page=Page +VersionAt=Version 1.3.1 \ No newline at end of file