This is an automated email from the ASF dual-hosted git repository. adamsaghy pushed a commit to branch revert-3998-enhancement/loan_account_current_payable_interest in repository https://gitbox.apache.org/repos/asf/fineract.git
commit 4ee33e2559e1e3331af77e8aff9da6348decde33 Author: Adam Saghy <[email protected]> AuthorDate: Wed Jul 31 09:20:21 2024 +0200 Revert "FINERACT-2081: Loan account summary with Unpaid Payable Interest" This reverts commit 737455f52f3330461f97486b5f99f74ec62ba6ec. --- .../src/main/avro/loan/v1/LoanSummaryDataV1.avsc | 4 +- .../loanaccount/data/LoanSummaryData.java | 86 +++++++++---- .../loanschedule/data/LoanSchedulePeriodData.java | 44 ------- .../loanaccount/api/LoansApiResourceSwagger.java | 4 +- ...PaymentAllocationLoanRepaymentScheduleTest.java | 141 +++++---------------- 5 files changed, 95 insertions(+), 184 deletions(-) diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc index 9ad816a55..5e74118cf 100644 --- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc +++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc @@ -437,7 +437,7 @@ }, { "default": null, - "name": "totalUnpaidPayableDueInterest", + "name": "totalUnpaidAccruedDueInterest", "type": [ "null", "bigdecimal" @@ -445,7 +445,7 @@ }, { "default": null, - "name": "totalUnpaidPayableNotDueInterest", + "name": "totalUnpaidAccruedNotDueInterest", "type": [ "null", "bigdecimal" diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java index 01d688f0b..af9e1b9f1 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java @@ -26,6 +26,7 @@ import lombok.Builder; import lombok.Data; import lombok.experimental.Accessors; import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.infrastructure.core.service.MathUtil; import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData; @@ -99,12 +100,11 @@ public class LoanSummaryData { private final Long chargeOffReasonId; private final String chargeOffReason; - private BigDecimal totalUnpaidPayableDueInterest; - private BigDecimal totalUnpaidPayableNotDueInterest; + private BigDecimal totalUnpaidAccruedDueInterest; + private BigDecimal totalUnpaidAccruedNotDueInterest; public static LoanSummaryData withTransactionAmountsSummary(final LoanSummaryData defaultSummaryData, final LoanScheduleData repaymentSchedule, final Collection<LoanTransactionBalance> loanTransactionBalances) { - final LocalDate businessDate = DateUtils.getBusinessLocalDate(); BigDecimal totalMerchantRefund = BigDecimal.ZERO; BigDecimal totalMerchantRefundReversed = BigDecimal.ZERO; @@ -121,8 +121,8 @@ public class LoanSummaryData { BigDecimal totalRepaymentTransactionReversed = BigDecimal.ZERO; BigDecimal totalInterestPaymentWaiver = BigDecimal.ZERO; BigDecimal totalInterestRefund = BigDecimal.ZERO; - BigDecimal totalUnpaidPayableDueInterest = BigDecimal.ZERO; - BigDecimal totalUnpaidPayableNotDueInterest = BigDecimal.ZERO; + BigDecimal totalUnpaidAccruedDueInterest = BigDecimal.ZERO; + BigDecimal totalUnpaidAccruedNotDueInterest = BigDecimal.ZERO; totalChargeAdjustment = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CHARGE_ADJUSTMENT.getValue()); @@ -160,12 +160,25 @@ public class LoanSummaryData { LoanTransactionType.REPAYMENT.getValue()); if (repaymentSchedule != null) { - // Outstanding Interest on Past due installments - totalUnpaidPayableDueInterest = computeTotalUnpaidPayableDueInterestAmount(repaymentSchedule.getPeriods(), businessDate); + // Accrued Due Interest on Past due installments + totalUnpaidAccruedDueInterest = computeTotalAccruedDueInterestAmount(repaymentSchedule.getPeriods()); + if (MathUtil.isGreaterThanZero(totalUnpaidAccruedDueInterest)) { + totalUnpaidAccruedDueInterest = totalUnpaidAccruedDueInterest + .subtract(computeTotalInterestPaidDueAmount(repaymentSchedule.getPeriods())); + if (MathUtil.isLessThanZero(totalUnpaidAccruedDueInterest)) { + totalUnpaidAccruedDueInterest = BigDecimal.ZERO; + } + } - // Accumulated daily interest of the current Installment period - totalUnpaidPayableNotDueInterest = computeTotalUnpaidPayableNotDueInterestAmountOnActualPeriod(repaymentSchedule.getPeriods(), - businessDate); + // Accrued Due Interest on Actual Installment + totalUnpaidAccruedNotDueInterest = computeTotalAccruedNotDueInterestAmountOnActualPeriod(repaymentSchedule.getPeriods()); + if (MathUtil.isGreaterThanZero(totalUnpaidAccruedNotDueInterest)) { + totalUnpaidAccruedNotDueInterest = totalUnpaidAccruedNotDueInterest + .subtract(computeTotalInterestPaidNotDueAmountOnActualPeriod(repaymentSchedule.getPeriods())); + if (MathUtil.isLessThanZero(totalUnpaidAccruedNotDueInterest)) { + totalUnpaidAccruedNotDueInterest = BigDecimal.ZERO; + } + } } return LoanSummaryData.builder().currency(defaultSummaryData.currency).principalDisbursed(defaultSummaryData.principalDisbursed) @@ -199,8 +212,8 @@ public class LoanSummaryData { .totalChargeback(totalChargeback).totalCreditBalanceRefund(totalCreditBalanceRefund) .totalCreditBalanceRefundReversed(totalCreditBalanceRefundReversed).totalRepaymentTransaction(totalRepaymentTransaction) .totalRepaymentTransactionReversed(totalRepaymentTransactionReversed).totalInterestPaymentWaiver(totalInterestPaymentWaiver) - .totalUnpaidPayableDueInterest(totalUnpaidPayableDueInterest) - .totalUnpaidPayableNotDueInterest(totalUnpaidPayableNotDueInterest).totalInterestRefund(totalInterestRefund).build(); + .totalUnpaidAccruedDueInterest(totalUnpaidAccruedDueInterest) + .totalUnpaidAccruedNotDueInterest(totalUnpaidAccruedNotDueInterest).totalInterestRefund(totalInterestRefund).build(); } private static BigDecimal fetchLoanTransactionBalanceByType(final Collection<LoanTransactionBalance> loanTransactionBalances, @@ -223,23 +236,44 @@ public class LoanSummaryData { return LoanSummaryData.builder().currency(currencyData).build(); } - private static BigDecimal computeTotalUnpaidPayableDueInterestAmount(Collection<LoanSchedulePeriodData> periods, - final LocalDate businessDate) { + private static BigDecimal computeTotalAccruedDueInterestAmount(Collection<LoanSchedulePeriodData> periods) { + final LocalDate businessDate = DateUtils.getBusinessLocalDate(); return periods.stream().filter(period -> !period.getDownPaymentPeriod() && businessDate.isAfter(period.getDueDate())) - .map(period -> period.getInterestOutstanding()).reduce(BigDecimal.ZERO, BigDecimal::add); + .map(period -> period.getTotalAccruedInterest()).reduce(BigDecimal.ZERO, BigDecimal::add); } - private static BigDecimal computeTotalUnpaidPayableNotDueInterestAmountOnActualPeriod(final Collection<LoanSchedulePeriodData> periods, - final LocalDate businessDate) { - // Default value equal to Zero - BigDecimal totalAccruedNotDueInterestAmount = BigDecimal.ZERO; - // Find the current Period (If exists one) based in the Business date - final Optional<LoanSchedulePeriodData> optCurrentPeriod = periods.stream() - .filter(period -> !period.getDownPaymentPeriod() && period.isActualPeriod(businessDate)).findFirst(); - if (optCurrentPeriod.isPresent()) { - totalAccruedNotDueInterestAmount = optCurrentPeriod.get().getInterestDueUntilDate(businessDate); - } - return totalAccruedNotDueInterestAmount; + private static BigDecimal computeTotalInterestPaidDueAmount(Collection<LoanSchedulePeriodData> periods) { + final LocalDate businessDate = DateUtils.getBusinessLocalDate(); + return periods.stream().filter(period -> !period.getDownPaymentPeriod() && businessDate.isAfter(period.getDueDate())) + .map(period -> period.getInterestPaid()).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + private static BigDecimal computeTotalAccruedNotDueInterestAmountOnActualPeriod(Collection<LoanSchedulePeriodData> periods) { + final LocalDate businessDate = DateUtils.getBusinessLocalDate(); + return periods.stream() + .filter(period -> !period.getDownPaymentPeriod() && isActualPeriod(period) && businessDate.isBefore(period.getDueDate())) + .map(period -> period.getTotalAccruedInterest()).reduce(BigDecimal.ZERO, BigDecimal::add); } + private static BigDecimal computeTotalInterestPaidNotDueAmountOnActualPeriod(Collection<LoanSchedulePeriodData> periods) { + final LocalDate businessDate = DateUtils.getBusinessLocalDate(); + return periods.stream() + .filter(period -> !period.getDownPaymentPeriod() && isActualPeriod(period) && businessDate.isBefore(period.getDueDate())) + .map(period -> period.getInterestPaid()).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + private static boolean isActualPeriod(LoanSchedulePeriodData period) { + final LocalDate businessDate = DateUtils.getBusinessLocalDate(); + boolean actualPeriod = false; + if (period.getPeriod() != null) { + if (period.getPeriod() == 1) { + actualPeriod = ((businessDate.isEqual(period.getFromDate()) || businessDate.isAfter(period.getFromDate())) + && businessDate.isBefore(period.getDueDate())); + } else { + actualPeriod = (businessDate.isAfter(period.getFromDate()) && businessDate.isBefore(period.getDueDate())); + } + } + + return actualPeriod; + } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java index 730b61a69..fcf050ee7 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java @@ -23,7 +23,6 @@ import java.time.LocalDate; import java.time.temporal.ChronoUnit; import lombok.Getter; import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.organisation.monetary.domain.MoneyHelper; /** * Immutable data object that represents a period of a loan schedule. @@ -403,49 +402,6 @@ public final class LoanSchedulePeriodData { return value; } - public BigDecimal getRatePerDay() { - return getInterestOriginalDue().divide(BigDecimal.valueOf(getDaysInPeriod()), MoneyHelper.getMathContext()); - } - - public BigDecimal getInterestDueUntilDate(final LocalDate businessDate) { - if (getComplete()) { - return BigDecimal.ZERO; - } else { - if (businessDate.compareTo(getDueDate()) >= 0) { // Period is matured - return getInterestOriginalDue(); - } - if (businessDate.compareTo(getFromDate()) >= 0) { // If It is the current period - return getRatePerDay().multiply(BigDecimal.valueOf(DateUtils.getDifferenceInDays(getPeriodStartDate(), businessDate)), - MoneyHelper.getMathContext()); - } - return BigDecimal.ZERO; - } - } - - public boolean isActualPeriod(final LocalDate businessDate) { - boolean actualPeriod = false; - if (getPeriod() != null) { - if (getPeriod() == 1) { - actualPeriod = ((businessDate.compareTo(getFromDate()) >= 0) && businessDate.compareTo(getDueDate()) <= 0); - } else { - actualPeriod = ((businessDate.compareTo(getFromDate()) > 0) && businessDate.compareTo(getDueDate()) <= 0); - } - } - - return actualPeriod; - } - - private LocalDate getPeriodStartDate() { - if (getPeriod() != null) { - if (getPeriod() == 1) { - return getFromDate(); - } else { - return getFromDate().plusDays(1); - } - } - return null; - } - public BigDecimal getPrincipalDisbursed() { return defaultToZeroIfNull(this.principalDisbursed); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java index 91ba44c03..44dbe6621 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java @@ -640,9 +640,9 @@ final class LoansApiResourceSwagger { @Schema(example = "0.000000") public Double totalRepaymentTransactionReversed; @Schema(example = "0.000000") - public BigDecimal totalUnpaidPayableDueInterest; + public BigDecimal totalUnpaidAccruedDueInterest; @Schema(example = "0.000000") - public BigDecimal totalUnpaidPayableNotDueInterest; + public BigDecimal totalUnpaidAccruedNotDueInterest; @Schema(example = "0.000000") public BigDecimal totalInterestRefund; public Set<GetLoansLoanIdOverdueCharges> overdueCharges; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java index e522f0bd9..f94bca231 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java @@ -4720,8 +4720,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan // After Disbursement we are expecting no Accrual transactions GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); }); // Not Due yet @@ -4732,14 +4732,14 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan periodicAccrualAccountingHelper.runPeriodicAccrualAccounting("30 January 2024"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(new BigDecimal("0.97"), loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(new BigDecimal("0.97"), loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); // Partial interest repayment addRepaymentForLoan(createdLoanId.get(), 20.50, "30 January 2024"); loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(new BigDecimal("0.05"), loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(new BigDecimal("0.05"), loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); }); // Not Due and Due Interest @@ -4749,8 +4749,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan periodicAccrualAccountingHelper.runPeriodicAccrualAccounting("20 February 2024"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(new BigDecimal("0.12"), loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(new BigDecimal("0.52"), loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(new BigDecimal("0.12"), loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(new BigDecimal("0.52"), loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); }); } @@ -4767,12 +4767,11 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan runAt(operationDate, () -> { Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId(); PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation() - .interestRatePerPeriod(108.0).interestCalculationPeriodType(RepaymentFrequencyType.DAYS) - .interestRateFrequencyType(YEARS).daysInMonthType(DaysInMonthType.ACTUAL.getValue()) - .daysInYearType(DaysInYearType.DAYS_360.getValue()).numberOfRepayments(4)// - .maxInterestRatePerPeriod((double) 110)// - .repaymentEvery(1)// - .repaymentFrequencyType(1L)// + .interestRatePerPeriod(12.0).interestCalculationPeriodType(RepaymentFrequencyType.DAYS).interestRateFrequencyType(YEARS) + .daysInMonthType(DaysInMonthType.ACTUAL.getValue()).daysInYearType(DaysInYearType.DAYS_365.getValue()) + .numberOfRepayments(4)// + .repaymentEvery(5)// + .repaymentFrequencyType(0L)// .allowPartialPeriodInterestCalcualtion(false)// .multiDisburseLoan(false)// .disallowExpectedDisbursements(null)// @@ -4782,8 +4781,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan .installmentAmountInMultiplesOf(null)// ;// PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product); - PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductResponse.getResourceId(), operationDate, 1000.0, 4) - .interestRatePerPeriod(BigDecimal.valueOf(108.0)); + PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductResponse.getResourceId(), operationDate, 1000.0, 4); applicationRequest = applicationRequest.interestCalculationPeriodType(DAYS) .transactionProcessingStrategyCode(LoanProductTestBuilder.ADVANCED_PAYMENT_ALLOCATION_STRATEGY); @@ -4798,13 +4796,12 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan loanTransactionHelper.disburseLoan(loanResponse.getLoanId(), new PostLoansLoanIdRequest().actualDisbursementDate(operationDate) .dateFormat(DATETIME_PATTERN).transactionAmount(BigDecimal.valueOf(1000.0)).locale("en")); - // After Disbursement we are expecting amount in Zero (first day) + // After Disbursement we are expecting no Accrual transactions GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); }); - // First day on First Period, then TotalUnpaidPayableDueInterest = 0 and TotalUnpaidPayableNotDueInterest = 3 runAt("2 January 2024", () -> { // Generate the Accruals final PeriodicAccrualAccountingHelper periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(requestSpec, @@ -4812,106 +4809,30 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan periodicAccrualAccountingHelper.runPeriodicAccrualAccounting("2 January 2024"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(3.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); }); - // Second day on First Period, then TotalUnpaidPayableDueInterest = 0 and TotalUnpaidPayableNotDueInterest = 6 runAt("3 January 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(6.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); - - // Third day on First Period, then TotalUnpaidPayableDueInterest = 0 and TotalUnpaidPayableNotDueInterest = 9 - runAt("4 January 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(9.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); - - // Fourth day on First Period, then TotalUnpaidPayableDueInterest = 0 and TotalUnpaidPayableNotDueInterest = 12 - runAt("5 January 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(12.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); - - // Last day on First Period, then TotalUnpaidPayableDueInterest = 0 and TotalUnpaidPayableNotDueInterest = 90 - runAt("31 January 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(90.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); + // Add a Charge + addCharge(createdLoanId.get(), false, 10, "6 January 2024"); - // First day on Second Period, then TotalUnpaidPayableDueInterest = 90 and TotalUnpaidPayableNotDueInterest = 0 - runAt("1 February 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.valueOf(90.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); - - // Second day on Second Period, then TotalUnpaidPayableDueInterest = 90 and TotalUnpaidPayableNotDueInterest = - // 2.344 - runAt("2 February 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.valueOf(90.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(2.344), loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); - - // Third day on Second Period, then TotalUnpaidPayableDueInterest = 90 and TotalUnpaidPayableNotDueInterest = - // 4.688 - runAt("3 February 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.valueOf(90.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(4.688), loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); - - // N day on Second Period, then TotalUnpaidPayableDueInterest = 90 and TotalUnpaidPayableNotDueInterest = 21.096 - runAt("10 February 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.valueOf(90.0).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(21.096).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); - - // First day on Third Period, then TotalUnpaidPayableDueInterest = 90 + 70.32 and - // TotalUnpaidPayableNotDueInterest = 0 - runAt("2 March 2024", () -> { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.valueOf(160.32).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); - }); + final PeriodicAccrualAccountingHelper periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(requestSpec, + responseSpec); + periodicAccrualAccountingHelper.runPeriodicAccrualAccounting("2 January 2024"); - // Second day on Third Period, then TotalUnpaidPayableDueInterest = 90 + 70.32 and - // TotalUnpaidPayableNotDueInterest = 0 - runAt("3 March 2024", () -> { GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.valueOf(160.32).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(1.629), loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); }); - // Add Payment to pay the First installment, then TotalUnpaidPayableDueInterest = 70.32 and - // TotalUnpaidPayableNotDueInterest = 14.661 - runAt("11 March 2024", () -> { - addRepaymentForLoan(createdLoanId.get(), 340.00, "11 March 2024"); + // Add Payment higher than accrued amount + runAt("4 January 2024", () -> { + addRepaymentForLoan(createdLoanId.get(), 150.0, "4 January 2024"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(createdLoanId.get()); - assertEquals(BigDecimal.valueOf(70.32).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableDueInterest().stripTrailingZeros()); - assertEquals(BigDecimal.valueOf(14.661).stripTrailingZeros(), - loanDetails.getSummary().getTotalUnpaidPayableNotDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedDueInterest().stripTrailingZeros()); + assertEquals(BigDecimal.ZERO, loanDetails.getSummary().getTotalUnpaidAccruedNotDueInterest().stripTrailingZeros()); }); }
