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

arnold 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 76a03ecdbf FINERACT-2232: Capitalized income and Caplitalized income 
adjustment in case of loan is overpaid
76a03ecdbf is described below

commit 76a03ecdbf23d86dbe98a50659bfe49267e8a013
Author: Jose Alberto Hernandez <[email protected]>
AuthorDate: Fri Jun 6 08:01:00 2025 -0500

    FINERACT-2232: Capitalized income and Caplitalized income adjustment in 
case of loan is overpaid
---
 .../ProgressiveLoanTransactionValidatorImpl.java   | 15 +++--
 .../LoanCapitalizedIncomeTest.java                 | 66 ++++++++++++++++++++++
 2 files changed, 75 insertions(+), 6 deletions(-)

diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanTransactionValidatorImpl.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanTransactionValidatorImpl.java
index 4837634050..54754195fb 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanTransactionValidatorImpl.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanTransactionValidatorImpl.java
@@ -47,6 +47,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeBal
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
@@ -95,9 +96,10 @@ public class ProgressiveLoanTransactionValidatorImpl 
implements ProgressiveLoanT
                 
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("income.capitalization.not.enabled");
             }
 
-            // Validate loan is active
-            if (!loan.getStatus().isActive()) {
-                
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.active");
+            // Validate loan is active, or closed or overpaid
+            final LoanStatus loanStatus = loan.getStatus();
+            if (!loanStatus.isActive() && !loanStatus.isClosed() && 
!loanStatus.isOverpaid()) {
+                
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.valid.loan.status");
             }
 
             final LocalDate transactionDate = 
this.fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
@@ -164,9 +166,10 @@ public class ProgressiveLoanTransactionValidatorImpl 
implements ProgressiveLoanT
                 
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("income.capitalization.not.enabled");
             }
 
-            // Validate loan is active
-            if (!loan.getStatus().isActive()) {
-                
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.active");
+            // Validate loan is active, or closed or overpaid
+            final LoanStatus loanStatus = loan.getStatus();
+            if (!loanStatus.isActive() && !loanStatus.isClosed() && 
!loanStatus.isOverpaid()) {
+                
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.valid.loan.status");
             }
 
             final LocalDate transactionDate = 
this.fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanCapitalizedIncomeTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanCapitalizedIncomeTest.java
index 756f13012e..b92341ec2f 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanCapitalizedIncomeTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanCapitalizedIncomeTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.math.BigDecimal;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
@@ -26,6 +28,7 @@ import 
org.apache.fineract.client.models.GetLoansLoanIdTransactions;
 import org.apache.fineract.client.models.PostClientsResponse;
 import org.apache.fineract.client.models.PostLoanProductsRequest;
 import org.apache.fineract.client.models.PostLoanProductsResponse;
+import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.client.util.CallFailedRuntimeException;
 import org.apache.fineract.integrationtests.common.BusinessStepHelper;
@@ -617,4 +620,67 @@ public class LoanCapitalizedIncomeTest extends 
BaseLoanIntegrationTest {
             });
         });
     }
+
+    @Test
+    public void testLoanCapitalizedIncomeOnLoanClosed() {
+        final AtomicReference<Long> loanIdRef = new AtomicReference<>();
+        final AtomicReference<Long> capitalizedIncomeTransactionIdRef = new 
AtomicReference<>();
+
+        final PostClientsResponse client = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
+
+        final PostLoanProductsResponse loanProductsResponse = loanProductHelper
+                
.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
+                        
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
+                        
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
+                        
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
+                        
.incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+                        
.capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE));
+
+        runAt("1 January 2024", () -> {
+            Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), 
loanProductsResponse.getResourceId(), "1 January 2024",
+                    500.0, 7.0, 3, null);
+            loanIdRef.set(loanId);
+
+            disburseLoan(loanId, BigDecimal.valueOf(100), "1 January 2024");
+            Long capitalizedIncomeTransactionId = 
loanTransactionHelper.addCapitalizedIncome(loanId, "1 January 2024", 50.0)
+                    .getResourceId();
+            
capitalizedIncomeTransactionIdRef.set(capitalizedIncomeTransactionId);
+        });
+        runAt("1 February 2024", () -> {
+            Long loanId = loanIdRef.get();
+            executeInlineCOB(loanId);
+
+            addRepaymentForLoan(loanId, 50.58, "1 February 2024");
+        });
+        runAt("1 March 2024", () -> {
+            Long loanId = loanIdRef.get();
+            executeInlineCOB(loanId);
+
+            addRepaymentForLoan(loanId, 50.58, "1 March 2024");
+        });
+        runAt("15 March 2024", () -> {
+            Long loanId = loanIdRef.get();
+            executeInlineCOB(loanId);
+
+            addRepaymentForLoan(loanId, 50.58, "15 March 2024");
+
+            loanTransactionHelper.makeCreditBalanceRefund(loanId, new 
PostLoansLoanIdTransactionsRequest().dateFormat(DATETIME_PATTERN)
+                    .transactionDate("15 March 
2024").locale("en").transactionAmount(0.15));
+
+            // Validate Loan is Closed
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId);
+            assertTrue(loanDetails.getStatus().getClosedObligationsMet());
+        });
+        runAt("16 March 2024", () -> {
+            Long loanId = loanIdRef.get();
+            executeInlineCOB(loanId);
+
+            Long capitalizedIncomeTransactionId = 
loanTransactionHelper.addCapitalizedIncome(loanId, "16 March 2024", 
50.0).getResourceId();
+
+            verifyTRJournalEntries(capitalizedIncomeTransactionId, 
journalEntry(50, loansReceivableAccount, "DEBIT"), //
+                    journalEntry(50, deferredIncomeLiabilityAccount, "CREDIT") 
//
+            );
+        });
+    }
+
 }

Reply via email to