diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java index a146fd850cf..306baeccca7 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java @@ -144,6 +144,10 @@ public LoanScheduleModel generate(final MathContext mc, final LoanApplicationTer scheduleParams.incrementPeriodNumber(); } + if (chargesDueAtTimeOfDisbursement.compareTo(BigDecimal.ZERO) > 0) { + scheduleParams.addTotalRepaymentExpected(Money.of(currency, chargesDueAtTimeOfDisbursement, mc)); + } + if (loanApplicationTerms.isMultiDisburseLoan()) { processDisbursements(loanApplicationTerms, disbursementDataList, scheduleParams, interestScheduleModel, periods, chargesDueAtTimeOfDisbursement, true, mc); diff --git a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java index 06d86fe6ad1..858e31978bf 100644 --- a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java +++ b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java @@ -49,6 +49,7 @@ class LoanScheduleGeneratorTest { private static final CurrencyData CURRENCY = APPLICATION_CURRENCY.toData(); private static final BigDecimal DISBURSEMENT_AMOUNT = BigDecimal.valueOf(192.22); private static final BigDecimal DISBURSEMENT_AMOUNT_100 = BigDecimal.valueOf(100); + private static final BigDecimal DISBURSEMENT_CHARGE = BigDecimal.valueOf(10.0); private static final BigDecimal NOMINAL_INTEREST_RATE = BigDecimal.valueOf(9.99); private static final int NUMBER_OF_REPAYMENTS = 6; private static final int REPAYMENT_FREQUENCY = 1; @@ -168,4 +169,37 @@ private void checkDownPaymentPeriod(LoanSchedulePlanDownPaymentPeriod period, in assertEquals(0, expectedTotalDue.compareTo(period.getTotalDueAmount())); assertEquals(0, expectedOutstandingLoanBalance.compareTo(period.getOutstandingLoanBalance())); } + + @Test + void testGenerateLoanScheduleWithDisbursementCharges() { + LoanRepaymentScheduleModelData modelData = new LoanRepaymentScheduleModelData(LocalDate.of(2024, 1, 1), CURRENCY, + DISBURSEMENT_AMOUNT, DISBURSEMENT_DATE, NUMBER_OF_REPAYMENTS, REPAYMENT_FREQUENCY, REPAYMENT_FREQUENCY_TYPE, + NOMINAL_INTEREST_RATE, false, DaysInMonthType.DAYS_30, DaysInYearType.DAYS_360, null, null, null, false, null, + InterestMethod.DECLINING_BALANCE, true, false); + + ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator(); + ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator, + interestScheduleModelRepositoryWrapperMock); + generator.setLoanTransactionProcessingService(loanTransactionProcessingService); + + LoanSchedulePlan loanSchedule = generator.generate(mc, modelData); + + BigDecimal totalPrincipal = BigDecimal.ZERO; + BigDecimal totalInterest = BigDecimal.ZERO; + BigDecimal totalDueAmount = BigDecimal.ZERO; + + for (var period : loanSchedule.getPeriods()) { + if (period instanceof LoanSchedulePlanRepaymentPeriod repayment) { + totalPrincipal = totalPrincipal.add(repayment.getPrincipalAmount()); + totalInterest = totalInterest.add(repayment.getInterestAmount()); + totalDueAmount = totalDueAmount.add(repayment.getTotalDueAmount()); + } + } + + BigDecimal expectedTotalWithCharge = totalPrincipal.add(totalInterest).add(DISBURSEMENT_CHARGE); + + assertEquals(0, expectedTotalWithCharge.stripTrailingZeros().compareTo(totalDueAmount.stripTrailingZeros()), + "The sum of all period totals should include the disbursement charge"); + } + }