FINERACT-2073: Client search v2 using Client Identifiers

This commit is contained in:
Jose Alberto Hernandez
2024-05-21 11:32:15 +02:00
committed by Adam Saghy
parent 63ee58aabd
commit e13a9cba01
15 changed files with 62 additions and 1 deletions
@@ -48,6 +48,7 @@
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
<class>org.apache.fineract.portfolio.rate.domain.Rate</class>
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket</class>
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.portfolio.client.domain;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
@@ -25,6 +26,7 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
@@ -220,6 +222,9 @@ public class Client extends AbstractAuditableWithUTCDateTimeCustom {
@Column(name = "proposed_transfer_date")
private LocalDate proposedTransferDate;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "client", orphanRemoval = true, fetch = FetchType.LAZY)
protected Set<ClientIdentifier> identifiers = new HashSet<>();
public static Client instance(final AppUser currentUser, final ClientStatus status, final Office office, final Group clientParentGroup,
final String accountNo, final String firstname, final String middlename, final String lastname, final String fullname,
final LocalDate activationDate, final LocalDate officeJoiningDate, final ExternalId externalId, final String mobileNo,
@@ -48,6 +48,7 @@
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.charge.domain.Charge</class>
<class>org.apache.fineract.portfolio.paymenttype.domain.PaymentType</class>
@@ -47,6 +47,7 @@
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
<class>org.apache.fineract.portfolio.rate.domain.Rate</class>
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket</class>
@@ -48,6 +48,7 @@
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
<class>org.apache.fineract.portfolio.rate.domain.Rate</class>
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket</class>
@@ -85,6 +85,8 @@ final class ClientIdentifiersApiResourceSwagger {
public String documentKey;
@Schema(example = "Document has been verified")
public String description;
@Schema(example = "Active")
public String status;
}
@Schema(description = "PutClientsClientIdIdentifiersIdentifierIdRequest")
@@ -98,6 +100,8 @@ final class ClientIdentifiersApiResourceSwagger {
public String documentKey;
@Schema(example = "Document has been updated")
public String description;
@Schema(example = "Active")
public String status;
}
@Schema(description = "PutClientsClientIdIdentifiersIdentifierIdResponse")
@@ -22,6 +22,8 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
@@ -32,6 +34,7 @@ import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.jpa.CriteriaQueryFactory;
import org.apache.fineract.organisation.office.domain.Office;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientIdentifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
@@ -62,13 +65,15 @@ public class SearchingClientRepositoryImpl implements SearchingClientRepository
Specification<Client> spec = (r, q, builder) -> {
Path<Office> o = r.get("office");
Join<Client, ClientIdentifier> identity = r.join("identifiers", JoinType.LEFT);
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.like(o.get("hierarchy"), hierarchyLikeValue));
String searchLikeValue = "%" + searchText + "%";
predicates.add(cb.or(cb.like(r.get("accountNumber"), searchLikeValue), cb.like(r.get("displayName"), searchLikeValue),
cb.like(r.get("externalId"), searchLikeValue), cb.like(r.get("mobileNo"), searchLikeValue)));
cb.like(r.get("externalId"), searchLikeValue), cb.like(r.get("mobileNo"), searchLikeValue),
cb.like(identity.get("documentKey"), searchLikeValue)));
return cb.and(predicates.toArray(new Predicate[0]));
};
@@ -48,6 +48,7 @@
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
<class>org.apache.fineract.portfolio.rate.domain.Rate</class>
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket</class>
@@ -48,6 +48,7 @@
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
<class>org.apache.fineract.portfolio.rate.domain.Rate</class>
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket</class>
@@ -48,6 +48,7 @@
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.charge.domain.Charge</class>
<class>org.apache.fineract.portfolio.paymenttype.domain.PaymentType</class>
@@ -27,6 +27,8 @@ import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import org.apache.fineract.client.models.GetClientsClientIdResponse;
import org.apache.fineract.client.models.PageClientSearchData;
import org.apache.fineract.client.models.PostClientsClientIdIdentifiersRequest;
import org.apache.fineract.client.models.PostClientsClientIdIdentifiersResponse;
import org.apache.fineract.client.models.PostClientsRequest;
import org.apache.fineract.client.models.PostClientsResponse;
import org.apache.fineract.client.models.SortOrder;
@@ -242,4 +244,29 @@ public class ClientSearchTest {
assertThat(result.getTotalElements()).isEqualTo(0);
assertThat(result.getContent()).isEmpty();
}
@Test
public void testClientSearchWorks_ByClientIdentifier() {
// given
PostClientsRequest request1 = ClientHelper.defaultClientCreationRequest();
request1.setMobileNo(Utils.randomNumberGenerator(8).toString());
PostClientsResponse clientResponse = clientHelper.createClient(request1);
final Long documentType = 1L;
PostClientsClientIdIdentifiersRequest identifierRequest = ClientHelper.createClientIdentifer(documentType);
final String documentKey = identifierRequest.getDocumentKey();
PostClientsClientIdIdentifiersResponse clientIdentifierResponse = clientHelper.createClientIdentifer(clientResponse.getClientId(),
identifierRequest);
PostClientsRequest request2 = ClientHelper.defaultClientCreationRequest();
clientHelper.createClient(request2);
PostClientsRequest request3 = ClientHelper.defaultClientCreationRequest();
clientHelper.createClient(request3);
// when
PageClientSearchData result = clientHelper.searchClients(documentKey);
// then
assertThat(result.getTotalElements()).isEqualTo(1);
assertThat(result.getContent().get(0).getMobileNo()).isEqualTo(request1.getMobileNo());
}
}
@@ -52,6 +52,8 @@ import org.apache.fineract.client.models.PageClientSearchData;
import org.apache.fineract.client.models.PagedRequestClientTextSearch;
import org.apache.fineract.client.models.PostClientClientIdAddressesRequest;
import org.apache.fineract.client.models.PostClientClientIdAddressesResponse;
import org.apache.fineract.client.models.PostClientsClientIdIdentifiersRequest;
import org.apache.fineract.client.models.PostClientsClientIdIdentifiersResponse;
import org.apache.fineract.client.models.PostClientsClientIdResponse;
import org.apache.fineract.client.models.PostClientsClientIdTransactionsTransactionIdResponse;
import org.apache.fineract.client.models.PostClientsRequest;
@@ -105,6 +107,11 @@ public class ClientHelper extends IntegrationTest {
return ok(fineract().clients.create6(request));
}
public PostClientsClientIdIdentifiersResponse createClientIdentifer(final Long clientId,
final PostClientsClientIdIdentifiersRequest request) {
return ok(fineract().clientIdentifiers.createClientIdentifier(clientId, request));
}
public PageClientSearchData searchClients(String text) {
ClientTextSearch clientTextSearch = new ClientTextSearch();
clientTextSearch.setText(text);
@@ -875,4 +882,10 @@ public class ClientHelper extends IntegrationTest {
public GetLoanAccountLockResponse retrieveLockedAccounts(int page, int limit) {
return ok(fineract().loanAccountLockApi.retrieveLockedAccounts(page, limit));
}
public static PostClientsClientIdIdentifiersRequest createClientIdentifer(final Long documentType) {
return new PostClientsClientIdIdentifiersRequest().documentTypeId(documentType).documentKey(Utils.randomStringGenerator("ID_", 10))
.description(Utils.randomStringGenerator("Desc_", 50)).status("Active");
}
}