This is an automated email from the ASF dual-hosted git repository. ptuomola pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract.git
commit db232c60883300953a0435a550a05b8d7343119c Author: Manthan Surkar <[email protected]> AuthorDate: Thu Aug 6 00:44:07 2020 +0530 FINERACT-1095 Added status parameter in Clients API --- .../fineract/integrationtests/ClientTest.java | 42 +++++++++++++++++-- .../integrationtests/common/ClientHelper.java | 9 +++++ .../core/service/SearchParameters.java | 47 ++++++++++++++++++++-- .../portfolio/client/api/ClientsApiResource.java | 12 +++--- .../portfolio/client/domain/ClientStatus.java | 29 +++++++++++++ .../service/ClientReadPlatformServiceImpl.java | 21 ++++++++++ .../self/client/api/SelfClientsApiResource.java | 5 ++- 7 files changed, 150 insertions(+), 15 deletions(-) diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientTest.java index 7c1978b..6c3133b 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientTest.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientTest.java @@ -18,12 +18,16 @@ */ package org.apache.fineract.integrationtests; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; import java.util.HashMap; +import java.util.List; +import java.util.Random; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.Utils; import org.junit.jupiter.api.Assertions; @@ -42,12 +46,12 @@ public class ClientTest { this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - + this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); } @Test public void testClientStatus() { - this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); + final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); Assertions.assertNotNull(clientId); @@ -80,7 +84,6 @@ public class ClientTest { @Test public void testClientAsPersonStatus() { - this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); final Integer clientId = ClientHelper.createClientAsPerson(this.requestSpec, this.responseSpec); Assertions.assertNotNull(clientId); @@ -113,7 +116,6 @@ public class ClientTest { @Test public void testClientAsEntityStatus() { - this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); final Integer clientId = ClientHelper.createClientAsEntity(this.requestSpec, this.responseSpec); Assertions.assertNotNull(clientId); @@ -143,4 +145,36 @@ public class ClientTest { } + @SuppressWarnings("unchecked") + @Test + public void testPendingOnlyClientRequest() { + + Random rand = new Random(); + // Add a few clients to the server and activate a random amount of them + for (int i = 0; i < 15; i++) { + final Integer clientId = ClientHelper.createClientAsEntity(this.requestSpec, this.responseSpec); + if (rand.nextInt(10) % 2 == 0) { + // Takes Client to pending status + this.clientHelper.closeClient(clientId); + this.clientHelper.reactivateClient(clientId); + } + // Other clients stay in Active status + } + List<HashMap<String, Object>> clientsRecieved = (List<HashMap<String, Object>>) clientHelper.getClientWithStatus(50, "pending"); + assertNotEquals(clientsRecieved.size(), 0); + for (int i = 0; i < clientsRecieved.size(); i++) { + HashMap<String, Object> clientStatus = ClientHelper.getClientStatus(requestSpec, responseSpec, + String.valueOf(clientsRecieved.get(i).get("id"))); + ClientStatusChecker.verifyClientPending(clientStatus); + } + + clientsRecieved = (List<HashMap<String, Object>>) clientHelper.getClientWithStatus(50, "active"); + assertNotEquals(clientsRecieved.size(), 0); + for (int i = 0; i < clientsRecieved.size(); i++) { + HashMap<String, Object> clientStatus = ClientHelper.getClientStatus(requestSpec, responseSpec, + String.valueOf(clientsRecieved.get(i).get("id"))); + ClientStatusChecker.verifyClientIsActive(clientStatus); + } + } + } diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java index f22f729..2cc5f3f 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; @@ -622,4 +623,12 @@ public class ClientHelper { return Utils.performServerTemplatePost(requestSpec, responseSpec, CLIENT_URL + "/uploadtemplate" + "?" + Utils.TENANT_IDENTIFIER, legalFormType, file, locale, dateFormat); } + + public List getClientWithStatus(final int limit, final String status) { + final String URL = "/fineract-provider/api/v1/clients?paged=true&status=" + status + "&limit=" + Integer.toString(limit) + "&" + + Utils.TENANT_IDENTIFIER; + LinkedHashMap responseClients = Utils.performServerGet(requestSpec, responseSpec, URL, ""); + return (List) responseClients.get("pageItems"); + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java index f51efd6..11e8af5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java @@ -29,6 +29,7 @@ public final class SearchParameters { private final String hierarchy; private final String firstname; private final String lastname; + private final String status; private final Integer offset; private final Integer limit; private final String orderBy; @@ -62,8 +63,9 @@ public final class SearchParameters { } public static SearchParameters forClients(final String sqlSearch, final Long officeId, final String externalId, - final String displayName, final String firstname, final String lastname, final String hierarchy, final Integer offset, - final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, final boolean isSelfUser) { + final String displayName, final String firstname, final String lastname, final String status, final String hierarchy, + final Integer offset, final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, + final boolean isSelfUser) { final Integer maxLimitAllowed = getCheckedLimit(limit); final Long staffId = null; @@ -71,8 +73,8 @@ public final class SearchParameters { final Long loanId = null; final Long savingsId = null; - return new SearchParameters(sqlSearch, officeId, externalId, displayName, hierarchy, firstname, lastname, offset, maxLimitAllowed, - orderBy, sortOrder, staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser); + return new SearchParameters(sqlSearch, officeId, externalId, displayName, hierarchy, firstname, lastname, status, offset, + maxLimitAllowed, orderBy, sortOrder, staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser); } public static SearchParameters forGroups(final String sqlSearch, final Long officeId, final Long staffId, final String externalId, @@ -266,6 +268,36 @@ public final class SearchParameters { this.productId = null; this.categoryId = null; this.isSelfUser = isSelfUser; + this.status = null; + + } + + private SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, + final String hierarchy, final String firstname, final String lastname, final String status, final Integer offset, + final Integer limit, final String orderBy, final String sortOrder, final Long staffId, final String accountNo, + final Long loanId, final Long savingsId, final Boolean orphansOnly, boolean isSelfUser) { + this.sqlSearch = sqlSearch; + this.officeId = officeId; + this.externalId = externalId; + this.name = name; + this.hierarchy = hierarchy; + this.firstname = firstname; + this.lastname = lastname; + this.offset = offset; + this.limit = limit; + this.orderBy = orderBy; + this.sortOrder = sortOrder; + this.staffId = staffId; + this.accountNo = accountNo; + this.loanId = loanId; + this.savingsId = savingsId; + this.orphansOnly = orphansOnly; + this.currencyCode = null; + this.provisioningEntryId = null; + this.productId = null; + this.categoryId = null; + this.isSelfUser = isSelfUser; + this.status = status; } @@ -292,6 +324,7 @@ public final class SearchParameters { this.productId = productId; this.categoryId = categoryId; this.isSelfUser = false; + this.status = null; } @@ -320,6 +353,8 @@ public final class SearchParameters { this.productId = null; this.categoryId = null; this.isSelfUser = false; + this.status = null; + } public boolean isOrderByRequested() { @@ -398,6 +433,10 @@ public final class SearchParameters { return this.lastname; } + public String getStatus() { + return this.status; + } + public Integer getOffset() { return this.offset; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java index fc3f163..986ca24 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java @@ -166,6 +166,7 @@ public class ClientsApiResource { @QueryParam("displayName") @Parameter(description = "displayName") final String displayName, @QueryParam("firstName") @Parameter(description = "firstName") final String firstname, @QueryParam("lastName") @Parameter(description = "lastName") final String lastname, + @QueryParam("status") @Parameter(description = "status") final String status, @QueryParam("underHierarchy") @Parameter(description = "underHierarchy") final String hierarchy, @QueryParam("offset") @Parameter(description = "offset") final Integer offset, @QueryParam("limit") @Parameter(description = "limit") final Integer limit, @@ -173,18 +174,19 @@ public class ClientsApiResource { @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, @QueryParam("orphansOnly") @Parameter(description = "orphansOnly") final Boolean orphansOnly) { - return this.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, hierarchy, offset, limit, - orderBy, sortOrder, orphansOnly, false); + return this.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, status, hierarchy, offset, + limit, orderBy, sortOrder, orphansOnly, false); } public String retrieveAll(final UriInfo uriInfo, final String sqlSearch, final Long officeId, final String externalId, - final String displayName, final String firstname, final String lastname, final String hierarchy, final Integer offset, - final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, final boolean isSelfUser) { + final String displayName, final String firstname, final String lastname, final String status, final String hierarchy, + final Integer offset, final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, + final boolean isSelfUser) { this.context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME); final SearchParameters searchParameters = SearchParameters.forClients(sqlSearch, officeId, externalId, displayName, firstname, - lastname, hierarchy, offset, limit, orderBy, sortOrder, orphansOnly, isSelfUser); + lastname, status, hierarchy, offset, limit, orderBy, sortOrder, orphansOnly, isSelfUser); final Page<ClientData> clientData = this.clientReadPlatformService.retrieveAll(searchParameters); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientStatus.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientStatus.java index 70cb708..87c4845 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientStatus.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientStatus.java @@ -18,6 +18,8 @@ */ package org.apache.fineract.portfolio.client.domain; +import org.springframework.util.StringUtils; + /** * Enum representation of client status states. */ @@ -63,6 +65,33 @@ public enum ClientStatus { return enumeration; } + public static ClientStatus fromString(final String clientString) { + + ClientStatus clientStatus = ClientStatus.INVALID; + + if (StringUtils.isEmpty(clientString)) { + return clientStatus; + } + + if (clientString.equalsIgnoreCase(ClientStatus.PENDING.toString())) { + clientStatus = ClientStatus.PENDING; + } else if (clientString.equalsIgnoreCase(ClientStatus.ACTIVE.toString())) { + clientStatus = ClientStatus.ACTIVE; + } else if (clientString.equalsIgnoreCase(ClientStatus.TRANSFER_IN_PROGRESS.toString())) { + clientStatus = ClientStatus.TRANSFER_IN_PROGRESS; + } else if (clientString.equalsIgnoreCase(ClientStatus.WITHDRAWN.toString())) { + clientStatus = ClientStatus.WITHDRAWN; + } else if (clientString.equalsIgnoreCase(ClientStatus.CLOSED.toString())) { + clientStatus = ClientStatus.CLOSED; + } else if (clientString.equalsIgnoreCase(ClientStatus.TRANSFER_ON_HOLD.toString())) { + clientStatus = ClientStatus.TRANSFER_ON_HOLD; + } else if (clientString.equalsIgnoreCase(ClientStatus.REJECTED.toString())) { + clientStatus = ClientStatus.REJECTED; + } + + return clientStatus; + } + private ClientStatus(final Integer value, final String code) { this.value = value; this.code = code; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java index 9bf6ccf..d295786 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java @@ -30,8 +30,10 @@ import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData; import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.infrastructure.core.domain.JdbcSupport; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.service.Page; import org.apache.fineract.infrastructure.core.service.PaginationHelper; import org.apache.fineract.infrastructure.core.service.RoutingDataSource; @@ -90,6 +92,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService private final ConfigurationReadPlatformService configurationReadPlatformService; private final EntityDatatableChecksReadService entityDatatableChecksReadService; private final ColumnValidator columnValidator; + private final List<String> supportedStatusvalues = new ArrayList<String>( + Arrays.asList("pending", "active", "withdrawn", "closed", "rejected", "transfer_on_hold", "transfer_in_progreess")); @Autowired public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, @@ -176,6 +180,17 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService // @Transactional(readOnly=true) public Page<ClientData> retrieveAll(final SearchParameters searchParameters) { + if (searchParameters != null && searchParameters.getStatus() != null + && !supportedStatusvalues.contains(searchParameters.getStatus())) { + final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); + final String defaultUserMessage = "The Status value '" + searchParameters.getStatus() + + "' is not supported. The supported status values are " + supportedStatusvalues.toString(); + final ApiParameterError error = ApiParameterError.parameterError("validation.msg.client.status.value.is.not.supported", + defaultUserMessage, "status", searchParameters.getStatus(), supportedStatusvalues.toString()); + dataValidationErrors.add(error); + throw new PlatformApiDataValidationException(dataValidationErrors); + } + final String userOfficeHierarchy = this.context.officeHierarchy(); final String underHierarchySearchString = userOfficeHierarchy + "%"; final String appUserID = String.valueOf(context.authenticatedUser().getId()); @@ -232,6 +247,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final String displayName = searchParameters.getName(); final String firstname = searchParameters.getFirstname(); final String lastname = searchParameters.getLastname(); + final String status = searchParameters.getStatus(); String extraCriteria = ""; if (sqlSearch != null) { @@ -258,6 +274,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService extraCriteria += " and c.display_name like ? "; } + if (status != null) { + ClientStatus clientStatus = ClientStatus.fromString(status); + extraCriteria += " and c.status_enum = " + clientStatus.getValue().toString() + " "; + } + if (firstname != null) { paramList.add(firstname); extraCriteria += " and c.firstname like ? "; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java index a7efcbd..6dd3af7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java @@ -99,6 +99,7 @@ public class SelfClientsApiResource { @QueryParam("firstName") @Parameter(description = "firstName") final String firstname, @QueryParam("lastName") @Parameter(description = "lastName") final String lastname, @QueryParam("offset") @Parameter(description = "offset") final Integer offset, + @QueryParam("status") @Parameter(description = "status") final String status, @QueryParam("limit") @Parameter(description = "limit") final Integer limit, @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { @@ -108,8 +109,8 @@ public class SelfClientsApiResource { final String externalId = null; final String hierarchy = null; final Boolean orphansOnly = null; - return this.clientApiResource.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, hierarchy, - offset, limit, orderBy, sortOrder, orphansOnly, true); + return this.clientApiResource.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, status, + hierarchy, offset, limit, orderBy, sortOrder, orphansOnly, true); } @GET
