Skip to content

Commit

Permalink
FINERACT-1971: Fix EMI Calculator: Last Unpaid Repayment Period Handl…
Browse files Browse the repository at this point in the history
…ing.

call calculateLastUnpaidRepaymentPeriodEMI recursively when emi would be less than already paid to adjust remaining emi correction for previous period.
Fixing AdvancedPaymentScheduleTransactionProcessor to handle division by installment count adjustment part in case of IN_ADVANCED payment
  • Loading branch information
somasorosdpc committed Jan 13, 2025
1 parent 3481761 commit 6cb1220
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1689,16 +1689,16 @@ private Money processAllocationsHorizontally(LoanTransaction loanTransaction, Tr
transactionMappings, loanTransaction, inAdvanceInstallment, currency);

Loan loan = loanTransaction.getLoan();
// Adjust the portion for the last installment
if (inAdvanceInstallment.equals(inAdvanceInstallments.get(numberOfInstallments - 1))) {
evenPortion = evenPortion.add(balanceAdjustment);
}
if (transactionCtx instanceof ProgressiveTransactionCtx ctx && loan.isInterestBearing()
&& loan.getLoanProductRelatedDetail().isInterestRecalculationEnabled() && !ctx.isChargedOff()) {
paidPortion = handlingPaymentAllocationForInterestBearingProgressiveLoan(loanTransaction, evenPortion,
balances, paymentAllocationType, inAdvanceInstallment, ctx,
loanTransactionToRepaymentScheduleMapping, inAdvanceInstallmentCharges);
} else {
// Adjust the portion for the last installment
if (inAdvanceInstallment.equals(inAdvanceInstallments.get(numberOfInstallments - 1))) {
evenPortion = evenPortion.add(balanceAdjustment);
}
paidPortion = processPaymentAllocation(paymentAllocationType, inAdvanceInstallment, loanTransaction,
evenPortion, loanTransactionToRepaymentScheduleMapping, inAdvanceInstallmentCharges, balances,
LoanRepaymentScheduleInstallment.PaymentAction.PAY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ private void calculateLastUnpaidRepaymentPeriodEMI(ProgressiveLoanInterestSchedu
.reduce((first, second) -> second);
findLastUnpaidRepaymentPeriod.ifPresent(repaymentPeriod -> {
repaymentPeriod.setEmi(repaymentPeriod.getEmi().add(diff, mc));
if (repaymentPeriod.getEmi().isLessThanZero()) {
repaymentPeriod.setEmi(repaymentPeriod.getEmi().zero());
if (repaymentPeriod.getEmi().isLessThan(repaymentPeriod.getTotalPaidAmount())) {
repaymentPeriod.setEmi(repaymentPeriod.getTotalPaidAmount());
calculateLastUnpaidRepaymentPeriodEMI(scheduleModel);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -128,6 +129,120 @@ public void verifyInterestRefundNotCreatedForMerchantIssuedRefundWhenTypesAreEmp
});
}

@Test
public void verifyFullMerchantIssuedRefundWithReAmortizationOnDay0HighInterest6month() {
runAt("1 January 2021", () -> {
PostLoanProductsResponse loanProduct = loanProductHelper
.createLoanProduct(create4IProgressive().daysInMonthType(DaysInMonthType.ACTUAL) //
.daysInYearType(DaysInYearType.ACTUAL) //
.addSupportedInterestRefundTypesItem(SupportedInterestRefundTypesItem.MERCHANT_ISSUED_REFUND) //
.paymentAllocation(List.of(createDefaultPaymentAllocation("REAMORTIZATION")))//
.recalculationRestFrequencyType(RecalculationRestFrequencyType.DAILY) //
);
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 January 2021", 600.0, 60.0,
6, null);
Assertions.assertNotNull(loanId);
disburseLoan(loanId, BigDecimal.valueOf(600), "1 January 2021");
PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper
.makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 600F, loanId.intValue());
Assertions.assertNotNull(postLoansLoanIdTransactionsResponse);
Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId());

verifyTransactions(loanId, transaction(600.0, "Disbursement", "01 January 2021"), //
transaction(600.0, "Merchant Issued Refund", "01 January 2021") //
);
verifyRepaymentSchedule(loanId, installment(600.0, null, "01 January 2021"), //
fullyRepaidInstallment(100.0, 0.0, "01 February 2021"), //
fullyRepaidInstallment(100.0, 0.0, "01 March 2021"), //
fullyRepaidInstallment(100.0, 0.0, "01 April 2021"), //
fullyRepaidInstallment(100.0, 0.0, "01 May 2021"), //
fullyRepaidInstallment(100.0, 0.0, "01 June 2021"), //
fullyRepaidInstallment(100.0, 0.0, "01 July 2021") //
);
});
}

@Test
public void verifyAlmostFullMerchantIssuedRefundWithReAmortizationOnDay0HighInterest12month() {
runAt("1 January 2021", () -> {
PostLoanProductsResponse loanProduct = loanProductHelper
.createLoanProduct(create4IProgressive().daysInMonthType(DaysInMonthType.ACTUAL) //
.daysInYearType(DaysInYearType.ACTUAL) //
.addSupportedInterestRefundTypesItem(SupportedInterestRefundTypesItem.MERCHANT_ISSUED_REFUND) //
.paymentAllocation(List.of(createDefaultPaymentAllocation("REAMORTIZATION")))//
.recalculationRestFrequencyType(RecalculationRestFrequencyType.DAILY) //
);
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 January 2021", 1000.0, 26.0,
12, null);
Assertions.assertNotNull(loanId);
disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021");

PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper
.makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 980F, loanId.intValue());
Assertions.assertNotNull(postLoansLoanIdTransactionsResponse);
Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId());

verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), //
transaction(980.0, "Merchant Issued Refund", "01 January 2021") //
);

