Skip to content

Commit

Permalink
FINERACT-1971: Disable delinquency calculation for non active loans
Browse files Browse the repository at this point in the history
  • Loading branch information
ruchiD committed May 9, 2024
1 parent be65575 commit 9a02a86
Show file tree
Hide file tree
Showing 8 changed files with 316 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4186,7 +4186,7 @@ private boolean isClosedWithOutsandingAmountMarkedForReschedule() {
return getStatus().isClosedWithOutsandingAmountMarkedForReschedule();
}

private boolean isCancelled() {
public boolean isCancelled() {
return isRejected() || isWithdrawn();
}

Expand Down Expand Up @@ -7273,5 +7273,4 @@ public boolean isEnableInstallmentLevelDelinquency() {
public void updateEnableInstallmentLevelDelinquency(boolean enableInstallmentLevelDelinquency) {
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
if (optLoan.isPresent()) {
final Loan loan = optLoan.get();

// If the Loan is not Active yet, return template data
if (loan.isSubmittedAndPendingApproval() || loan.isApproved()) {
// If the Loan is not Active yet or is cancelled (rejected or withdrawn), return template data
if (loan.isSubmittedAndPendingApproval() || loan.isApproved() || loan.isCancelled()) {
return CollectionData.template();
}

Expand All @@ -137,6 +137,9 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {

final String nextPaymentDueDateConfig = configurationDomainService.getNextPaymentDateConfigForLoan();

// Below method calculates delinquency for active loans only and returns template data for Closed or
// Overpaid
// loans
collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan, effectiveDelinquencyList);
collectionData.setAvailableDisbursementAmount(loan.getApprovedPrincipal().subtract(loan.getDisbursedAmount()));
collectionData.setNextPaymentDueDate(loan.possibleNextRepaymentDate(nextPaymentDueDateConfig));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ public LoanScheduleDelinquencyData calculateDelinquencyData(LoanScheduleDelinque
}
CollectionData collectionData = null;
// If the Loan is not Active yet, return template data
if (loan.isSubmittedAndPendingApproval() || loan.isApproved()) {
// If the Loan is Rejected, Closed written-off, Withdrawn by Client, Closed with outstanding marked for
// reschedule, Closed obligation met, Overpaid, return template data
if (loan.isSubmittedAndPendingApproval() || loan.isApproved() || loan.isClosed() || loan.getStatus().isOverpaid()) {
collectionData = CollectionData.template();
} else {
collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan, effectiveDelinquencyList);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ public CollectionData getOverdueCollectionData(final Loan loan, List<LoanDelinqu
boolean overdueSinceDateWasSet = false;
boolean firstNotYetDueInstallment = false;
log.debug("Loan id {} with {} installments", loan.getId(), loan.getRepaymentScheduleInstallments().size());

// If the Loan is not Active yet, return template data
// If the Loan is Rejected, Closed written-off, Withdrawn by Client, Closed with outstanding marked for
// reschedule, Closed obligation met, Overpaid return template data
if (loan.isSubmittedAndPendingApproval() || loan.isApproved() || loan.isClosed() || loan.getStatus().isOverpaid()) {
return CollectionData.template();
}

// Get the oldest overdue installment if exists one
for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
if (!installment.isObligationsMet()) {
Expand Down Expand Up @@ -124,6 +132,14 @@ public LoanDelinquencyData getLoanDelinquencyData(final Loan loan, List<LoanDeli
boolean overdueSinceDateWasSet = false;
boolean firstNotYetDueInstallment = false;
log.debug("Loan id {} with {} installments", loan.getId(), loan.getRepaymentScheduleInstallments().size());

// If the Loan is not Active yet, return template data
// If the Loan is Rejected, Closed written-off, Withdrawn by Client, Closed with outstanding marked for
// reschedule, Closed obligation met, Overpaid, return template data
if (loan.isSubmittedAndPendingApproval() || loan.isApproved() || loan.isClosed() || loan.getStatus().isOverpaid()) {
return new LoanDelinquencyData(collectionData, loanInstallmentsCollectionData);
}

for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
CollectionData installmentCollectionData = CollectionData.template();
if (!installment.isObligationsMet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.apache.fineract.portfolio.loanaccount.data.LoanDelinquencyData;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
Expand Down Expand Up @@ -123,6 +124,7 @@ public void givenLoanAccountWithoutOverdueThenCalculateDelinquentData() {
when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
when(loan.getCurrency()).thenReturn(currency);
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);

CollectionData collectionData = underTest.getOverdueCollectionData(loan, effectiveDelinquencyList);

Expand Down Expand Up @@ -150,6 +152,7 @@ public void givenLoanAccountWithOverdueThenCalculateDelinquentData() {
when(loan.getLoanTransactions(Mockito.any(Predicate.class))).thenReturn(Collections.emptyList());
when(loan.getLastLoanRepaymentScheduleInstallment()).thenReturn(repaymentScheduleInstallments.get(0));
when(loan.getCurrency()).thenReturn(currency);
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
when(delinquencyEffectivePauseHelper.getPausedDaysBeforeDate(effectiveDelinquencyList, businessDate)).thenReturn(0L);

CollectionData collectionData = underTest.getOverdueCollectionData(loan, effectiveDelinquencyList);
Expand Down Expand Up @@ -186,6 +189,7 @@ public void givenLoanAccountWithoutOverdueWithChargebackThenCalculateDelinquentD
when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
when(loan.getCurrency()).thenReturn(currency);
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);

CollectionData collectionData = underTest.getOverdueCollectionData(loan, effectiveDelinquencyList);

Expand Down Expand Up @@ -217,6 +221,7 @@ public void givenLoanInstallmentWithOverdueEnableInstallmentDelinquencyThenCalcu
when(loan.getLastLoanRepaymentScheduleInstallment()).thenReturn(repaymentScheduleInstallments.get(0));
when(loan.getCurrency()).thenReturn(currency);
when(loan.isEnableInstallmentLevelDelinquency()).thenReturn(true);
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
when(delinquencyEffectivePauseHelper.getPausedDaysBeforeDate(effectiveDelinquencyList, businessDate)).thenReturn(0L);

LoanDelinquencyData collectionData = underTest.getLoanDelinquencyData(loan, effectiveDelinquencyList);
Expand Down Expand Up @@ -266,6 +271,7 @@ public void givenLoanInstallmentWithoutOverdueWithChargebackAndEnableInstallment
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
when(loan.isEnableInstallmentLevelDelinquency()).thenReturn(true);
when(loan.getCurrency()).thenReturn(currency);
when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
when(loan.getLoanTransactions(Mockito.any(Predicate.class))).thenReturn(Arrays.asList(loanTransaction));
when(delinquencyEffectivePauseHelper.getPausedDaysBeforeDate(effectiveDelinquencyList, businessDate)).thenReturn(0L);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,15 @@ protected void verifyLoanStatus(long loanId, LoanStatus loanStatus) {
assertEquals(loanStatus.getCode(), loanDetails.getStatus().getCode());
}

protected void undoLoanApproval(Long loanId) {
loanTransactionHelper.undoApprovalForLoan(loanId, new PostLoansLoanIdRequest());
}

protected void rejectLoan(Long loanId, String rejectedOnDate) {
loanTransactionHelper.rejectLoan(loanId,
new PostLoansLoanIdRequest().rejectedOnDate(rejectedOnDate).locale("en").dateFormat(DATETIME_PATTERN));
}

@RequiredArgsConstructor
public static class BatchRequestBuilder {

Expand Down
Loading

0 comments on commit 9a02a86

Please sign in to comment.