FINERACT-1968: Enhanced charge handling

This commit is contained in:
Adam Saghy
2023-11-23 19:21:43 +01:00
parent 48300cd19d
commit 054903a952
11 changed files with 638 additions and 148 deletions
@@ -612,15 +612,17 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
CurrencyData currencyData = applicationCurrency.toData();
Set<LoanCharge> loanCharges = loan.getActiveCharges();
int firstNormalInstallmentNumber = LoanRepaymentScheduleProcessingWrapper.fetchFirstNormalInstallmentNumber(installments);
for (LoanRepaymentScheduleInstallment installment : installments) {
if (DateUtils.isAfter(installment.getDueDate(), loan.getMaturityDate())) {
accruedTill = DateUtils.getBusinessLocalDate();
}
if (!isOrganisationDateEnabled || DateUtils.isBefore(organisationStartDate, installment.getDueDate())) {
boolean isFirstNormalInstallment = installment.getInstallmentNumber().equals(firstNormalInstallmentNumber);
generateLoanScheduleAccrualData(accruedTill, loanScheduleAccrualList, loanId, officeId, accrualStartDate,
repaymentFrequency, repayEvery, interestCalculatedFrom, loanProductId, currency, currencyData, loanCharges,
installment);
installment, isFirstNormalInstallment);
}
}
@@ -639,7 +641,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
final Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas, final Long loanId, Long officeId,
final LocalDate accrualStartDate, final PeriodFrequencyType repaymentFrequency, final Integer repayEvery,
final LocalDate interestCalculatedFrom, final Long loanProductId, final MonetaryCurrency currency,
final CurrencyData currencyData, final Set<LoanCharge> loanCharges, final LoanRepaymentScheduleInstallment installment) {
final CurrencyData currencyData, final Set<LoanCharge> loanCharges, final LoanRepaymentScheduleInstallment installment,
boolean isFirstNormalInstallment) {
if (!DateUtils.isBefore(accruedTill, installment.getDueDate()) || (DateUtils.isAfter(accruedTill, installment.getFromDate())
&& !DateUtils.isAfter(accruedTill, installment.getDueDate()))) {
@@ -651,7 +654,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
}
for (final LoanCharge loanCharge : loanCharges) {
boolean isDue = installment.isFirstPeriod()
boolean isDue = isFirstNormalInstallment
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(installment.getFromDate(), chargesTillDate)
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(), chargesTillDate);
if (isDue) {
@@ -109,7 +109,6 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
Mockito.when(charge.getAmountOutstanding(currency)).thenReturn(chargeAmountMoney);
Mockito.when(loanTransaction.getLoan()).thenReturn(loan);
Mockito.when(loan.getDisbursementDate()).thenReturn(disbursementDate);
Mockito.when(installment.isFirstPeriod()).thenReturn(true);
Mockito.when(charge.isDueForCollectionFromIncludingAndUpToAndIncluding(disbursementDate, installment.getDueDate()))
.thenReturn(true);
Mockito.when(installment.getInstallmentNumber()).thenReturn(1);
@@ -154,7 +153,6 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
Mockito.when(charge.getAmountOutstanding(currency)).thenReturn(chargeAmountMoney);
Mockito.when(loanTransaction.getLoan()).thenReturn(loan);
Mockito.when(loan.getDisbursementDate()).thenReturn(disbursementDate);
Mockito.when(installment.isFirstPeriod()).thenReturn(true);
Mockito.when(charge.isDueForCollectionFromIncludingAndUpToAndIncluding(disbursementDate, installment.getDueDate()))
.thenReturn(true);
Mockito.when(installment.getInstallmentNumber()).thenReturn(1);
@@ -204,7 +202,6 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
Mockito.when(loanTransaction.getLoan().getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
Mockito.when(loanProductRelatedDetail.getLoanScheduleProcessingType()).thenReturn(LoanScheduleProcessingType.HORIZONTAL);
Mockito.when(loan.getDisbursementDate()).thenReturn(disbursementDate);
Mockito.when(installment.isFirstPeriod()).thenReturn(true);
Mockito.when(charge.isDueForCollectionFromIncludingAndUpToAndIncluding(disbursementDate, installment.getDueDate()))
.thenReturn(true);
Mockito.when(installment.getInstallmentNumber()).thenReturn(1);
@@ -40,6 +40,14 @@ public class ChargeOrTransactionTest {
Assertions.assertTrue(transaction.compareTo(charge) == 0);
}
@Test
public void testCompareToEqualBackdatedCharge() {
ChargeOrTransaction charge = createCharge("2023-10-16", "2023-10-17", "2023-10-17T10:15:30+01:00");
ChargeOrTransaction transaction = createTransaction("2023-10-16", "2023-10-17", "2023-10-17T10:15:30+01:00");
Assertions.assertTrue(charge.compareTo(transaction) == 0);
Assertions.assertTrue(transaction.compareTo(charge) == 0);
}
@Test
public void testCompareToCreatedDateTime() {
ChargeOrTransaction charge = createCharge("2023-10-17", "2023-10-17", "2023-10-17T10:15:31+01:00");
@@ -77,7 +85,7 @@ public class ChargeOrTransactionTest {
}
@Test
public void testComparatorOnSameDay() {
public void testComparatorOnSameDayBackdatedCharge() {
ChargeOrTransaction cot1 = createCharge("2023-10-17", "2023-10-19", "2023-10-19T10:15:31+01:00");
ChargeOrTransaction cot2 = createTransaction("2023-10-17", "2023-10-19", "2023-10-19T10:15:33+01:00");
ChargeOrTransaction cot3 = createCharge("2023-10-17", "2023-10-19", "2023-10-19T10:15:32+01:00");
@@ -88,6 +96,18 @@ public class ChargeOrTransactionTest {
}
}
@Test
public void testComparatorOnSameDay() {
ChargeOrTransaction cot1 = createCharge("2023-10-24", "2023-10-19", "2023-10-19T10:15:31+01:00");
ChargeOrTransaction cot2 = createTransaction("2023-10-19", "2023-10-19", "2023-10-19T10:15:33+01:00");
ChargeOrTransaction cot3 = createCharge("2023-10-24", "2023-10-19", "2023-10-19T10:15:32+01:00");
Collection<List<ChargeOrTransaction>> permutations = Collections2.permutations(List.of(cot1, cot2, cot3));
List<ChargeOrTransaction> expected = List.of(cot1, cot3, cot2);
for (List<ChargeOrTransaction> permutation : permutations) {
Assertions.assertEquals(expected, permutation.stream().sorted().toList());
}
}
private ChargeOrTransaction createCharge(String effectiveDate, String submittedDate, String creationDateTime) {
LoanCharge charge = Mockito.mock(LoanCharge.class);
Mockito.when(charge.getDueDate()).thenReturn(LocalDate.parse(effectiveDate));