verifyRepaymentSchedule(loanId, installment(1000.0, null, "01 January 2021"), //
installment(95.04, 0.44, 13.81, false, "01 February 2021"), //
installment(88.30, 0.13, 6.76, false, "01 March 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 April 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 May 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 June 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 July 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 August 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 September 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 October 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 November 2021"), //
fullyRepaidInstallment(81.67, 0.0, "01 December 2021"), //
fullyRepaidInstallment(81.63, 0.0, "01 January 2022") //
);
});
}

@Test
public void verifyFullMerchantIssuedRefundWithReAmortizationOnDay0HighInterest12month() {
runAt("1 January 2021", () -> {
PostLoanProductsResponse loanProduct = loanProductHelper
.createLoanProduct(create4IProgressive().daysInMonthType(DaysInMonthType.ACTUAL) //
.daysInYearType(DaysInYearType.ACTUAL) //
.addSupportedInterestRefundTypesItem(SupportedInterestRefundTypesItem.MERCHANT_ISSUED_REFUND) //
.paymentAllocation(List.of(createDefaultPaymentAllocation("REAMORTIZATION")))//
.recalculationRestFrequencyType(RecalculationRestFrequencyType.DAILY) //
);
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 January 2021", 1000.0, 26.0,
12, null);
Assertions.assertNotNull(loanId);
disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021");

PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper
.makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 1000F, loanId.intValue());
Assertions.assertNotNull(postLoansLoanIdTransactionsResponse);
Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId());

verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), //
transaction(1000.0, "Merchant Issued Refund", "01 January 2021") //
);
verifyRepaymentSchedule(loanId, installment(1000.0, null, "01 January 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 February 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 March 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 April 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 May 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 June 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 July 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 August 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 September 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 October 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 November 2021"), //
fullyRepaidInstallment(83.33, 0.0, "01 December 2021"), //
fullyRepaidInstallment(83.37, 0.0, "01 January 2022") //
);
});
}

@Test
public void verifyInterestRefundCreatedForPayoutRefund() {
AtomicReference<Long> loanIdRef = new AtomicReference<>();
Expand Down

0 comments on commit 6cb1220

Please sign in to comment.