WIP client search and enable Pentaho Reports

This commit is contained in:
John Woodlock
2012-07-11 15:15:18 +10:00
parent 7138a70026
commit 57556d3a1a
6 changed files with 183 additions and 124 deletions
+3
View File
@@ -0,0 +1,3 @@
/* remove column org_id */
ALTER TABLE `mifosngprovider`.`portfolio_client` DROP FOREIGN KEY `FKCE00CAB354DF2770` ;ALTER TABLE `mifosngprovider`.`portfolio_client` DROP COLUMN `org_id` , DROP INDEX `org_id` , ADD INDEX `external_id` (`external_id` ASC) , DROP INDEX `FKCE00CAB354DF2770` ;
@@ -27,7 +27,7 @@ import org.mifosng.platform.api.data.ResultsetDataRow;
import org.mifosng.platform.exceptions.AdditionalFieldsNotFoundException;
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
import org.mifosng.platform.exceptions.ReportNotFoundException;
//import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.PdfReportUtil;
@@ -56,8 +56,8 @@ public class ReadExtraDataAndReportingServiceImpl implements
@Autowired
public ReadExtraDataAndReportingServiceImpl(final DataSource dataSource) {
// kick off pentaho reports server
// ClassicEngineBoot.getInstance().start();
noPentaho = true;
ClassicEngineBoot.getInstance().start();
noPentaho = false;
try {
this.dataSource = dataSource;
@@ -718,22 +718,26 @@ public class ReadExtraDataAndReportingServiceImpl implements
}
@Override
public Response processPentahoRequest(String reportName, String outputTypeParam,
Map<String, String> queryParams) {
public Response processPentahoRequest(String reportName,
String outputTypeParam, Map<String, String> queryParams) {
String outputType = "HTML";
if (StringUtils.isNotBlank(outputTypeParam)) outputType = outputTypeParam;
if (!(outputType.equalsIgnoreCase("HTML") || outputType.equalsIgnoreCase("PDF") || outputType.equalsIgnoreCase("XLS") || outputType.equalsIgnoreCase("CSV")))
if (StringUtils.isNotBlank(outputTypeParam))
outputType = outputTypeParam;
if (!(outputType.equalsIgnoreCase("HTML")
|| outputType.equalsIgnoreCase("PDF")
|| outputType.equalsIgnoreCase("XLS") || outputType
.equalsIgnoreCase("CSV")))
throw new PlatformDataIntegrityException(
"error.msg.invalid.outputType", "No matching Output Type: "
+ outputType);
if (noPentaho)
throw new PlatformDataIntegrityException("error.msg.no.pentaho",
"Pentaho is not enabled", "Pentaho is not enabled");
//TODO - use pentaho location finder like Pawel does in Mifos
// TODO - use pentaho location finder like Pawel does in Mifos
String reportPath = "C:\\dev\\apache-tomcat-7.0.25\\webapps\\ROOT\\PentahoReports\\"
+ reportName + ".prpt";
// String reportPath =
@@ -785,7 +789,8 @@ public class ReadExtraDataAndReportingServiceImpl implements
if ("HTML".equalsIgnoreCase(outputType)) {
HtmlReportUtil.createStreamHTML(masterReport, baos);
return Response.ok().entity(baos.toByteArray()).type("text/html").build();
return Response.ok().entity(baos.toByteArray())
.type("text/html").build();
}
} catch (ResourceException e) {
throw new PlatformDataIntegrityException(
@@ -16,6 +16,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.commands.NoteCommand;
@@ -29,6 +30,8 @@ import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService;
import org.mifosng.platform.client.service.ClientReadPlatformService;
import org.mifosng.platform.client.service.ClientWritePlatformService;
import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -38,6 +41,9 @@ import org.springframework.stereotype.Component;
@Scope("singleton")
public class ClientApiResource {
private final static Logger logger = LoggerFactory
.getLogger(ClientApiResource.class);
private String defaultFieldList = "joinedDate";
private String allowedFieldList = "allowedOffices";
private String filterName = "myFilter";
@@ -60,16 +66,64 @@ public class ClientApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllIndividualClients(@Context UriInfo uriInfo) {
public String retrieveAllIndividualClients(@Context UriInfo uriInfo,
@QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("officeId") final Integer officeId,
@QueryParam("externalId") final String externalId,
@QueryParam("displayName") final String displayName,
@QueryParam("firstName") final String firstName,
@QueryParam("lastName") final String lastName) {
String extraCriteria = getClientCriteria(sqlSearch, officeId,
externalId, displayName, firstName, lastName);
Collection<ClientData> clients = this.clientReadPlatformService
.retrieveAllIndividualClients();
.retrieveAllIndividualClients(extraCriteria);
String selectedFields = "";
return this.jsonFormattingService.convertRequest(clients, filterName,
allowedFieldList, selectedFields, uriInfo.getQueryParameters());
}
private String getClientCriteria(String sqlSearch, Integer officeId,
String externalId, String displayName, String firstName,
String lastName) {
String extraCriteria = "";
if (sqlSearch != null)
extraCriteria = " and (" + sqlSearch + ")";
if (officeId != null)
extraCriteria += " and office_id = " + officeId;
if (externalId != null)
extraCriteria += " and external_id like "
+ sqlEncodeString(externalId);
if (displayName != null)
extraCriteria += " and concat(ifnull(firstname, ''), if(firstname > '',' ', '') , ifnull(lastname, '')) like "
+ sqlEncodeString(displayName);
if (firstName != null)
extraCriteria += " and firstname like "
+ sqlEncodeString(firstName);
if (lastName != null)
extraCriteria += " and lastname like " + sqlEncodeString(lastName);
if (StringUtils.isNotBlank(extraCriteria))
extraCriteria = extraCriteria.substring(4);
logger.info("extraCriteria; " + extraCriteria);
return extraCriteria;
}
private String sqlEncodeString(String str) {
String singleQuote = "'";
String twoSingleQuotes = "''";
return singleQuote
+ StringUtils.replace(str, singleQuote, twoSingleQuotes, -1)
+ singleQuote;
}
@GET
@Path("{clientId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@@ -5,16 +5,12 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonFilter;
import org.joda.time.LocalDate;
@JsonIgnoreProperties({ "organisationId","organisationName"})
@JsonFilter("myFilter")
public class ClientData implements Serializable {
private Long organisationId;
private String organisationName;
private Long officeId;
private String officeName;
private Long id;
@@ -30,24 +26,21 @@ public class ClientData implements Serializable {
//
}
public ClientData(final Long organisationId, final String organisationName,
final Long officeId, final String officeName, final Long id,
final String firstname, final String lastname,
public ClientData(final Long officeId, final String officeName,
final Long id, final String firstname, final String lastname,
final String externalId, final LocalDate joinedDate) {
this.organisationId = organisationId;
this.organisationName = organisationName;
this.officeId = officeId;
this.officeName = officeName;
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
StringBuilder nameBuilder = new StringBuilder(this.firstname);
if (StringUtils.isNotBlank(nameBuilder.toString())) {
nameBuilder.append(' ');
}
nameBuilder.append(this.lastname);
this.displayName = nameBuilder.toString();
this.externalId = externalId;
this.joinedDate = joinedDate;
@@ -69,14 +62,6 @@ public class ClientData implements Serializable {
return this.externalId;
}
public Long getOrganisationId() {
return this.organisationId;
}
public String getOrganisationName() {
return this.organisationName;
}
public Long getOfficeId() {
return this.officeId;
}
@@ -89,14 +74,6 @@ public class ClientData implements Serializable {
return this.joinedDate;
}
public void setOrganisationId(final Long organisationId) {
this.organisationId = organisationId;
}
public void setOrganisationName(final String organisationName) {
this.organisationName = organisationName;
}
public void setOfficeId(final Long officeId) {
this.officeId = officeId;
}
@@ -8,14 +8,15 @@ import org.mifosng.platform.api.data.NoteData;
public interface ClientReadPlatformService {
Collection<ClientData> retrieveAllIndividualClients();
Collection<ClientData> retrieveAllIndividualClients(String extraCriteria);
ClientData retrieveIndividualClient(Long clientId);
ClientData retrieveNewClientDetails();
ClientLoanAccountSummaryCollectionData retrieveClientAccountDetails(Long clientId);
ClientLoanAccountSummaryCollectionData retrieveClientAccountDetails(
Long clientId);
Collection<NoteData> retrieveAllClientNotes(Long clientId);
NoteData retrieveClientNote(Long clientId, Long noteId);
@@ -23,7 +23,6 @@ import org.mifosng.platform.client.domain.NoteEnumerations;
import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.NoteNotFoundException;
import org.mifosng.platform.infrastructure.JdbcSupport;
import org.mifosng.platform.organisation.domain.Organisation;
import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
@@ -43,14 +42,16 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
private final AppUserReadPlatformService appUserReadPlatformService;
@Autowired
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource, final OfficeReadPlatformService officeReadPlatformService,
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context,
final DataSource dataSource,
final OfficeReadPlatformService officeReadPlatformService,
final AppUserReadPlatformService appUserReadPlatformService) {
this.context = context;
this.officeReadPlatformService = officeReadPlatformService;
this.appUserReadPlatformService = appUserReadPlatformService;
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
private String generateOfficeIdInClause(List<OfficeData> offices) {
String officeIdsList = "";
for (int i = 0; i < offices.size(); i++) {
@@ -63,79 +64,84 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
return officeIdsList;
}
@Override
public Collection<ClientData> retrieveAllIndividualClients() {
public Collection<ClientData> retrieveAllIndividualClients(
String extraCriteria) {
AppUser currentUser = this.context.authenticatedUser();
List<OfficeData> offices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOffices());
List<OfficeData> offices = new ArrayList<OfficeData>(
officeReadPlatformService.retrieveAllOffices());
String officeIdsList = generateOfficeIdInClause(offices);
ClientMapper rm = new ClientMapper(offices, currentUser.getOrganisation());
String sql = "select " + rm.clientSchema()
+ " where c.org_id = ? and c.office_id in (" + officeIdsList
+ ") order by c.lastname ASC, c.firstname ASC";
ClientMapper rm = new ClientMapper(offices);
return this.jdbcTemplate.query(sql, rm, new Object[] { currentUser
.getOrganisation().getId() });
String sql = "select " + rm.clientSchema() + " where c.office_id in ("
+ officeIdsList + ") ";
if (StringUtils.isNotBlank(extraCriteria))
sql += " and " + extraCriteria;
sql += " order by c.lastname ASC, c.firstname ASC";
return this.jdbcTemplate.query(sql, rm, new Object[] {});
}
@Override
public ClientData retrieveIndividualClient(final Long clientId) {
try {
AppUser currentUser = this.context.authenticatedUser();
//TODO - JW include office name in query rather than get the lot for office name
List<OfficeData> offices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOffices());
ClientMapper rm = new ClientMapper(offices, currentUser.getOrganisation());
// TODO - JW include office name in query rather than get the lot
// for office name
List<OfficeData> offices = new ArrayList<OfficeData>(
officeReadPlatformService.retrieveAllOffices());
ClientMapper rm = new ClientMapper(offices);
String sql = "select " + rm.clientSchema() + " where c.id = ? and c.org_id = ?";
String sql = "select " + rm.clientSchema()
+ " where c.id = ? and c.org_id = ?";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {clientId, currentUser.getOrganisation().getId() });
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {
clientId, currentUser.getOrganisation().getId() });
} catch (EmptyResultDataAccessException e) {
throw new ClientNotFoundException(clientId);
}
}
@Override
public ClientData retrieveNewClientDetails() {
AppUser currentUser = context.authenticatedUser();
List<OfficeLookup> offices = new ArrayList<OfficeLookup>(officeReadPlatformService.retrieveAllOfficesForLookup());
List<OfficeLookup> offices = new ArrayList<OfficeLookup>(
officeReadPlatformService.retrieveAllOfficesForLookup());
ClientData clientData = new ClientData();
clientData.setOfficeId(currentUser.getOffice().getId());
clientData.setOrganisationId(currentUser.getOrganisation().getId());
clientData.setAllowedOffices(offices);
clientData.setJoinedDate(new LocalDate());
return clientData;
}
private static final class ClientMapper implements RowMapper<ClientData> {
private final List<OfficeData> offices;
private final Organisation organisation;
public ClientMapper(final List<OfficeData> offices,
Organisation organisation) {
public ClientMapper(final List<OfficeData> offices) {
this.offices = offices;
this.organisation = organisation;
}
public String clientSchema() {
return "c.org_id as orgId, c.office_id as officeId, c.id as id, c.firstname as firstname, c.lastname as lastname, c.external_id as externalId, c.joining_date as joinedDate from portfolio_client c";
return "c.office_id as officeId, c.id as id, c.firstname as firstname, c.lastname as lastname, c.external_id as externalId, c.joining_date as joinedDate from portfolio_client c";
}
@Override
public ClientData mapRow(final ResultSet rs, final int rowNum)
throws SQLException {
Long orgId = JdbcSupport.getLong(rs, "orgId");
Long officeId = JdbcSupport.getLong(rs, "officeId");
Long id = JdbcSupport.getLong(rs, "id");
String firstname = rs.getString("firstname");
@@ -148,12 +154,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
String officeName = fromOfficeList(this.offices, officeId);
String orgname = "";
if (organisation.getId().equals(orgId)) {
orgname = organisation.getName();
}
return new ClientData(orgId, orgname, officeId, officeName, id, firstname, lastname, externalId, joinedDate);
return new ClientData(officeId, officeName, id, firstname,
lastname, externalId, joinedDate);
}
private String fromOfficeList(final List<OfficeData> officeList,
@@ -168,13 +170,14 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
return match;
}
}
@Override
public ClientLoanAccountSummaryCollectionData retrieveClientAccountDetails(final Long clientId) {
public ClientLoanAccountSummaryCollectionData retrieveClientAccountDetails(
final Long clientId) {
try {
AppUser currentUser = this.context.authenticatedUser();
List<ClientLoanAccountSummaryData> pendingApprovalLoans = new ArrayList<ClientLoanAccountSummaryData>();
List<ClientLoanAccountSummaryData> awaitingDisbursalLoans = new ArrayList<ClientLoanAccountSummaryData>();
List<ClientLoanAccountSummaryData> openLoans = new ArrayList<ClientLoanAccountSummaryData>();
@@ -182,14 +185,18 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
ClientLoanAccountSummaryDataMapper rm = new ClientLoanAccountSummaryDataMapper();
String sql = "select " + rm.loanAccountSummarySchema() + " where l.client_id = ? and l.org_id = ?";
String sql = "select " + rm.loanAccountSummarySchema()
+ " where l.client_id = ? and l.org_id = ?";
List<ClientLoanAccountSummaryData> results = this.jdbcTemplate.query(sql, rm, new Object[] {clientId, currentUser.getOrganisation().getId()});
List<ClientLoanAccountSummaryData> results = this.jdbcTemplate
.query(sql, rm, new Object[] { clientId,
currentUser.getOrganisation().getId() });
if (results != null) {
for (ClientLoanAccountSummaryData row : results) {
LoanStatusMapper statusMapper = new LoanStatusMapper(row.getLoanStatusId());
LoanStatusMapper statusMapper = new LoanStatusMapper(
row.getLoanStatusId());
if (statusMapper.isOpen()) {
openLoans.add(row);
} else if (statusMapper.isAwaitingDisbursal()) {
@@ -201,58 +208,67 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
}
}
return new ClientLoanAccountSummaryCollectionData(pendingApprovalLoans, awaitingDisbursalLoans, openLoans, closedLoans);
return new ClientLoanAccountSummaryCollectionData(
pendingApprovalLoans, awaitingDisbursalLoans, openLoans,
closedLoans);
} catch (EmptyResultDataAccessException e) {
throw new ClientNotFoundException(clientId);
}
}
private static final class ClientLoanAccountSummaryDataMapper implements RowMapper<ClientLoanAccountSummaryData> {
private static final class ClientLoanAccountSummaryDataMapper implements
RowMapper<ClientLoanAccountSummaryData> {
public String loanAccountSummarySchema() {
StringBuilder loanAccountSummary = new StringBuilder("l.id as id, l.external_id as externalId,");
loanAccountSummary.append("l.product_id as productId, lp.name as productName,")
.append("l.loan_status_id as statusId, ls.display_name as statusName ")
.append("from portfolio_loan l ")
.append("LEFT JOIN portfolio_product_loan AS lp ON lp.id = l.product_id ")
.append("LEFT JOIN ref_loan_status AS ls ON ls.id = l.loan_status_id ");
StringBuilder loanAccountSummary = new StringBuilder(
"l.id as id, l.external_id as externalId,");
loanAccountSummary
.append("l.product_id as productId, lp.name as productName,")
.append("l.loan_status_id as statusId, ls.display_name as statusName ")
.append("from portfolio_loan l ")
.append("LEFT JOIN portfolio_product_loan AS lp ON lp.id = l.product_id ")
.append("LEFT JOIN ref_loan_status AS ls ON ls.id = l.loan_status_id ");
return loanAccountSummary.toString();
}
@Override
public ClientLoanAccountSummaryData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
public ClientLoanAccountSummaryData mapRow(final ResultSet rs,
final int rowNum) throws SQLException {
Long id = JdbcSupport.getLong(rs, "id");
String externalId = rs.getString("externalId");
Long productId = JdbcSupport.getLong(rs, "productId");
String loanProductName = rs.getString("productName");
Integer loanStatusId = JdbcSupport.getInteger(rs, "statusId");
// String lifeCycleStatusText = rs.getString("statusName");
//
// LoanStatusMapper statusMapper = new LoanStatusMapper(loanStatusId);
//
// boolean pendingApproval = statusMapper.isPendingApproval();
// boolean waitingForDisbursal = statusMapper.isAwaitingDisbursal();
// boolean open = statusMapper.isOpen();
// boolean closed = statusMapper.isClosed();
return new ClientLoanAccountSummaryData(id, externalId, productId, loanProductName, loanStatusId);
// String lifeCycleStatusText = rs.getString("statusName");
//
// LoanStatusMapper statusMapper = new
// LoanStatusMapper(loanStatusId);
//
// boolean pendingApproval = statusMapper.isPendingApproval();
// boolean waitingForDisbursal = statusMapper.isAwaitingDisbursal();
// boolean open = statusMapper.isOpen();
// boolean closed = statusMapper.isClosed();
return new ClientLoanAccountSummaryData(id, externalId, productId,
loanProductName, loanStatusId);
}
}
@Override
public NoteData retrieveClientNote(Long clientId, Long noteId) {
try {
AppUser currentUser = context.authenticatedUser();
// FIXME - use join on sql query to fetch user information for note rather than fetching users?
Collection<AppUserData> allUsers = this.appUserReadPlatformService.retrieveAllUsers();
// FIXME - use join on sql query to fetch user information for note
// rather than fetching users?
Collection<AppUserData> allUsers = this.appUserReadPlatformService
.retrieveAllUsers();
NoteMapper noteMapper = new NoteMapper(allUsers);
@@ -272,8 +288,10 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
AppUser currentUser = context.authenticatedUser();
// FIXME - use join on sql query to fetch user information for note rather than fetching users?
Collection<AppUserData> allUsers = this.appUserReadPlatformService.retrieveAllUsers();
// FIXME - use join on sql query to fetch user information for note
// rather than fetching users?
Collection<AppUserData> allUsers = this.appUserReadPlatformService
.retrieveAllUsers();
NoteMapper noteMapper = new NoteMapper(allUsers);
@@ -315,17 +333,18 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
Long createdById = JdbcSupport.getLong(rs, "createdById");
String createdByUsername = findUserById(createdById, allUsers);
DateTime lastModifiedDate = JdbcSupport.getDateTime(rs, "lastModifiedDate");
DateTime lastModifiedDate = JdbcSupport.getDateTime(rs,
"lastModifiedDate");
Long lastModifiedById = JdbcSupport.getLong(rs, "lastModifiedById");
String updatedByUsername = findUserById(createdById, allUsers);
return new NoteData(id, clientId, loanId, transactionId,
noteType, note, createdDate, createdById,
createdByUsername, lastModifiedDate, lastModifiedById,
updatedByUsername);
return new NoteData(id, clientId, loanId, transactionId, noteType,
note, createdDate, createdById, createdByUsername,
lastModifiedDate, lastModifiedById, updatedByUsername);
}
private String findUserById(Long createdById, Collection<AppUserData> allUsers) {
private String findUserById(Long createdById,
Collection<AppUserData> allUsers) {
String username = "";
for (AppUserData appUserData : allUsers) {
if (appUserData.getId().equals(createdById)) {