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<>();