Skip to content

Commit

Permalink
FINERACT-2081: Apply penalty to overdue loans enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
Jose Alberto Hernandez committed Sep 4, 2024
1 parent a6e3517 commit 1cd227e
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 27 deletions.
30 changes: 15 additions & 15 deletions fineract-e2e-tests-runner/src/test/resources/features/COB.feature
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ Feature: COBFeature
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_1 | 04 August 2023 | 10 August 2023 |
When Admin sets the business date to "12 August 2023"
When Admin runs COB job
Then Admin checks that last closed business date of loan is "09 August 2023"
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_3 | 10 August 2023 | |
| RANGE_1 | 04 August 2023 | 10 August 2023 |


Scenario: Verify that COB doesn’t touch CLOSED loans
Expand All @@ -89,22 +89,22 @@ Feature: COBFeature
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2023-08-03"
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_3 | 10 August 2023 | |
| RANGE_1 | 04 August 2023 | 10 August 2023 |
And Customer makes "AUTOPAY" repayment on "10 August 2023" with 1000 EUR transaction amount
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_3 | 10 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 10 August 2023 |
When Admin sets the business date to "11 August 2023"
When Admin runs COB job
Then Admin checks that last closed business date of loan is "09 August 2023"
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_3 | 10 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 10 August 2023 |


Scenario: Verify that COB doesn’t touch OVERPAID loans
Expand All @@ -121,22 +121,22 @@ Feature: COBFeature
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2023-08-03"
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_3 | 10 August 2023 | |
| RANGE_1 | 04 August 2023 | 10 August 2023 |
And Customer makes "AUTOPAY" repayment on "10 August 2023" with 1200 EUR transaction amount
Then Loan status will be "OVERPAID"
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_3 | 10 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 10 August 2023 |
When Admin sets the business date to "11 August 2023"
When Admin runs COB job
Then Admin checks that last closed business date of loan is "09 August 2023"
Then Loan delinquency history has the following details:
| Range (Classification) | Added on date | Lifted on date |
| RANGE_3 | 09 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 09 August 2023 |
| RANGE_3 | 10 August 2023 | 10 August 2023 |
| RANGE_1 | 04 August 2023 | 10 August 2023 |

@Skip
Scenario: Verify that COB catch up runs properly on loan which is behind date because of locked with error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public class ApplyChargeToOverdueLoansBusinessStep implements LoanCOBBusinessSte
public Loan execute(Loan loan) {
final Collection<OverdueLoanScheduleData> overdueLoanScheduleDataList = loanReadPlatformService
.retrieveAllOverdueInstallmentsForLoan(loan);
loanChargeWritePlatformService.applyOverdueChargesForLoan(loan.getId(), overdueLoanScheduleDataList);
if (!overdueLoanScheduleDataList.isEmpty()) {
loanChargeWritePlatformService.applyOverdueChargesForLoan(loan.getId(), overdueLoanScheduleDataList);
}
return loan;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon
List<Throwable> exceptions = new ArrayList<>();
for (Map.Entry<Long, Collection<OverdueLoanScheduleData>> entry : overdueScheduleData.entrySet()) {
try {
loanChargeWritePlatformService.applyOverdueChargesForLoan(entry.getKey(), entry.getValue());

if (!entry.getValue().isEmpty()) {
loanChargeWritePlatformService.applyOverdueChargesForLoan(entry.getKey(), entry.getValue());
}
} catch (final PlatformApiDataValidationException e) {
final List<ApiParameterError> errors = e.getErrors();
for (final ApiParameterError error : errors) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -757,11 +758,19 @@ public CommandProcessingResult adjustmentForLoanCharge(Long loanId, Long loanCha
@Transactional
@Override
public void applyOverdueChargesForLoan(final Long loanId, Collection<OverdueLoanScheduleData> overdueLoanScheduleDataList) {
if (overdueLoanScheduleDataList.isEmpty()) {
return;
}
Loan loan = this.loanAssembler.assembleFrom(loanId);
if (loan.isChargedOff()) {
log.warn("Adding charge to Loan: {} is not allowed. Loan Account is Charged-off", loanId);
return;
}
Optional<Charge> optPenaltyCharge = loan.getLoanProduct().getCharges().stream()
.filter((e) -> ChargeTimeType.OVERDUE_INSTALLMENT.getValue().equals(e.getChargeTimeType()) && e.isLoanCharge()).findFirst();
if (optPenaltyCharge.isEmpty()) {
return;
}
final List<Long> existingTransactionIds = loan.findExistingTransactionIds();
final List<Long> existingReversedTransactionIds = loan.findExistingReversedTransactionIds();
boolean runInterestRecalculation = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,15 @@ public Collection<OverdueLoanScheduleData> retrieveAllOverdueInstallmentsForLoan
if (!loan.isOpen()) {
return list;
}

Optional<Charge> optPenaltyCharge = loan.getLoanProduct().getCharges().stream()
.filter((e) -> ChargeTimeType.OVERDUE_INSTALLMENT.getValue().equals(e.getChargeTimeType()) && e.isLoanCharge()).findFirst();

if (optPenaltyCharge.isEmpty()) {
return list;
}
final Charge penaltyCharge = optPenaltyCharge.get();

final Long penaltyWaitPeriod = configurationDomainService.retrievePenaltyWaitPeriod();
final boolean backdatePenalties = configurationDomainService.isBackdatePenaltiesEnabled();

Expand All @@ -1657,16 +1666,9 @@ public Collection<OverdueLoanScheduleData> retrieveAllOverdueInstallmentsForLoan
if (!backdatePenalties && !isDueToday) {
continue;
}
Optional<Charge> penaltyCharge = loan.getLoanProduct().getCharges().stream()
.filter((e) -> ChargeTimeType.OVERDUE_INSTALLMENT.getValue().equals(e.getChargeTimeType()) && e.isLoanCharge())
.findFirst();

if (penaltyCharge.isEmpty()) {
continue;
}

list.add(new OverdueLoanScheduleData(loan.getId(), penaltyCharge.get().getId(),
DateUtils.DEFAULT_DATE_FORMATTER.format(installment.getDueDate()), penaltyCharge.get().getAmount(),
list.add(new OverdueLoanScheduleData(loan.getId(), penaltyCharge.getId(),
DateUtils.DEFAULT_DATE_FORMATTER.format(installment.getDueDate()), penaltyCharge.getAmount(),
DateUtils.DEFAULT_DATE_FORMAT, Locale.ENGLISH.toLanguageTag(),
installment.getPrincipalOutstanding(loan.getCurrency()).getAmount(),
installment.getInterestOutstanding(loan.getCurrency()).getAmount(), installment.getInstallmentNumber()));
Expand Down

0 comments on commit 1cd227e

Please sign in to comment.