This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit 83905d627d98fcbc3b3bb643de111e6ef08410cf
Author: mark.vituska <[email protected]>
AuthorDate: Tue Jun 3 12:55:01 2025 +0200

    FINERACT-2181: fix name collision in swagger resources
---
 .../InternalProgressiveLoanApiResource.java        |   8 --
 .../InternalProgressiveLoanApiResourceSwagger.java | 126 ---------------------
 .../LoanRescheduleRequestTest.java                 |  78 +++++++++++++
 .../ProgressiveLoanModelIntegrationTest.java       |  90 ---------------
 .../common/LoanRescheduleRequestHelper.java        |   5 +
 5 files changed, 83 insertions(+), 224 deletions(-)

diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
index 7485d14114..61e5a9d388 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
@@ -21,10 +21,6 @@ package org.apache.fineract.portfolio.loanaccount.service;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.responses.ApiResponses;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.ws.rs.GET;
 import jakarta.ws.rs.POST;
@@ -80,8 +76,6 @@ public class InternalProgressiveLoanApiResource implements 
InitializingBean {
     @Produces({ MediaType.APPLICATION_JSON })
     @Path("{loanId}/model")
     @Operation(summary = "Fetch ProgressiveLoanInterestScheduleModel", 
description = "DO NOT USE THIS IN PRODUCTION!")
-    @ApiResponses({
-            @ApiResponse(responseCode = "200", description = "OK", content = 
@Content(schema = @Schema(implementation = 
InternalProgressiveLoanApiResourceSwagger.ProgressiveLoanInterestScheduleModel.class)))
 })
     public String fetchModel(@PathParam("loanId") @Parameter(description = 
"loanId") long loanId) {
         Loan loan = loanRepository.findOneWithNotFoundDetection(loanId);
         if (!loan.isProgressiveSchedule()) {
@@ -116,8 +110,6 @@ public class InternalProgressiveLoanApiResource implements 
InitializingBean {
     @Path("{loanId}/model")
     @Produces({ MediaType.APPLICATION_JSON })
     @Operation(summary = "Update and Save 
ProgressiveLoanInterestScheduleModel", description = "DO NOT USE THIS IN 
PRODUCTION!")
-    @ApiResponses({
-            @ApiResponse(responseCode = "200", description = "OK", content = 
@Content(schema = @Schema(implementation = 
InternalProgressiveLoanApiResourceSwagger.ProgressiveLoanInterestScheduleModel.class)))
 })
     public String updateModel(@PathParam("loanId") @Parameter(description = 
"loanId") long loanId) {
         Loan loan = loanRepository.findOneWithNotFoundDetection(loanId);
         if (!loan.isProgressiveSchedule()) {
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResourceSwagger.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResourceSwagger.java
deleted file mode 100644
index 9c249db68b..0000000000
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResourceSwagger.java
+++ /dev/null
@@ -1,126 +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.loanaccount.service;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeSet;
-import org.apache.fineract.infrastructure.core.data.EnumOptionData;
-
-final class InternalProgressiveLoanApiResourceSwagger {
-
-    @Schema(description = "ProgressiveLoanInterestScheduleModel")
-    static final class ProgressiveLoanInterestScheduleModel {
-
-        private ProgressiveLoanInterestScheduleModel() {}
-
-        @Schema(example = "[]")
-        public List<RepaymentPeriod> repaymentPeriods;
-        @Schema(example = "[]")
-        public TreeSet<InterestRate> interestRates;
-        @Schema(example = "{}")
-        public Map<Integer, List<LoanTermVariationsData>> loanTermVariations;
-        @Schema(example = "1")
-        public Integer installmentAmountInMultiplesOf;
-        @Schema(example = "{}")
-        public Map<Integer, Boolean> modifiers;
-    }
-
-    @Schema(description = "Interest Period")
-    static final class InterestPeriod {
-
-        private InterestPeriod() {}
-
-        @Schema(example = "01/01/2024")
-        public String fromDate;
-        @Schema(example = "01/09/2024")
-        public String dueDate;
-        @Schema(example = "0.9636548454")
-        public BigDecimal rateFactor;
-        @Schema(example = "0.9456878987")
-        public BigDecimal rateFactorTillPeriodDueDate;
-        @Schema(example = "0.0")
-        public BigDecimal chargebackPrincipal;
-        @Schema(example = "0.0")
-        public BigDecimal chargebackInterest;
-        @Schema(example = "1000.0")
-        public BigDecimal disbursementAmount;
-        @Schema(example = "3.38")
-        public BigDecimal balanceCorrectionAmount;
-        @Schema(example = "865.71")
-        public BigDecimal outstandingLoanBalance;
-        @Schema(example = "false")
-        public boolean isPaused;
-    }
-
-    @Schema(description = "Repayment Period")
-    static final class RepaymentPeriod {
-
-        private RepaymentPeriod() {}
-
-        @Schema(example = "01/01/2024")
-        public String fromDate;
-        @Schema(example = "01/02/2024")
-        public String dueDate;
-        @Schema(example = "[]")
-        public List<InterestPeriod> interestPeriods;
-        @Schema(example = "127.04")
-        public BigDecimal emi;
-        @Schema(example = "127.04")
-        public BigDecimal originalEmi;
-        @Schema(example = "104.04")
-        public BigDecimal paidPrincipal;
-        @Schema(example = "23.00")
-        public BigDecimal paidInterest;
-    }
-
-    @Schema(description = "Interest Rate")
-    static final class InterestRate {
-
-        private InterestRate() {}
-
-        @Schema(example = "21/12/2024")
-        public String effectiveFrom;
-        @Schema(example = "7.963")
-        public BigDecimal interestRate;
-    }
-
-    @Schema(description = "Loan Term Variations Data")
-    static final class LoanTermVariationsData {
-
-        private LoanTermVariationsData() {}
-
-        @Schema(example = "12345")
-        public Long id;
-        @Schema(example = "null")
-        public EnumOptionData termType;
-        @Schema(example = "21/12/2024")
-        public String termVariationApplicableFrom;
-        @Schema(example = "1.20")
-        public BigDecimal decimalValue;
-        @Schema(example = "21/12/2024")
-        public String dateValue;
-        @Schema(example = "true")
-        public boolean isSpecificToInstallment;
-        @Schema(example = "true")
-        public Boolean isProcessed;
-    }
-}
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java
index 0c5a9551eb..9cac88e05c 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.DEFAULT_STRATEGY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -34,10 +35,12 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 import org.apache.fineract.client.models.AdvancedPaymentData;
+import org.apache.fineract.client.models.GetLoanRescheduleRequestResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import org.apache.fineract.client.models.PostClientsResponse;
 import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
 import org.apache.fineract.client.models.PostCreateRescheduleLoansResponse;
+import org.apache.fineract.client.models.PostLoanProductsRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdRequest;
 import org.apache.fineract.client.models.PostLoansRequest;
 import org.apache.fineract.client.models.PostLoansResponse;
@@ -398,6 +401,31 @@ public class LoanRescheduleRequestTest extends 
BaseLoanIntegrationTest {
         });
     }
 
+    @Test
+    public void testLoanTermVariationDeserializesProperly() {
+        PostClientsResponse client = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
+        Long commonLoanProductId = createLoanProductPeriodicWithInterest();
+
+        AtomicReference<Long> loanIdRef = new AtomicReference<>();
+        runAt("01 March 2024", () -> {
+            Long loanId = 
applyForLoanApplicationWithInterest(client.getClientId(), commonLoanProductId, 
BigDecimal.valueOf(4000),
+                    "1 March 2023", "1 March 2024");
+            loanIdRef.set(loanId);
+            loanTransactionHelper.approveLoan("1 March 2024", 
loanId.intValue());
+
+            loanTransactionHelper.disburseLoan("1 March 2024", 
loanId.intValue(), "400", null);
+
+            PostCreateRescheduleLoansResponse rescheduleLoansResponse = 
loanRescheduleRequestHelper
+                    .createLoanRescheduleRequest(new 
PostCreateRescheduleLoansRequest().loanId(loanIdRef.get()).dateFormat(DATETIME_PATTERN)
+                            .locale("en").submittedOnDate("1 March 
2024").newInterestRate(BigDecimal.ONE).rescheduleReasonId(1L)
+                            .rescheduleFromDate("1 April 2024"));
+
+            GetLoanRescheduleRequestResponse getLoanRescheduleRequestResponse 
= Assertions.assertDoesNotThrow(
+                    () -> 
loanRescheduleRequestHelper.readLoanRescheduleRequest(rescheduleLoansResponse.getResourceId(),
 null));
+            Assertions.assertNotNull(getLoanRescheduleRequestResponse);
+        });
+    }
+
     private Integer createProgressiveLoanProduct() {
         AdvancedPaymentData defaultAllocation = 
createDefaultPaymentAllocation("NEXT_INSTALLMENT");
         final String loanProductJSON = new 
LoanProductTestBuilder().withNumberOfRepayments(numberOfRepayments)
@@ -501,4 +529,54 @@ public class LoanRescheduleRequestTest extends 
BaseLoanIntegrationTest {
                 .withDaysInYear("365").withMoratorium("0", "0").build(null);
         return loanTransactionHelper.getLoanProductId(loanProductJSON);
     }
+
+    private Long createLoanProductPeriodicWithInterest() {
+        String name = Utils.uniqueRandomStringGenerator("LOAN_PRODUCT_", 6);
+        String shortName = Utils.uniqueRandomStringGenerator("", 4);
+        Long resourceId = loanTransactionHelper.createLoanProduct(new 
PostLoanProductsRequest() //
+                .name(name) //
+                .shortName(shortName) //
+                .multiDisburseLoan(true) //
+                .maxTrancheCount(2) //
+                .interestType(InterestType.DECLINING_BALANCE) //
+                
.interestCalculationPeriodType(InterestCalculationPeriodType.DAILY) //
+                .disallowExpectedDisbursements(true) //
+                .description("Test loan description") //
+                .currencyCode("USD") //
+                .digitsAfterDecimal(2) //
+                .daysInYearType(DaysInYearType.ACTUAL) //
+                .daysInMonthType(DaysInYearType.ACTUAL) //
+                .interestRecalculationCompoundingMethod(0) //
+                .recalculationRestFrequencyType(1) //
+                .rescheduleStrategyMethod(1) //
+                .recalculationRestFrequencyInterval(0) //
+                .isInterestRecalculationEnabled(false) //
+                .interestRateFrequencyType(2) //
+                .locale("en_GB") //
+                .numberOfRepayments(4) //
+                
.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue()) //
+                .interestRatePerPeriod(2.0) //
+                .repaymentEvery(1) //
+                .minPrincipal(100.0) //
+                .principal(1000.0) //
+                .maxPrincipal(10000000.0) //
+                .amortizationType(AmortizationType.EQUAL_INSTALLMENTS) //
+                .dateFormat(DATETIME_PATTERN) //
+                .transactionProcessingStrategyCode(DEFAULT_STRATEGY) //
+                .accountingRule(1)) //
+                .getResourceId();
+        return resourceId;
+    }
+
+    private Long applyForLoanApplicationWithInterest(final Long clientId, 
final Long loanProductId, BigDecimal principal,
+            String submittedOnDate, String expectedDisburmentDate) {
+        final PostLoansRequest loanRequest = new PostLoansRequest() //
+                
.loanTermFrequency(4).locale("en_GB").loanTermFrequencyType(2).numberOfRepayments(4).repaymentFrequencyType(2)
+                
.interestRatePerPeriod(BigDecimal.valueOf(2)).repaymentEvery(1).principal(principal).amortizationType(1).interestType(1)
+                .interestCalculationPeriodType(0).dateFormat("dd MMMM 
yyyy").transactionProcessingStrategyCode(DEFAULT_STRATEGY)
+                
.loanType("individual").submittedOnDate(submittedOnDate).expectedDisbursementDate(expectedDisburmentDate).clientId(clientId)
+                .productId(loanProductId);
+        Long loanId = loanTransactionHelper.applyLoan(loanRequest).getLoanId();
+        return loanId;
+    }
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ProgressiveLoanModelIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ProgressiveLoanModelIntegrationTest.java
deleted file mode 100644
index ed0c17a921..0000000000
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ProgressiveLoanModelIntegrationTest.java
+++ /dev/null
@@ -1,90 +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.integrationtests;
-
-import java.math.BigDecimal;
-import java.util.concurrent.atomic.AtomicLong;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.fineract.client.models.GetLoansLoanIdResponse;
-import org.apache.fineract.client.models.ProgressiveLoanInterestScheduleModel;
-import org.apache.fineract.integrationtests.common.ClientHelper;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-@Slf4j
-public class ProgressiveLoanModelIntegrationTest extends 
BaseLoanIntegrationTest {
-
-    private final Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
-    private final Long loanProductId = 
loanProductHelper.createLoanProduct(create4IProgressive().isInterestRecalculationEnabled(true))
-            .getResourceId();
-
-    @Test
-    public void testModelReturnsSavedModelAfterDisbursement() {
-        AtomicLong loanIdA = new AtomicLong();
-        runAt("1 January 2024", () -> {
-            Long loanId = applyAndApproveProgressiveLoan(clientId, 
loanProductId, "1 January 2024", 1000.0, 96.32, 6, null);
-            loanIdA.set(loanId);
-            log.info("Testing on loanId: {}", loanId);
-            loanTransactionHelper.disburseLoan(loanId, "1 January 2024", 
1000.0);
-            // Model saved automatically, fetching it. It should return non 
null
-            ProgressiveLoanInterestScheduleModel model = 
assertNotNullAndChanged(null, loanId);
-            loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 
January 2024", 12.78);
-            model = assertNotNullAndChanged(model, loanId);
-            assertNotNullAndSame(model, loanId);
-        });
-        runAt("28 February 2024", () -> {
-            Long loanId = loanIdA.get();
-            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId);
-            BigDecimal totalUnpaidPayableNotDueInterest = 
loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest();
-            BigDecimal totalUnpaidDueInterest = 
loanDetails.getSummary().getTotalUnpaidPayableDueInterest();
-
-            Assertions.assertEquals(73.78, 
totalUnpaidPayableNotDueInterest.doubleValue(), 0.001);
-            Assertions.assertEquals(79.24, 
totalUnpaidDueInterest.doubleValue(), 0.001);
-        });
-    }
-
-    private ProgressiveLoanInterestScheduleModel 
assertNotNullAndChanged(ProgressiveLoanInterestScheduleModel prev, Long loanId) 
{
-        return assertNotNullAndChanged(prev, 
ok(fineractClient().progressiveLoanApi.fetchModel(loanId)));
-    }
-
-    private ProgressiveLoanInterestScheduleModel 
assertNotNullAndSame(ProgressiveLoanInterestScheduleModel prev, Long loanId) {
-        return assertNotNullAndSame(prev, 
ok(fineractClient().progressiveLoanApi.fetchModel(loanId)));
-    }
-
-    private ProgressiveLoanInterestScheduleModel 
assertNotNullAndSame(ProgressiveLoanInterestScheduleModel prev,
-            ProgressiveLoanInterestScheduleModel actual) {
-        if (actual == null) {
-            Assertions.fail("Model is null");
-        }
-        Assertions.assertEquals(prev.toString(), actual.toString());
-        return actual;
-    }
-
-    private ProgressiveLoanInterestScheduleModel 
assertNotNullAndChanged(ProgressiveLoanInterestScheduleModel prev,
-            ProgressiveLoanInterestScheduleModel actual) {
-        if (actual == null) {
-            Assertions.fail("Model is null");
-        }
-        if (prev != null) {
-            Assertions.assertNotEquals(prev.toString(), actual.toString());
-        }
-        return actual;
-    }
-
-}
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
index fa2c3eb7f6..e7a2d17403 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
@@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.util.HashMap;
+import org.apache.fineract.client.models.GetLoanRescheduleRequestResponse;
 import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
 import org.apache.fineract.client.models.PostCreateRescheduleLoansResponse;
 import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest;
@@ -89,6 +90,10 @@ public class LoanRescheduleRequestHelper {
         return Utils.performServerGet(requestSpec, responseSpec, URL, param);
     }
 
+    public GetLoanRescheduleRequestResponse readLoanRescheduleRequest(final 
Long requestId, final String param) {
+        return 
Calls.ok(FineractClientHelper.getFineractClient().rescheduleLoans.readLoanRescheduleRequest(requestId,
 param));
+    }
+
     // TODO: Rewrite to use fineract-client instead!
     // Example: 
org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper.disburseLoan(java.lang.Long,
     // org.apache.fineract.client.models.PostLoansLoanIdRequest)

Reply via email to