From b1cfa996b484b164cc9a287c8c36a1d248498c9c Mon Sep 17 00:00:00 2001 From: Nitesh Yadav Date: Thu, 30 Jul 2026 10:33:48 +0530 Subject: [PATCH] feat(clients): fromDate/toDate submittedon_date range filter on GET /clients Backs the Client Approval tab's Today/Yesterday quick filters server-side. offset/limit/displayName/orderBy/sortOrder/status already existed on this endpoint; added fromDate/toDate (yyyy-MM-dd, inclusive) alongside them, filtering on c.submittedon_date, following the same ::date-cast convention already used by ClientPendingEditReadPlatformServiceImpl for the equivalent pending-edits filter. Updated the one other caller (SelfClientsApiResource) to pass null/null. --- .../client/api/ClientsApiResource.java | 18 +++++++++++++----- .../service/ClientReadPlatformServiceImpl.java | 10 ++++++++++ .../client/api/SelfClientsApiResource.java | 2 +- 3 files changed, 24 insertions(+), 6 deletions(-) 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 d348b42a6..19a64c334 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 @@ -44,6 +44,7 @@ import java.time.LocalDate; import java.util.Collection; import java.util.List; import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; import org.apache.fineract.commands.data.AuditData; import org.apache.fineract.commands.domain.CommandWrapper; import org.apache.fineract.commands.service.AuditReadPlatformService; @@ -142,7 +143,8 @@ public class ClientsApiResource { @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "List Clients", description = "The list capability of clients can support pagination and sorting.\n\n" + "Example Requests:\n" + "\n" + "clients\n" + "\n" + "clients?fields=displayName,officeName,timeline\n" + "\n" - + "clients?offset=10&limit=50\n" + "\n" + "clients?orderBy=displayName&sortOrder=DESC") + + "clients?offset=10&limit=50\n" + "\n" + "clients?orderBy=displayName&sortOrder=DESC\n\n" + + "clients?fromDate=2026-01-01&toDate=2026-01-31 (submittedon_date range, yyyy-MM-dd, inclusive)") @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientsApiResourceSwagger.GetClientsResponse.class))) public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("officeId") @Parameter(description = "officeId") final Long officeId, @@ -157,10 +159,15 @@ public class ClientsApiResource { @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, @QueryParam("orphansOnly") @Parameter(description = "orphansOnly") final Boolean orphansOnly, - @QueryParam("legalForm") final Integer legalForm) { + @QueryParam("legalForm") final Integer legalForm, + @QueryParam("fromDate") @Parameter(description = "fromDate") final String fromDate, + @QueryParam("toDate") @Parameter(description = "toDate") final String toDate) { + + final LocalDate fromDateParsed = StringUtils.isNotBlank(fromDate) ? LocalDate.parse(fromDate) : null; + final LocalDate toDateParsed = StringUtils.isNotBlank(toDate) ? LocalDate.parse(toDate) : null; return retrieveAll(uriInfo, officeId, externalId, displayName, firstname, lastname, status, legalForm, hierarchy, offset, limit, - orderBy, sortOrder, orphansOnly, false); + orderBy, sortOrder, orphansOnly, false, fromDateParsed, toDateParsed); } @GET @@ -437,7 +444,7 @@ public class ClientsApiResource { public String retrieveAll(final UriInfo uriInfo, final Long officeId, final String externalId, final String displayName, final String firstname, final String lastname, final String status, final Integer legalForm, final String hierarchy, final Integer offset, final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, - final boolean isSelfUser) { + final boolean isSelfUser, final LocalDate fromDate, final LocalDate toDate) { context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME); sqlValidator.validate(orderBy); sqlValidator.validate(sortOrder); @@ -445,7 +452,8 @@ public class ClientsApiResource { sqlValidator.validate(hierarchy); final SearchParameters searchParameters = SearchParameters.builder().limit(limit).officeId(officeId).externalId(externalId) .name(displayName).hierarchy(hierarchy).firstname(firstname).lastname(lastname).status(status).orphansOnly(orphansOnly) - .isSelfUser(isSelfUser).offset(offset).orderBy(orderBy).sortOrder(sortOrder).legalForm(legalForm).build(); + .isSelfUser(isSelfUser).offset(offset).orderBy(orderBy).sortOrder(sortOrder).legalForm(legalForm).fromDate(fromDate) + .toDate(toDate).build(); final Page clientData = clientReadPlatformService.retrieveAll(searchParameters); final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return toApiJsonSerializer.serialize(settings, clientData, ClientApiConstants.CLIENT_RESPONSE_DATA_PARAMETERS); 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 f1d56e87f..4a2480852 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 @@ -178,6 +178,16 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService extraCriteria += " and c.status_enum = " + clientStatus.getValue().toString() + " "; } + if (searchParameters.hasFromDate()) { + paramList.add(searchParameters.getFromDate().toString()); + extraCriteria += " and c.submittedon_date >= ?::date "; + } + + if (searchParameters.hasToDate()) { + paramList.add(searchParameters.getToDate().toString()); + extraCriteria += " and c.submittedon_date <= ?::date "; + } + 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 9037547bb..00f111896 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 @@ -135,7 +135,7 @@ public class SelfClientsApiResource { final String hierarchy = null; final Boolean orphansOnly = null; return this.clientApiResource.retrieveAll(uriInfo, officeId, externalId, displayName, firstname, lastname, status, legalForm, - hierarchy, offset, limit, orderBy, sortOrder, orphansOnly, true); + hierarchy, offset, limit, orderBy, sortOrder, orphansOnly, true, null, null); } @GET