From c595e94a37a8e9a0d188149a56ea2b1b23343970 Mon Sep 17 00:00:00 2001 From: elnafateh Date: Tue, 11 Aug 2026 23:34:45 +0100 Subject: [PATCH 1/2] FINERACT-2749: Add v2 paginated endpoints to resolve ambiguous OpenAPI response typing - Introduce v2 endpoints for Audits, Groups, Centers, FixedDeposit, and RecurringDeposit accounts. - Consistently return the paginated wrapper (totalFilteredRecords, pageItems) to fix OpenAPI schema generation. - Retain v1 behavior for backward compatibility. --- .../fineract/commands/api/v2/AuditsV2Api.java | 30 ++++++ .../commands/api/v2/AuditsV2ApiDelegate.java | 98 +++++++++++++++++++ .../commands/api/v2/AuditsV2ApiResource.java | 67 +++++++++++++ .../portfolio/group/api/v2/CentersV2Api.java | 29 ++++++ .../group/api/v2/CentersV2ApiDelegate.java | 39 ++++++++ .../group/api/v2/CentersV2ApiResource.java | 75 ++++++++++++++ .../portfolio/group/api/v2/GroupsV2Api.java | 29 ++++++ .../group/api/v2/GroupsV2ApiDelegate.java | 39 ++++++++ .../group/api/v2/GroupsV2ApiResource.java | 77 +++++++++++++++ .../savings/api/v2/DepositAccountsV2Api.java | 29 ++++++ .../api/v2/DepositAccountsV2ApiDelegate.java | 39 ++++++++ .../v2/FixedDepositAccountsV2ApiResource.java | 66 +++++++++++++ ...RecurringDepositAccountsV2ApiResource.java | 66 +++++++++++++ 13 files changed, 683 insertions(+) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2Api.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2Api.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiDelegate.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2Api.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiDelegate.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2Api.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2ApiDelegate.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/FixedDepositAccountsV2ApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/RecurringDepositAccountsV2ApiResource.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2Api.java b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2Api.java new file mode 100644 index 00000000000..751c681f0d0 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2Api.java @@ -0,0 +1,30 @@ +/** + * 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.commands.api.v2; + +import jakarta.ws.rs.core.UriInfo; +import org.apache.fineract.commands.data.AuditData; +import org.apache.fineract.commands.data.request.AuditRequest; +import org.apache.fineract.infrastructure.core.service.Page; + +public interface AuditsV2Api { + + Page retrieveAllAudits(UriInfo uriInfo, AuditRequest auditRequest, Integer offset, Integer limit, String orderBy, + String sortOrder, boolean includeJson); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java new file mode 100644 index 00000000000..910ce49e397 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java @@ -0,0 +1,98 @@ +/** + * 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.commands.api.v2; + +import jakarta.ws.rs.core.UriInfo; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.commands.data.AuditData; +import org.apache.fineract.commands.data.request.AuditRequest; +import org.apache.fineract.commands.service.AuditReadPlatformService; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.security.utils.SQLBuilder; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class AuditsV2ApiDelegate implements AuditsV2Api { + + private final AuditReadPlatformService auditReadPlatformService; + private final ApiRequestParameterHelper apiRequestParameterHelper; + + @Override + public Page retrieveAllAudits(UriInfo uriInfo, AuditRequest auditRequest, Integer offset, Integer limit, String orderBy, + String sortOrder, boolean includeJson) { + final PaginationParameters parameters = PaginationParameters.builder().paged(true).limit(limit).offset(offset).orderBy(orderBy) + .sortOrder(sortOrder).build(); + final SQLBuilder extraCriteria = getExtraCriteria(auditRequest); + return auditReadPlatformService.retrievePaginatedAuditEntries(extraCriteria, includeJson, parameters); + } + + private SQLBuilder getExtraCriteria(AuditRequest auditRequest) { + SQLBuilder extraCriteria = new SQLBuilder(); + extraCriteria.addNonNullCriteria("aud.action_name = ", auditRequest.getActionName()); + if (auditRequest.getEntityName() != null) { + extraCriteria.addCriteria("aud.entity_name like", auditRequest.getEntityName() + "%"); + } + extraCriteria.addNonNullCriteria("aud.resource_id = ", auditRequest.getResourceId()); + extraCriteria.addNonNullCriteria("aud.maker_id = ", auditRequest.getMakerId()); + extraCriteria.addNonNullCriteria("aud.checker_id = ", auditRequest.getCheckerId()); + if (auditRequest.getMakerDateTimeFrom() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.made_on_date >= ", auditRequest.getMakerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.made_on_date_utc >= ", auditRequest.getMakerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + if (auditRequest.getMakerDateTimeTo() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.made_on_date <= ", auditRequest.getMakerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.made_on_date_utc <= ", auditRequest.getMakerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + if (auditRequest.getCheckerDateTimeFrom() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.checked_on_date >= ", auditRequest.getCheckerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.checked_on_date_utc >= ", auditRequest.getCheckerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + if (auditRequest.getCheckerDateTimeTo() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.checked_on_date <= ", auditRequest.getCheckerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.checked_on_date_utc <= ", auditRequest.getCheckerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + extraCriteria.addNonNullCriteria("aud.status = ", auditRequest.getStatus()); + extraCriteria.addNonNullCriteria("aud.office_id = ", auditRequest.getOfficeId()); + extraCriteria.addNonNullCriteria("aud.group_id = ", auditRequest.getGroupId()); + extraCriteria.addNonNullCriteria("aud.client_id = ", auditRequest.getClientId()); + extraCriteria.addNonNullCriteria("aud.loan_id = ", auditRequest.getLoanId()); + extraCriteria.addNonNullCriteria("aud.savings_account_id = ", auditRequest.getSavingsAccountId()); + + return extraCriteria; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiResource.java new file mode 100644 index 00000000000..c8d88c293f5 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiResource.java @@ -0,0 +1,67 @@ +/** + * 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.commands.api.v2; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.BeanParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.UriInfo; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.commands.data.AuditData; +import org.apache.fineract.commands.data.request.AuditRequest; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.springframework.stereotype.Component; + +@Path("/v2/audits") +@Component +@Tag(name = "AuditsV2", description = "V2 endpoint that always returns a paged response (totalFilteredRecords + pageItems) for audits, removing the ambiguous paged response typing of the v1 endpoint.") +@RequiredArgsConstructor +public class AuditsV2ApiResource { + + private static final String RESOURCE_NAME_FOR_PERMISSIONS = "AUDIT"; + + private final PlatformSecurityContext context; + private final AuditsV2ApiDelegate delegate; + private final ApiRequestParameterHelper apiRequestParameterHelper; + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Audits", operationId = "retrieveAllAuditsV2", description = "Get a paged list of audits that match the criteria supplied and sorted by audit id in descending order, and are within the requestors' data scope. Unlike the v1 endpoint, this endpoint always returns a paged response containing totalFilteredRecords and pageItems.\n\n" + + "Example Requests:\n\n" + "audits\n\n" + "audits?fields=madeOnDate,maker,processingResult\n\n" + "audits?officeId=1\n\n" + + "audits?officeId=1&includeJson=true") + public Page retrieveAllAudits(@Context final UriInfo uriInfo, @BeanParam AuditRequest auditRequest, + @QueryParam("offset") @Parameter(description = "offset") final Integer offset, + @QueryParam("limit") @Parameter(description = "limit") final Integer limit, + @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { + + context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); + final boolean includeJson = apiRequestParameterHelper.process(uriInfo.getQueryParameters()).isIncludeJson(); + return delegate.retrieveAllAudits(uriInfo, auditRequest, offset, limit, orderBy, sortOrder, includeJson); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2Api.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2Api.java new file mode 100644 index 00000000000..56190862cdc --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2Api.java @@ -0,0 +1,29 @@ +/** + * 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.group.api.v2; + +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.core.service.SearchParameters; +import org.apache.fineract.portfolio.group.data.CenterData; + +public interface CentersV2Api { + + Page retrieveAllCenters(SearchParameters searchParameters, PaginationParameters parameters); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiDelegate.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiDelegate.java new file mode 100644 index 00000000000..e839bc3f14d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiDelegate.java @@ -0,0 +1,39 @@ +/** + * 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.group.api.v2; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.core.service.SearchParameters; +import org.apache.fineract.portfolio.group.data.CenterData; +import org.apache.fineract.portfolio.group.service.CenterReadPlatformService; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class CentersV2ApiDelegate implements CentersV2Api { + + private final CenterReadPlatformService centerReadPlatformService; + + @Override + public Page retrieveAllCenters(SearchParameters searchParameters, PaginationParameters parameters) { + return centerReadPlatformService.retrievePagedAll(searchParameters, parameters); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiResource.java new file mode 100644 index 00000000000..f62b0b97ff1 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/CentersV2ApiResource.java @@ -0,0 +1,75 @@ +/** + * 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.group.api.v2; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.core.service.SearchParameters; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.infrastructure.security.service.SqlValidator; +import org.apache.fineract.portfolio.group.api.GroupingTypesApiConstants; +import org.apache.fineract.portfolio.group.data.CenterData; +import org.springframework.stereotype.Component; + +@Path("/v2/centers") +@Component +@Tag(name = "CentersV2", description = "V2 endpoint that always returns a paged response (totalFilteredRecords + pageItems) for centers, removing the ambiguous paged response typing of the v1 endpoint. The non-paged meeting-date lookup branch of the v1 endpoint is intentionally omitted.") +@RequiredArgsConstructor +public class CentersV2ApiResource { + + private final PlatformSecurityContext context; + private final CentersV2ApiDelegate delegate; + private final SqlValidator sqlValidator; + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Centers", operationId = "retrieveAllCentersV2", description = "Get a paged list of centers that match the criteria supplied and sorted by hierarchy. Unlike the v1 endpoint, this endpoint always returns a paged response containing totalFilteredRecords and pageItems.\n\n" + + "Example Requests:\n\n" + "centers\n\n" + "centers?fields=name,officeName,joinedDate\n\n" + "centers?offset=10&limit=50\n\n" + + "centers?orderBy=name&sortOrder=DESC") + public Page retrieveAllCenters(@QueryParam("officeId") @Parameter(description = "officeId") final Long officeId, + @QueryParam("staffId") @Parameter(description = "staffId") final Long staffId, + @QueryParam("externalId") @Parameter(description = "externalId") final String externalId, + @QueryParam("name") @Parameter(description = "name") final String name, + @QueryParam("underHierarchy") @Parameter(description = "underHierarchy") final String hierarchy, + @QueryParam("offset") @Parameter(description = "offset") final Integer offset, + @QueryParam("limit") @Parameter(description = "limit") final Integer limit, + @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { + + context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME); + sqlValidator.validate(orderBy); + sqlValidator.validate(sortOrder); + sqlValidator.validate(externalId); + sqlValidator.validate(hierarchy); + final PaginationParameters parameters = PaginationParameters.builder().paged(true).limit(limit).offset(offset).orderBy(orderBy) + .sortOrder(sortOrder).build(); + final SearchParameters searchParameters = SearchParameters.builder().limit(limit).officeId(officeId).externalId(externalId) + .name(name).hierarchy(hierarchy).offset(offset).orderBy(orderBy).sortOrder(sortOrder).staffId(staffId).build(); + return delegate.retrieveAllCenters(searchParameters, parameters); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2Api.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2Api.java new file mode 100644 index 00000000000..ae7859362d9 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2Api.java @@ -0,0 +1,29 @@ +/** + * 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.group.api.v2; + +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.core.service.SearchParameters; +import org.apache.fineract.portfolio.group.data.GroupGeneralData; + +public interface GroupsV2Api { + + Page retrieveAllGroups(SearchParameters searchParameters, PaginationParameters parameters); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiDelegate.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiDelegate.java new file mode 100644 index 00000000000..60d4609d3a6 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiDelegate.java @@ -0,0 +1,39 @@ +/** + * 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.group.api.v2; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.core.service.SearchParameters; +import org.apache.fineract.portfolio.group.data.GroupGeneralData; +import org.apache.fineract.portfolio.group.service.GroupReadPlatformService; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class GroupsV2ApiDelegate implements GroupsV2Api { + + private final GroupReadPlatformService groupReadPlatformService; + + @Override + public Page retrieveAllGroups(SearchParameters searchParameters, PaginationParameters parameters) { + return groupReadPlatformService.retrievePagedAll(searchParameters, parameters); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiResource.java new file mode 100644 index 00000000000..9046231fd9c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/v2/GroupsV2ApiResource.java @@ -0,0 +1,77 @@ +/** + * 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.group.api.v2; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.core.service.SearchParameters; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.infrastructure.security.service.SqlValidator; +import org.apache.fineract.portfolio.group.api.GroupingTypesApiConstants; +import org.apache.fineract.portfolio.group.data.GroupGeneralData; +import org.springframework.stereotype.Component; + +@Path("/v2/groups") +@Component +@Tag(name = "GroupsV2", description = "V2 endpoint that always returns a paged response (totalFilteredRecords + pageItems) for groups, removing the ambiguous paged response typing of the v1 endpoint.") +@RequiredArgsConstructor +public class GroupsV2ApiResource { + + private final PlatformSecurityContext context; + private final GroupsV2ApiDelegate delegate; + private final SqlValidator sqlValidator; + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Groups", operationId = "retrieveAllGroupsV2", description = "Get a paged list of groups that match the criteria supplied and sorted by hierarchy. Unlike the v1 endpoint, this endpoint always returns a paged response containing totalFilteredRecords and pageItems.\n\n" + + "Example Requests:\n\n" + "groups\n\n" + "groups?fields=name,officeName,joinedDate\n\n" + "groups?offset=10&limit=50\n\n" + + "groups?orderBy=name&sortOrder=DESC") + public Page retrieveAllGroups(@QueryParam("officeId") @Parameter(description = "officeId") final Long officeId, + @QueryParam("staffId") @Parameter(description = "staffId") final Long staffId, + @QueryParam("externalId") @Parameter(description = "externalId") final String externalId, + @QueryParam("name") @Parameter(description = "name") final String name, + @QueryParam("underHierarchy") @Parameter(description = "underHierarchy") final String hierarchy, + @QueryParam("offset") @Parameter(description = "offset") final Integer offset, + @QueryParam("limit") @Parameter(description = "limit") final Integer limit, + @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, + @QueryParam("orphansOnly") @Parameter(description = "orphansOnly") final Boolean orphansOnly) { + + context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME); + sqlValidator.validate(orderBy); + sqlValidator.validate(sortOrder); + sqlValidator.validate(externalId); + sqlValidator.validate(hierarchy); + final PaginationParameters parameters = PaginationParameters.builder().paged(true).limit(limit).offset(offset).orderBy(orderBy) + .sortOrder(sortOrder).build(); + final SearchParameters searchParameters = SearchParameters.builder().limit(limit).officeId(officeId).externalId(externalId) + .name(name).hierarchy(hierarchy).offset(offset).orderBy(orderBy).sortOrder(sortOrder).staffId(staffId) + .orphansOnly(orphansOnly).build(); + return delegate.retrieveAllGroups(searchParameters, parameters); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2Api.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2Api.java new file mode 100644 index 00000000000..5680d622af4 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2Api.java @@ -0,0 +1,29 @@ +/** + * 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.savings.api.v2; + +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.portfolio.savings.DepositAccountType; +import org.apache.fineract.portfolio.savings.data.DepositAccountData; + +public interface DepositAccountsV2Api { + + Page retrieveAllDepositAccounts(DepositAccountType depositAccountType, PaginationParameters parameters); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2ApiDelegate.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2ApiDelegate.java new file mode 100644 index 00000000000..e8013a230e4 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/DepositAccountsV2ApiDelegate.java @@ -0,0 +1,39 @@ +/** + * 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.savings.api.v2; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.portfolio.savings.DepositAccountType; +import org.apache.fineract.portfolio.savings.data.DepositAccountData; +import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class DepositAccountsV2ApiDelegate implements DepositAccountsV2Api { + + private final DepositAccountReadPlatformService depositAccountReadPlatformService; + + @Override + public Page retrieveAllDepositAccounts(DepositAccountType depositAccountType, PaginationParameters parameters) { + return depositAccountReadPlatformService.retrieveAllPaged(depositAccountType, parameters); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/FixedDepositAccountsV2ApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/FixedDepositAccountsV2ApiResource.java new file mode 100644 index 00000000000..a70aedbe669 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/FixedDepositAccountsV2ApiResource.java @@ -0,0 +1,66 @@ +/** + * 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.savings.api.v2; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.infrastructure.security.service.SqlValidator; +import org.apache.fineract.portfolio.savings.DepositAccountType; +import org.apache.fineract.portfolio.savings.DepositsApiConstants; +import org.apache.fineract.portfolio.savings.data.DepositAccountData; +import org.springframework.stereotype.Component; + +@Path("/v2/fixeddepositaccounts") +@Component +@Tag(name = "FixedDepositAccountsV2", description = "V2 endpoint that always returns a paged response (totalFilteredRecords + pageItems) for fixed deposit accounts, removing the ambiguous paged response typing of the v1 endpoint.") +@RequiredArgsConstructor +public class FixedDepositAccountsV2ApiResource { + + private final PlatformSecurityContext context; + private final DepositAccountsV2ApiDelegate delegate; + private final SqlValidator sqlValidator; + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Fixed deposit applications/accounts", operationId = "retrieveAllFixedDepositAccountsV2", description = "Get a paged list of fixed deposit accounts. Unlike the v1 endpoint, this endpoint always returns a paged response containing totalFilteredRecords and pageItems.\n\n" + + "Example Requests:\n\n" + "fixeddepositaccounts\n\n" + "fixeddepositaccounts?fields=name") + public Page retrieveAllDepositAccounts( + @QueryParam("offset") @Parameter(description = "offset") final Integer offset, + @QueryParam("limit") @Parameter(description = "limit") final Integer limit, + @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { + + context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME); + sqlValidator.validate(orderBy); + sqlValidator.validate(sortOrder); + final PaginationParameters parameters = PaginationParameters.builder().paged(true).limit(limit).offset(offset).orderBy(orderBy) + .sortOrder(sortOrder).build(); + return delegate.retrieveAllDepositAccounts(DepositAccountType.FIXED_DEPOSIT, parameters); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/RecurringDepositAccountsV2ApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/RecurringDepositAccountsV2ApiResource.java new file mode 100644 index 00000000000..a4ee9e10357 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/v2/RecurringDepositAccountsV2ApiResource.java @@ -0,0 +1,66 @@ +/** + * 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.savings.api.v2; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; +import org.apache.fineract.infrastructure.core.service.Page; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.infrastructure.security.service.SqlValidator; +import org.apache.fineract.portfolio.savings.DepositAccountType; +import org.apache.fineract.portfolio.savings.DepositsApiConstants; +import org.apache.fineract.portfolio.savings.data.DepositAccountData; +import org.springframework.stereotype.Component; + +@Path("/v2/recurringdepositaccounts") +@Component +@Tag(name = "RecurringDepositAccountsV2", description = "V2 endpoint that always returns a paged response (totalFilteredRecords + pageItems) for recurring deposit accounts, removing the ambiguous paged response typing of the v1 endpoint.") +@RequiredArgsConstructor +public class RecurringDepositAccountsV2ApiResource { + + private final PlatformSecurityContext context; + private final DepositAccountsV2ApiDelegate delegate; + private final SqlValidator sqlValidator; + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Recurring deposit applications/accounts", operationId = "retrieveAllRecurringDepositAccountsV2", description = "Get a paged list of recurring deposit accounts. Unlike the v1 endpoint, this endpoint always returns a paged response containing totalFilteredRecords and pageItems.\n\n" + + "Example Requests:\n\n" + "recurringdepositaccounts\n\n" + "recurringdepositaccounts?fields=name") + public Page retrieveAllDepositAccounts( + @QueryParam("offset") @Parameter(description = "offset") final Integer offset, + @QueryParam("limit") @Parameter(description = "limit") final Integer limit, + @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { + + context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME); + sqlValidator.validate(orderBy); + sqlValidator.validate(sortOrder); + final PaginationParameters parameters = PaginationParameters.builder().paged(true).limit(limit).offset(offset).orderBy(orderBy) + .sortOrder(sortOrder).build(); + return delegate.retrieveAllDepositAccounts(DepositAccountType.RECURRING_DEPOSIT, parameters); + } +} From b77253d3582632c3864827cbec2dbc413e4840fc Mon Sep 17 00:00:00 2001 From: elnafateh Date: Sat, 15 Aug 2026 12:01:14 +0100 Subject: [PATCH 2/2] FINERACT-2749: Move audit criteria building into service layer Consolidate the duplicated getExtraCriteria logic from v1 and v2 audit endpoints into AuditReadPlatformService so both share one implementation --- .../commands/api/AuditsApiResource.java | 53 +------------------ .../commands/api/v2/AuditsV2ApiDelegate.java | 52 +----------------- .../service/AuditReadPlatformService.java | 3 ++ .../service/AuditReadPlatformServiceImpl.java | 53 +++++++++++++++++++ 4 files changed, 58 insertions(+), 103 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/api/AuditsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/commands/api/AuditsApiResource.java index b2387ba6795..cfe8b2227e9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/api/AuditsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/api/AuditsApiResource.java @@ -76,7 +76,7 @@ public String retrieveAuditEntries(@Context final UriInfo uriInfo, @BeanParam Au context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); final PaginationParameters parameters = PaginationParameters.builder().paged(Boolean.TRUE.equals(paged)).limit(limit).offset(offset) .orderBy(orderBy).sortOrder(sortOrder).build(); - final SQLBuilder extraCriteria = getExtraCriteria(auditRequest); + final SQLBuilder extraCriteria = auditReadPlatformService.getExtraCriteria(auditRequest); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return toApiJsonSerializer.serialize(parameters.isPaged() @@ -105,55 +105,4 @@ public AuditSearchData retrieveAuditSearchTemplate() { return this.auditReadPlatformService.retrieveSearchTemplate("audit"); } - private SQLBuilder getExtraCriteria(AuditRequest auditRequest) { - - SQLBuilder extraCriteria = new SQLBuilder(); - extraCriteria.addNonNullCriteria("aud.action_name = ", auditRequest.getActionName()); - if (auditRequest.getEntityName() != null) { - extraCriteria.addCriteria("aud.entity_name like", auditRequest.getEntityName() + "%"); - } - extraCriteria.addNonNullCriteria("aud.resource_id = ", auditRequest.getResourceId()); - extraCriteria.addNonNullCriteria("aud.maker_id = ", auditRequest.getMakerId()); - extraCriteria.addNonNullCriteria("aud.checker_id = ", auditRequest.getCheckerId()); - if (auditRequest.getMakerDateTimeFrom() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.made_on_date >= ", auditRequest.getMakerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.made_on_date_utc >= ", auditRequest.getMakerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - if (auditRequest.getMakerDateTimeTo() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.made_on_date <= ", auditRequest.getMakerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.made_on_date_utc <= ", auditRequest.getMakerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - if (auditRequest.getCheckerDateTimeFrom() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.checked_on_date >= ", auditRequest.getCheckerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.checked_on_date_utc >= ", auditRequest.getCheckerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - if (auditRequest.getCheckerDateTimeTo() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.checked_on_date <= ", auditRequest.getCheckerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.checked_on_date_utc <= ", auditRequest.getCheckerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - extraCriteria.addNonNullCriteria("aud.status = ", auditRequest.getStatus()); - extraCriteria.addNonNullCriteria("aud.office_id = ", auditRequest.getOfficeId()); - extraCriteria.addNonNullCriteria("aud.group_id = ", auditRequest.getGroupId()); - extraCriteria.addNonNullCriteria("aud.client_id = ", auditRequest.getClientId()); - extraCriteria.addNonNullCriteria("aud.loan_id = ", auditRequest.getLoanId()); - extraCriteria.addNonNullCriteria("aud.savings_account_id = ", auditRequest.getSavingsAccountId()); - - return extraCriteria; - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java index 910ce49e397..002f16dbce2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/api/v2/AuditsV2ApiDelegate.java @@ -41,58 +41,8 @@ public Page retrieveAllAudits(UriInfo uriInfo, AuditRequest auditRequ String sortOrder, boolean includeJson) { final PaginationParameters parameters = PaginationParameters.builder().paged(true).limit(limit).offset(offset).orderBy(orderBy) .sortOrder(sortOrder).build(); - final SQLBuilder extraCriteria = getExtraCriteria(auditRequest); + final SQLBuilder extraCriteria = auditReadPlatformService.getExtraCriteria(auditRequest); return auditReadPlatformService.retrievePaginatedAuditEntries(extraCriteria, includeJson, parameters); } - private SQLBuilder getExtraCriteria(AuditRequest auditRequest) { - SQLBuilder extraCriteria = new SQLBuilder(); - extraCriteria.addNonNullCriteria("aud.action_name = ", auditRequest.getActionName()); - if (auditRequest.getEntityName() != null) { - extraCriteria.addCriteria("aud.entity_name like", auditRequest.getEntityName() + "%"); - } - extraCriteria.addNonNullCriteria("aud.resource_id = ", auditRequest.getResourceId()); - extraCriteria.addNonNullCriteria("aud.maker_id = ", auditRequest.getMakerId()); - extraCriteria.addNonNullCriteria("aud.checker_id = ", auditRequest.getCheckerId()); - if (auditRequest.getMakerDateTimeFrom() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.made_on_date >= ", auditRequest.getMakerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.made_on_date_utc >= ", auditRequest.getMakerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - if (auditRequest.getMakerDateTimeTo() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.made_on_date <= ", auditRequest.getMakerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.made_on_date_utc <= ", auditRequest.getMakerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - if (auditRequest.getCheckerDateTimeFrom() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.checked_on_date >= ", auditRequest.getCheckerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.checked_on_date_utc >= ", auditRequest.getCheckerDateTimeFrom(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - if (auditRequest.getCheckerDateTimeTo() != null) { - extraCriteria.addSubOperation((SQLBuilder criteria) -> { - criteria.addNonNullCriteria("aud.checked_on_date <= ", auditRequest.getCheckerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.NONE); - criteria.addNonNullCriteria("aud.checked_on_date_utc <= ", auditRequest.getCheckerDateTimeTo(), - SQLBuilder.WhereLogicalOperator.OR); - }); - } - extraCriteria.addNonNullCriteria("aud.status = ", auditRequest.getStatus()); - extraCriteria.addNonNullCriteria("aud.office_id = ", auditRequest.getOfficeId()); - extraCriteria.addNonNullCriteria("aud.group_id = ", auditRequest.getGroupId()); - extraCriteria.addNonNullCriteria("aud.client_id = ", auditRequest.getClientId()); - extraCriteria.addNonNullCriteria("aud.loan_id = ", auditRequest.getLoanId()); - extraCriteria.addNonNullCriteria("aud.savings_account_id = ", auditRequest.getSavingsAccountId()); - - return extraCriteria; - } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformService.java index 059f40d24a1..27776f8a8ab 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformService.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.fineract.commands.data.AuditData; import org.apache.fineract.commands.data.AuditSearchData; +import org.apache.fineract.commands.data.request.AuditRequest; import org.apache.fineract.infrastructure.core.data.PaginationParameters; import org.apache.fineract.infrastructure.core.service.Page; import org.apache.fineract.infrastructure.security.utils.SQLBuilder; @@ -36,4 +37,6 @@ public interface AuditReadPlatformService { AuditData retrieveAuditEntry(Long auditId); AuditSearchData retrieveSearchTemplate(String useType); + + SQLBuilder getExtraCriteria(AuditRequest auditRequest); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java index 89c3b8f3fb5..22bc22a05c1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java @@ -38,6 +38,7 @@ import org.apache.fineract.commands.data.AuditData; import org.apache.fineract.commands.data.AuditSearchData; import org.apache.fineract.commands.data.ProcessingResultLookup; +import org.apache.fineract.commands.data.request.AuditRequest; import org.apache.fineract.commands.exception.CommandNotFoundException; import org.apache.fineract.infrastructure.core.data.PaginationParameters; import org.apache.fineract.infrastructure.core.data.PaginationParametersDataValidator; @@ -454,6 +455,58 @@ public AuditSearchData retrieveSearchTemplate(final String useType) { return new AuditSearchData(appUsers, actionNames, entityNames, processingResults); } + @Override + public SQLBuilder getExtraCriteria(final AuditRequest auditRequest) { + final SQLBuilder extraCriteria = new SQLBuilder(); + extraCriteria.addNonNullCriteria("aud.action_name = ", auditRequest.getActionName()); + if (auditRequest.getEntityName() != null) { + extraCriteria.addCriteria("aud.entity_name like", auditRequest.getEntityName() + "%"); + } + extraCriteria.addNonNullCriteria("aud.resource_id = ", auditRequest.getResourceId()); + extraCriteria.addNonNullCriteria("aud.maker_id = ", auditRequest.getMakerId()); + extraCriteria.addNonNullCriteria("aud.checker_id = ", auditRequest.getCheckerId()); + if (auditRequest.getMakerDateTimeFrom() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.made_on_date >= ", auditRequest.getMakerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.made_on_date_utc >= ", auditRequest.getMakerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + if (auditRequest.getMakerDateTimeTo() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.made_on_date <= ", auditRequest.getMakerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.made_on_date_utc <= ", auditRequest.getMakerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + if (auditRequest.getCheckerDateTimeFrom() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.checked_on_date >= ", auditRequest.getCheckerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.checked_on_date_utc >= ", auditRequest.getCheckerDateTimeFrom(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + if (auditRequest.getCheckerDateTimeTo() != null) { + extraCriteria.addSubOperation((SQLBuilder criteria) -> { + criteria.addNonNullCriteria("aud.checked_on_date <= ", auditRequest.getCheckerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.NONE); + criteria.addNonNullCriteria("aud.checked_on_date_utc <= ", auditRequest.getCheckerDateTimeTo(), + SQLBuilder.WhereLogicalOperator.OR); + }); + } + extraCriteria.addNonNullCriteria("aud.status = ", auditRequest.getStatus()); + extraCriteria.addNonNullCriteria("aud.office_id = ", auditRequest.getOfficeId()); + extraCriteria.addNonNullCriteria("aud.group_id = ", auditRequest.getGroupId()); + extraCriteria.addNonNullCriteria("aud.client_id = ", auditRequest.getClientId()); + extraCriteria.addNonNullCriteria("aud.loan_id = ", auditRequest.getLoanId()); + extraCriteria.addNonNullCriteria("aud.savings_account_id = ", auditRequest.getSavingsAccountId()); + + return extraCriteria; + } + private String makercheckerCapabilityOnly(final String useType, final AppUser currentUser) { String sql = ""; Boolean isLimitedChecker = false;