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
@@ -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")
@@ -1,130 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.client.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
@Entity
@Table(name = "m_client_identifier", uniqueConstraints = {
@UniqueConstraint(columnNames = { "document_type_id", "document_key" }, name = "unique_identifier_key"),
@UniqueConstraint(columnNames = { "client_id", "document_key", "active" }, name = "unique_active_client_identifier") })
public class ClientIdentifier extends AbstractAuditableWithUTCDateTimeCustom {
@ManyToOne
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@ManyToOne
@JoinColumn(name = "document_type_id", nullable = false)
private CodeValue documentType;
@Column(name = "document_key", length = 1000)
private String documentKey;
@Column(name = "status", nullable = false)
private Integer status;
@Column(name = "description", length = 1000)
private String description;
@Column(name = "active")
private Integer active;
public static ClientIdentifier fromJson(final Client client, final CodeValue documentType, final JsonCommand command) {
final String documentKey = command.stringValueOfParameterNamed("documentKey");
final String description = command.stringValueOfParameterNamed("description");
final String status = command.stringValueOfParameterNamed("status");
return new ClientIdentifier(client, documentType, documentKey, status, description);
}
protected ClientIdentifier() {
//
}
private ClientIdentifier(final Client client, final CodeValue documentType, final String documentKey, final String statusName,
String description) {
this.client = client;
this.documentType = documentType;
this.documentKey = StringUtils.defaultIfEmpty(documentKey, null);
this.description = StringUtils.defaultIfEmpty(description, null);
ClientIdentifierStatus statusEnum = ClientIdentifierStatus.valueOf(statusName.toUpperCase());
this.active = null;
if (statusEnum.isActive()) {
this.active = statusEnum.getValue();
}
this.status = statusEnum.getValue();
}
public void update(final CodeValue documentType) {
this.documentType = documentType;
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
final String documentTypeIdParamName = "documentTypeId";
if (command.isChangeInLongParameterNamed(documentTypeIdParamName, this.documentType.getId())) {
final Long newValue = command.longValueOfParameterNamed(documentTypeIdParamName);
actualChanges.put(documentTypeIdParamName, newValue);
}
final String documentKeyParamName = "documentKey";
if (command.isChangeInStringParameterNamed(documentKeyParamName, this.documentKey)) {
final String newValue = command.stringValueOfParameterNamed(documentKeyParamName);
actualChanges.put(documentKeyParamName, newValue);
this.documentKey = StringUtils.defaultIfEmpty(newValue, null);
}
final String descriptionParamName = "description";
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
actualChanges.put(descriptionParamName, newValue);
this.description = StringUtils.defaultIfEmpty(newValue, null);
}
final String statusParamName = "status";
if (command.isChangeInStringParameterNamed(statusParamName, ClientIdentifierStatus.fromInt(this.status).getCode())) {
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
actualChanges.put(descriptionParamName, ClientIdentifierStatus.valueOf(newValue));
this.status = ClientIdentifierStatus.valueOf(newValue).getValue();
}
return actualChanges;
}
public String documentKey() {
return this.documentKey;
}
public Long documentTypeId() {
return this.documentType.getId();
}
}
@@ -1,26 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.client.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface ClientIdentifierRepository extends JpaRepository<ClientIdentifier, Long>, JpaSpecificationExecutor<ClientIdentifier> {
// no behaviour
}
@@ -1,71 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.client.domain;
/**
* Enum representation of client identifier status states.
*/
public enum ClientIdentifierStatus {
INACTIVE(100, "clientIdentifierStatusType.inactive"), //
ACTIVE(200, "clientIdentifierStatusType.active"), //
INVALID(0, "clientIdentifierStatusType.invalid");
private final Integer value;
private final String code;
public static ClientIdentifierStatus fromInt(final Integer statusValue) {
ClientIdentifierStatus enumeration = ClientIdentifierStatus.INVALID;
switch (statusValue) {
case 100:
enumeration = ClientIdentifierStatus.INACTIVE;
break;
case 200:
enumeration = ClientIdentifierStatus.ACTIVE;
break;
}
return enumeration;
}
ClientIdentifierStatus(final Integer value, final String code) {
this.value = value;
this.code = code;
}
// public boolean hasStateOf(final ClientIdentifierStatus state) {
// return this.value.equals(state.getValue());
// }
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isInactive() {
return this.value.equals(ClientIdentifierStatus.INACTIVE.getValue());
}
public boolean isActive() {
return this.value.equals(ClientIdentifierStatus.ACTIVE.getValue());
}
}
@@ -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>