wip mifosx-195 refactor list reports api for maintenance function use and change api-docs

This commit is contained in:
John Woodlock
2013-04-13 19:33:43 +01:00
parent 9cc6abd6c4
commit e777491d76
7 changed files with 836 additions and 1145 deletions
+66 -752
View File
@@ -10254,19 +10254,6 @@ No Request Body:
<div class="method-section"> <div class="method-section">
<div class="method-description"> <div class="method-description">
<h3>Reports</h3> <h3>Reports</h3>
<p>The reports resource allows you to run and receive output
from pre-defined Mifos X reports. The default output is a JSON
formatted "Generic Resultset". The Generic Resultset contains
Column Heading as well as Data information. However, you can
export to CSV format by simply adding "&exportCSV=true" to the end
of your URL.</p>
<p>If Pentaho reports have been pre-defined, they can also be
run through this resource. Pentaho reports can return HTML, PDF or
CSV formats.</p>
<p>The Mifos X Individual Lending client application uses a
JQuery plugin called stretchyreporting which, itself, uses this
reports resource to provide a pretty flexible reporting User
Interface (UI).</p>
</div> </div>
</div> </div>
@@ -10276,753 +10263,67 @@ No Request Body:
<div class="method-section"> <div class="method-section">
<div class="method-description"> <div class="method-description">
<h4>List Reports</h4> <h4>List Reports</h4>
<p>Lists all reports and their parameters. If a report has more <p>Lists all reports and their parameters. </p>
than one parameter it will be listed the same number of times as
it has parameters.</p>
<h5>Arguments</h5> <p>Example Request:</p>
<dl class="argument-list">
<dt>exportCSV</dt>
<dd>
optional, <span>The only valid value is 'true'. If any
other value is provided the argument will be ignored</span>
</dd>
<dd>Output will be delivered as a CSV file instead of JSON.</dd>
</dl>
<p>Example Requests:</p>
<div class=apiClick>reports</div> <div class=apiClick>reports</div>
<br>
<br>
<div class=apiClick>reports?exportCSV=true</div>
</div> </div>
<div class="method-example"> <div class="method-example">
<code class="method-declaration"> <code class="method-declaration">
GET https://DomainName/api/v1/reports GET https://DomainName/api/v1/reports
</code> </code>
<code class="method-response"> <code class="method-response">
{ [
"columnHeaders": [ {
{ "reportId": 1,
"columnName": "report_id", "reportName": "Client Listing",
"columnType": "INT", "reportType": "Table",
"isColumnNullable": false, "reportCategory": "Client",
"isColumnPrimaryKey": false, "coreReport": true,
"columnValues": [] "useReport": true,
}, "reportParameters": [
{ {
"columnName": "report_name", "reportParameterId": 5,
"columnType": "VARCHAR", "parameterName": "OfficeIdSelectOne"
"isColumnNullable": false, }
"isColumnPrimaryKey": false,
"columnValues": []
},
{
"columnName": "report_type",
"columnType": "VARCHAR",
"isColumnNullable": false,
"isColumnPrimaryKey": false,
"columnValues": []
},
{
"columnName": "report_subtype",
"columnType": "VARCHAR",
"isColumnNullable": false,
"isColumnPrimaryKey": false,
"columnValues": []
},
{
"columnName": "report_category",
"columnType": "VARCHAR",
"isColumnNullable": false,
"isColumnPrimaryKey": false,
"columnValues": []
},
{
"columnName": "parameter_id",
"columnType": "INT",
"isColumnNullable": false,
"isColumnPrimaryKey": false,
"columnValues": []
},
{
"columnName": "report_parameter_name",
"columnType": "VARCHAR",
"isColumnNullable": false,
"isColumnPrimaryKey": false,
"columnValues": []
},
{
"columnName": "parameter_name",
"columnType": "VARCHAR",
"isColumnNullable": false,
"isColumnPrimaryKey": false,
"columnValues": []
}
],
"data": [
{
"row": [
"10",
"Active Loans Portfolio Status",
"Table",
null,
"Loan",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"10",
"Active Loans Portfolio Status",
"Table",
null,
"Loan",
"6",
null,
"loanOfficerIdSelectAll"
]
},
{
"row": [
"10",
"Active Loans Portfolio Status",
"Table",
null,
"Loan",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"10",
"Active Loans Portfolio Status",
"Table",
null,
"Loan",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"10",
"Active Loans Portfolio Status",
"Table",
null,
"Loan",
"25",
null,
"loanProductIdSelectAll"
]
},
{
"row": [
"11",
"Active Loans Summary per Branch",
"Table",
null,
"Loan Portfolio",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"11",
"Active Loans Summary per Branch",
"Table",
null,
"Loan Portfolio",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"48",
"Balance Sheet",
"Pentaho",
null,
"Accounting",
"5",
"branch",
"OfficeIdSelectOne"
]
},
{
"row": [
"48",
"Balance Sheet",
"Pentaho",
null,
"Accounting",
"41",
"date",
"endDateSelect"
]
},
{
"row": [
"1",
"Client Listing",
"Table",
null,
"Client",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"2",
"Client Loans Listing",
"Table",
null,
"Client",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"2",
"Client Loans Listing",
"Table",
null,
"Client",
"6",
null,
"loanOfficerIdSelectAll"
]
},
{
"row": [
"2",
"Client Loans Listing",
"Table",
null,
"Client",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"2",
"Client Loans Listing",
"Table",
null,
"Client",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"2",
"Client Loans Listing",
"Table",
null,
"Client",
"25",
null,
"loanProductIdSelectAll"
]
},
{
"row": [
"20",
"Funds Disbursed Between Dates Summary",
"Table",
null,
"Fund",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"20",
"Funds Disbursed Between Dates Summary",
"Table",
null,
"Fund",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"20",
"Funds Disbursed Between Dates Summary",
"Table",
null,
"Fund",
"40",
null,
"startDateSelect"
]
},
{
"row": [
"20",
"Funds Disbursed Between Dates Summary",
"Table",
null,
"Fund",
"41",
null,
"endDateSelect"
]
},
{
"row": [
"21",
"Funds Disbursed Between Dates Summary by Office",
"Table",
null,
"Fund",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"21",
"Funds Disbursed Between Dates Summary by Office",
"Table",
null,
"Fund",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"21",
"Funds Disbursed Between Dates Summary by Office",
"Table",
null,
"Fund",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"21",
"Funds Disbursed Between Dates Summary by Office",
"Table",
null,
"Fund",
"40",
null,
"startDateSelect"
]
},
{
"row": [
"21",
"Funds Disbursed Between Dates Summary by Office",
"Table",
null,
"Fund",
"41",
null,
"endDateSelect"
]
},
{
"row": [
"49",
"Income Statement",
"Pentaho",
null,
"Accounting",
"5",
"branch",
"OfficeIdSelectOne"
]
},
{
"row": [
"49",
"Income Statement",
"Pentaho",
null,
"Accounting",
"40",
"fromDate",
"startDateSelect"
]
},
{
"row": [
"49",
"Income Statement",
"Pentaho",
null,
"Accounting",
"41",
"toDate",
"endDateSelect"
]
},
{
"row": [
"5",
"Loans Awaiting Disbursal",
"Table",
null,
"Loan Portfolio",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"5",
"Loans Awaiting Disbursal",
"Table",
null,
"Loan Portfolio",
"6",
null,
"loanOfficerIdSelectAll"
]
},
{
"row": [
"5",
"Loans Awaiting Disbursal",
"Table",
null,
"Loan Portfolio",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"5",
"Loans Awaiting Disbursal",
"Table",
null,
"Loan Portfolio",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"5",
"Loans Awaiting Disbursal",
"Table",
null,
"Loan Portfolio",
"25",
null,
"loanProductIdSelectAll"
]
},
{
"row": [
"6",
"Loans Awaiting Disbursal Summary",
"Table",
null,
"Loan Portfolio",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"6",
"Loans Awaiting Disbursal Summary",
"Table",
null,
"Loan Portfolio",
"6",
null,
"loanOfficerIdSelectAll"
]
},
{
"row": [
"6",
"Loans Awaiting Disbursal Summary",
"Table",
null,
"Loan Portfolio",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"6",
"Loans Awaiting Disbursal Summary",
"Table",
null,
"Loan Portfolio",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"6",
"Loans Awaiting Disbursal Summary",
"Table",
null,
"Loan Portfolio",
"25",
null,
"loanProductIdSelectAll"
]
},
{
"row": [
"7",
"Loans Awaiting Disbursal Summary by Month",
"Table",
null,
"Loan Portfolio",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"7",
"Loans Awaiting Disbursal Summary by Month",
"Table",
null,
"Loan Portfolio",
"6",
null,
"loanOfficerIdSelectAll"
]
},
{
"row": [
"7",
"Loans Awaiting Disbursal Summary by Month",
"Table",
null,
"Loan Portfolio",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"7",
"Loans Awaiting Disbursal Summary by Month",
"Table",
null,
"Loan Portfolio",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"7",
"Loans Awaiting Disbursal Summary by Month",
"Table",
null,
"Loan Portfolio",
"25",
null,
"loanProductIdSelectAll"
]
},
{
"row": [
"15",
"Portfolio at Risk",
"Table",
null,
"Loan Portfolio",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"15",
"Portfolio at Risk",
"Table",
null,
"Loan Portfolio",
"6",
null,
"loanOfficerIdSelectAll"
]
},
{
"row": [
"15",
"Portfolio at Risk",
"Table",
null,
"Loan Portfolio",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"15",
"Portfolio at Risk",
"Table",
null,
"Loan Portfolio",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"15",
"Portfolio at Risk",
"Table",
null,
"Loan Portfolio",
"25",
null,
"loanProductIdSelectAll"
]
},
{
"row": [
"16",
"Portfolio at Risk by Branch",
"Table",
null,
"Loan Portfolio",
"5",
null,
"OfficeIdSelectOne"
]
},
{
"row": [
"16",
"Portfolio at Risk by Branch",
"Table",
null,
"Loan Portfolio",
"6",
null,
"loanOfficerIdSelectAll"
]
},
{
"row": [
"16",
"Portfolio at Risk by Branch",
"Table",
null,
"Loan Portfolio",
"10",
null,
"currencyIdSelectAll"
]
},
{
"row": [
"16",
"Portfolio at Risk by Branch",
"Table",
null,
"Loan Portfolio",
"20",
null,
"fundIdSelectAll"
]
},
{
"row": [
"16",
"Portfolio at Risk by Branch",
"Table",
null,
"Loan Portfolio",
"25",
null,
"loanProductIdSelectAll"
]
},
{
"row": [
"50",
"Trial Balance",
"Pentaho",
null,
"Accounting",
"5",
"branch",
"OfficeIdSelectOne"
]
},
{
"row": [
"50",
"Trial Balance",
"Pentaho",
null,
"Accounting",
"40",
"fromDate",
"startDateSelect"
]
},
{
"row": [
"50",
"Trial Balance",
"Pentaho",
null,
"Accounting",
"41",
"toDate",
"endDateSelect"
]
}
] ]
} },
</code> {
"reportId": 2,
"reportName": "Client Loans Listing",
"reportType": "Table",
"reportCategory": "Client",
"coreReport": true,
"useReport": true,
"reportParameters": [
{
"reportParameterId": 5,
"parameterName": "OfficeIdSelectOne"
},
{
"reportParameterId": 6,
"parameterName": "loanOfficerIdSelectAll"
},
{
"reportParameterId": 10,
"parameterName": "currencyIdSelectAll"
},
{
"reportParameterId": 20,
"parameterName": "fundIdSelectAll"
},
{
"reportParameterId": 25,
"parameterName": "loanProductIdSelectAll"
},
{
"reportParameterId": 26,
"parameterName": "loanPurposeIdSelectAll"
}
]
},...
]
</code>
</div> </div>
</div> </div>
@@ -11030,7 +10331,20 @@ GET https://DomainName/api/v1/reports
<div class="method-section"> <div class="method-section">
<div class="method-description"> <div class="method-description">
<h4>Running a Report</h4> <h4>Running a Report</h4>
<p>Runs a report and returns the report output.</p> <p>This resource allows you to run and receive output from pre-defined Mifos X reports. </p>
<p>Reports can also be used to provide data for searching and workflow functionality.</p>
<p>
The default output is a JSON formatted "Generic Resultset". The Generic Resultset contains
Column Heading as well as Data information. However, you can
export to CSV format by simply adding "&exportCSV=true" to the end
of your URL.</p>
<p>If Pentaho reports have been pre-defined, they can also be
run through this resource. Pentaho reports can return HTML, PDF or
CSV formats.</p>
<p>The Mifos X reference application uses a
JQuery plugin called stretchyreporting which, itself, uses this
reports resource to provide a pretty flexible reporting User
Interface (UI).</p>
<h5>Arguments</h5> <h5>Arguments</h5>
<dl class="argument-list"> <dl class="argument-list">
<dt>R_'parameter names' ...</dt> <dt>R_'parameter names' ...</dt>
@@ -6,6 +6,7 @@
package org.mifosplatform.infrastructure.dataqueries.api; package org.mifosplatform.infrastructure.dataqueries.api;
import java.io.File; import java.io.File;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -26,6 +27,7 @@ import javax.ws.rs.core.UriInfo;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer; import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
import org.mifosplatform.infrastructure.dataqueries.data.ReportData;
import org.mifosplatform.infrastructure.dataqueries.service.GenericDataService; import org.mifosplatform.infrastructure.dataqueries.service.GenericDataService;
import org.mifosplatform.infrastructure.dataqueries.service.ReadReportingService; import org.mifosplatform.infrastructure.dataqueries.service.ReadReportingService;
import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException; import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException;
@@ -56,32 +58,16 @@ public class ReportsApiResource {
@GET @GET
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON, "application/x-msdownload" }) @Produces({ MediaType.APPLICATION_JSON })
public Response retrieveReportList(@Context final UriInfo uriInfo) { public Response retrieveReportList(@Context final UriInfo uriInfo) {
Map<String, String> extractedQueryParams = new HashMap<String, String>();
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
boolean exportCsv = ApiParameterHelper.exportCsv(uriInfo.getQueryParameters());
boolean exportPdf = ApiParameterHelper.exportPdf(uriInfo.getQueryParameters()); final Collection<ReportData> result = this.readExtraDataAndReportingService.retrieveReportList();
final String json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
if (exportPdf) { return Response.ok().entity(json).build();
String result = this.readExtraDataAndReportingService.retrieveReportPDF(".", ".", extractedQueryParams);
return Response.ok().entity(result).header("Content-Disposition", "attachment;filename=ReportList.pdf").build();
}
if (!exportCsv) {
GenericResultsetData result = this.readExtraDataAndReportingService.retrieveGenericResultset(".", ".", extractedQueryParams);
final String json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
return Response.ok().entity(json).build();
}
StreamingOutput result = this.readExtraDataAndReportingService.retrieveReportCSV(".", ".", extractedQueryParams);
return Response.ok().entity(result).header("Content-Disposition", "attachment;filename=ReportList.csv").build();
} }
@GET @GET
@@ -0,0 +1,47 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.dataqueries.data;
import java.util.Collection;
final public class ReportData {
@SuppressWarnings("unused")
private final Long reportId;
@SuppressWarnings("unused")
private final String reportName;
@SuppressWarnings("unused")
private final String reportType;
@SuppressWarnings("unused")
private final String reportSubType;
@SuppressWarnings("unused")
private final String reportCategory;
@SuppressWarnings("unused")
private final String reportSql;
@SuppressWarnings("unused")
private final Boolean coreReport;
@SuppressWarnings("unused")
private final Boolean useReport;
@SuppressWarnings("unused")
private final Collection<ReportParameterData> reportParameters;
public ReportData(final Long reportId, final String reportName,
final String reportType, final String reportSubType,
final String reportCategory, final String reportSql,
final Boolean coreReport, final Boolean useReport,
final Collection<ReportParameterData> reportParameters) {
this.reportId = reportId;
this.reportName = reportName;
this.reportType = reportType;
this.reportSubType = reportSubType;
this.reportCategory = reportCategory;
this.reportParameters = reportParameters;
this.reportSql = reportSql;
this.coreReport = coreReport;
this.useReport = useReport;
}
}
@@ -0,0 +1,24 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.dataqueries.data;
final public class ReportParameterData {
@SuppressWarnings("unused")
private final Long reportParameterId;
@SuppressWarnings("unused")
private final String reportParameterName;
@SuppressWarnings("unused")
private final String parameterName;
public ReportParameterData(final Long reportParameterId,
final String reportParameterName, final String parameterName) {
this.reportParameterId = reportParameterId;
this.reportParameterName = reportParameterName;
this.parameterName = parameterName;
}
}
@@ -0,0 +1,86 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.dataqueries.data;
final public class ReportParameterJoinData {
private final Long reportId;
private final String reportName;
private final String reportType;
private final String reportSubType;
private final String reportCategory;
private final String reportSql;
private final Boolean coreReport;
private final Boolean useReport;
private final Long reportParameterId;
private final String reportParameterName;
private final String parameterName;
public ReportParameterJoinData(final Long reportId,
final String reportName, final String reportType,
final String reportSubType, final String reportCategory,
final String reportSql, final Boolean coreReport,
final Boolean useReport, final Long reportParameterId,
final String reportParameterName, final String parameterName) {
this.reportId = reportId;
this.reportName = reportName;
this.reportType = reportType;
this.reportSubType = reportSubType;
this.reportCategory = reportCategory;
this.reportSql = reportSql;
this.coreReport = coreReport;
this.useReport = useReport;
this.reportParameterId = reportParameterId;
this.reportParameterName = reportParameterName;
this.parameterName = parameterName;
}
public Long getReportId() {
return reportId;
}
public String getReportName() {
return reportName;
}
public String getReportType() {
return reportType;
}
public String getReportSubType() {
return reportSubType;
}
public String getReportCategory() {
return reportCategory;
}
public String getReportSql() {
return reportSql;
}
public Boolean getCoreReport() {
return coreReport;
}
public Boolean getUseReport() {
return useReport;
}
public Long getReportParameterId() {
return reportParameterId;
}
public String getReportParameterName() {
return reportParameterName;
}
public String getParameterName() {
return parameterName;
}
}
@@ -5,22 +5,30 @@
*/ */
package org.mifosplatform.infrastructure.dataqueries.service; package org.mifosplatform.infrastructure.dataqueries.service;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
import org.mifosplatform.infrastructure.dataqueries.data.ReportData;
public interface ReadReportingService { public interface ReadReportingService {
StreamingOutput retrieveReportCSV(String name, String type, Map<String, String> extractedQueryParams); StreamingOutput retrieveReportCSV(String name, String type,
Map<String, String> extractedQueryParams);
GenericResultsetData retrieveGenericResultset(String name, String type, Map<String, String> extractedQueryParams); GenericResultsetData retrieveGenericResultset(String name, String type,
Map<String, String> extractedQueryParams);
Response processPentahoRequest(String reportName, String outputType, Map<String, String> queryParams); Response processPentahoRequest(String reportName, String outputType,
Map<String, String> queryParams);
String retrieveReportPDF(String name, String type, Map<String, String> extractedQueryParams); String retrieveReportPDF(String name, String type,
Map<String, String> extractedQueryParams);
String getReportType(String reportName); String getReportType(String reportName);
Collection<ReportData> retrieveReportList();
} }
@@ -13,6 +13,10 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.sql.Date; import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -22,10 +26,14 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.service.FileUtils; import org.mifosplatform.infrastructure.core.service.FileUtils;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource; import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
import org.mifosplatform.infrastructure.dataqueries.data.ReportData;
import org.mifosplatform.infrastructure.dataqueries.data.ReportParameterData;
import org.mifosplatform.infrastructure.dataqueries.data.ReportParameterJoinData;
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData; import org.mifosplatform.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
import org.mifosplatform.infrastructure.dataqueries.data.ResultsetRowData; import org.mifosplatform.infrastructure.dataqueries.data.ResultsetRowData;
import org.mifosplatform.infrastructure.dataqueries.exception.ReportNotFoundException; import org.mifosplatform.infrastructure.dataqueries.exception.ReportNotFoundException;
@@ -48,6 +56,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.rowset.SqlRowSet; import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -59,372 +68,589 @@ import com.lowagie.text.pdf.PdfWriter;
@Service @Service
public class ReadReportingServiceImpl implements ReadReportingService { public class ReadReportingServiceImpl implements ReadReportingService {
private final static Logger logger = LoggerFactory.getLogger(ReadReportingServiceImpl.class); private final static Logger logger = LoggerFactory
.getLogger(ReadReportingServiceImpl.class);
private final JdbcTemplate jdbcTemplate;
private final DataSource dataSource; private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context; private final DataSource dataSource;
private final GenericDataService genericDataService; private final PlatformSecurityContext context;
private boolean noPentaho = false; private final GenericDataService genericDataService;
private boolean noPentaho = false;
@Autowired
public ReadReportingServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource, @Autowired
final GenericDataService genericDataService) { public ReadReportingServiceImpl(final PlatformSecurityContext context,
// kick off pentaho reports server final TenantAwareRoutingDataSource dataSource,
ClassicEngineBoot.getInstance().start(); final GenericDataService genericDataService) {
noPentaho = false; // kick off pentaho reports server
ClassicEngineBoot.getInstance().start();
this.context = context; noPentaho = false;
this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(this.dataSource); this.context = context;
this.genericDataService = genericDataService; this.dataSource = dataSource;
} this.jdbcTemplate = new JdbcTemplate(this.dataSource);
this.genericDataService = genericDataService;
@Override }
public StreamingOutput retrieveReportCSV(final String name, final String type, final Map<String, String> queryParams) {
@Override
return new StreamingOutput() { public StreamingOutput retrieveReportCSV(final String name,
final String type, final Map<String, String> queryParams) {
@Override
public void write(final OutputStream out) { return new StreamingOutput() {
try {
@Override
GenericResultsetData result = retrieveGenericResultset(name, type, queryParams); public void write(final OutputStream out) {
StringBuffer sb = generateCsvFileBuffer(result); try {
InputStream in = new ByteArrayInputStream(sb.toString().getBytes("UTF-8")); GenericResultsetData result = retrieveGenericResultset(
name, type, queryParams);
byte[] outputByte = new byte[4096]; StringBuffer sb = generateCsvFileBuffer(result);
Integer readLen = in.read(outputByte, 0, 4096);
InputStream in = new ByteArrayInputStream(sb.toString()
while (readLen != -1) { .getBytes("UTF-8"));
out.write(outputByte, 0, readLen);
readLen = in.read(outputByte, 0, 4096); byte[] outputByte = new byte[4096];
} Integer readLen = in.read(outputByte, 0, 4096);
// in.close();
// out.flush(); while (readLen != -1) {
// out.close(); out.write(outputByte, 0, readLen);
} catch (Exception e) { readLen = in.read(outputByte, 0, 4096);
throw new PlatformDataIntegrityException("error.msg.exception.error", e.getMessage()); }
} // in.close();
} // out.flush();
}; // out.close();
} catch (Exception e) {
} throw new PlatformDataIntegrityException(
"error.msg.exception.error", e.getMessage());
private StringBuffer generateCsvFileBuffer(final GenericResultsetData result) { }
StringBuffer writer = new StringBuffer(); }
};
List<ResultsetColumnHeaderData> columnHeaders = result.getColumnHeaders();
logger.info("NO. of Columns: " + columnHeaders.size()); }
Integer chSize = columnHeaders.size();
for (int i = 0; i < chSize; i++) { private StringBuffer generateCsvFileBuffer(final GenericResultsetData result) {
writer.append('"' + columnHeaders.get(i).getColumnName() + '"'); StringBuffer writer = new StringBuffer();
if (i < (chSize - 1)) writer.append(",");
} List<ResultsetColumnHeaderData> columnHeaders = result
writer.append('\n'); .getColumnHeaders();
logger.info("NO. of Columns: " + columnHeaders.size());
List<ResultsetRowData> data = result.getData(); Integer chSize = columnHeaders.size();
List<String> row; for (int i = 0; i < chSize; i++) {
Integer rSize; writer.append('"' + columnHeaders.get(i).getColumnName() + '"');
// String currCol; if (i < (chSize - 1))
String currColType; writer.append(",");
String currVal; }
String doubleQuote = "\""; writer.append('\n');
String twoDoubleQuotes = doubleQuote + doubleQuote;
logger.info("NO. of Rows: " + data.size()); List<ResultsetRowData> data = result.getData();
for (int i = 0; i < data.size(); i++) { List<String> row;
row = data.get(i).getRow(); Integer rSize;
rSize = row.size(); // String currCol;
for (int j = 0; j < rSize; j++) { String currColType;
// currCol = columnHeaders.get(j).getColumnName(); String currVal;
currColType = columnHeaders.get(j).getColumnType(); String doubleQuote = "\"";
currVal = row.get(j); String twoDoubleQuotes = doubleQuote + doubleQuote;
if (currVal != null) { logger.info("NO. of Rows: " + data.size());
if (currColType.equals("DECIMAL") || currColType.equals("DOUBLE") || currColType.equals("BIGINT") for (int i = 0; i < data.size(); i++) {
|| currColType.equals("SMALLINT") || currColType.equals("INT")) row = data.get(i).getRow();
writer.append(currVal); rSize = row.size();
else for (int j = 0; j < rSize; j++) {
writer.append('"' + genericDataService.replace(currVal, doubleQuote, twoDoubleQuotes) + '"'); // currCol = columnHeaders.get(j).getColumnName();
currColType = columnHeaders.get(j).getColumnType();
} currVal = row.get(j);
if (j < (rSize - 1)) writer.append(","); if (currVal != null) {
} if (currColType.equals("DECIMAL")
writer.append('\n'); || currColType.equals("DOUBLE")
} || currColType.equals("BIGINT")
|| currColType.equals("SMALLINT")
return writer; || currColType.equals("INT"))
} writer.append(currVal);
else
@Override writer.append('"' + genericDataService.replace(currVal,
public GenericResultsetData retrieveGenericResultset(final String name, final String type, final Map<String, String> queryParams) { doubleQuote, twoDoubleQuotes) + '"');
long startTime = System.currentTimeMillis(); }
logger.info("STARTING REPORT: " + name + " Type: " + type); if (j < (rSize - 1))
writer.append(",");
String sql; }
if (name.equals(".")) { writer.append('\n');
// this is to support api /reports - which isn't an important }
// call. It isn't used in the default reporting UI. But there is a
// need to provide an api that does bring back 'permitted' reports return writer;
// PERMITTED REPORTS SQL }
sql = "select r.report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,"
+ " rp.parameter_id, rp.report_parameter_name, p.parameter_name" + " from stretchy_report r" @Override
+ " left join stretchy_report_parameter rp on rp.report_id = r.report_id" public GenericResultsetData retrieveGenericResultset(final String name,
+ " left join stretchy_parameter p on p.parameter_id = rp.parameter_id" + " where exists" + " (select 'f'" final String type, final Map<String, String> queryParams) {
+ " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
+ " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id" long startTime = System.currentTimeMillis();
+ " where ur.appuser_id = " + context.authenticatedUser().getId() logger.info("STARTING REPORT: " + name + " Type: " + type);
+ " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', r.report_name))) "
+ " order by r.report_name, rp.parameter_id"; String sql;
} else { if (name.equals(".")) {
sql = getSQLtoRun(name, type, queryParams); // this is to support api /reports - which isn't an important
} // call. It isn't used in the default reporting UI. But there is a
// need to provide an api that does bring back 'permitted' reports
GenericResultsetData result = genericDataService.fillGenericResultSet(sql); // PERMITTED REPORTS SQL
sql = "select r.report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,"
long elapsed = System.currentTimeMillis() - startTime; + " rp.parameter_id, rp.report_parameter_name, p.parameter_name"
logger.info("FINISHING Report/Request Name: " + name + " - " + type + " Elapsed Time: " + elapsed); + " from stretchy_report r"
return result; + " left join stretchy_report_parameter rp on rp.report_id = r.report_id"
} + " left join stretchy_parameter p on p.parameter_id = rp.parameter_id"
+ " where exists"
private String getSQLtoRun(final String name, final String type, final Map<String, String> queryParams) { + " (select 'f'"
+ " from m_appuser_role ur "
String sql = getSql(name, type); + " join m_role r on r.id = ur.role_id"
+ " left join m_role_permission rp on rp.role_id = r.id"
Set<String> keys = queryParams.keySet(); + " left join m_permission p on p.id = rp.permission_id"
for (String key : keys) { + " where ur.appuser_id = "
String pValue = queryParams.get(key); + context.authenticatedUser().getId()
// logger.info("(" + key + " : " + pValue + ")"); + " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', r.report_name))) "
sql = genericDataService.replace(sql, key, pValue); + " order by r.report_name, rp.parameter_id";
} } else {
sql = getSQLtoRun(name, type, queryParams);
AppUser currentUser = context.authenticatedUser(); }
// Allows sql query to restrict data by office hierarchy if required
sql = genericDataService.replace(sql, "${currentUserHierarchy}", currentUser.getOffice().getHierarchy()); GenericResultsetData result = genericDataService
// Allows sql query to restrict data by current user Id if required .fillGenericResultSet(sql);
// (typically used to return report lists containing only reports
// permitted to be run by the user long elapsed = System.currentTimeMillis() - startTime;
sql = genericDataService.replace(sql, "${currentUserId}", currentUser.getId().toString()); logger.info("FINISHING Report/Request Name: " + name + " - " + type
+ " Elapsed Time: " + elapsed);
sql = genericDataService.wrapSQL(sql); return result;
}
return sql;
private String getSQLtoRun(final String name, final String type,
} final Map<String, String> queryParams) {
private String getSql(final String name, final String type) { String sql = getSql(name, type);
final String inputSql = "select " + type + "_sql as the_sql from stretchy_" + type + " where " + type + "_name = '" + name + "'"; Set<String> keys = queryParams.keySet();
final String inputSqlWrapped = genericDataService.wrapSQL(inputSql); for (String key : keys) {
String pValue = queryParams.get(key);
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(inputSqlWrapped); // logger.info("(" + key + " : " + pValue + ")");
sql = genericDataService.replace(sql, key, pValue);
if (rs.next()) { return rs.getString("the_sql"); } }
throw new ReportNotFoundException(inputSql);
} AppUser currentUser = context.authenticatedUser();
// Allows sql query to restrict data by office hierarchy if required
@Override sql = genericDataService.replace(sql, "${currentUserHierarchy}",
public String getReportType(final String reportName) { currentUser.getOffice().getHierarchy());
// Allows sql query to restrict data by current user Id if required
final String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '" + reportName + "'"; // (typically used to return report lists containing only reports
// permitted to be run by the user
final String sqlWrapped = genericDataService.wrapSQL(sql); sql = genericDataService.replace(sql, "${currentUserId}", currentUser
.getId().toString());
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sqlWrapped);
sql = genericDataService.wrapSQL(sql);
if (rs.next()) { return rs.getString("report_type"); }
throw new ReportNotFoundException(sql); return sql;
}
}
@Override
public Response processPentahoRequest(final String reportName, final String outputTypeParam, final Map<String, String> queryParams) { private String getSql(final String name, final String type) {
String outputType = "HTML"; final String inputSql = "select " + type
if (StringUtils.isNotBlank(outputTypeParam)) outputType = outputTypeParam; + "_sql as the_sql from stretchy_" + type + " where " + type
+ "_name = '" + name + "'";
if (!(outputType.equalsIgnoreCase("HTML") || outputType.equalsIgnoreCase("PDF") || outputType.equalsIgnoreCase("XLS") || outputType final String inputSqlWrapped = genericDataService.wrapSQL(inputSql);
.equalsIgnoreCase("CSV")))
throw new PlatformDataIntegrityException("error.msg.invalid.outputType", "No matching Output Type: " + outputType); final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(inputSqlWrapped);
if (noPentaho) { throw new PlatformDataIntegrityException("error.msg.no.pentaho", "Pentaho is not enabled", if (rs.next()) {
"Pentaho is not enabled"); } return rs.getString("the_sql");
}
// TODO - JW - use pentaho location finder like Pawel does in Mifos throw new ReportNotFoundException(inputSql);
// String reportPath = }
// "C:\\dev\\apache-tomcat-7.0.25\\webapps\\ROOT\\PentahoReports\\"
// + reportName + ".prpt"; @Override
/* public String getReportType(final String reportName) {
* String reportPath = FileUtils.MIFOSX_BASE_DIR + File.separator +
* ThreadLocalContextUtil.getTenant().getName() .replaceAll(" ", final String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '"
* "").trim() + File.separator + "reports" + File.separator + reportName + reportName + "'";
* + ".prpt";
*/ final String sqlWrapped = genericDataService.wrapSQL(sql);
final String reportPath = FileUtils.MIFOSX_BASE_DIR + File.separator + "pentahoReports" + File.separator + reportName + ".prpt";
logger.info("Report path: " + reportPath); final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sqlWrapped);
// load report definition if (rs.next()) {
ResourceManager manager = new ResourceManager(); return rs.getString("report_type");
manager.registerDefaults(); }
Resource res; throw new ReportNotFoundException(sql);
}
try {
res = manager.createDirectly(reportPath, MasterReport.class); @Override
MasterReport masterReport = (MasterReport) res.getResource(); public Response processPentahoRequest(final String reportName,
final String outputTypeParam, final Map<String, String> queryParams) {
addParametersToReport(masterReport, queryParams);
String outputType = "HTML";
ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (StringUtils.isNotBlank(outputTypeParam))
outputType = outputTypeParam;
if ("PDF".equalsIgnoreCase(outputType)) {
PdfReportUtil.createPDF(masterReport, baos); if (!(outputType.equalsIgnoreCase("HTML")
return Response.ok().entity(baos.toByteArray()).type("application/pdf").build(); || outputType.equalsIgnoreCase("PDF")
} || outputType.equalsIgnoreCase("XLS") || outputType
.equalsIgnoreCase("CSV")))
if ("XLS".equalsIgnoreCase(outputType)) { throw new PlatformDataIntegrityException(
ExcelReportUtil.createXLS(masterReport, baos); "error.msg.invalid.outputType", "No matching Output Type: "
return Response.ok().entity(baos.toByteArray()).type("application/vnd.ms-excel") + outputType);
.header("Content-Disposition", "attachment;filename=" + reportName.replaceAll(" ", "") + ".xls").build();
} if (noPentaho) {
throw new PlatformDataIntegrityException("error.msg.no.pentaho",
if ("CSV".equalsIgnoreCase(outputType)) { "Pentaho is not enabled", "Pentaho is not enabled");
CSVReportUtil.createCSV(masterReport, baos, "UTF-8"); }
return Response.ok().entity(baos.toByteArray()).type("application/x-msdownload")
.header("Content-Disposition", "attachment;filename=" + reportName.replaceAll(" ", "") + ".csv").build(); final String reportPath = FileUtils.MIFOSX_BASE_DIR + File.separator
} + "pentahoReports" + File.separator + reportName + ".prpt";
logger.info("Report path: " + reportPath);
if ("HTML".equalsIgnoreCase(outputType)) {
HtmlReportUtil.createStreamHTML(masterReport, baos); // load report definition
return Response.ok().entity(baos.toByteArray()).type("text/html").build(); ResourceManager manager = new ResourceManager();
} manager.registerDefaults();
} catch (ResourceException e) { Resource res;
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage());
} catch (ReportProcessingException e) { try {
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage()); res = manager.createDirectly(reportPath, MasterReport.class);
} catch (IOException e) { MasterReport masterReport = (MasterReport) res.getResource();
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage());
} addParametersToReport(masterReport, queryParams);
throw new PlatformDataIntegrityException("error.msg.invalid.outputType", "No matching Output Type: " + outputType); ByteArrayOutputStream baos = new ByteArrayOutputStream();
}
if ("PDF".equalsIgnoreCase(outputType)) {
private void addParametersToReport(final MasterReport report, final Map<String, String> queryParams) { PdfReportUtil.createPDF(masterReport, baos);
return Response.ok().entity(baos.toByteArray())
AppUser currentUser = context.authenticatedUser(); .type("application/pdf").build();
}
try {
if ("XLS".equalsIgnoreCase(outputType)) {
ReportParameterValues rptParamValues = report.getParameterValues(); ExcelReportUtil.createXLS(masterReport, baos);
ReportParameterDefinition paramsDefinition = report.getParameterDefinition(); return Response
.ok()
/* .entity(baos.toByteArray())
* only allow integer, long, date and string parameter types and .type("application/vnd.ms-excel")
* assume all mandatory - could go more detailed like Pawel did in .header("Content-Disposition",
* Mifos later and could match incoming and pentaho parameters "attachment;filename="
* better... currently assuming they come in ok... and if not an + reportName.replaceAll(" ", "")
* error + ".xls").build();
*/ }
for (ParameterDefinitionEntry paramDefEntry : paramsDefinition.getParameterDefinitions()) {
String paramName = paramDefEntry.getName(); if ("CSV".equalsIgnoreCase(outputType)) {
if (!((paramName.equals("tenantdb")) || (paramName.equals("userhierarchy")))) { CSVReportUtil.createCSV(masterReport, baos, "UTF-8");
logger.info("paramName:" + paramName); return Response
String pValue = queryParams.get(paramName); .ok()
if (StringUtils.isBlank(pValue)) .entity(baos.toByteArray())
throw new PlatformDataIntegrityException("error.msg.reporting.error", "Pentaho Parameter: " + paramName .type("application/x-msdownload")
+ " - not Provided"); .header("Content-Disposition",
"attachment;filename="
Class<?> clazz = paramDefEntry.getValueType(); + reportName.replaceAll(" ", "")
logger.info("addParametersToReport(" + paramName + " : " + pValue + " : " + clazz.getCanonicalName() + ")"); + ".csv").build();
if (clazz.getCanonicalName().equalsIgnoreCase("java.lang.Integer")) }
rptParamValues.put(paramName, Integer.parseInt(pValue));
else if (clazz.getCanonicalName().equalsIgnoreCase("java.lang.Long")) if ("HTML".equalsIgnoreCase(outputType)) {
rptParamValues.put(paramName, Long.parseLong(pValue)); HtmlReportUtil.createStreamHTML(masterReport, baos);
else if (clazz.getCanonicalName().equalsIgnoreCase("java.sql.Date")) return Response.ok().entity(baos.toByteArray())
rptParamValues.put(paramName, Date.valueOf(pValue)); .type("text/html").build();
else }
rptParamValues.put(paramName, pValue); } catch (ResourceException e) {
} throw new PlatformDataIntegrityException(
"error.msg.reporting.error", e.getMessage());
} } catch (ReportProcessingException e) {
throw new PlatformDataIntegrityException(
// tenant database name and current user's office hierarchy "error.msg.reporting.error", e.getMessage());
// passed as parameters to allow multitenant penaho reporting } catch (IOException e) {
// and throw new PlatformDataIntegrityException(
// data scoping "error.msg.reporting.error", e.getMessage());
String tenantdb = dataSource.getConnection().getCatalog(); }
String userhierarchy = currentUser.getOffice().getHierarchy();
logger.info("db name:" + tenantdb + " userhierarchy:" + userhierarchy); throw new PlatformDataIntegrityException(
rptParamValues.put("tenantdb", tenantdb); "error.msg.invalid.outputType", "No matching Output Type: "
rptParamValues.put("userhierarchy", userhierarchy); + outputType);
} catch (Exception e) { }
logger.error("error.msg.reporting.error:" + e.getMessage());
throw new PlatformDataIntegrityException("error.msg.reporting.error", e.getMessage()); private void addParametersToReport(final MasterReport report,
} final Map<String, String> queryParams) {
}
AppUser currentUser = context.authenticatedUser();
@Override
public String retrieveReportPDF(final String reportName, final String type, final Map<String, String> queryParams) { try {
String fileLocation = FileUtils.MIFOSX_BASE_DIR + File.separator + ""; ReportParameterValues rptParamValues = report.getParameterValues();
if (!new File(fileLocation).isDirectory()) { ReportParameterDefinition paramsDefinition = report
new File(fileLocation).mkdirs(); .getParameterDefinition();
}
/*
String genaratePdf = fileLocation + File.separator + reportName + ".pdf"; * only allow integer, long, date and string parameter types and
* assume all mandatory - could go more detailed like Pawel did in
try { * Mifos later and could match incoming and pentaho parameters
GenericResultsetData result = retrieveGenericResultset(reportName, type, queryParams); * better... currently assuming they come in ok... and if not an
* error
List<ResultsetColumnHeaderData> columnHeaders = result.getColumnHeaders(); */
List<ResultsetRowData> data = result.getData(); for (ParameterDefinitionEntry paramDefEntry : paramsDefinition
List<String> row; .getParameterDefinitions()) {
String paramName = paramDefEntry.getName();
logger.info("NO. of Columns: " + columnHeaders.size()); if (!((paramName.equals("tenantdb")) || (paramName
Integer chSize = columnHeaders.size(); .equals("userhierarchy")))) {
logger.info("paramName:" + paramName);
Document document = new Document(PageSize.B0.rotate()); String pValue = queryParams.get(paramName);
if (StringUtils.isBlank(pValue))
PdfWriter.getInstance(document, new FileOutputStream(new File(fileLocation + reportName + ".pdf"))); throw new PlatformDataIntegrityException(
document.open(); "error.msg.reporting.error",
"Pentaho Parameter: " + paramName
PdfPTable table = new PdfPTable(chSize); + " - not Provided");
table.setWidthPercentage(100);
Class<?> clazz = paramDefEntry.getValueType();
for (int i = 0; i < chSize; i++) { logger.info("addParametersToReport(" + paramName + " : "
+ pValue + " : " + clazz.getCanonicalName() + ")");
table.addCell(columnHeaders.get(i).getColumnName()); if (clazz.getCanonicalName().equalsIgnoreCase(
"java.lang.Integer"))
} rptParamValues.put(paramName, Integer.parseInt(pValue));
table.completeRow(); else if (clazz.getCanonicalName().equalsIgnoreCase(
"java.lang.Long"))
Integer rSize; rptParamValues.put(paramName, Long.parseLong(pValue));
String currColType; else if (clazz.getCanonicalName().equalsIgnoreCase(
String currVal; "java.sql.Date"))
logger.info("NO. of Rows: " + data.size()); rptParamValues.put(paramName, Date.valueOf(pValue));
for (int i = 0; i < data.size(); i++) { else
row = data.get(i).getRow(); rptParamValues.put(paramName, pValue);
rSize = row.size(); }
for (int j = 0; j < rSize; j++) {
currColType = columnHeaders.get(j).getColumnType(); }
currVal = row.get(j);
if (currVal != null) { // tenant database name and current user's office hierarchy
if (currColType.equals("DECIMAL") || currColType.equals("DOUBLE") || currColType.equals("BIGINT") // passed as parameters to allow multitenant penaho reporting
|| currColType.equals("SMALLINT") || currColType.equals("INT")) { // and
// data scoping
table.addCell(currVal.toString()); String tenantdb = dataSource.getConnection().getCatalog();
} else { String userhierarchy = currentUser.getOffice().getHierarchy();
table.addCell(currVal.toString()); logger.info("db name:" + tenantdb + " userhierarchy:"
} + userhierarchy);
} rptParamValues.put("tenantdb", tenantdb);
} rptParamValues.put("userhierarchy", userhierarchy);
} } catch (Exception e) {
table.completeRow(); logger.error("error.msg.reporting.error:" + e.getMessage());
document.add(table); throw new PlatformDataIntegrityException(
document.close(); "error.msg.reporting.error", e.getMessage());
return genaratePdf; }
} catch (Exception e) { }
logger.error("error.msg.reporting.error:" + e.getMessage());
throw new PlatformDataIntegrityException("error.msg.exception.error", e.getMessage()); @Override
} public String retrieveReportPDF(final String reportName, final String type,
} final Map<String, String> queryParams) {
String fileLocation = FileUtils.MIFOSX_BASE_DIR + File.separator + "";
if (!new File(fileLocation).isDirectory()) {
new File(fileLocation).mkdirs();
}
String genaratePdf = fileLocation + File.separator + reportName
+ ".pdf";
try {
GenericResultsetData result = retrieveGenericResultset(reportName,
type, queryParams);
List<ResultsetColumnHeaderData> columnHeaders = result
.getColumnHeaders();
List<ResultsetRowData> data = result.getData();
List<String> row;
logger.info("NO. of Columns: " + columnHeaders.size());
Integer chSize = columnHeaders.size();
Document document = new Document(PageSize.B0.rotate());
PdfWriter.getInstance(document, new FileOutputStream(new File(
fileLocation + reportName + ".pdf")));
document.open();
PdfPTable table = new PdfPTable(chSize);
table.setWidthPercentage(100);
for (int i = 0; i < chSize; i++) {
table.addCell(columnHeaders.get(i).getColumnName());
}
table.completeRow();
Integer rSize;
String currColType;
String currVal;
logger.info("NO. of Rows: " + data.size());
for (int i = 0; i < data.size(); i++) {
row = data.get(i).getRow();
rSize = row.size();
for (int j = 0; j < rSize; j++) {
currColType = columnHeaders.get(j).getColumnType();
currVal = row.get(j);
if (currVal != null) {
if (currColType.equals("DECIMAL")
|| currColType.equals("DOUBLE")
|| currColType.equals("BIGINT")
|| currColType.equals("SMALLINT")
|| currColType.equals("INT")) {
table.addCell(currVal.toString());
} else {
table.addCell(currVal.toString());
}
}
}
}
table.completeRow();
document.add(table);
document.close();
return genaratePdf;
} catch (Exception e) {
logger.error("error.msg.reporting.error:" + e.getMessage());
throw new PlatformDataIntegrityException(
"error.msg.exception.error", e.getMessage());
}
}
@Override
public Collection<ReportData> retrieveReportList() {
ReportParameterJoinMapper rm = new ReportParameterJoinMapper();
String sql = rm.schema(false, context.authenticatedUser().getId());
Collection<ReportParameterJoinData> rpJoins = this.jdbcTemplate.query(
sql, rm, new Object[] {});
Collection<ReportData> reportList = new ArrayList<ReportData>();
if (rpJoins == null)
return reportList;
Collection<ReportParameterData> reportParameters = null;
Long reportId = null;
String reportName = null;
String reportType = null;
String reportSubType = null;
String reportCategory = null;
Boolean coreReport = null;
Boolean useReport = null;
String reportSql = null;
Long prevReportId = (long) -1234;
Boolean firstReport = true;
for (ReportParameterJoinData rpJoin : rpJoins) {
if (rpJoin.getReportId().equals(prevReportId)) {
// more than one parameter for report
reportParameters.add(new ReportParameterData(rpJoin
.getReportParameterId(), rpJoin
.getReportParameterName(), rpJoin.getParameterName()));
} else {
if (firstReport) {
firstReport = false;
}
else
{
// write report entry
reportList
.add(new ReportData(reportId, reportName,
reportType, reportSubType, reportCategory,
reportSql, coreReport, useReport,
reportParameters));
}
prevReportId = rpJoin.getReportId();
reportId = rpJoin.getReportId();
reportName = rpJoin.getReportName();
reportType = rpJoin.getReportType();
reportSubType = rpJoin.getReportSubType();
reportCategory = rpJoin.getReportCategory();
reportSql = rpJoin.getReportSql();
coreReport = rpJoin.getCoreReport();
useReport = rpJoin.getUseReport();
if (rpJoin.getReportParameterId() != null) {
// report has at least one parameter
reportParameters = new ArrayList<ReportParameterData>();
reportParameters.add(new ReportParameterData(rpJoin
.getReportParameterId(), rpJoin
.getReportParameterName(), rpJoin
.getParameterName()));
} else {
reportParameters = null;
}
}
}
// write last report
reportList.add(new ReportData(reportId, reportName, reportType,
reportSubType, reportCategory, reportSql, coreReport,
useReport, reportParameters));
return reportList;
}
private static final class ReportParameterJoinMapper implements
RowMapper<ReportParameterJoinData> {
public String schema(boolean includeSql, Long userId) {
String sql = "select r.report_id as reportId, r.report_name as reportName, r.report_type as reportType, "
+ " r.report_subtype as reportSubType, r.report_category as reportCategory, r.core_report as coreReport, r.use_report as useReport, "
+ " rp.parameter_id as reportParameterId, rp.report_parameter_name as reportParameterName, p.parameter_name as parameterName";
if (includeSql)
sql += ", r.report_sql as reportSql ";
sql += " from stretchy_report r"
+ " left join stretchy_report_parameter rp on rp.report_id = r.report_id"
+ " left join stretchy_parameter p on p.parameter_id = rp.parameter_id"
+ " where exists"
+ " (select 'f'"
+ " from m_appuser_role ur "
+ " join m_role r on r.id = ur.role_id"
+ " left join m_role_permission rp on rp.role_id = r.id"
+ " left join m_permission p on p.id = rp.permission_id"
+ " where ur.appuser_id = "
+ userId
+ " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', r.report_name))) "
+ " order by r.report_id, rp.parameter_id";
return sql;
}
@Override
public ReportParameterJoinData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long reportId = rs.getLong("reportId");
final String reportName = rs.getString("reportName");
final String reportType = rs.getString("reportType");
final String reportSubType = rs.getString("reportSubType");
final String reportCategory = rs.getString("reportCategory");
final Boolean coreReport = rs.getBoolean("coreReport");
final Boolean useReport = rs.getBoolean("useReport");
String reportSql;
// reportSql might not be on the select list of columns
try {
reportSql = rs.getString("reportSql");
} catch (SQLException e) {
reportSql = null;
}
final Long reportParameterId = JdbcSupport.getLong(rs,
"reportParameterId");
final String reportParameterName = rs
.getString("reportParameterName");
final String parameterName = rs.getString("parameterName");
return new ReportParameterJoinData(reportId, reportName,
reportType, reportSubType, reportCategory, reportSql,
coreReport, useReport, reportParameterId,
reportParameterName, parameterName);
}
}
} }