From 96926b94d20c3507ecefd6f5d5957e284fe750e9 Mon Sep 17 00:00:00 2001 From: Ralph Hopman Date: Thu, 12 Feb 2026 22:06:42 +0100 Subject: [PATCH] FINERACT-2488: Fix duplicate results in /api/v2/clients/search --- .../search/SearchingClientRepositoryImpl.java | 1 + .../client/ClientSearchTest.java | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/search/SearchingClientRepositoryImpl.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/search/SearchingClientRepositoryImpl.java index 94cf4e2dc02..fcfefb751d7 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/search/SearchingClientRepositoryImpl.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/search/SearchingClientRepositoryImpl.java @@ -67,6 +67,7 @@ public Page searchByText(String searchText, Pageable pageable, S Path office = root.get("office"); Specification spec = (r, q, builder) -> { + q.distinct(true); Path o = r.get("office"); Join identity = r.join("identifiers", JoinType.LEFT); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientSearchTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientSearchTest.java index eed2076d675..456d8d87211 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientSearchTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientSearchTest.java @@ -36,6 +36,7 @@ import org.apache.fineract.client.models.SortOrder; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.integrationtests.common.system.CodeHelper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -271,6 +272,36 @@ public void testClientSearchWorks_ByClientIdentifier() { assertThat(result.getContent().get(0).getMobileNo()).isEqualTo(request1.getMobileNo()); } + @Test + public void testClientSearchDoesNotDuplicateResults_WhenIdentifierHasMultipleMatches() { + // given + PostClientsRequest request = ClientHelper.defaultClientCreationRequest(); + PostClientsResponse clientResponse = clientHelper.createClient(request); + + Integer codeId = (Integer) CodeHelper.createCode(requestSpec, responseSpec, Utils.randomStringGenerator("ClientIdentifierTest_", 6), + CodeHelper.RESPONSE_ID_ATTRIBUTE_NAME); + Integer documentTypeIdOne = CodeHelper.createCodeValue(requestSpec, responseSpec, codeId, + Utils.randomStringGenerator("DocType_", 6), 1); + Integer documentTypeIdTwo = CodeHelper.createCodeValue(requestSpec, responseSpec, codeId, + Utils.randomStringGenerator("DocType_", 6), 2); + + String documentKeyToken = Utils.randomStringGenerator("DUP_ID_", 6); + PostClientsClientIdIdentifiersRequest identifierOne = new PostClientsClientIdIdentifiersRequest() + .documentTypeId(documentTypeIdOne.longValue()).documentKey(documentKeyToken + "_A").description("Test").status("Active"); + PostClientsClientIdIdentifiersRequest identifierTwo = new PostClientsClientIdIdentifiersRequest() + .documentTypeId(documentTypeIdTwo.longValue()).documentKey(documentKeyToken + "_B").description("Test").status("Active"); + clientHelper.createClientIdentifer(clientResponse.getClientId(), identifierOne); + clientHelper.createClientIdentifer(clientResponse.getClientId(), identifierTwo); + + // when + PageClientSearchData result = clientHelper.searchClients(documentKeyToken); + + // then + assertThat(result.getTotalElements()).isEqualTo(1); + assertThat(result.getContent().size()).isEqualTo(1); + assertThat(result.getContent().get(0).getExternalId().getValue()).isEqualTo(request.getExternalId()); + } + @Test public void testClientSearchByLegalForm() { // given