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


The following commit(s) were added to refs/heads/develop by this push:
     new c9dc87f62 FINERACT-1981: Fix Charge Creation After Maturity Date on 
Interest Bearing Progressive Loan
c9dc87f62 is described below

commit c9dc87f62ab0935c06ebbd9d1c4d6f86609647ef
Author: Soma Sörös <[email protected]>
AuthorDate: Thu Nov 14 16:48:27 2024 +0100

    FINERACT-1981: Fix Charge Creation After Maturity Date on Interest Bearing 
Progressive Loan
---
 .../portfolio/loanaccount/domain/Loan.java         |   3 +-
 ...anChargeRepaymentScheduleProcessingWrapper.java |   2 +-
 .../LoanInterestRecalculationCOBTest.java          | 124 +++++++++++++++++++++
 3 files changed, 127 insertions(+), 2 deletions(-)

diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 4ba2c3b24..d607f2764 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -2446,7 +2446,8 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom<Long> {
             }
         }
         if (reprocess) {
-            if 
(this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
+            if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()
+                    && 
!getLoanProductRelatedDetail().getLoanScheduleType().equals(LoanScheduleType.PROGRESSIVE))
 {
                 
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
             }
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retrieveListOfTransactionsForReprocessing();
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java
index a3237dd7e..e31f6c113 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java
@@ -46,7 +46,7 @@ public class 
SingleLoanChargeRepaymentScheduleProcessingWrapper {
             totalPrincipal = 
totalPrincipal.plus(installment.getPrincipal(currency));
         }
         LoanChargePaidBy accrualBy = null;
-        if (!loan.isInterestBearing() && loanCharge.isSpecifiedDueDate()) { // 
TODO: why only if not interest bearing
+        if (loanCharge.isSpecifiedDueDate()) {
             LoanRepaymentScheduleInstallment addedPeriod = 
addChargeOnlyRepaymentInstallmentIfRequired(loanCharge, installments);
             if (addedPeriod != null) {
                 addedPeriod.updateObligationsMet(currency, disbursementDate);
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRecalculationCOBTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRecalculationCOBTest.java
index 3378f7b5c..63395b1b9 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRecalculationCOBTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRecalculationCOBTest.java
@@ -38,8 +38,10 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Stream;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
+import org.apache.fineract.client.models.PostChargesResponse;
 import org.apache.fineract.client.models.PostClientsResponse;
 import org.apache.fineract.client.models.PostLoanProductsResponse;
+import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.integrationtests.common.BusinessStepHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
@@ -656,6 +658,128 @@ public class LoanInterestRecalculationCOBTest extends 
BaseLoanIntegrationTest {
         });
     }
 
+    @Test
+    public void 
verifyChargeCreationAfterMaturityDateOnInterestBearingProgressiveLoan() {
+        AtomicReference<Long> loanIdRef = new AtomicReference<>();
+        runAt("1 January 2024", () -> {
+            PostLoanProductsResponse loanProduct = 
loanProductHelper.createLoanProduct(create4IProgressive() //
+                    
.recalculationRestFrequencyType(RecalculationRestFrequencyType.DAILY) //
+                    .currencyCode("USD"));
+
+            Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), 
loanProduct.getResourceId(), "1 January 2024", 100.0, 7.0, 6,
+                    null);
+            loanIdRef.set(loanId);
+
+            disburseLoan(loanId, BigDecimal.valueOf(100), "1 January 2024");
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId);
+            logLoanDetails(loanDetails);
+
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 1, "01 February 
2024", 16.43, 0.0, 0.0, 0.58);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 2, "01 March 
2024", 16.52, 0.0, 0.0, 0.49);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 3, "01 April 
2024", 16.62, 0.0, 0.0, 0.39);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 4, "01 May 2024", 
16.72, 0.0, 0.0, 0.29);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 5, "01 June 2024", 
16.81, 0.0, 0.0, 0.20);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 6, "01 July 2024", 
16.90, 0.0, 0.0, 0.10);
+
+        });
+        runAt("10 July 2024", () -> {
+            Long loanId = loanIdRef.get();
+
+            inlineLoanCOBHelper.executeInlineCOB(List.of(loanId));
+
+            // create charge
+            PostChargesResponse chargeResult = createCharge(10.0);
+            Assertions.assertNotNull(chargeResult);
+            Long chargeId = chargeResult.getResourceId();
+            Assertions.assertNotNull(chargeId);
+
+            // add charge after maturity
+            PostLoansLoanIdChargesResponse loanChargeResult = 
addLoanCharge(loanId, chargeId, "15 July 2024", 10.0);
+            Assertions.assertNotNull(loanChargeResult.getResourceId());
+
+            // verify N+1 installment in schedule
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId);
+            logLoanDetails(loanDetails);
+
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 1, "01 February 
2024", 16.43, 0.0, 0.0, 0.58);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 2, "01 March 
2024", 16.43, 0.0, 0.0, 0.58);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 3, "01 April 
2024", 16.43, 0.0, 0.0, 0.58);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 4, "01 May 2024", 
16.43, 0.0, 0.0, 0.58);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 5, "01 June 2024", 
16.43, 0.0, 0.0, 0.58);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 6, "01 July 2024", 
17.85, 0.0, 0.0, 0.58);
+            validateFullyUnpaidRepaymentPeriod(loanDetails, 7, "15 July 2024", 
0.0, 10.0, 0.0, 0.0);
+
+            Assertions.assertNotNull(loanDetails.getStatus());
+            Assertions.assertEquals(300, loanDetails.getStatus().getId());
+        });
+        runAt("15 July 2024", () -> {
+            Long loanId = loanIdRef.get();
+
+            loanTransactionHelper.makeLoanRepayment("15 July 2024", 113.48F, 
loanId.intValue());
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId);
+            logLoanDetails(loanDetails);
+
+            validateFullyPaidRepaymentPeriod(loanDetails, 1, "01 February 
2024", 16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 2, "01 March 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 3, "01 April 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 4, "01 May 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 5, "01 June 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 6, "01 July 2024", 
17.85, 0.0, 0.0, 0.58, 18.43);
+            validateFullyPaidRepaymentPeriod(loanDetails, 7, "15 July 2024", 
0.0, 10.0, 0.0, 0.0);
+
+            Assertions.assertNotNull(loanDetails.getStatus());
+            Assertions.assertEquals(600, loanDetails.getStatus().getId());
+        });
+        runAt("16 July 2024", () -> {
+            Long loanId = loanIdRef.get();
+
+            // create charge
+            PostChargesResponse chargeResult = createCharge(10.0);
+            Assertions.assertNotNull(chargeResult);
+            Long chargeId = chargeResult.getResourceId();
+            Assertions.assertNotNull(chargeId);
+
+            // add charge after maturity
+            PostLoansLoanIdChargesResponse loanChargeResult = 
addLoanCharge(loanId, chargeId, "20 July 2024", 15.0);
+            Assertions.assertNotNull(loanChargeResult.getResourceId());
+
+            // verify N+1 installment in schedule
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId);
+            logLoanDetails(loanDetails);
+
+            validateFullyPaidRepaymentPeriod(loanDetails, 1, "01 February 
2024", 16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 2, "01 March 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 3, "01 April 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 4, "01 May 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 5, "01 June 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 6, "01 July 2024", 
17.85, 0.0, 0.0, 0.58, 18.43);
+            validateRepaymentPeriod(loanDetails, 7, LocalDate.of(2024, 7, 20), 
0.0, 0.0, 0.0, 25.0, 10.0, 15.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+
+            Assertions.assertNotNull(loanDetails.getStatus());
+            Assertions.assertEquals(300, loanDetails.getStatus().getId());
+        });
+        runAt("20 July 2024", () -> {
+            Long loanId = loanIdRef.get();
+
+            loanTransactionHelper.makeLoanRepayment("20 July 2024", 15.0F, 
loanId.intValue());
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId);
+            logLoanDetails(loanDetails);
+
+            validateFullyPaidRepaymentPeriod(loanDetails, 1, "01 February 
2024", 16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 2, "01 March 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 3, "01 April 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 4, "01 May 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 5, "01 June 2024", 
16.43, 0.0, 0.0, 0.58, 17.01);
+            validateFullyPaidRepaymentPeriod(loanDetails, 6, "01 July 2024", 
17.85, 0.0, 0.0, 0.58, 18.43);
+            validateFullyPaidRepaymentPeriod(loanDetails, 7, "20 July 2024", 
0.0, 25.0, 0.0, 0.0);
+
+            Assertions.assertNotNull(loanDetails.getStatus());
+            Assertions.assertEquals(600, loanDetails.getStatus().getId());
+        });
+    }
+
     @Test
     public void 
verifyEarlyLateRepaymentOnProgressiveLoanNextInstallmentAllocationRepayEmi() {
         AtomicReference<Long> loanIdRef = new AtomicReference<>();

Reply via email to