FINERACT-2272: Move fetching chargeback transactions out of foreach of delinquency calculation

This commit is contained in:
mariiaKraievska
2025-05-22 10:22:35 +02:00
committed by Adam Saghy
parent 91da34a8c6
commit 5cd604df43
@@ -48,12 +48,14 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
@Override
@Transactional(readOnly = true)
public CollectionData getOverdueCollectionData(final Loan loan, List<LoanDelinquencyActionData> effectiveDelinquencyList) {
public CollectionData getOverdueCollectionData(final Loan loan, final List<LoanDelinquencyActionData> effectiveDelinquencyList) {
final List<LoanTransaction> chargebackTransactions = loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null,
LoanTransactionType.CHARGEBACK);
final LocalDate businessDate = DateUtils.getBusinessLocalDate();
final MonetaryCurrency loanCurrency = loan.getCurrency();
final CollectionData collectionData = CollectionData.template();
LocalDate overdueSinceDate = null;
CollectionData collectionData = CollectionData.template();
BigDecimal outstandingAmount = BigDecimal.ZERO;
boolean oldestOverdueInstallment = false;
boolean overdueSinceDateWasSet = false;
@@ -85,7 +87,8 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
delinquentPenalty = delinquentPenalty.add(installment.getPenaltyChargesOutstanding(loanCurrency).getAmount());
if (!oldestOverdueInstallment) {
log.debug("Oldest installment {} {}", installment.getInstallmentNumber(), installment.getDueDate());
CollectionData overDueInstallmentDelinquentData = calculateDelinquencyDataForOverdueInstallment(loan, installment);
final CollectionData overDueInstallmentDelinquentData = calculateDelinquencyDataForOverdueInstallment(loan,
installment, chargebackTransactions);
overdueSinceDate = overDueInstallmentDelinquentData.getDelinquentDate();
oldestOverdueInstallment = true;
overdueSinceDateWasSet = true;
@@ -94,7 +97,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
log.debug("Loan Id: {} with installment {} due date {}", loan.getId(), installment.getInstallmentNumber(),
installment.getDueDate());
firstNotYetDueInstallment = true;
CollectionData nonOverDueInstallmentDelinquentData = calculateDelinquencyDataForNonOverdueInstallment(loan,
final CollectionData nonOverDueInstallmentDelinquentData = calculateDelinquencyDataForNonOverdueInstallment(loan,
installment);
outstandingAmount = outstandingAmount.add(nonOverDueInstallmentDelinquentData.getDelinquentAmount());
delinquentPrincipal = delinquentPrincipal.add(nonOverDueInstallmentDelinquentData.getDelinquentPrincipal());
@@ -115,7 +118,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
}
log.debug("Loan id {} with overdue since date {} and outstanding amount {}", loan.getId(), overdueSinceDate, outstandingAmount);
Long overdueDays = 0L;
long overdueDays = 0L;
if (overdueSinceDate != null) {
overdueDays = DateUtils.getDifferenceInDays(overdueSinceDate, businessDate);
if (overdueDays < 0) {
@@ -132,22 +135,23 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
collectionData.setDelinquentPenalty(delinquentPenalty);
collectionData.setDelinquentDays(0L);
Long delinquentDays = overdueDays - graceDays;
final long delinquentDays = overdueDays - graceDays;
if (delinquentDays > 0) {
calculateDelinquentDays(effectiveDelinquencyList, businessDate, collectionData, delinquentDays);
}
log.debug("Result: {}", collectionData.toString());
log.debug("Result: {}", collectionData);
return collectionData;
}
@Override
public LoanDelinquencyData getLoanDelinquencyData(final Loan loan, List<LoanDelinquencyActionData> effectiveDelinquencyList) {
final List<LoanTransaction> chargebackTransactions = loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null,
LoanTransactionType.CHARGEBACK);
final LocalDate businessDate = DateUtils.getBusinessLocalDate();
final CollectionData collectionData = CollectionData.template();
final Map<Long, CollectionData> loanInstallmentsCollectionData = new HashMap<>();
LocalDate overdueSinceDate = null;
CollectionData collectionData = CollectionData.template();
Map<Long, CollectionData> loanInstallmentsCollectionData = new HashMap<>();
BigDecimal outstandingAmount = BigDecimal.ZERO;
boolean oldestOverdueInstallment = false;
boolean overdueSinceDateWasSet = false;
@@ -164,7 +168,8 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
CollectionData installmentCollectionData = CollectionData.template();
if (!installment.isObligationsMet()) {
installmentCollectionData = getInstallmentOverdueCollectionData(loan, installment, effectiveDelinquencyList);
installmentCollectionData = getInstallmentOverdueCollectionData(loan, installment, effectiveDelinquencyList,
chargebackTransactions);
outstandingAmount = outstandingAmount.add(installmentCollectionData.getDelinquentAmount());
// Get the oldest overdue installment if exists
if (DateUtils.isBefore(installment.getDueDate(), businessDate)) {
@@ -194,7 +199,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
}
log.debug("Loan id {} with overdue since date {} and outstanding amount {}", loan.getId(), overdueSinceDate, outstandingAmount);
Long overdueDays = 0L;
long overdueDays = 0L;
if (overdueSinceDate != null) {
overdueDays = DateUtils.getDifferenceInDays(overdueSinceDate, businessDate);
if (overdueDays < 0) {
@@ -206,7 +211,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
}
collectionData.setDelinquentAmount(outstandingAmount);
collectionData.setDelinquentDays(0L);
Long delinquentDays = overdueDays - graceDays;
final long delinquentDays = overdueDays - graceDays;
if (delinquentDays > 0) {
calculateDelinquentDays(effectiveDelinquencyList, businessDate, collectionData, delinquentDays);
}
@@ -221,28 +226,28 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
}
private CollectionData getInstallmentOverdueCollectionData(final Loan loan, final LoanRepaymentScheduleInstallment installment,
List<LoanDelinquencyActionData> effectiveDelinquencyList) {
final List<LoanDelinquencyActionData> effectiveDelinquencyList, final List<LoanTransaction> chargebackTransactions) {
final LocalDate businessDate = DateUtils.getBusinessLocalDate();
LocalDate overdueSinceDate = null;
CollectionData collectionData = CollectionData.template();
final CollectionData collectionData = CollectionData.template();
LocalDate overdueSinceDate;
BigDecimal outstandingAmount = BigDecimal.ZERO;
if (DateUtils.isBefore(installment.getDueDate(), businessDate)) {
// checking overdue installment delinquency data
CollectionData overDueInstallmentDelinquentData = calculateDelinquencyDataForOverdueInstallment(loan, installment);
final CollectionData overDueInstallmentDelinquentData = calculateDelinquencyDataForOverdueInstallment(loan, installment,
chargebackTransactions);
outstandingAmount = outstandingAmount.add(overDueInstallmentDelinquentData.getDelinquentAmount());
overdueSinceDate = overDueInstallmentDelinquentData.getDelinquentDate();
} else {
// checking non overdue installment for chargeback transactions before installment due date and before
// business date
CollectionData nonOverDueInstallmentDelinquentData = calculateDelinquencyDataForNonOverdueInstallment(loan, installment);
final CollectionData nonOverDueInstallmentDelinquentData = calculateDelinquencyDataForNonOverdueInstallment(loan, installment);
outstandingAmount = outstandingAmount.add(nonOverDueInstallmentDelinquentData.getDelinquentAmount());
overdueSinceDate = nonOverDueInstallmentDelinquentData.getDelinquentDate();
}
// Grace days are not considered for installment level delinquency calculation currently.
Long overdueDays = 0L;
long overdueDays = 0L;
if (overdueSinceDate != null) {
overdueDays = DateUtils.getDifferenceInDays(overdueSinceDate, businessDate);
if (overdueDays < 0) {
@@ -253,7 +258,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
}
collectionData.setDelinquentAmount(outstandingAmount);
collectionData.setDelinquentDays(0L);
Long delinquentDays = overdueDays;
final long delinquentDays = overdueDays;
if (delinquentDays > 0) {
calculateDelinquentDays(effectiveDelinquencyList, businessDate, collectionData, delinquentDays);
}
@@ -262,13 +267,11 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
}
private CollectionData calculateDelinquencyDataForOverdueInstallment(final Loan loan,
final LoanRepaymentScheduleInstallment installment) {
final LoanRepaymentScheduleInstallment installment, final List<LoanTransaction> chargebackTransactions) {
final MonetaryCurrency loanCurrency = loan.getCurrency();
LoanRepaymentScheduleInstallment latestInstallment = loan.getLastLoanRepaymentScheduleInstallment();
List<LoanTransaction> chargebackTransactions = loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null,
LoanTransactionType.CHARGEBACK);
LocalDate overdueSinceDate = null;
CollectionData collectionData = CollectionData.template();
final LoanRepaymentScheduleInstallment latestInstallment = loan.getLastLoanRepaymentScheduleInstallment();
final CollectionData collectionData = CollectionData.template();
LocalDate overdueSinceDate;
BigDecimal outstandingAmount = BigDecimal.ZERO;
BigDecimal delinquentPrincipal = BigDecimal.ZERO;
BigDecimal delinquentInterest = BigDecimal.ZERO;
@@ -283,13 +286,13 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
overdueSinceDate = installment.getDueDate();
BigDecimal amountAvailable = installment.getTotalPaid(loanCurrency).getAmount();
boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId());
final boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId());
for (LoanTransaction loanTransaction : chargebackTransactions) {
boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = DateUtils.isEqual(loanTransaction.getTransactionDate(),
final boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = DateUtils.isEqual(loanTransaction.getTransactionDate(),
installment.getFromDate()) || DateUtils.isAfter(loanTransaction.getTransactionDate(), installment.getFromDate());
boolean isLoanTransactionIsBeforeNotLastInstallmentDueDate = !isLatestInstallment
final boolean isLoanTransactionIsBeforeNotLastInstallmentDueDate = !isLatestInstallment
&& DateUtils.isBefore(loanTransaction.getTransactionDate(), installment.getDueDate());
boolean isLoanTransactionIsOnOrBeforeLastInstallmentDueDate = isLatestInstallment
final boolean isLoanTransactionIsOnOrBeforeLastInstallmentDueDate = isLatestInstallment
&& (DateUtils.isEqual(loanTransaction.getTransactionDate(), installment.getDueDate())
|| DateUtils.isBefore(loanTransaction.getTransactionDate(), installment.getDueDate()));
if (isLoanTransactionIsOnOrAfterInstallmentFromDate