Merge pull request #735 from lingalamadhukar/mifosx-871
MIFOSX-871 Advanced search query with search operators
This commit is contained in:
@@ -1406,6 +1406,14 @@
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#advance_search">AdHoc Search</a></td>
|
||||
<td>search/advance</td>
|
||||
<td><a href="#advance_search_resource">Advance Search</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -21053,6 +21061,211 @@ GET https://DomainName/api/v1/search?query=000000111
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
<a id="advance_search" name="advance_search" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h3>Advance Search</h3>
|
||||
<p>AdHoc Query search supported parameters and field descriptions</p>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>entities</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Entities to be included for search.(presently support added only for loans)<br></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>loanStatus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Loan status values to be included for search.<br>
|
||||
Supported loan status:["all","active","overpaid","closed","writeoff"]
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>loanProducts</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Array of loanproduct ids.
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>offices</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Array of office ids.
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>loanDateOption</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Date condition name for search query.<br>
|
||||
Supported values "approvalDate" or "createdDate" or "disbursalDate".
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>loanFromDate</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Start date for 'loanDateOption' in 'yyyy-MM-dd' format. </td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>loanToDate</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>End date for 'loanDateOption' in 'yyyy-MM-dd' format. </td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>includeOutStandingAmountPercentage</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>It is a Boolean value, allows to search percentage of loan outstanding amount with in a given range</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>outStandingAmountPercentageCondition</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Condition type for outstanding amount percentage.
|
||||
Supported values: between or <= or >= or < or > or = <br>
|
||||
When 'outStandingAmountPercentageCondition' is <b>between</b> required fields <b>minOutStandingAmountPercentage</b> and <b>maxOutStandingAmountPercentage</b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>minOutStandingAmountPercentage</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Minimum percentage of outstanding amount. <br> Mandatory when 'outStandingAmountPercentageCondition' type is 'between' </td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>maxOutStandingAmountPercentage </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Maximum percentage of outstanding amount. <br> Mandatory when 'outStandingAmountPercentageCondition' type is 'between' </td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>outStandingAmountPercentage</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Percentage of outstanding amount for search. <br> Mandatory when 'outStandingAmountPercentageCondition' type is otherthan 'between' </td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>includeOutstandingAmount</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Boolean value, allows user to search loan outstanding amount with in a given range</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>outstandingAmountCondition</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Condition type to search outstanding amount.
|
||||
Supported values: between or <= or >= or < or > or = <br>
|
||||
When 'outstandingAmountCondition' is <b>between</b> required fields <b>minOutStandingAmount</b> and <b>maxOutStandingAmount</b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>minOutStandingAmount</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Minimum value of outstanding amount for outstandingAmountCondition type between. <br> Mandatory when 'outstandingAmountCondition' type is 'between' </td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>maxOutStandingAmount</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Maximum value of outstanding amount for outstandingAmountCondition type between. <br> Mandatory when 'outstandingAmountCondition' type is 'between' </td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>outStandingAmount</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Default value of outstanding amount for search. <br> Mandatory when 'outstandingAmountCondition' type is otherthan 'between' </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<a id="advance_search_resource" name="advance_search_resource" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>AdHoc Query Search</h4>
|
||||
<p>
|
||||
AdHocQuery search has more search options, it is a <b>POST</b> request, it uses request body to send search parameters<br>
|
||||
</p>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>entities</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Optional Fields</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>
|
||||
loanStatus, loanProducts, offices, loanDateOption, loanFromDate, loanToDate, <br>includeOutStandingAmountPercentage, outStandingAmountPercentageCondition, <br>
|
||||
minOutStandingAmountPercentage and maxOutStandingAmountPercentage OR outStandingAmountPercentage, <br>includeOutstandingAmount, outstandingAmountCondition, <br>
|
||||
minOutstandingAmount and maxOutstandingAmount OR outstandingAmount</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
POST https://DomainName/api/v1/search/advance
|
||||
</code>
|
||||
<code class="method-request">
|
||||
POST search/advance
|
||||
Content-Type: application/json Request Body:
|
||||
{
|
||||
"locale": "en",
|
||||
"dateFormat": "yyyy-MM-dd",
|
||||
"entities": ["loans"],
|
||||
"loanStatus": ["all","active","overpaid"],
|
||||
"loanProducts": ["65","97","73","82"],
|
||||
"offices": ["1","10","100"],
|
||||
"loanDateOption": "approvalDate",
|
||||
"loanFromDate": "2013-01-01",
|
||||
"loanToDate": "2014-01-27",
|
||||
"includeOutStandingAmountPercentage": true,
|
||||
"outStandingAmountPercentageCondition": "<=",
|
||||
"outStandingAmountPercentage": "80",
|
||||
"includeOutstandingAmount": true,
|
||||
"outstandingAmountCondition": "between",
|
||||
"minOutstandingAmount": "100",
|
||||
"maxOutstandingAmount": "10000"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
[{
|
||||
"officeName": "HFC",
|
||||
"loanProductName": "01 BC3M",
|
||||
"count": 86,
|
||||
"loanOutStanding": 5692.41,
|
||||
"percentage": 76.4
|
||||
},
|
||||
{
|
||||
"officeName": "keithoffice",
|
||||
"loanProductName": "IGL",
|
||||
"count": 3,
|
||||
"loanOutStanding": 4168.23,
|
||||
"percentage": 56.9
|
||||
},
|
||||
{
|
||||
"officeName": "Rio",
|
||||
"loanProductName": "IGL",
|
||||
"count": 1,
|
||||
"loanOutStanding": 1681.12,
|
||||
"percentage": 55.56
|
||||
}]
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ends Search API docs-->
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ public class LoanProductData {
|
||||
* Used when returning lookup information about loan product for dropdowns.
|
||||
*/
|
||||
public static LoanProductData lookup(final Long id, final String name) {
|
||||
final String shortName = null;
|
||||
final String shortName = null;
|
||||
final String description = null;
|
||||
final CurrencyData currency = null;
|
||||
final BigDecimal principal = null;
|
||||
|
||||
+30
@@ -100,4 +100,34 @@ public class SearchConstants {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum SEARCH_LOAN_DATE {
|
||||
APPROVAL_DATE("approvalDate"), CREATED_DATE("createdDate"), DISBURSAL_DATE("disbursalDate");
|
||||
|
||||
private final String value;
|
||||
|
||||
private SEARCH_LOAN_DATE(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<String>();
|
||||
static {
|
||||
for (final SEARCH_LOAN_DATE param : SEARCH_LOAN_DATE.values()) {
|
||||
values.add(param.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
-2
@@ -10,6 +10,7 @@ import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
@@ -21,6 +22,9 @@ import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||
import org.mifosplatform.portfolio.search.SearchConstants.SEARCH_RESPONSE_PARAMETERS;
|
||||
import org.mifosplatform.portfolio.search.data.AdHocQueryDataValidator;
|
||||
import org.mifosplatform.portfolio.search.data.AdHocQuerySearchConditions;
|
||||
import org.mifosplatform.portfolio.search.data.AdHocSearchQueryData;
|
||||
import org.mifosplatform.portfolio.search.data.SearchConditions;
|
||||
import org.mifosplatform.portfolio.search.data.SearchData;
|
||||
import org.mifosplatform.portfolio.search.service.SearchReadPlatformService;
|
||||
@@ -36,18 +40,33 @@ public class SearchApiResource {
|
||||
private final Set<String> searchResponseParameters = SEARCH_RESPONSE_PARAMETERS.getAllValues();
|
||||
|
||||
private final SearchReadPlatformService searchReadPlatformService;
|
||||
private final ToApiJsonSerializer<SearchData> toApiJsonSerializer;
|
||||
private final ToApiJsonSerializer<Object> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final AdHocQueryDataValidator fromApiJsonDeserializer;
|
||||
|
||||
@Autowired
|
||||
public SearchApiResource(final SearchReadPlatformService searchReadPlatformService,
|
||||
final ToApiJsonSerializer<SearchData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper) {
|
||||
final ToApiJsonSerializer<Object> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final AdHocQueryDataValidator fromApiJsonDeserializer) {
|
||||
|
||||
this.searchReadPlatformService = searchReadPlatformService;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveAdHocSearchQueryTemplate(@Context final UriInfo uriInfo) {
|
||||
|
||||
final AdHocSearchQueryData templateData = this.searchReadPlatformService.retrieveAdHocQueryTemplate();
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, templateData);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -62,4 +81,18 @@ public class SearchApiResource {
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, searchResults, this.searchResponseParameters);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/advance")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String advancedSearch(@Context final UriInfo uriInfo,final String json) {
|
||||
|
||||
final AdHocQuerySearchConditions searchConditions = this.fromApiJsonDeserializer.retrieveSearchConditions(json);
|
||||
|
||||
final Collection<AdHocSearchQueryData> searchResults = this.searchReadPlatformService.retrieveAdHocQueryMatchingData(searchConditions);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, searchResults);
|
||||
}
|
||||
}
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
package org.mifosplatform.portfolio.search.data;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Component
|
||||
public class AdHocQueryDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public AdHocQueryDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validateAdHocQueryParameters(final String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
|
||||
AdHocQuerySearchConstants.AD_HOC_SEARCH_QUERY_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(AdHocQuerySearchConstants.AD_HOC_SEARCH_QUERY_RESOURCE_NAME);
|
||||
|
||||
final String[] entities = this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.entitiesParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.entitiesParamName).value(entities).arrayNotEmpty();
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanStatusParamName, element)) {
|
||||
final String[] loanStatus = this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.loanStatusParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanStatusParamName).value(loanStatus).arrayNotEmpty();
|
||||
if (loanStatus != null && loanStatus.length > 0) {
|
||||
for (String status : loanStatus) {
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanStatusParamName).value(status)
|
||||
.isOneOfTheseValues(AdHocQuerySearchConstants.loanStatusOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanProductsParamName, element)) {
|
||||
final String[] loanProducts = this.fromApiJsonHelper
|
||||
.extractArrayNamed(AdHocQuerySearchConstants.loanProductsParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanProductsParamName).value(loanProducts).arrayNotEmpty();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.officesParamName, element)) {
|
||||
final String[] offices = this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.officesParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.officesParamName).value(offices).arrayNotEmpty();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanDateOptionParamName, element)) {
|
||||
final String loanDateOption = this.fromApiJsonHelper.extractStringNamed(AdHocQuerySearchConstants.loanDateOptionParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanDateOptionParamName).value(loanDateOption)
|
||||
.isOneOfTheseValues(AdHocQuerySearchConstants.loanDateOptions);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanFromDateParamName, element)) {
|
||||
final LocalDate loanFromDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanFromDateParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanFromDateParamName).value(loanFromDate).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanToDateParamName, element)) {
|
||||
final LocalDate loanToDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanToDateParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanToDateParamName).value(loanToDate).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element)) {
|
||||
final boolean includeOutStandingAmountPercentage = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName)
|
||||
.value(includeOutStandingAmountPercentage).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element)) {
|
||||
final String outStandingAmountPercentageCondition = this.fromApiJsonHelper.extractStringNamed(
|
||||
AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName)
|
||||
.value(outStandingAmountPercentageCondition)
|
||||
.isNotOneOfTheseValues(AdHocQuerySearchConstants.AD_HOC_SEARCH_QUERY_CONDITIONS);
|
||||
if (outStandingAmountPercentageCondition.equals("between")) {
|
||||
final BigDecimal minOutStandingAmountPercentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName)
|
||||
.value(minOutStandingAmountPercentage).notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
final BigDecimal maxOutStandingAmountPercentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName)
|
||||
.value(maxOutStandingAmountPercentage).notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
baseDataValidator.reset().comapareMinAndMaxOfTwoBigDecmimalNos(minOutStandingAmountPercentage,
|
||||
maxOutStandingAmountPercentage);
|
||||
} else {
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element)) {
|
||||
final BigDecimal outStandingAmountPercentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outStandingAmountPercentageParamName)
|
||||
.value(outStandingAmountPercentage).notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutstandingAmountParamName, element)) {
|
||||
final Boolean includeOutstandingAmountParamName = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
AdHocQuerySearchConstants.includeOutstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.includeOutstandingAmountParamName)
|
||||
.value(includeOutstandingAmountParamName).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outstandingAmountConditionParamName, element)) {
|
||||
final String outstandingAmountCondition = this.fromApiJsonHelper.extractStringNamed(
|
||||
AdHocQuerySearchConstants.outstandingAmountConditionParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outstandingAmountConditionParamName)
|
||||
.value(outstandingAmountCondition).isNotOneOfTheseValues(AdHocQuerySearchConstants.AD_HOC_SEARCH_QUERY_CONDITIONS);
|
||||
if (outstandingAmountCondition.equals("between")) {
|
||||
final BigDecimal minOutstandingAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.minOutstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.minOutstandingAmountParamName).value(minOutstandingAmount)
|
||||
.notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
final BigDecimal maxOutstandingAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.maxOutstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.maxOutstandingAmountParamName).value(maxOutstandingAmount)
|
||||
.notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
baseDataValidator.reset().comapareMinAndMaxOfTwoBigDecmimalNos(minOutstandingAmount, maxOutstandingAmount);
|
||||
} else {
|
||||
final BigDecimal outstandingAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.outstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outstandingAmountParamName).value(outstandingAmount)
|
||||
.notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
public AdHocQuerySearchConditions retrieveSearchConditions(String json) {
|
||||
|
||||
validateAdHocQueryParameters(json);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
List<String> loanStatus = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanStatusParamName, element)) {
|
||||
loanStatus = Arrays.asList(this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.loanStatusParamName, element));
|
||||
}
|
||||
|
||||
List<Long> loanProducts = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanProductsParamName, element)) {
|
||||
loanProducts = extractLongValuesList(Arrays.asList(this.fromApiJsonHelper.extractArrayNamed(
|
||||
AdHocQuerySearchConstants.loanProductsParamName, element)));
|
||||
}
|
||||
|
||||
List<Long> offices = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.officesParamName, element)) {
|
||||
offices = extractLongValuesList(Arrays.asList(this.fromApiJsonHelper.extractArrayNamed(
|
||||
AdHocQuerySearchConstants.officesParamName, element)));
|
||||
}
|
||||
|
||||
String loanDateOption = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanDateOptionParamName, element)) {
|
||||
loanDateOption = this.fromApiJsonHelper.extractStringNamed(AdHocQuerySearchConstants.loanDateOptionParamName, element);
|
||||
}
|
||||
|
||||
LocalDate loanFromDate = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanFromDateParamName, element)) {
|
||||
loanFromDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanFromDateParamName, element);
|
||||
}
|
||||
|
||||
LocalDate loanToDate = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanToDateParamName, element)) {
|
||||
loanToDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanToDateParamName, element);
|
||||
}
|
||||
|
||||
Boolean includeOutStandingAmountPercentage = false;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element)) {
|
||||
includeOutStandingAmountPercentage = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
String outStandingAmountPercentageCondition = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element)) {
|
||||
outStandingAmountPercentageCondition = this.fromApiJsonHelper.extractStringNamed(
|
||||
AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal minOutStandingAmountPercentage = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName, element)) {
|
||||
minOutStandingAmountPercentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal maxOutStandingAmountPercentage = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName, element)) {
|
||||
maxOutStandingAmountPercentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal outStandingAmountPercentage = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element)) {
|
||||
outStandingAmountPercentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
Boolean includeOutstandingAmountParamName = false;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutstandingAmountParamName, element)) {
|
||||
includeOutstandingAmountParamName = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
AdHocQuerySearchConstants.includeOutstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
String outstandingAmountCondition = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outstandingAmountConditionParamName, element)) {
|
||||
outstandingAmountCondition = this.fromApiJsonHelper.extractStringNamed(
|
||||
AdHocQuerySearchConstants.outstandingAmountConditionParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal minOutstandingAmount = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.minOutstandingAmountParamName, element)) {
|
||||
minOutstandingAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.minOutstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal maxOutstandingAmount = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.maxOutstandingAmountParamName, element)) {
|
||||
maxOutstandingAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.maxOutstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal outstandingAmount = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outstandingAmountParamName, element)) {
|
||||
outstandingAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
AdHocQuerySearchConstants.outstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
return AdHocQuerySearchConditions.instance(loanStatus, loanProducts, offices, loanDateOption, loanFromDate, loanToDate,
|
||||
includeOutStandingAmountPercentage, outStandingAmountPercentageCondition, minOutStandingAmountPercentage,
|
||||
maxOutStandingAmountPercentage, outStandingAmountPercentage, includeOutstandingAmountParamName, outstandingAmountCondition,
|
||||
minOutstandingAmount, maxOutstandingAmount, outstandingAmount);
|
||||
|
||||
}
|
||||
|
||||
private List<Long> extractLongValuesList(List<String> listTobeConverted) {
|
||||
List<Long> tempList = new ArrayList<Long>();
|
||||
for (String temp : listTobeConverted) {
|
||||
tempList.add(Long.valueOf(temp));
|
||||
}
|
||||
return tempList;
|
||||
}
|
||||
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
package org.mifosplatform.portfolio.search.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus;
|
||||
|
||||
public class AdHocQuerySearchConditions {
|
||||
|
||||
private final List<String> loanStatus;
|
||||
private final List<Long> loanProducts;
|
||||
private final List<Long> offices;
|
||||
private final String loanDateOption;
|
||||
private final LocalDate loanFromDate;
|
||||
private final LocalDate loanToDate;
|
||||
private final Boolean includeOutStandingAmountPercentage;
|
||||
private final String outStandingAmountPercentageCondition;
|
||||
private final BigDecimal minOutStandingAmountPercentage;
|
||||
private final BigDecimal maxOutStandingAmountPercentage;
|
||||
private final BigDecimal outStandingAmountPercentage;
|
||||
private final Boolean includeOutstandingAmount;
|
||||
private final String outstandingAmountCondition;
|
||||
private final BigDecimal minOutstandingAmount;
|
||||
private final BigDecimal maxOutstandingAmount;
|
||||
private final BigDecimal outstandingAmount;
|
||||
|
||||
public static AdHocQuerySearchConditions instance(final List<String> loanStatus,
|
||||
final List<Long> loanProducts, final List<Long> offices, final String loanDateOption, final LocalDate loanFromDate,
|
||||
final LocalDate loanToDate, final Boolean includeOutStandingAmountPercentage,
|
||||
final String outStandingAmountPercentageCondition, final BigDecimal minOutStandingAmountPercentage,
|
||||
final BigDecimal maxOutStandingAmountPercentage, final BigDecimal outStandingAmountPercentage,
|
||||
final Boolean includeOutstandingAmountParamName, final String outstandingAmountCondition,
|
||||
final BigDecimal minOutstandingAmount, final BigDecimal maxOutstandingAmount, final BigDecimal outstandingAmount) {
|
||||
|
||||
return new AdHocQuerySearchConditions(loanStatus, loanProducts, offices, loanDateOption, loanFromDate, loanToDate,
|
||||
includeOutStandingAmountPercentage, outStandingAmountPercentageCondition, minOutStandingAmountPercentage,
|
||||
maxOutStandingAmountPercentage, outStandingAmountPercentage, includeOutstandingAmountParamName, outstandingAmountCondition,
|
||||
minOutstandingAmount, maxOutstandingAmount, outstandingAmount);
|
||||
|
||||
}
|
||||
|
||||
public AdHocQuerySearchConditions(final List<String> loanStatus, final List<Long> loanProducts,
|
||||
final List<Long> offices, final String loanDateOption, final LocalDate loanFromDate, final LocalDate loanToDate,
|
||||
final Boolean includeOutStandingAmountPercentage, final String outStandingAmountPercentageCondition,
|
||||
final BigDecimal minOutStandingAmountPercentage, final BigDecimal maxOutStandingAmountPercentage,
|
||||
final BigDecimal outStandingAmountPercentage, final Boolean includeOutstandingAmount, final String outstandingAmountCondition,
|
||||
final BigDecimal minOutstandingAmount, final BigDecimal maxOutstandingAmount, final BigDecimal outstandingAmount) {
|
||||
|
||||
this.loanStatus = loanStatus;
|
||||
this.loanProducts = loanProducts;
|
||||
this.offices = offices;
|
||||
this.loanDateOption = loanDateOption;
|
||||
this.loanFromDate = loanFromDate;
|
||||
this.loanToDate = loanToDate;
|
||||
this.includeOutStandingAmountPercentage = includeOutStandingAmountPercentage;
|
||||
this.outStandingAmountPercentageCondition = outStandingAmountPercentageCondition;
|
||||
this.minOutStandingAmountPercentage = minOutStandingAmountPercentage;
|
||||
this.maxOutStandingAmountPercentage = maxOutStandingAmountPercentage;
|
||||
this.outStandingAmountPercentage = outStandingAmountPercentage;
|
||||
this.includeOutstandingAmount = includeOutstandingAmount;
|
||||
this.outstandingAmountCondition = outstandingAmountCondition;
|
||||
this.minOutstandingAmount = minOutstandingAmount;
|
||||
this.maxOutstandingAmount = maxOutstandingAmount;
|
||||
this.outstandingAmount = outstandingAmount;
|
||||
|
||||
}
|
||||
|
||||
public List<String> getLoanStatus() {
|
||||
return getStatusVluesFromStatusCodes();
|
||||
}
|
||||
|
||||
private List<String> getStatusVluesFromStatusCodes() {
|
||||
List<String> loanStatusValues = new ArrayList<String>();
|
||||
if (this.loanStatus != null) {
|
||||
for (String statusCode : this.loanStatus) {
|
||||
|
||||
if (statusCode.equalsIgnoreCase("active")) {
|
||||
loanStatusValues.add(LoanStatus.ACTIVE.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("overpaid")) {
|
||||
loanStatusValues.add(LoanStatus.OVERPAID.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("closed")) {
|
||||
loanStatusValues.add(LoanStatus.CLOSED_OBLIGATIONS_MET.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("writeoff")) {
|
||||
loanStatusValues.add(LoanStatus.CLOSED_WRITTEN_OFF.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("arrears")) {
|
||||
//TODO - No status code is there for loans which are in active bad standing
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("all")) {
|
||||
loanStatusValues.add("all");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loanStatusValues;
|
||||
}
|
||||
|
||||
public List<Long> getLoanProducts() {
|
||||
return this.loanProducts;
|
||||
}
|
||||
|
||||
public List<Long> getOffices() {
|
||||
return this.offices;
|
||||
}
|
||||
|
||||
public String getLoanDateOption() {
|
||||
return this.loanDateOption;
|
||||
}
|
||||
|
||||
public LocalDate getLoanFromDate() {
|
||||
return this.loanFromDate;
|
||||
}
|
||||
|
||||
public LocalDate getLoanToDate() {
|
||||
return this.loanToDate;
|
||||
}
|
||||
|
||||
public Boolean getIncludeOutStandingAmountPercentage() {
|
||||
return this.includeOutStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public String getOutStandingAmountPercentageCondition() {
|
||||
return this.outStandingAmountPercentageCondition;
|
||||
}
|
||||
|
||||
public BigDecimal getMinOutStandingAmountPercentage() {
|
||||
return this.minOutStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxOutStandingAmountPercentage() {
|
||||
return this.maxOutStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public BigDecimal getOutStandingAmountPercentage() {
|
||||
return this.outStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public Boolean getIncludeOutstandingAmount() {
|
||||
return this.includeOutstandingAmount;
|
||||
}
|
||||
|
||||
public String getOutstandingAmountCondition() {
|
||||
return this.outstandingAmountCondition;
|
||||
}
|
||||
|
||||
public BigDecimal getMinOutstandingAmount() {
|
||||
return this.minOutstandingAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxOutstandingAmount() {
|
||||
return this.maxOutstandingAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getOutstandingAmount() {
|
||||
return this.outstandingAmount;
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package org.mifosplatform.portfolio.search.data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public interface AdHocQuerySearchConstants {
|
||||
|
||||
public static final String AD_HOC_SEARCH_QUERY_RESOURCE_NAME = "adHocQuery";
|
||||
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
public static final String entitiesParamName = "entities";
|
||||
public static final String loanStatusParamName = "loanStatus";
|
||||
public static final String loanProductsParamName = "loanProducts";
|
||||
public static final String officesParamName = "offices";
|
||||
public static final String loanDateOptionParamName = "loanDateOption";
|
||||
public static final String loanFromDateParamName = "loanFromDate";
|
||||
public static final String loanToDateParamName = "loanToDate";
|
||||
public static final String includeOutStandingAmountPercentageParamName = "includeOutStandingAmountPercentage";
|
||||
public static final String outStandingAmountPercentageConditionParamName = "outStandingAmountPercentageCondition";
|
||||
public static final String minOutStandingAmountPercentageParamName = "minOutStandingAmountPercentage";
|
||||
public static final String maxOutStandingAmountPercentageParamName = "maxOutStandingAmountPercentage";
|
||||
public static final String outStandingAmountPercentageParamName = "outStandingAmountPercentage";
|
||||
public static final String includeOutstandingAmountParamName = "includeOutstandingAmount";
|
||||
public static final String outstandingAmountConditionParamName = "outstandingAmountCondition";
|
||||
public static final String minOutstandingAmountParamName = "minOutstandingAmount";
|
||||
public static final String maxOutstandingAmountParamName = "maxOutstandingAmount";
|
||||
public static final String outstandingAmountParamName = "outstandingAmount";
|
||||
|
||||
public static final Set<String> AD_HOC_SEARCH_QUERY_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(loanStatusParamName,
|
||||
loanProductsParamName, officesParamName, loanDateOptionParamName, loanFromDateParamName, loanToDateParamName,
|
||||
includeOutStandingAmountPercentageParamName, outStandingAmountPercentageConditionParamName,
|
||||
minOutStandingAmountPercentageParamName, maxOutStandingAmountPercentageParamName, outStandingAmountPercentageParamName,
|
||||
includeOutstandingAmountParamName, outstandingAmountConditionParamName, minOutstandingAmountParamName,
|
||||
maxOutstandingAmountParamName, outstandingAmountParamName, localeParamName, dateFormatParamName));
|
||||
|
||||
public static final Set<String> AD_HOC_SEARCH_QUERY_CONDITIONS = new HashSet<String>(
|
||||
Arrays.asList("between", "<=", ">=", "<", ">", "="));
|
||||
|
||||
public static final Object[] loanDateOptions = {"approvalDate", "createdDate", "disbursalDate"};
|
||||
public static final Object[] entityTypeOptions = {"clients", "groups", "loans", "clientIdentifiers"};
|
||||
public static final Object[] loanStatusOptions = {"all", "active", "overpaid", "arrears", "closed", "writeoff"};
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package org.mifosplatform.portfolio.search.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
|
||||
|
||||
public class AdHocSearchQueryData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final String officeName;
|
||||
@SuppressWarnings("unused")
|
||||
private final String loanProductName;
|
||||
@SuppressWarnings("unused")
|
||||
private final Integer count;
|
||||
@SuppressWarnings("unused")
|
||||
private final BigDecimal loanOutStanding;
|
||||
@SuppressWarnings("unused")
|
||||
private final Double percentage;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<LoanProductData> loanProducts;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<OfficeData> offices;
|
||||
|
||||
public static AdHocSearchQueryData template(final Collection<LoanProductData> loanProducts, final Collection<OfficeData> offices) {
|
||||
final String officeName = null;
|
||||
final String loanProductName = null;
|
||||
final Integer count = null;
|
||||
final BigDecimal loanOutStanding = null;
|
||||
final Double percentage = null;
|
||||
return new AdHocSearchQueryData(officeName, loanProductName, count, loanOutStanding, percentage, loanProducts, offices);
|
||||
}
|
||||
|
||||
public static AdHocSearchQueryData matchedResult(final String officeName, final String loanProductName, final Integer count,
|
||||
final BigDecimal loanOutStanding, final Double percentage) {
|
||||
|
||||
final Collection<LoanProductData> loanProducts = null;
|
||||
final Collection<OfficeData> offices = null;
|
||||
return new AdHocSearchQueryData(officeName, loanProductName, count, loanOutStanding, percentage, loanProducts, offices);
|
||||
}
|
||||
|
||||
private AdHocSearchQueryData(final String officeName, final String loanProductName, final Integer count,
|
||||
final BigDecimal loanOutStanding, final Double percentage, final Collection<LoanProductData> loanProducts,
|
||||
final Collection<OfficeData> offices) {
|
||||
|
||||
this.officeName = officeName;
|
||||
this.loanProductName = loanProductName;
|
||||
this.count = count;
|
||||
this.loanOutStanding = loanOutStanding;
|
||||
this.percentage = percentage;
|
||||
|
||||
this.loanProducts = loanProducts;
|
||||
this.offices = offices;
|
||||
}
|
||||
}
|
||||
+6
@@ -7,10 +7,16 @@ package org.mifosplatform.portfolio.search.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.portfolio.search.data.AdHocQuerySearchConditions;
|
||||
import org.mifosplatform.portfolio.search.data.AdHocSearchQueryData;
|
||||
import org.mifosplatform.portfolio.search.data.SearchConditions;
|
||||
import org.mifosplatform.portfolio.search.data.SearchData;
|
||||
|
||||
public interface SearchReadPlatformService {
|
||||
|
||||
Collection<SearchData> retriveMatchingData(SearchConditions searchConditions);
|
||||
|
||||
AdHocSearchQueryData retrieveAdHocQueryTemplate();
|
||||
|
||||
Collection<AdHocSearchQueryData> retrieveAdHocQueryMatchingData(AdHocQuerySearchConditions searchConditions);
|
||||
}
|
||||
|
||||
+157
-1
@@ -5,13 +5,23 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.search.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
|
||||
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
|
||||
import org.mifosplatform.portfolio.loanproduct.service.LoanProductReadPlatformService;
|
||||
import org.mifosplatform.portfolio.search.SearchConstants;
|
||||
import org.mifosplatform.portfolio.search.data.AdHocQuerySearchConditions;
|
||||
import org.mifosplatform.portfolio.search.data.AdHocSearchQueryData;
|
||||
import org.mifosplatform.portfolio.search.data.SearchConditions;
|
||||
import org.mifosplatform.portfolio.search.data.SearchData;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
@@ -26,11 +36,16 @@ public class SearchReadPlatformServiceImpl implements SearchReadPlatformService
|
||||
|
||||
private final NamedParameterJdbcTemplate namedParameterjdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final LoanProductReadPlatformService loanProductReadPlatformService;
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public SearchReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource) {
|
||||
public SearchReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
|
||||
final LoanProductReadPlatformService loanProductReadPlatformService, final OfficeReadPlatformService officeReadPlatformService ) {
|
||||
this.context = context;
|
||||
this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
this.loanProductReadPlatformService = loanProductReadPlatformService;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,4 +160,145 @@ public class SearchReadPlatformServiceImpl implements SearchReadPlatformService
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdHocSearchQueryData retrieveAdHocQueryTemplate() {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final Collection<LoanProductData> loanProducts = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup();
|
||||
final Collection<OfficeData> offices = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
|
||||
return AdHocSearchQueryData.template(loanProducts, offices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AdHocSearchQueryData> retrieveAdHocQueryMatchingData(final AdHocQuerySearchConditions searchConditions) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final AdHocQuerySearchMapper rm = new AdHocQuerySearchMapper();
|
||||
final MapSqlParameterSource params = new MapSqlParameterSource();
|
||||
|
||||
return this.namedParameterjdbcTemplate.query(rm.schema(searchConditions, params), params, rm);
|
||||
}
|
||||
|
||||
private static final class AdHocQuerySearchMapper implements RowMapper<AdHocSearchQueryData> {
|
||||
|
||||
private boolean isWhereClauseAdded = false;
|
||||
|
||||
//TODO- build the query dynamically based on selected entity types, for now adding query for only loan entity.
|
||||
public String schema(final AdHocQuerySearchConditions searchConditions, final MapSqlParameterSource params) {
|
||||
final StringBuffer sql = new StringBuffer();
|
||||
sql.append("Select a.name as officeName, a.Product as productName, a.cnt as 'count', a.outstandingAmt as outstanding, a.percentOut as percentOut ")
|
||||
.append("from (select mo.name, mp.name Product, sum(ifnull(ml.total_expected_repayment_derived,0.0)) TotalAmt, count(*) cnt, ")
|
||||
.append("sum(ifnull(ml.total_outstanding_derived,0.0)) outstandingAmt, ")
|
||||
.append("(sum(ifnull(ml.total_outstanding_derived,0.0)) * 100 / sum(ifnull(ml.total_expected_repayment_derived,0.0))) percentOut ")
|
||||
.append("from m_loan ml inner join m_product_loan mp on mp.id=ml.product_id ")
|
||||
.append("inner join m_client mc on mc.id=ml.client_id ")
|
||||
.append("inner join m_office mo on mo.id=mc.office_id ");
|
||||
|
||||
if (searchConditions.getLoanStatus() != null && searchConditions.getLoanStatus().size() > 0) {
|
||||
//If user requests for all statuses no need to add loanStatus filter
|
||||
if (!searchConditions.getLoanStatus().contains("all")) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
params.addValue("loanStatus", searchConditions.getLoanStatus());
|
||||
sql.append(" ml.loan_status_id in (:loanStatus) ");
|
||||
}
|
||||
}
|
||||
|
||||
if (searchConditions.getLoanProducts() != null && searchConditions.getLoanProducts().size() > 0 ) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
params.addValue("loanProducts", searchConditions.getLoanProducts());
|
||||
sql.append(" mp.id in (:loanProducts) ");
|
||||
}
|
||||
|
||||
if (searchConditions.getOffices() != null && searchConditions.getOffices().size() > 0) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
params.addValue("offices", searchConditions.getOffices());
|
||||
sql.append(" mo.id in (:offices) ");
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(searchConditions.getLoanDateOption())) {
|
||||
if (searchConditions.getLoanDateOption().equals(SearchConstants.SEARCH_LOAN_DATE.APPROVAL_DATE.getValue())) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
params.addValue("loanFromDate", searchConditions.getLoanFromDate().toDate());
|
||||
params.addValue("loanToDate", searchConditions.getLoanToDate().toDate());
|
||||
sql.append(" ( ml.approvedon_date between :loanFromDate and :loanToDate ) ");
|
||||
} else if (searchConditions.getLoanDateOption().equals(SearchConstants.SEARCH_LOAN_DATE.CREATED_DATE.getValue())) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
params.addValue("loanFromDate", searchConditions.getLoanFromDate().toDate());
|
||||
params.addValue("loanToDate", searchConditions.getLoanToDate().toDate());
|
||||
sql.append(" ( ml.submittedon_date between :loanFromDate and :loanToDate ) ");
|
||||
} else if (searchConditions.getLoanDateOption().equals(SearchConstants.SEARCH_LOAN_DATE.DISBURSAL_DATE.getValue())) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
params.addValue("loanFromDate", searchConditions.getLoanFromDate().toDate());
|
||||
params.addValue("loanToDate", searchConditions.getLoanToDate().toDate());
|
||||
sql.append(" ( ml.disbursedon_date between :loanFromDate and :loanToDate ) ");
|
||||
}
|
||||
}
|
||||
|
||||
sql.append(" group by mo.id) a ");
|
||||
|
||||
//update isWhereClauseAdded to false to add filters for derived table
|
||||
isWhereClauseAdded = false;
|
||||
|
||||
if (searchConditions.getIncludeOutStandingAmountPercentage()) {
|
||||
if (searchConditions.getOutStandingAmountPercentageCondition().equals("between")) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
// params.addValue("outStandingAmountPercentageCondition", searchConditions.getOutStandingAmountPercentageCondition());
|
||||
params.addValue("minOutStandingAmountPercentage", searchConditions.getMinOutStandingAmountPercentage());
|
||||
params.addValue("maxOutStandingAmountPercentage", searchConditions.getMaxOutStandingAmountPercentage());
|
||||
sql.append(" ( a.percentOut between :minOutStandingAmountPercentage and :maxOutStandingAmountPercentage ) ");
|
||||
} else {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
// params.addValue("outStandingAmountPercentageCondition", searchConditions.getOutStandingAmountPercentageCondition());
|
||||
params.addValue("outStandingAmountPercentage", searchConditions.getOutStandingAmountPercentage());
|
||||
sql.append(" a.percentOut ")
|
||||
.append(searchConditions.getOutStandingAmountPercentageCondition())
|
||||
.append(" :outStandingAmountPercentage ");
|
||||
}
|
||||
}
|
||||
|
||||
if (searchConditions.getIncludeOutstandingAmount()) {
|
||||
if (searchConditions.getOutstandingAmountCondition().equals("between")) {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
// params.addValue("outstandingAmountCondition", searchConditions.getOutstandingAmountCondition());
|
||||
params.addValue("minOutstandingAmount", searchConditions.getMinOutstandingAmount());
|
||||
params.addValue("maxOutstandingAmount", searchConditions.getMaxOutstandingAmount());
|
||||
sql.append(" ( a.outstandingAmt between :minOutstandingAmount and :maxOutstandingAmount ) ");
|
||||
} else {
|
||||
checkAndUpdateWhereClause(sql);
|
||||
// params.addValue("outstandingAmountCondition", searchConditions.getOutstandingAmountCondition());
|
||||
params.addValue("outstandingAmount", searchConditions.getOutstandingAmount());
|
||||
sql.append(" a.outstandingAmt ")
|
||||
.append(searchConditions.getOutstandingAmountCondition())
|
||||
.append(" :outstandingAmount ");
|
||||
}
|
||||
}
|
||||
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
private void checkAndUpdateWhereClause(final StringBuffer sql){
|
||||
if (isWhereClauseAdded) {
|
||||
sql.append(" and ");
|
||||
} else {
|
||||
sql.append(" where ");
|
||||
isWhereClauseAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdHocSearchQueryData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
|
||||
|
||||
final String officeName = rs.getString("officeName");
|
||||
final String loanProductName = rs.getString("productName");
|
||||
final Integer count = JdbcSupport.getInteger(rs, "count");
|
||||
final BigDecimal loanOutStanding = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "outstanding").setScale(2, RoundingMode.HALF_UP);
|
||||
final Double percentage = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "percentOut").setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
return AdHocSearchQueryData.matchedResult(officeName, loanProductName, count, loanOutStanding, percentage);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user