FINERACT-2221: Fix - Interest not counted towards totalUnpaidPayableNotDueInterest after partial repayment
This commit is contained in:
+2
-2
@@ -87,13 +87,13 @@ public abstract class CommonLoanSummaryDataProvider implements LoanSummaryDataPr
|
||||
totalRepaymentTransactionReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances,
|
||||
LoanTransactionType.REPAYMENT);
|
||||
|
||||
if (repaymentSchedule != null) {
|
||||
if (repaymentSchedule != null && defaultSummaryData.getInterestCharged().compareTo(BigDecimal.ZERO) > 0) {
|
||||
// Outstanding Interest on Past due installments
|
||||
totalUnpaidPayableDueInterest = computeTotalUnpaidPayableDueInterestAmount(repaymentSchedule.getPeriods(), businessDate);
|
||||
|
||||
// Accumulated daily interest of the current Installment period
|
||||
totalUnpaidPayableNotDueInterest = computeTotalUnpaidPayableNotDueInterestAmountOnActualPeriod(loan,
|
||||
repaymentSchedule.getPeriods(), businessDate, defaultSummaryData.getCurrency());
|
||||
repaymentSchedule.getPeriods(), businessDate, defaultSummaryData.getCurrency(), totalUnpaidPayableDueInterest);
|
||||
}
|
||||
|
||||
return LoanSummaryData.builder().currency(defaultSummaryData.getCurrency())
|
||||
|
||||
+2
-1
@@ -44,7 +44,8 @@ public class CumulativeLoanSummaryDataProvider extends CommonLoanSummaryDataProv
|
||||
|
||||
@Override
|
||||
public BigDecimal computeTotalUnpaidPayableNotDueInterestAmountOnActualPeriod(final Loan loan,
|
||||
final Collection<LoanSchedulePeriodData> periods, final LocalDate businessDate, final CurrencyData currency) {
|
||||
final Collection<LoanSchedulePeriodData> periods, final LocalDate businessDate, final CurrencyData currency,
|
||||
BigDecimal totalUnpaidPayableDueInterest) {
|
||||
// Find the current Period (If exists one) based on the Business date
|
||||
final Optional<LoanSchedulePeriodData> optCurrentPeriod = periods.stream().filter(period -> !period.isDownPaymentPeriod() //
|
||||
&& period.getPeriod() != null //
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ public interface LoanSummaryDataProvider {
|
||||
BigDecimal computeTotalUnpaidPayableDueInterestAmount(Collection<LoanSchedulePeriodData> periods, LocalDate businessDate);
|
||||
|
||||
BigDecimal computeTotalUnpaidPayableNotDueInterestAmountOnActualPeriod(Loan loan, Collection<LoanSchedulePeriodData> periods,
|
||||
LocalDate businessDate, CurrencyData currency);
|
||||
LocalDate businessDate, CurrencyData currency, BigDecimal totalUnpaidPayableDueInterest);
|
||||
|
||||
LoanSummaryData withOnlyCurrencyData(CurrencyData currencyData);
|
||||
|
||||
|
||||
+21
-27
@@ -21,9 +21,9 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -40,7 +40,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.imp
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
||||
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
||||
import org.apache.fineract.portfolio.loanproduct.calc.data.PeriodDueDetails;
|
||||
import org.apache.fineract.portfolio.loanproduct.calc.data.OutstandingDetails;
|
||||
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -71,26 +71,25 @@ public class ProgressiveLoanSummaryDataProvider extends CommonLoanSummaryDataPro
|
||||
return super.withTransactionAmountsSummary(loan, defaultSummaryData, repaymentSchedule, loanTransactionBalances);
|
||||
}
|
||||
|
||||
private LoanRepaymentScheduleInstallment getRelatedRepaymentScheduleInstallment(Loan loan, LocalDate businessDate) {
|
||||
private Optional<LoanRepaymentScheduleInstallment> getRelatedRepaymentScheduleInstallment(Loan loan, LocalDate businessDate) {
|
||||
return loan.getRepaymentScheduleInstallments().stream().filter(i -> !i.isDownPayment() && !i.isAdditional()
|
||||
&& !businessDate.isBefore(i.getFromDate()) && businessDate.isBefore(i.getDueDate())).findFirst().orElseGet(() -> {
|
||||
List<LoanRepaymentScheduleInstallment> list = loan.getRepaymentScheduleInstallments().stream()
|
||||
.filter(i -> !i.isDownPayment() && !i.isAdditional()).toList();
|
||||
return !list.isEmpty() ? list.get(list.size() - 1) : null;
|
||||
});
|
||||
&& businessDate.isAfter(i.getFromDate()) && !businessDate.isAfter(i.getDueDate())).findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal computeTotalUnpaidPayableNotDueInterestAmountOnActualPeriod(final Loan loan,
|
||||
final Collection<LoanSchedulePeriodData> periods, final LocalDate businessDate, final CurrencyData currency) {
|
||||
if (loan.isMatured(businessDate)) {
|
||||
final Collection<LoanSchedulePeriodData> periods, final LocalDate businessDate, final CurrencyData currency,
|
||||
BigDecimal totalUnpaidPayableDueInterest) {
|
||||
if (loan.isMatured(businessDate) || !loan.isInterestBearing()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = getRelatedRepaymentScheduleInstallment(loan, businessDate);
|
||||
if (loan.isInterestBearing() && loanRepaymentScheduleInstallment != null) {
|
||||
Optional<LoanRepaymentScheduleInstallment> currentRepaymentPeriod = getRelatedRepaymentScheduleInstallment(loan, businessDate);
|
||||
|
||||
if (currentRepaymentPeriod.isPresent()) {
|
||||
if (loan.isChargedOff()) {
|
||||
return loanRepaymentScheduleInstallment.getInterestOutstanding(loan.getCurrency()).getAmount();
|
||||
return MathUtil.subtractToZero(currentRepaymentPeriod.get().getInterestOutstanding(loan.getCurrency()).getAmount(),
|
||||
totalUnpaidPayableDueInterest);
|
||||
} else {
|
||||
List<LoanTransaction> transactionsToReprocess = loan.retrieveListOfTransactionsForReprocessing().stream()
|
||||
.filter(t -> !t.isAccrualActivity()).toList();
|
||||
@@ -107,20 +106,15 @@ public class ProgressiveLoanSummaryDataProvider extends CommonLoanSummaryDataPro
|
||||
replayedTransactions);
|
||||
}
|
||||
if (model != null) {
|
||||
LoanRepaymentScheduleInstallment nextUnpaidInAdvanceInstallment = loanRepaymentScheduleInstallment.isNotFullyPaidOff()
|
||||
? loanRepaymentScheduleInstallment
|
||||
: loan.getRepaymentScheduleInstallments().stream().filter(LoanRepaymentScheduleInstallment::isNotFullyPaidOff)
|
||||
.filter(i -> i.getInstallmentNumber() != null)
|
||||
.min(Comparator.comparingInt(LoanRepaymentScheduleInstallment::getInstallmentNumber)).orElse(null);
|
||||
if (nextUnpaidInAdvanceInstallment == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
PeriodDueDetails dueAmounts = emiCalculator.getDueAmounts(model, nextUnpaidInAdvanceInstallment.getDueDate(),
|
||||
businessDate);
|
||||
if (dueAmounts != null) {
|
||||
BigDecimal interestPaid = nextUnpaidInAdvanceInstallment.getInterestPaid();
|
||||
BigDecimal dueInterest = dueAmounts.getDueInterest().getAmount();
|
||||
return MathUtil.subtractToZero(dueInterest, interestPaid);
|
||||
OutstandingDetails outstandingDetails = emiCalculator.getOutstandingAmountsTillDate(model, businessDate);
|
||||
if (!loan.isInterestRecalculationEnabled()) {
|
||||
BigDecimal interestPaid = periods.stream().map(LoanSchedulePeriodData::getInterestPaid).reduce(BigDecimal.ZERO,
|
||||
BigDecimal::add);
|
||||
BigDecimal dueInterest = outstandingDetails.getOutstandingInterest().getAmount();
|
||||
return MathUtil.subtractToZero(dueInterest, interestPaid, totalUnpaidPayableDueInterest);
|
||||
} else {
|
||||
return MathUtil.subtractToZero(outstandingDetails.getOutstandingInterest().getAmount(),
|
||||
totalUnpaidPayableDueInterest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user