FINERACT-1095 Added status parameter in Clients API

This commit is contained in:
Manthan Surkar
2020-08-15 04:58:51 +03:00
committed by Petri Tuomola
parent bd9119e35f
commit db232c6088
7 changed files with 150 additions and 15 deletions
@@ -18,12 +18,16 @@
*/ */
package org.apache.fineract.integrationtests; package org.apache.fineract.integrationtests;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder; import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification; import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification; import io.restassured.specification.ResponseSpecification;
import java.util.HashMap; 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.ClientHelper;
import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
@@ -42,12 +46,12 @@ public class ClientTest {
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
} }
@Test @Test
public void testClientStatus() { public void testClientStatus() {
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId); Assertions.assertNotNull(clientId);
@@ -80,7 +84,6 @@ public class ClientTest {
@Test @Test
public void testClientAsPersonStatus() { public void testClientAsPersonStatus() {
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
final Integer clientId = ClientHelper.createClientAsPerson(this.requestSpec, this.responseSpec); final Integer clientId = ClientHelper.createClientAsPerson(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId); Assertions.assertNotNull(clientId);
@@ -113,7 +116,6 @@ public class ClientTest {
@Test @Test
public void testClientAsEntityStatus() { public void testClientAsEntityStatus() {
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
final Integer clientId = ClientHelper.createClientAsEntity(this.requestSpec, this.responseSpec); final Integer clientId = ClientHelper.createClientAsEntity(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId); 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);
}
}
} }
@@ -29,6 +29,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
@@ -622,4 +623,12 @@ public class ClientHelper {
return Utils.performServerTemplatePost(requestSpec, responseSpec, CLIENT_URL + "/uploadtemplate" + "?" + Utils.TENANT_IDENTIFIER, return Utils.performServerTemplatePost(requestSpec, responseSpec, CLIENT_URL + "/uploadtemplate" + "?" + Utils.TENANT_IDENTIFIER,
legalFormType, file, locale, dateFormat); 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");
}
} }
@@ -29,6 +29,7 @@ public final class SearchParameters {
private final String hierarchy; private final String hierarchy;
private final String firstname; private final String firstname;
private final String lastname; private final String lastname;
private final String status;
private final Integer offset; private final Integer offset;
private final Integer limit; private final Integer limit;
private final String orderBy; 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, 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 String displayName, final String firstname, final String lastname, final String status, final String hierarchy,
final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, final boolean isSelfUser) { final Integer offset, final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly,
final boolean isSelfUser) {
final Integer maxLimitAllowed = getCheckedLimit(limit); final Integer maxLimitAllowed = getCheckedLimit(limit);
final Long staffId = null; final Long staffId = null;
@@ -71,8 +73,8 @@ public final class SearchParameters {
final Long loanId = null; final Long loanId = null;
final Long savingsId = null; final Long savingsId = null;
return new SearchParameters(sqlSearch, officeId, externalId, displayName, hierarchy, firstname, lastname, offset, maxLimitAllowed, return new SearchParameters(sqlSearch, officeId, externalId, displayName, hierarchy, firstname, lastname, status, offset,
orderBy, sortOrder, staffId, accountNo, loanId, savingsId, orphansOnly, isSelfUser); 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, 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.productId = null;
this.categoryId = null; this.categoryId = null;
this.isSelfUser = isSelfUser; 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.productId = productId;
this.categoryId = categoryId; this.categoryId = categoryId;
this.isSelfUser = false; this.isSelfUser = false;
this.status = null;
} }
@@ -320,6 +353,8 @@ public final class SearchParameters {
this.productId = null; this.productId = null;
this.categoryId = null; this.categoryId = null;
this.isSelfUser = false; this.isSelfUser = false;
this.status = null;
} }
public boolean isOrderByRequested() { public boolean isOrderByRequested() {
@@ -398,6 +433,10 @@ public final class SearchParameters {
return this.lastname; return this.lastname;
} }
public String getStatus() {
return this.status;
}
public Integer getOffset() { public Integer getOffset() {
return this.offset; return this.offset;
} }
@@ -166,6 +166,7 @@ public class ClientsApiResource {
@QueryParam("displayName") @Parameter(description = "displayName") final String displayName, @QueryParam("displayName") @Parameter(description = "displayName") final String displayName,
@QueryParam("firstName") @Parameter(description = "firstName") final String firstname, @QueryParam("firstName") @Parameter(description = "firstName") final String firstname,
@QueryParam("lastName") @Parameter(description = "lastName") final String lastname, @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("underHierarchy") @Parameter(description = "underHierarchy") final String hierarchy,
@QueryParam("offset") @Parameter(description = "offset") final Integer offset, @QueryParam("offset") @Parameter(description = "offset") final Integer offset,
@QueryParam("limit") @Parameter(description = "limit") final Integer limit, @QueryParam("limit") @Parameter(description = "limit") final Integer limit,
@@ -173,18 +174,19 @@ public class ClientsApiResource {
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder,
@QueryParam("orphansOnly") @Parameter(description = "orphansOnly") final Boolean orphansOnly) { @QueryParam("orphansOnly") @Parameter(description = "orphansOnly") final Boolean orphansOnly) {
return this.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, hierarchy, offset, limit, return this.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, status, hierarchy, offset,
orderBy, sortOrder, orphansOnly, false); limit, orderBy, sortOrder, orphansOnly, false);
} }
public String retrieveAll(final UriInfo uriInfo, final String sqlSearch, final Long officeId, final String externalId, 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 String displayName, final String firstname, final String lastname, final String status, final String hierarchy,
final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, final boolean isSelfUser) { 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); this.context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forClients(sqlSearch, officeId, externalId, displayName, firstname, 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); final Page<ClientData> clientData = this.clientReadPlatformService.retrieveAll(searchParameters);
@@ -18,6 +18,8 @@
*/ */
package org.apache.fineract.portfolio.client.domain; package org.apache.fineract.portfolio.client.domain;
import org.springframework.util.StringUtils;
/** /**
* Enum representation of client status states. * Enum representation of client status states.
*/ */
@@ -63,6 +65,33 @@ public enum ClientStatus {
return enumeration; 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) { private ClientStatus(final Integer value, final String code) {
this.value = value; this.value = value;
this.code = code; this.code = code;
@@ -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.codes.service.CodeValueReadPlatformService;
import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData; import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData;
import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService; 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.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport; 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.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper; import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource; import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
@@ -90,6 +92,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
private final ConfigurationReadPlatformService configurationReadPlatformService; private final ConfigurationReadPlatformService configurationReadPlatformService;
private final EntityDatatableChecksReadService entityDatatableChecksReadService; private final EntityDatatableChecksReadService entityDatatableChecksReadService;
private final ColumnValidator columnValidator; 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 @Autowired
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
@@ -176,6 +180,17 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
// @Transactional(readOnly=true) // @Transactional(readOnly=true)
public Page<ClientData> retrieveAll(final SearchParameters searchParameters) { 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 userOfficeHierarchy = this.context.officeHierarchy();
final String underHierarchySearchString = userOfficeHierarchy + "%"; final String underHierarchySearchString = userOfficeHierarchy + "%";
final String appUserID = String.valueOf(context.authenticatedUser().getId()); final String appUserID = String.valueOf(context.authenticatedUser().getId());
@@ -232,6 +247,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
final String displayName = searchParameters.getName(); final String displayName = searchParameters.getName();
final String firstname = searchParameters.getFirstname(); final String firstname = searchParameters.getFirstname();
final String lastname = searchParameters.getLastname(); final String lastname = searchParameters.getLastname();
final String status = searchParameters.getStatus();
String extraCriteria = ""; String extraCriteria = "";
if (sqlSearch != null) { if (sqlSearch != null) {
@@ -258,6 +274,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
extraCriteria += " and c.display_name like ? "; 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) { if (firstname != null) {
paramList.add(firstname); paramList.add(firstname);
extraCriteria += " and c.firstname like ? "; extraCriteria += " and c.firstname like ? ";
@@ -99,6 +99,7 @@ public class SelfClientsApiResource {
@QueryParam("firstName") @Parameter(description = "firstName") final String firstname, @QueryParam("firstName") @Parameter(description = "firstName") final String firstname,
@QueryParam("lastName") @Parameter(description = "lastName") final String lastname, @QueryParam("lastName") @Parameter(description = "lastName") final String lastname,
@QueryParam("offset") @Parameter(description = "offset") final Integer offset, @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("limit") @Parameter(description = "limit") final Integer limit,
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
@@ -108,8 +109,8 @@ public class SelfClientsApiResource {
final String externalId = null; final String externalId = null;
final String hierarchy = null; final String hierarchy = null;
final Boolean orphansOnly = null; final Boolean orphansOnly = null;
return this.clientApiResource.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, hierarchy, return this.clientApiResource.retrieveAll(uriInfo, sqlSearch, officeId, externalId, displayName, firstname, lastname, status,
offset, limit, orderBy, sortOrder, orphansOnly, true); hierarchy, offset, limit, orderBy, sortOrder, orphansOnly, true);
} }
@GET @GET