You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ar...@apache.org on 2022/09/22 08:58:31 UTC
[fineract] branch develop updated: Fix loan repayment schedule with multidisburse
This is an automated email from the ASF dual-hosted git repository.
arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 1521b9dcf Fix loan repayment schedule with multidisburse
1521b9dcf is described below
commit 1521b9dcf64c67be48389be6556b7f080e54f5c8
Author: Jose Alberto Hernandez <al...@MacBook-Pro.local>
AuthorDate: Thu Aug 18 19:38:47 2022 -0500
Fix loan repayment schedule with multidisburse
---
.../portfolio/calendar/service/CalendarUtils.java | 1 -
.../portfolio/loanaccount/domain/Loan.java | 30 ++-
.../domain/AbstractLoanScheduleGenerator.java | 10 +-
.../domain/DefaultScheduledDateGenerator.java | 23 +-
.../loanschedule/domain/LoanApplicationTerms.java | 126 +---------
.../LoanWritePlatformServiceJpaRepositoryImpl.java | 12 +-
.../ClientLoanIntegrationTest.java | 8 +-
.../DelinquencyBucketsIntegrationTest.java | 6 +-
.../LoanAuditingIntegrationTest.java | 2 +-
.../LoanDisbursementDetailsIntegrationTest.java | 276 +++++++++++----------
.../LoanRepaymentRescheduleAtDisbursementTest.java | 2 +-
.../LoanRescheduleWithAdvancePaymentTest.java | 4 +-
.../LoanReschedulingWithinCenterTest.java | 2 +-
.../LoanTransactionAuditingIntegrationTest.java | 2 +-
.../common/loans/LoanApplicationTestBuilder.java | 2 +-
.../common/loans/LoanProductTestBuilder.java | 7 +
.../common/loans/LoanTransactionHelper.java | 14 ++
17 files changed, 237 insertions(+), 290 deletions(-)
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
index 16cd36a8d..d5332238a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
@@ -373,7 +373,6 @@ public final class CalendarUtils {
}
public static boolean isValidRedurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate date) {
-
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
if (recur == null) {
return false;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 3acf93cc1..105fdbfe9 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -59,6 +59,7 @@ import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
@@ -142,6 +143,7 @@ import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDat
import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.stereotype.Component;
+@Slf4j
@Entity
@Component
@Table(name = "m_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "loan_account_no_UNIQUE"),
@@ -5112,15 +5114,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
actualChanges.put(LoanApiConstants.disbursementPrincipalParameterName,
command.bigDecimalValueOfParameterNamed(LoanApiConstants.disbursementPrincipalParameterName, locale));
- Collection<LoanDisbursementDetails> loanDisburseDetails = this.getDisbursementDetails();
- BigDecimal setPrincipalAmount = BigDecimal.ZERO;
- for (LoanDisbursementDetails details : loanDisburseDetails) {
- if (details.actualDisbursementDate() != null) {
- setPrincipalAmount = setPrincipalAmount.add(details.principal());
- }
- }
+ this.loanRepaymentScheduleDetail.setPrincipal(getPrincipalAmountForRepaymentSchedule());
- this.loanRepaymentScheduleDetail.setPrincipal(setPrincipalAmount);
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
} else {
@@ -5141,6 +5136,25 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
return changedTransactionDetail;
}
+ public BigDecimal getPrincipalAmountForRepaymentSchedule() {
+ BigDecimal principalAmount = BigDecimal.ZERO;
+
+ if (isMultiDisburmentLoan() && isDisbursed()) {
+ Collection<LoanDisbursementDetails> loanDisburseDetails = this.getDisbursementDetails();
+ for (LoanDisbursementDetails details : loanDisburseDetails) {
+ if (details.actualDisbursementDate() != null) {
+ principalAmount = principalAmount.add(details.principal());
+ }
+ }
+ } else if (isApproved()) {
+ principalAmount = getApprovedPrincipal();
+ } else {
+ principalAmount = getPrincipal().getAmount();
+ }
+
+ return principalAmount;
+ }
+
public BigDecimal retriveLastEmiAmount() {
BigDecimal emiAmount = this.fixedEmiAmount;
LocalDate startDate = this.getDisbursementDate();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
index 3a695c326..1bb5793e7 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
@@ -1259,8 +1259,14 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
*/
private Money getPrincipalToBeScheduled(final LoanApplicationTerms loanApplicationTerms) {
Money principalToBeScheduled;
- if (loanApplicationTerms.isMultiDisburseLoan() && loanApplicationTerms.getApprovedPrincipal().isGreaterThanZero()) {
- principalToBeScheduled = loanApplicationTerms.getApprovedPrincipal();
+ if (loanApplicationTerms.isMultiDisburseLoan()) {
+ if (loanApplicationTerms.getTotalDisbursedAmount().isGreaterThanZero()) {
+ principalToBeScheduled = loanApplicationTerms.getTotalMultiDisbursedAmount();
+ } else if (loanApplicationTerms.getApprovedPrincipal().isGreaterThanZero()) {
+ principalToBeScheduled = loanApplicationTerms.getApprovedPrincipal();
+ } else {
+ principalToBeScheduled = loanApplicationTerms.getPrincipal();
+ }
} else {
principalToBeScheduled = loanApplicationTerms.getPrincipal();
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
index 154856a4c..b4abfea6d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
@@ -20,9 +20,11 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
+import net.fortuna.ical4j.model.Recur;
import org.apache.fineract.organisation.holiday.domain.Holiday;
import org.apache.fineract.organisation.holiday.service.HolidayUtil;
import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
+import org.apache.fineract.organisation.workingdays.domain.RepaymentRescheduleType;
import org.apache.fineract.organisation.workingdays.service.WorkingDaysUtil;
import org.apache.fineract.portfolio.calendar.data.CalendarHistoryDataWrapper;
import org.apache.fineract.portfolio.calendar.domain.Calendar;
@@ -131,10 +133,14 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
private AdjustedDateDetailsDTO recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(
final AdjustedDateDetailsDTO adjustedDateDetailsDTO, final LoanApplicationTerms loanApplicationTerms,
final HolidayDetailDTO holidayDetailDTO, final boolean isFirstRepayment) {
-
- checkAndUpdateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
- isFirstRepayment);
-
+ final Recur recur = CalendarUtils.getICalRecur(holidayDetailDTO.getWorkingDays().getRecurrence());
+ final boolean isSevenDaysWeek = (recur.getDayList().size() == 7); // 7 Seven days in the week
+ // If Workings days are not seven day week
+ if (!isSevenDaysWeek) {
+ checkAndUpdateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
+ isFirstRepayment);
+ }
+ // Check Holidays If applied
checkAndUpdateWorkingDayIfRepaymentDateIsHolidayDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
isFirstRepayment);
@@ -148,6 +154,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(adjustedDateDetailsDTO,
loanApplicationTerms, holidayDetailDTO, isFirstRepayment);
}
+
return adjustedDateDetailsDTO;
}
@@ -192,10 +199,12 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
*/
private void checkAndUpdateWorkingDayIfRepaymentDateIsNonWorkingDay(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
final HolidayDetailDTO holidayDetailDTO, final LoanApplicationTerms loanApplicationTerms, final boolean isFirstRepayment) {
+
while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), adjustedDateDetailsDTO.getChangedScheduleDate())) {
- if (WorkingDaysUtil
- .getRepaymentRescheduleType(holidayDetailDTO.getWorkingDays(), adjustedDateDetailsDTO.getChangedScheduleDate())
- .isMoveToNextRepaymentDay()) {
+ final RepaymentRescheduleType repaymentRescheduleType = WorkingDaysUtil
+ .getRepaymentRescheduleType(holidayDetailDTO.getWorkingDays(), adjustedDateDetailsDTO.getChangedScheduleDate());
+
+ if (repaymentRescheduleType.isMoveToNextRepaymentDay()) {
while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(),
adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate())
|| adjustedDateDetailsDTO.getChangedScheduleDate()
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index f0bb45fc2..bfa24b54d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -43,7 +43,6 @@ import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrapper;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
@@ -252,32 +251,6 @@ public final class LoanApplicationTerms {
}
- public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
- final PeriodFrequencyType loanTermPeriodFrequencyType, NthDayType nthDay, DayOfWeekType dayOfWeek,
- final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
- final LocalDate calculatedRepaymentsStartingFromDate, final Money inArrearsTolerance,
- final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan, final BigDecimal emiAmount,
- final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance, final LocalDate interestChargedFromDate,
- final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
- final RecalculationFrequencyType recalculationFrequencyType, final CalendarInstance restCalendarInstance,
- final InterestRecalculationCompoundingMethod compoundingMethod, final CalendarInstance compoundingCalendarInstance,
- final RecalculationFrequencyType compoundingFrequencyType,
- final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy,
- final LoanRescheduleStrategyMethod rescheduleStrategyMethod, BigDecimal approvedAmount, BigDecimal annualNominalInterestRate,
- List<LoanTermVariationsData> loanTermVariations, final Integer numberOfDays, final boolean isSkipRepaymentOnFirstDayOfMonth,
- final Calendar loanCalendar, final HolidayDetailDTO holidayDetailDTO, final boolean allowCompoundingOnEod) {
- final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
-
- return assembleFrom(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, nthDay, dayOfWeek,
- expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, inArrearsTolerance,
- loanProductRelatedDetail, multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance, interestChargedFromDate,
- principalThresholdForLastInstalment, installmentAmountInMultiplesOf, recalculationFrequencyType, restCalendarInstance,
- compoundingMethod, compoundingCalendarInstance, compoundingFrequencyType, loanPreClosureInterestCalculationStrategy,
- rescheduleStrategyMethod, loanCalendar, approvedAmount, annualNominalInterestRate, loanTermVariations,
- calendarHistoryDataWrapper, numberOfDays, isSkipRepaymentOnFirstDayOfMonth, holidayDetailDTO, allowCompoundingOnEod, false,
- false, null, false);
- }
-
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
final PeriodFrequencyType loanTermPeriodFrequencyType, NthDayType nthDay, DayOfWeekType dayOfWeek,
final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
@@ -337,93 +310,6 @@ public final class LoanApplicationTerms {
isPrincipalCompoundingDisabledForOverdueLoans);
}
- public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
- final PeriodFrequencyType loanTermPeriodFrequencyType, final LocalDate expectedDisbursementDate,
- final LocalDate repaymentsStartingFromDate, final LocalDate calculatedRepaymentsStartingFromDate,
- final Money inArrearsTolerance, final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan,
- final BigDecimal emiAmount, final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
- final LocalDate interestChargedFromDate, final LoanInterestRecalculationDetails interestRecalculationDetails,
- final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType,
- final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
- final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
- final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy, final Calendar loanCalendar,
- BigDecimal approvedAmount, final BigDecimal annualNominalInterestRate, final List<LoanTermVariationsData> loanTermVariations,
- Integer numberOfDays, boolean isSkipRepaymentOnFirstDayOfMonth, final HolidayDetailDTO holidayDetailDTO,
- final boolean allowCompoundingOnEod) {
-
- final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
- final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
- final PeriodFrequencyType repaymentPeriodFrequencyType = loanProductRelatedDetail.getRepaymentPeriodFrequencyType();
- final AmortizationMethod amortizationMethod = loanProductRelatedDetail.getAmortizationMethod();
- final InterestMethod interestMethod = loanProductRelatedDetail.getInterestMethod();
- final BigDecimal interestRatePerPeriod = loanProductRelatedDetail.getNominalInterestRatePerPeriod();
- final PeriodFrequencyType interestRatePeriodFrequencyType = loanProductRelatedDetail.getInterestPeriodFrequencyType();
- final InterestCalculationPeriodMethod interestCalculationPeriodMethod = loanProductRelatedDetail
- .getInterestCalculationPeriodMethod();
- final boolean allowPartialPeriodInterestCalcualtion = loanProductRelatedDetail.isAllowPartialPeriodInterestCalcualtion();
- final Money principalMoney = loanProductRelatedDetail.getPrincipal();
-
- //
- final Integer graceOnPrincipalPayment = loanProductRelatedDetail.graceOnPrincipalPayment();
- final Integer recurringMoratoriumOnPrincipalPeriods = loanProductRelatedDetail.recurringMoratoriumOnPrincipalPeriods();
- final Integer graceOnInterestPayment = loanProductRelatedDetail.graceOnInterestPayment();
- final Integer graceOnInterestCharged = loanProductRelatedDetail.graceOnInterestCharged();
-
- // Interest recalculation settings
- final DaysInMonthType daysInMonthType = loanProductRelatedDetail.fetchDaysInMonthType();
- final DaysInYearType daysInYearType = loanProductRelatedDetail.fetchDaysInYearType();
- final boolean isInterestRecalculationEnabled = loanProductRelatedDetail.isInterestRecalculationEnabled();
- LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
- InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
- if (isInterestRecalculationEnabled) {
- rescheduleStrategyMethod = interestRecalculationDetails.getRescheduleStrategyMethod();
- interestRecalculationCompoundingMethod = interestRecalculationDetails.getInterestRecalculationCompoundingMethod();
- }
- final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
- final boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = false;
- final boolean isEqualAmortization = loanProductRelatedDetail.isEqualAmortization();
- return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
- repaymentEvery, repaymentPeriodFrequencyType, null, null, amortizationMethod, interestMethod, interestRatePerPeriod,
- interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod,
- allowPartialPeriodInterestCalcualtion, principalMoney, expectedDisbursementDate, repaymentsStartingFromDate,
- calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, recurringMoratoriumOnPrincipalPeriods,
- graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
- disbursementDatas, maxOutstandingBalance, loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType,
- isInterestRecalculationEnabled, rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance,
- recalculationFrequencyType, compoundingCalendarInstance, compoundingFrequencyType, principalThresholdForLastInstalment,
- installmentAmountInMultiplesOf, loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations,
- calendarHistoryDataWrapper, isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfDays,
- isSkipRepaymentOnFirstDayOfMonth, holidayDetailDTO, allowCompoundingOnEod, isEqualAmortization, false, false, null, false);
-
- }
-
- public static LoanApplicationTerms assembleFrom(final LoanApplicationTerms applicationTerms,
- final List<LoanTermVariationsData> loanTermVariations) {
- return new LoanApplicationTerms(applicationTerms.currency, applicationTerms.loanTermFrequency,
- applicationTerms.loanTermPeriodFrequencyType, applicationTerms.numberOfRepayments, applicationTerms.repaymentEvery,
- applicationTerms.repaymentPeriodFrequencyType, applicationTerms.nthDay, applicationTerms.weekDayType,
- applicationTerms.amortizationMethod, applicationTerms.interestMethod, applicationTerms.interestRatePerPeriod,
- applicationTerms.interestRatePeriodFrequencyType, applicationTerms.annualNominalInterestRate,
- applicationTerms.interestCalculationPeriodMethod, applicationTerms.allowPartialPeriodInterestCalcualtion,
- applicationTerms.principal, applicationTerms.expectedDisbursementDate, applicationTerms.repaymentsStartingFromDate,
- applicationTerms.calculatedRepaymentsStartingFromDate, applicationTerms.principalGrace,
- applicationTerms.recurringMoratoriumOnPrincipalPeriods, applicationTerms.interestPaymentGrace,
- applicationTerms.interestChargingGrace, applicationTerms.interestChargedFromDate, applicationTerms.inArrearsTolerance,
- applicationTerms.multiDisburseLoan, applicationTerms.actualFixedEmiAmount, applicationTerms.disbursementDatas,
- applicationTerms.maxOutstandingBalance, applicationTerms.graceOnArrearsAgeing, applicationTerms.daysInMonthType,
- applicationTerms.daysInYearType, applicationTerms.interestRecalculationEnabled, applicationTerms.rescheduleStrategyMethod,
- applicationTerms.interestRecalculationCompoundingMethod, applicationTerms.restCalendarInstance,
- applicationTerms.recalculationFrequencyType, applicationTerms.compoundingCalendarInstance,
- applicationTerms.compoundingFrequencyType, applicationTerms.principalThresholdForLastInstalment,
- applicationTerms.installmentAmountInMultiplesOf, applicationTerms.preClosureInterestCalculationStrategy,
- applicationTerms.loanCalendar, applicationTerms.approvedPrincipal.getAmount(), loanTermVariations,
- applicationTerms.calendarHistoryDataWrapper, applicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled,
- applicationTerms.numberOfDays, applicationTerms.isSkipRepaymentOnFirstDayOfMonth, applicationTerms.holidayDetailDTO,
- applicationTerms.allowCompoundingOnEod, applicationTerms.isEqualAmortization,
- applicationTerms.isFirstRepaymentDateAllowedOnHoliday, applicationTerms.isInterestToBeRecoveredFirstWhenGreaterThanEMI,
- applicationTerms.fixedPrincipalPercentagePerInstallment, applicationTerms.isPrincipalCompoundingDisabledForOverdueLoans);
- }
-
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer nthDay, final DayOfWeekType weekDayType,
@@ -1702,6 +1588,18 @@ public final class LoanApplicationTerms {
return disbursedAmount;
}
+ public Money getTotalMultiDisbursedAmount() {
+ Money disbursedAmount = Money.zero(getCurrency());
+ if (isMultiDisburseLoan()) {
+ for (DisbursementData disbursement : getDisbursementDatas()) {
+ disbursedAmount = disbursedAmount.plus(disbursement.getPrincipal());
+ }
+ } else {
+ disbursedAmount = getPrincipal();
+ }
+ return disbursedAmount;
+ }
+
public void updatePeriodNumberApplicableForPrincipalOrInterestGrace(final Integer periodsApplicationForGrace) {
int applicablePeriodNumber = periodsApplicationForGrace;
int graceOnPrincipal = defaultToZeroIfNull(this.principalGrace);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index 58ff84cbb..19c9462b5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -2996,20 +2996,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
ChangedTransactionDetail changedTransactionDetail = null;
if (command.entityId() != null) {
-
changedTransactionDetail = loan.updateDisbursementDateAndAmountForTranche(loanDisbursementDetails, command, changes,
scheduleGeneratorDTO);
} else {
- // BigDecimal setAmount = loan.getApprovedPrincipal();
- Collection<LoanDisbursementDetails> loanDisburseDetails = loan.getDisbursementDetails();
- BigDecimal setAmount = BigDecimal.ZERO;
- for (LoanDisbursementDetails details : loanDisburseDetails) {
- if (details.actualDisbursementDate() != null) {
- setAmount = setAmount.add(details.principal());
- }
- }
-
- loan.repaymentScheduleDetail().setPrincipal(setAmount);
+ loan.repaymentScheduleDetail().setPrincipal(loan.getPrincipalAmountForRepaymentSchedule());
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
loan.regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
index f2a61b0db..0303cf825 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
@@ -1288,7 +1288,7 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("20 September 2011") //
.withSubmittedOnDate("20 September 2011") //
- .withwithRepaymentStrategy(repaymentStrategy) //
+ .withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -1316,7 +1316,7 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(fourMonthsfromNow) //
.withSubmittedOnDate(fourMonthsfromNow) //
- .withwithRepaymentStrategy(repaymentStrategy) //
+ .withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -4757,7 +4757,7 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
- .withwithRepaymentStrategy(repaymentStrategy) //
+ .withRepaymentStrategy(repaymentStrategy) //
.withPrincipalGrace(graceOnPrincipalPayment) //
.withInterestGrace(graceOnInterestPayment)//
.withCharges(charges)//
@@ -5816,7 +5816,7 @@ public class ClientLoanIntegrationTest {
.withRepaymentEveryAfter("2")
//
.withAmortizationTypeAsEqualPrincipalPayments().withRepaymentFrequencyTypeAsWeeks()
- .withwithRepaymentStrategy(LoanProductTestBuilder.RBI_INDIA_STRATEGY).withInterestTypeAsFlatBalance()
+ .withRepaymentStrategy(LoanProductTestBuilder.RBI_INDIA_STRATEGY).withInterestTypeAsFlatBalance()
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withPrincipalGrace("1").withInterestGrace("1")
.withLoanTermFrequency("4") //
.withLoanTermFrequencyAsMonths() //
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java
index ab5c8e10d..17814e645 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java
@@ -478,7 +478,7 @@ public class DelinquencyBucketsIntegrationTest {
// First Loan Delinquency Classification after Disbursement command
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), classificationExpected);
- printRepaymentSchedule(getLoansLoanIdResponse);
+ loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
// Apply a partial repayment
operationDate = Utils.dateFormatter.format(todaysDate);
@@ -660,7 +660,7 @@ public class DelinquencyBucketsIntegrationTest {
// First Loan Delinquency Classification after Disbursement command
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), classificationExpected01);
- printRepaymentSchedule(getLoansLoanIdResponse);
+ loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
// Apply a repayment to get a first full paid installment
operationDate = Utils.dateFormatter.format(todaysDate);
@@ -752,7 +752,7 @@ public class DelinquencyBucketsIntegrationTest {
// First Loan Delinquency Classification after Disbursement command
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), classificationExpected);
- printRepaymentSchedule(getLoansLoanIdResponse);
+ loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
// Apply a repayment to get a full paid installment
operationDate = Utils.dateFormatter.format(todaysDate);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java
index fc2de616f..05396c2ed 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java
@@ -176,7 +176,7 @@ public class LoanAuditingIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(submittedOnDate) //
.withSubmittedOnDate(submittedOnDate) //
- .withwithRepaymentStrategy(repaymentStrategy) //
+ .withRepaymentStrategy(repaymentStrategy) //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java
index a2c3d5de0..6b6df5410 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java
@@ -19,6 +19,8 @@
package org.apache.fineract.integrationtests;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
@@ -32,6 +34,10 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
+import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
+import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -43,17 +49,15 @@ import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+@Slf4j
@SuppressWarnings({ "rawtypes", "unchecked" })
public class LoanDisbursementDetailsIntegrationTest {
- private static final Logger LOG = LoggerFactory.getLogger(LoanDisbursementDetailsIntegrationTest.class);
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private LoanTransactionHelper loanTransactionHelper;
- private Integer loanID;
+ private Integer loanId;
private Integer disbursementId;
final String approveDate = "01 March 2014";
final String expectedDisbursementDate = "01 March 2014";
@@ -80,18 +84,18 @@ public class LoanDisbursementDetailsIntegrationTest {
createTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "01 September 2015", "5000"));
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
- LOG.info("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------{}", clientID);
+ log.info("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------{}", clientID);
final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder()
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withAmortizationTypeAsEqualInstallments().withTranches(true)
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null));
- LOG.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
+ log.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
loanProductID);
final Integer loanIDWithEmi = applyForLoanApplicationWithEmiAmount(clientID, loanProductID, proposedAmount, createTranches,
installmentAmount);
- LOG.info("-----------------------------------LOAN CREATED WITH EMI LOANID------------------------------------------------- {}",
+ log.info("-----------------------------------LOAN CREATED WITH EMI LOANID------------------------------------------------- {}",
loanIDWithEmi);
HashMap repaymentScheduleWithEmi = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec,
@@ -105,24 +109,23 @@ public class LoanDisbursementDetailsIntegrationTest {
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanIDWithEmi);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
- LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+ log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount("01 June 2015", "01 June 2015", "10000", loanIDWithEmi,
createTranches);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
- LOG.info(
+ log.info(
"-----------------------------------MULTI DISBURSAL LOAN WITH EMI APPROVED SUCCESSFULLY---------------------------------------");
final Integer loanIDWithoutEmi = applyForLoanApplicationWithEmiAmount(clientID, loanProductID, proposedAmount, createTranches,
withoutInstallmentAmount);
- HashMap repaymentScheduleWithoutEmi = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec,
- loanIDWithoutEmi, "repaymentSchedule");
+ this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanIDWithoutEmi, "repaymentSchedule");
ArrayList<HashMap> periods1 = (ArrayList<HashMap>) repaymentScheduleWithEmi.get("periods");
assertEquals(15, periods1.size());
- LOG.info("-----------------------------------LOAN CREATED WITHOUT EMI LOANID------------------------------------------------- {}",
+ log.info("-----------------------------------LOAN CREATED WITHOUT EMI LOANID------------------------------------------------- {}",
loanIDWithoutEmi);
/* To be uncommented once issue MIFOSX-2006 is closed. */
@@ -131,12 +134,12 @@ public class LoanDisbursementDetailsIntegrationTest {
HashMap loanStatusMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanIDWithoutEmi);
LoanStatusChecker.verifyLoanIsPending(loanStatusMap);
- LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+ log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount("01 June 2015", "01 June 2015", "10000",
loanIDWithoutEmi, createTranches);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
- LOG.info(
+ log.info(
"-----------------------------------MULTI DISBURSAL LOAN WITHOUT EMI APPROVED SUCCESSFULLY---------------------------------------");
}
@@ -205,6 +208,7 @@ public class LoanDisbursementDetailsIntegrationTest {
list.add(expectedRepaymentSchedule14);
for (int i = 0; i < list.size(); i++) {
+ log.info("values {} {} {}", i, periods.get(i), list.get(i));
this.assertRepaymentScheduleValuesWithEMI(periods.get(i), list.get(i), i);
}
}
@@ -213,7 +217,7 @@ public class LoanDisbursementDetailsIntegrationTest {
assertEquals(period.get("dueDate").toString(), expectedRepaymentSchedule.getDueDate());
assertEquals(period.get("principalLoanBalanceOutstanding"), expectedRepaymentSchedule.getPrincipalLoanBalanceOutstanding());
- LOG.info("{}", period.get("totalOriginalDueForPeriod").toString());
+ log.info("{}", period.get("totalOriginalDueForPeriod").toString());
assertEquals(Float.parseFloat(period.get("totalOriginalDueForPeriod").toString()),
expectedRepaymentSchedule.getTotalOriginalDueForPeriod().floatValue(), 0.0f);
@@ -233,103 +237,25 @@ public class LoanDisbursementDetailsIntegrationTest {
}
}
- /* Uncomment and modify test builder values once MIFOSX-2006 is closed. */
- /*
- * private void validateRepaymentScheduleWithoutEMI(ArrayList<HashMap> periods){ LoanDisbursementTestBuilder
- * expectedRepaymentSchedule0 = new LoanDisbursementTestBuilder( "[2015, 6, 1]", 0.0f, 0.0f, null, null, 5000.0f,
- * null, null, null);
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule1 = new LoanDisbursementTestBuilder( "[2015, 7, 1]", 800.0f,
- * 800.0f, 50.0f, 750.0f, 4250.0f, 750.0f, 750.0f, "[2015, 6, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule2 = new LoanDisbursementTestBuilder( "[2015, 8, 1]", 800.0f,
- * 800.0f, 42.5f, 757.5f, 3492.5f, 757.5f, 757.5f, "[2015, 7, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule3 = new LoanDisbursementTestBuilder( "[2015, 9, 1]", 0.0f,
- * 0.0f, null, null, 5000.0f, null, null, null);
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule4 = new LoanDisbursementTestBuilder( "[2015, 9, 1]", 800.0f,
- * 800.0f, 34.92f, 765.08f, 7727.42f, 765.08f, 765.08f, "[2015, 8, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule5 = new LoanDisbursementTestBuilder( "[2015, 10, 1]",
- * 800.0f, 800.0f, 77.27f, 722.73f, 7004.69f, 722.73f, 722.73f, "[2015, 9, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule6 = new LoanDisbursementTestBuilder( "[2015, 11, 1]",
- * 800.0f, 800.0f, 70.05f, 729.95f, 6274.74f, 729.95f, 729.95f, "[2015, 10, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule7 = new LoanDisbursementTestBuilder( "[2015, 12, 1]",
- * 800.0f, 800.0f, 62.75f, 737.25f, 5537.49f, 737.25f, 737.25f, "[2015, 11, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule8 = new LoanDisbursementTestBuilder( "[2016, 1, 1]", 800.0f,
- * 800.0f, 55.37f, 744.63f, 4792.86f, 744.63f, 744.63f, "[2015, 12, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule9 = new LoanDisbursementTestBuilder( "[2016, 2, 1]", 800.0f,
- * 800.0f, 47.93f, 752.07f, 4040.79f, 752.07f, 752.07f, "[2016, 1, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule10 = new LoanDisbursementTestBuilder( "[2016, 3, 1]",
- * 800.0f, 800.0f, 40.41f, 759.59f, 3281.2f, 759.59f, 759.59f, "[2016, 2, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule11 = new LoanDisbursementTestBuilder( "[2016, 4, 1]",
- * 800.0f, 800.0f, 32.81f, 767.19f, 2514.01f, 767.19f, 767.19f, "[2016, 3, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule12 = new LoanDisbursementTestBuilder( "[2016, 5, 1]",
- * 800.0f, 800.0f, 25.14f, 774.86f, 1739.15f, 774.86f, 774.86f, "[2016, 4, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule13 = new LoanDisbursementTestBuilder( "[2016, 6, 1]",
- * 800.0f, 800.0f, 17.39f, 782.61f, 956.54f, 782.61f, 782.61f, "[2016, 5, 1]");
- *
- * LoanDisbursementTestBuilder expectedRepaymentSchedule14 = new LoanDisbursementTestBuilder( "[2016, 7, 1]",
- * 966.11f, 966.11f, 9.57f, 956.54f, 0.0f, 956.54f, 956.54f, "[2016, 6, 1]");
- *
- * ArrayList<LoanDisbursementTestBuilder> list = new ArrayList<LoanDisbursementTestBuilder>();
- * list.add(expectedRepaymentSchedule0); list.add(expectedRepaymentSchedule1); list.add(expectedRepaymentSchedule2);
- * list.add(expectedRepaymentSchedule3); list.add(expectedRepaymentSchedule4); list.add(expectedRepaymentSchedule5);
- * list.add(expectedRepaymentSchedule6); list.add(expectedRepaymentSchedule7); list.add(expectedRepaymentSchedule8);
- * list.add(expectedRepaymentSchedule9); list.add(expectedRepaymentSchedule10);
- * list.add(expectedRepaymentSchedule11); list.add(expectedRepaymentSchedule12);
- * list.add(expectedRepaymentSchedule13); list.add(expectedRepaymentSchedule14);
- *
- * for (int i = 0; i < list.size(); i++) { this.assertRepaymentScheduleValuesWithoutEMI(periods.get(i), list.get(i),
- * i); } }
- *
- * private void assertRepaymentScheduleValuesWithoutEMI(HashMap period, LoanDisbursementTestBuilder
- * expectedRepaymentSchedule, int position) {
- *
- * assertEquals(period.get("dueDate").toString(), expectedRepaymentSchedule.getDueDate());
- * assertEquals(period.get("principalLoanBalanceOutstanding"),
- * expectedRepaymentSchedule.getPrincipalLoanBalanceOutstanding());
- * assertEquals(period.get("totalOriginalDueForPeriod"), expectedRepaymentSchedule.getTotalOriginalDueForPeriod());
- * assertEquals(period.get("totalOutstandingForPeriod"), expectedRepaymentSchedule.getTotalOutstandingForPeriod());
- *
- * if (position != 0 && position != 3) {
- *
- * assertEquals(period.get("interestOutstanding"), expectedRepaymentSchedule.getInterestOutstanding());
- * assertEquals(period.get("principalOutstanding"), expectedRepaymentSchedule.getPrincipalOutstanding());
- * assertEquals(period.get("principalDue"), expectedRepaymentSchedule.getPrincipalDue());
- * assertEquals(period.get("principalOriginalDue"), expectedRepaymentSchedule.getPrincipalOriginalDue());
- * assertEquals(period.get("fromDate").toString(), expectedRepaymentSchedule.getFromDate()); } }
- */
- private Integer applyForLoanApplicationWithEmiAmount(final Integer clientID, final Integer loanProductID, final String proposedAmount,
+ private Integer applyForLoanApplicationWithEmiAmount(final Integer clientId, final Integer loanProductId, final String proposedAmount,
List<HashMap> tranches, final String installmentAmount) {
- LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+ log.info("----------------APPLYING FOR LOAN APPLICATION");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
- clientID.toString(), collateralId);
+ clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
- final String loanApplicationJSON = new LoanApplicationTestBuilder()
- //
- .withPrincipal(proposedAmount)
- //
- .withLoanTermFrequency("12")
- //
- .withLoanTermFrequencyAsMonths()
- //
- .withNumberOfRepayments("12").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
+ final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+ .withPrincipal(proposedAmount) //
+ .withLoanTermFrequency("12") //
+ .withLoanTermFrequencyAsMonths() //
+ .withNumberOfRepayments("12") //
+ .withRepaymentEveryAfter("1") //
+ .withRepaymentFrequencyTypeAsMonths() //
.withInterestRatePerPeriod("1") //
.withExpectedDisbursementDate("01 June 2015") //
.withTranches(tranches) //
@@ -337,12 +263,55 @@ public class LoanDisbursementDetailsIntegrationTest {
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 June 2015") //
.withAmortizationTypeAsEqualInstallments() //
- .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
+ .withCollaterals(collaterals).build(clientId.toString(), loanProductId.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
+ @Test
+ public void validateEqualInstallmentsForMultiTrancheLoan() {
+ List<HashMap> emptyTranches = new ArrayList<>();
+
+ final String operationDate = "01 January 2014";
+ final String principal = "1000";
+ final String disbursedPrincipal = "900";
+
+ final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, operationDate);
+ log.info("-----------------CLIENT CREATED WITH ID------------------- {}", clientId);
+
+ final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments() //
+ .withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
+ .withInterestTypeAsDecliningBalance() //
+ .withMultiDisburse() //
+ .withDisallowExpectectedDisbursements(true) //
+ .build(null);
+ log.info("Product {}", loanProductJSON);
+ final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+ log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
+
+ final Integer loanId = applyForMultiTrancheLoanApplication(clientId.toString(), loanProductId.toString(), principal, operationDate);
+
+ log.info("-------------------LOAN CREATED WITH loanId----------------- {}", loanId);
+
+ this.loanTransactionHelper.approveLoanWithApproveAmount(operationDate, expectedDisbursementDate, principal, loanId, emptyTranches);
+ log.info("-------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY-------");
+
+ GetLoansLoanIdResponse getLoansLoanIdResponse = this.loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+ assertNotNull(getLoansLoanIdResponse);
+
+ this.loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
+
+ loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, disbursedPrincipal);
+ log.info("-------------------MULTI DISBURSAL LOAN DISBURSED SUCCESSFULLY-------");
+ getLoansLoanIdResponse = this.loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+ assertNotNull(getLoansLoanIdResponse);
+ this.loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
+ final Double limit = 2.0;
+ evaluateEqualInstallmentsForRepaymentSchedule(getLoansLoanIdResponse.getRepaymentSchedule(), limit);
+ log.info("-----------MULTI DISBURSAL LOAN EQUAL INSTALLMENTS SUCCESSFULLY-------");
+ }
+
@Test
public void createApproveAndValidateMultiDisburseLoan() throws ParseException {
@@ -351,28 +320,29 @@ public class LoanDisbursementDetailsIntegrationTest {
createTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "01 March 2014", "1000"));
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
- LOG.info("---------------------------------CLIENT CREATED WITH ID--------------------------------------------------- {}", clientID);
+ log.info("---------------------------------CLIENT CREATED WITH ID--------------------------------------------------- {}", clientID);
final Integer loanProductID = this.loanTransactionHelper
.getLoanProductId(new LoanProductTestBuilder().withInterestTypeAsDecliningBalance().withTranches(true)
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null));
- LOG.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
+ log.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
loanProductID);
- this.loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
- LOG.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}", loanID);
+ this.loanId = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
+ log.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}",
+ this.loanId);
- HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+ HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, this.loanId);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
- LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+ log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
- loanID, createTranches);
+ this.loanId, createTranches);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
- LOG.info("-----------------------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY---------------------------------------");
+ log.info("-----------------------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY---------------------------------------");
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
- this.responseSpec, this.loanID, "disbursementDetails");
+ this.responseSpec, this.loanId, "disbursementDetails");
this.disbursementId = (Integer) disbursementDetails.get(0).get("id");
this.editLoanDisbursementDetails();
}
@@ -386,7 +356,7 @@ public class LoanDisbursementDetailsIntegrationTest {
private void addNewDisbursementDetails() throws ParseException {
List<HashMap> addTranches = new ArrayList<>();
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
- this.responseSpec, this.loanID, "disbursementDetails");
+ this.responseSpec, this.loanId, "disbursementDetails");
ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(0).get("expectedDisbursementDate");
String date = formatExpectedDisbursementDate(expectedDisbursementDate.toString());
@@ -397,14 +367,14 @@ public class LoanDisbursementDetailsIntegrationTest {
addTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "04 March 2014", "500"));
/* Add disbursement detail */
- this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanID, this.approvalAmount, this.expectedDisbursementDate,
+ this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanId, this.approvalAmount, this.expectedDisbursementDate,
addTranches, "");
}
private void deleteDisbursmentDetails() throws ParseException {
List<HashMap> deleteTranches = new ArrayList<>();
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
- this.responseSpec, this.loanID, "disbursementDetails");
+ this.responseSpec, this.loanId, "disbursementDetails");
/* Delete the last tranche */
for (int i = 0; i < disbursementDetails.size() - 1; i++) {
ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(i).get("expectedDisbursementDate");
@@ -414,7 +384,7 @@ public class LoanDisbursementDetailsIntegrationTest {
}
/* Add disbursement detail */
- this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanID, this.approvalAmount, this.expectedDisbursementDate,
+ this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanId, this.approvalAmount, this.expectedDisbursementDate,
deleteTranches, "");
}
@@ -422,11 +392,11 @@ public class LoanDisbursementDetailsIntegrationTest {
String updatedExpectedDisbursementDate = "01 March 2014";
String updatedPrincipal = "900";
/* Update */
- this.loanTransactionHelper.editDisbursementDetail(this.loanID, this.disbursementId, this.approvalAmount,
+ this.loanTransactionHelper.editDisbursementDetail(this.loanId, this.disbursementId, this.approvalAmount,
this.expectedDisbursementDate, updatedExpectedDisbursementDate, updatedPrincipal, "");
/* Validate Edit */
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
- this.responseSpec, this.loanID, "disbursementDetails");
+ this.responseSpec, this.loanId, "disbursementDetails");
assertEquals(Float.parseFloat(updatedPrincipal), disbursementDetails.get(0).get("principal"));
ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(0).get("expectedDisbursementDate");
String date = formatExpectedDisbursementDate(expectedDisbursementDate.toString());
@@ -435,7 +405,6 @@ public class LoanDisbursementDetailsIntegrationTest {
}
private String formatExpectedDisbursementDate(String expectedDisbursementDate) throws ParseException {
-
SimpleDateFormat source = new SimpleDateFormat("[yyyy, MM, dd]");
SimpleDateFormat target = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
String date = target.format(source.parse(expectedDisbursementDate));
@@ -443,32 +412,53 @@ public class LoanDisbursementDetailsIntegrationTest {
return date;
}
- private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
+ private Integer applyForLoanApplicationWithTranches(final Integer clientId, final Integer loanProductId, String principal,
List<HashMap> tranches) {
- LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+ log.info("----------------APPLYING FOR LOAN APPLICATION");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
- clientID.toString(), collateralId);
+ clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
- final String loanApplicationJSON = new LoanApplicationTestBuilder()
- //
- .withPrincipal(principal)
- //
- .withLoanTermFrequency("5")
- //
- .withLoanTermFrequencyAsMonths()
- //
- .withNumberOfRepayments("5").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
+ final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+ .withPrincipal(principal) //
+ .withLoanTermFrequency("5") //
+ .withLoanTermFrequencyAsMonths() //
+ .withNumberOfRepayments("5") //
+ .withRepaymentEveryAfter("1") //
+ .withRepaymentFrequencyTypeAsMonths() //
.withInterestRatePerPeriod("2") //
.withExpectedDisbursementDate("01 March 2014") //
.withTranches(tranches) //
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 March 2014") //
- .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
+ .withCollaterals(collaterals).build(clientId.toString(), loanProductId.toString(), null);
+
+ return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+ }
+
+ private Integer applyForMultiTrancheLoanApplication(final String clientId, final String loanProductId, String principal,
+ String operationDate) {
+ log.info("----------------APPLYING FOR MULTI TRANCHE LOAN APPLICATION");
+ List<HashMap> emptyData = new ArrayList<>();
+ final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+ .withPrincipal(principal) //
+ .withLoanTermFrequency("3") //
+ .withLoanTermFrequencyAsMonths() //
+ .withNumberOfRepayments("3") //
+ .withRepaymentEveryAfter("1") //
+ .withRepaymentFrequencyTypeAsMonths() //
+ .withInterestRatePerPeriod("0") //
+ .withExpectedDisbursementDate(operationDate) //
+ .withTranches(emptyData) //
+ .withInterestTypeAsDecliningBalance() //
+ .withSubmittedOnDate(operationDate) //
+ .withCollaterals(emptyData) //
+ .build(clientId, loanProductId, null);
+ log.info("Loan account {}", loanApplicationJSON);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -483,4 +473,24 @@ public class LoanDisbursementDetailsIntegrationTest {
return collateral;
}
+ public void evaluateEqualInstallmentsForRepaymentSchedule(GetLoansLoanIdRepaymentSchedule getLoanRepaymentSchedule, Double limit) {
+ Double totalOutstandingForPeriod = 0.0;
+ Double totalInstallmentAmountForPeriod = 0.0;
+ if (getLoanRepaymentSchedule != null) {
+ log.info("Loan with {} periods", getLoanRepaymentSchedule.getPeriods().size());
+ for (GetLoansLoanIdRepaymentPeriod period : getLoanRepaymentSchedule.getPeriods()) {
+ if (period.getPeriod() != null) {
+ log.info("Period number {} for due date {} and outstanding {} {}", period.getPeriod(), period.getDueDate(),
+ period.getTotalOutstandingForPeriod(), period.getTotalInstallmentAmountForPeriod());
+ if (period.getPeriod() == 1) {
+ totalOutstandingForPeriod = period.getTotalOutstandingForPeriod();
+ totalInstallmentAmountForPeriod = period.getTotalInstallmentAmountForPeriod();
+ } else {
+ assertTrue(Math.abs(period.getTotalOutstandingForPeriod() - totalOutstandingForPeriod) <= limit);
+ assertTrue(Math.abs(period.getTotalInstallmentAmountForPeriod() - totalInstallmentAmountForPeriod) <= limit);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java
index 1e4efa84b..9afe6f55f 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java
@@ -245,7 +245,7 @@ public class LoanRepaymentRescheduleAtDisbursementTest {
.withInterestCalculationPeriodTypeAsDays() //
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
- .withwithRepaymentStrategy(repaymentStrategy) //
+ .withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges)//
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleWithAdvancePaymentTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleWithAdvancePaymentTest.java
index 2e8616f06..0f78248d8 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleWithAdvancePaymentTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleWithAdvancePaymentTest.java
@@ -204,7 +204,7 @@ public class LoanRescheduleWithAdvancePaymentTest {
.withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeAsDays()
.withInterestRatePerPeriod("12").withInterestTypeAsDecliningBalance().withSubmittedOnDate(submittedDate)
.withExpectedDisbursementDate(submittedDate).withFirstRepaymentDate(firstRepaymentDate)
- .withwithRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
+ .withRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
.withinterestChargedFromDate(submittedDate).build(this.clientId.toString(), this.loanProductId.toString(), null);
this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -318,7 +318,7 @@ public class LoanRescheduleWithAdvancePaymentTest {
.withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeAsDays()
.withInterestRatePerPeriod("12").withInterestTypeAsDecliningBalance().withSubmittedOnDate(submittedDate)
.withExpectedDisbursementDate(submittedDate).withFirstRepaymentDate(firstRepaymentDate)
- .withwithRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
+ .withRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
.withinterestChargedFromDate(submittedDate).build(this.clientId.toString(), this.loanProductId.toString(), null);
this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
index b2db9dd80..8c1ebbd6f 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
@@ -409,7 +409,7 @@ public class LoanReschedulingWithinCenterTest {
.withInterestCalculationPeriodTypeAsDays() //
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
- .withwithRepaymentStrategy(repaymentStrategy) //
+ .withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges)//
.build(clientID.toString(), groupId.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java
index 8475f84ba..4817046e2 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java
@@ -187,7 +187,7 @@ public class LoanTransactionAuditingIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(submittedOnDate) //
.withSubmittedOnDate(submittedOnDate) //
- .withwithRepaymentStrategy(repaymentStrategy) //
+ .withRepaymentStrategy(repaymentStrategy) //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
index a480de000..94ae8bf60 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
@@ -335,7 +335,7 @@ public class LoanApplicationTestBuilder {
return this;
}
- public LoanApplicationTestBuilder withwithRepaymentStrategy(final String transactionProcessingStrategy) {
+ public LoanApplicationTestBuilder withRepaymentStrategy(final String transactionProcessingStrategy) {
this.transactionProcessingID = transactionProcessingStrategy;
return this;
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index 4d9ff06bd..936dee5f4 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -98,6 +98,7 @@ public class LoanProductTestBuilder {
private Boolean allowApprovedDisbursedAmountsOverApplied = false;
private String overAppliedCalculationType = null;
private Integer overAppliedNumber = null;
+ private Boolean isEqualAmortization = false;
private Boolean isInterestRecalculationEnabled = false;
private String daysInYearType = "1";
@@ -168,6 +169,7 @@ public class LoanProductTestBuilder {
map.put("accountingRule", this.accountingRule);
map.put("minPrincipal", this.minPrincipal);
map.put("maxPrincipal", this.maxPrincipal);
+ map.put("isEqualAmortization", this.isEqualAmortization);
map.put("overdueDaysForNPA", this.overdueDaysForNPA);
if (this.minimumDaysBetweenDisbursalAndFirstRepayment != null) {
map.put("minimumDaysBetweenDisbursalAndFirstRepayment", this.minimumDaysBetweenDisbursalAndFirstRepayment);
@@ -382,6 +384,11 @@ public class LoanProductTestBuilder {
return this;
}
+ public LoanProductTestBuilder withEqualAmortization(boolean isEqualAmortization) {
+ this.isEqualAmortization = isEqualAmortization;
+ return this;
+ }
+
public LoanProductTestBuilder withMultiDisburse() {
this.multiDisburseLoan = true;
return this;
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index ae7379972..890d2d6f2 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -42,6 +42,8 @@ import javax.ws.rs.core.MediaType;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.GetDelinquencyTagHistoryResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
+import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
+import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.util.JSON;
@@ -1062,4 +1064,16 @@ public class LoanTransactionHelper {
"---------------------------------GET A LOAN TRANSACTION ENTITY AUDIT FIELDS---------------------------------------------");
return Utils.performServerGet(requestSpec, responseSpec, GET_LOAN_TRANSACTION_URL, jsonReturn);
}
+
+ public void printRepaymentSchedule(GetLoansLoanIdResponse getLoansLoanIdResponse) {
+ GetLoansLoanIdRepaymentSchedule getLoanRepaymentSchedule = getLoansLoanIdResponse.getRepaymentSchedule();
+ if (getLoanRepaymentSchedule != null) {
+ log.info("Loan with {} periods", getLoanRepaymentSchedule.getPeriods().size());
+ for (GetLoansLoanIdRepaymentPeriod period : getLoanRepaymentSchedule.getPeriods()) {
+ log.info("Period number {} for due date {} and outstanding {}", period.getPeriod(), period.getDueDate(),
+ period.getTotalOutstandingForPeriod());
+ }
+ }
+ }
+
}