This is an automated email from the ASF dual-hosted git repository.
adamsaghy 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 ae77d29be FINERACT-1958: Fix down-payment for loan reschedule and for
interest bearing loans
ae77d29be is described below
commit ae77d29be240f7239173f7996bc601006a6fc85f
Author: Adam Saghy <[email protected]>
AuthorDate: Thu Dec 7 14:43:24 2023 +0100
FINERACT-1958: Fix down-payment for loan reschedule and for interest
bearing loans
---
.../portfolio/loanaccount/domain/Loan.java | 11 +-
.../portfolio/loanaccount/domain/LoanCharge.java | 2 +-
.../loanschedule/domain/LoanApplicationTerms.java | 15 +
.../loanaccount/api/LoansApiResourceSwagger.java | 6 +-
.../loanschedule/data/LoanScheduleParams.java | 138 ++++---
.../AbstractCumulativeLoanScheduleGenerator.java | 163 ++++----
.../AbstractProgressiveLoanScheduleGenerator.java | 9 +-
.../service/LoanScheduleAssembler.java | 12 +-
.../LoanReschedulePreviewPlatformServiceImpl.java | 5 +-
...nRescheduleRequestWritePlatformServiceImpl.java | 4 +-
...PaymentAllocationLoanRepaymentScheduleTest.java | 95 ++---
.../integrationtests/BaseLoanIntegrationTest.java | 14 +-
.../ClientLoanIntegrationTest.java | 6 +-
.../ExternalIdSupportIntegrationTest.java | 9 +-
...gePaymentWithAdvancedPaymentAllocationTest.java | 6 +-
.../LoanInstallmentMultiplesOfTest.java | 10 +-
.../LoanRescheduleTestWithDownpayment.java | 415 ++++++++++++++++++++-
...LoanSpecificDueDateChargeAfterMaturityTest.java | 6 +-
.../integrationtests/LoanWaiveChargeTest.java | 2 +-
...tiveLoansWithAdvancedPaymentAllocationTest.java | 10 +-
20 files changed, 717 insertions(+), 221 deletions(-)
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index d8432f0cb..e89880f11 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -41,7 +41,6 @@ import jakarta.persistence.Version;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.math.MathContext;
-import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
@@ -2823,8 +2822,7 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
public LoanScheduleModel regenerateScheduleModel(final
ScheduleGeneratorDTO scheduleGeneratorDTO) {
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mc = new MathContext(8, roundingMode);
+ final MathContext mc = MoneyHelper.getMathContext();
final LoanApplicationTerms loanApplicationTerms =
constructLoanApplicationTerms(scheduleGeneratorDTO);
LoanScheduleGenerator loanScheduleGenerator;
@@ -5762,8 +5760,7 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
final LoanScheduleGenerator loanScheduleGenerator =
generatorDTO.getLoanScheduleFactory()
.create(this.loanRepaymentScheduleDetail.getLoanScheduleType(), interestMethod);
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mc = new MathContext(19, roundingMode);
+ final MathContext mc = MoneyHelper.getMathContext();
final LoanApplicationTerms loanApplicationTerms =
constructLoanApplicationTerms(generatorDTO);
@@ -5778,8 +5775,8 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
LoanRepaymentScheduleInstallment installment = null;
if (this.loanRepaymentScheduleDetail.isInterestRecalculationEnabled())
{
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mc = new MathContext(8, roundingMode);
+
+ final MathContext mc = MoneyHelper.getMathContext();
final InterestMethod interestMethod =
this.loanRepaymentScheduleDetail.getInterestMethod();
final LoanApplicationTerms loanApplicationTerms =
constructLoanApplicationTerms(scheduleGeneratorDTO);
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
index 252886de6..42ec041a6 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
@@ -565,7 +565,7 @@ public class LoanCharge extends
AbstractAuditableWithUTCDateTimeCustom {
BigDecimal percentageOf = BigDecimal.ZERO;
if (isGreaterThanZero(value)) {
- final MathContext mc = new MathContext(8,
MoneyHelper.getRoundingMode());
+ final MathContext mc = MoneyHelper.getMathContext();
final BigDecimal multiplicand =
percentage.divide(BigDecimal.valueOf(100L), mc);
percentageOf = value.multiply(multiplicand, mc);
}
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index 52e43ac1e..19bee527a 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
@@ -212,6 +213,7 @@ public final class LoanApplicationTerms {
private LocalDate newScheduledDueDateStart;
private boolean isDownPaymentEnabled;
private BigDecimal disbursedAmountPercentageForDownPayment;
+ private Money downPaymentAmount;
private boolean isAutoRepaymentForDownPaymentEnabled;
private RepaymentStartDateType repaymentStartDateType;
@@ -450,6 +452,15 @@ public final class LoanApplicationTerms {
this.isPrincipalCompoundingDisabledForOverdueLoans =
isPrincipalCompoundingDisabledForOverdueLoans;
this.isDownPaymentEnabled = isDownPaymentEnabled;
this.disbursedAmountPercentageForDownPayment =
disbursedAmountPercentageForDownPayment;
+ this.downPaymentAmount = Money.zero(getCurrency());
+ if (isDownPaymentEnabled) {
+ this.downPaymentAmount = Money.of(getCurrency(),
+ MathUtil.percentageOf(getPrincipal().getAmount(),
getDisbursedAmountPercentageForDownPayment(), 19));
+ if (getInstallmentAmountInMultiplesOf() != null) {
+ downPaymentAmount =
Money.roundToMultiplesOf(downPaymentAmount,
getInstallmentAmountInMultiplesOf());
+ }
+ }
+
this.isAutoRepaymentForDownPaymentEnabled =
isAutoRepaymentForDownPaymentEnabled;
this.repaymentStartDateType = repaymentStartDateType;
this.submittedOnDate = submittedOnDate;
@@ -1817,4 +1828,8 @@ public final class LoanApplicationTerms {
public LoanScheduleType getLoanScheduleType() {
return loanScheduleType;
}
+
+ public Money getDownPaymentAmount() {
+ return downPaymentAmount;
+ }
}
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 a06bcb780..b90d184d3 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
@@ -1082,7 +1082,7 @@ final class LoansApiResourceSwagger {
public Integer repaymentEvery;
public GetLoansLoanIdRepaymentFrequencyType repaymentFrequencyType;
@Schema(example = "24")
- public Integer interestRatePerPeriod;
+ public BigDecimal interestRatePerPeriod;
public GetLoansLoanIdInterestRateFrequencyType
interestRateFrequencyType;
@Schema(example = "24")
public Integer annualInterestRate;
@@ -1180,7 +1180,7 @@ final class LoansApiResourceSwagger {
@Schema(example = "2")
public Integer repaymentFrequencyType;
@Schema(example = "2")
- public Integer interestRatePerPeriod;
+ public BigDecimal interestRatePerPeriod;
@Schema(example = "1")
public Integer amortizationType;
@Schema(example = "5.5")
@@ -1318,7 +1318,7 @@ final class LoansApiResourceSwagger {
@Schema(example = "0")
public Integer repaymentFrequencyType;
@Schema(example = "2")
- public Integer interestRatePerPeriod;
+ public BigDecimal interestRatePerPeriod;
@Schema(example = "0")
public Integer interestType;
@Schema(example = "0")
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
index 282915b45..f73f67b19 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
@@ -180,7 +180,7 @@ public final class LoanScheduleParams {
final Money principalToBeScheduled = null;
final Money outstandingBalance = null;
final Money outstandingBalanceAsPerRest = null;
- final List<LoanRepaymentScheduleInstallment> installments = null;
+ final List<LoanRepaymentScheduleInstallment> installments = new
ArrayList<>();
final boolean partialUpdate = false;
final int loanTermInDays = 0;
final Money totalOutstandingInterestPaymentDueToGrace = null;
@@ -266,6 +266,10 @@ public final class LoanScheduleParams {
return this.periodNumber;
}
+ public void setPeriodNumber(int periodNumber) {
+ this.periodNumber = periodNumber;
+ }
+
public int getInstalmentNumber() {
return this.instalmentNumber;
}
@@ -274,12 +278,20 @@ public final class LoanScheduleParams {
return this.actualRepaymentDate;
}
+ public void setActualRepaymentDate(LocalDate actualRepaymentDate) {
+ this.actualRepaymentDate = actualRepaymentDate;
+ }
+
public Money getTotalCumulativePrincipal() {
return this.totalCumulativePrincipal;
}
public void addTotalCumulativePrincipal(final Money
totalCumulativePrincipal) {
- this.totalCumulativePrincipal =
this.totalCumulativePrincipal.plus(totalCumulativePrincipal);
+ if (this.totalCumulativePrincipal != null) {
+ this.totalCumulativePrincipal =
this.totalCumulativePrincipal.plus(totalCumulativePrincipal);
+ } else {
+ this.totalCumulativePrincipal = totalCumulativePrincipal;
+ }
}
public Money getTotalCumulativeInterest() {
@@ -287,7 +299,11 @@ public final class LoanScheduleParams {
}
public void addTotalCumulativeInterest(final Money
totalCumulativeInterest) {
- this.totalCumulativeInterest =
this.totalCumulativeInterest.plus(totalCumulativeInterest);
+ if (this.totalCumulativeInterest != null) {
+ this.totalCumulativeInterest =
this.totalCumulativeInterest.plus(totalCumulativeInterest);
+ } else {
+ this.totalCumulativeInterest = totalCumulativeInterest;
+ }
}
public Money getTotalFeeChargesCharged() {
@@ -295,7 +311,11 @@ public final class LoanScheduleParams {
}
public void addTotalFeeChargesCharged(final Money totalFeeChargesCharged) {
- this.totalFeeChargesCharged =
this.totalFeeChargesCharged.plus(totalFeeChargesCharged);
+ if (this.totalFeeChargesCharged != null) {
+ this.totalFeeChargesCharged =
this.totalFeeChargesCharged.plus(totalFeeChargesCharged);
+ } else {
+ this.totalFeeChargesCharged = totalFeeChargesCharged;
+ }
}
public Money getTotalPenaltyChargesCharged() {
@@ -303,7 +323,11 @@ public final class LoanScheduleParams {
}
public void addTotalPenaltyChargesCharged(final Money
totalPenaltyChargesCharged) {
- this.totalPenaltyChargesCharged =
this.totalPenaltyChargesCharged.plus(totalPenaltyChargesCharged);
+ if (this.totalPenaltyChargesCharged != null) {
+ this.totalPenaltyChargesCharged =
this.totalPenaltyChargesCharged.plus(totalPenaltyChargesCharged);
+ } else {
+ this.totalPenaltyChargesCharged = totalPenaltyChargesCharged;
+ }
}
public Money getTotalRepaymentExpected() {
@@ -311,13 +335,21 @@ public final class LoanScheduleParams {
}
public void addTotalRepaymentExpected(final Money totalRepaymentExpected) {
- this.totalRepaymentExpected =
this.totalRepaymentExpected.plus(totalRepaymentExpected);
+ if (this.totalRepaymentExpected != null) {
+ this.totalRepaymentExpected =
this.totalRepaymentExpected.plus(totalRepaymentExpected);
+ } else {
+ this.totalRepaymentExpected = totalRepaymentExpected;
+ }
}
public Money getReducePrincipal() {
return this.reducePrincipal;
}
+ public void setReducePrincipal(Money reducePrincipal) {
+ this.reducePrincipal = reducePrincipal;
+ }
+
public Map<LocalDate, Money> getPrincipalPortionMap() {
return this.principalPortionMap;
}
@@ -338,10 +370,18 @@ public final class LoanScheduleParams {
return this.outstandingBalance;
}
+ public void setOutstandingBalance(Money outstandingBalance) {
+ this.outstandingBalance = outstandingBalance;
+ }
+
public Money getOutstandingBalanceAsPerRest() {
return this.outstandingBalanceAsPerRest;
}
+ public void setOutstandingBalanceAsPerRest(Money
outstandingBalanceAsPerRest) {
+ this.outstandingBalanceAsPerRest = outstandingBalanceAsPerRest;
+ }
+
public List<LoanRepaymentScheduleInstallment> getInstallments() {
return this.installments;
}
@@ -366,12 +406,16 @@ public final class LoanScheduleParams {
return this.periodStartDate;
}
+ public void setPeriodStartDate(LocalDate periodStartDate) {
+ this.periodStartDate = periodStartDate;
+ }
+
public Money getPrincipalToBeScheduled() {
return this.principalToBeScheduled;
}
- public void setPeriodNumber(int periodNumber) {
- this.periodNumber = periodNumber;
+ public void setPrincipalToBeScheduled(Money principalToBeScheduled) {
+ this.principalToBeScheduled = principalToBeScheduled;
}
public void incrementPeriodNumber() {
@@ -382,56 +426,54 @@ public final class LoanScheduleParams {
this.instalmentNumber++;
}
- public void setPeriodStartDate(LocalDate periodStartDate) {
- this.periodStartDate = periodStartDate;
- }
-
- public void setActualRepaymentDate(LocalDate actualRepaymentDate) {
- this.actualRepaymentDate = actualRepaymentDate;
- }
-
- public void setReducePrincipal(Money reducePrincipal) {
- this.reducePrincipal = reducePrincipal;
- }
-
public void addReducePrincipal(Money reducePrincipal) {
- this.reducePrincipal = this.reducePrincipal.plus(reducePrincipal);
+ if (this.reducePrincipal != null) {
+ this.reducePrincipal = this.reducePrincipal.plus(reducePrincipal);
+ } else {
+ this.reducePrincipal = reducePrincipal;
+ }
}
public void reduceReducePrincipal(Money reducePrincipal) {
- this.reducePrincipal = this.reducePrincipal.minus(reducePrincipal);
- }
-
- public void setPrincipalToBeScheduled(Money principalToBeScheduled) {
- this.principalToBeScheduled = principalToBeScheduled;
+ if (this.reducePrincipal != null) {
+ this.reducePrincipal = this.reducePrincipal.minus(reducePrincipal);
+ }
}
public void addPrincipalToBeScheduled(Money principalToBeScheduled) {
- this.principalToBeScheduled =
this.principalToBeScheduled.plus(principalToBeScheduled);
- }
-
- public void setOutstandingBalance(Money outstandingBalance) {
- this.outstandingBalance = outstandingBalance;
+ if (this.principalToBeScheduled != null) {
+ this.principalToBeScheduled =
this.principalToBeScheduled.plus(principalToBeScheduled);
+ } else {
+ this.principalToBeScheduled = principalToBeScheduled;
+ }
}
public void addOutstandingBalance(Money outstandingBalance) {
- this.outstandingBalance =
this.outstandingBalance.plus(outstandingBalance);
+ if (this.outstandingBalance != null) {
+ this.outstandingBalance =
this.outstandingBalance.plus(outstandingBalance);
+ } else {
+ this.outstandingBalance = outstandingBalance;
+ }
}
public void reduceOutstandingBalance(Money outstandingBalance) {
- this.outstandingBalance =
this.outstandingBalance.minus(outstandingBalance);
- }
-
- public void setOutstandingBalanceAsPerRest(Money
outstandingBalanceAsPerRest) {
- this.outstandingBalanceAsPerRest = outstandingBalanceAsPerRest;
+ if (this.outstandingBalance != null) {
+ this.outstandingBalance =
this.outstandingBalance.minus(outstandingBalance);
+ }
}
public void addOutstandingBalanceAsPerRest(Money
outstandingBalanceAsPerRest) {
- this.outstandingBalanceAsPerRest =
this.outstandingBalanceAsPerRest.plus(outstandingBalanceAsPerRest);
+ if (this.outstandingBalanceAsPerRest != null) {
+ this.outstandingBalanceAsPerRest =
this.outstandingBalanceAsPerRest.plus(outstandingBalanceAsPerRest);
+ } else {
+ this.outstandingBalanceAsPerRest = outstandingBalanceAsPerRest;
+ }
}
public void reduceOutstandingBalanceAsPerRest(Money
outstandingBalanceAsPerRest) {
- this.outstandingBalanceAsPerRest =
this.outstandingBalanceAsPerRest.minus(outstandingBalanceAsPerRest);
+ if (this.outstandingBalanceAsPerRest != null) {
+ this.outstandingBalanceAsPerRest =
this.outstandingBalanceAsPerRest.minus(outstandingBalanceAsPerRest);
+ }
}
public int getLoanTermInDays() {
@@ -466,16 +508,22 @@ public final class LoanScheduleParams {
return this.unCompoundedAmount;
}
- public void addUnCompoundedAmount(Money unCompoundedAmount) {
- this.unCompoundedAmount =
this.unCompoundedAmount.plus(unCompoundedAmount);
+ public void setUnCompoundedAmount(Money unCompoundedAmount) {
+ this.unCompoundedAmount = unCompoundedAmount;
}
- public void minusUnCompoundedAmount(Money unCompoundedAmount) {
- this.unCompoundedAmount =
this.unCompoundedAmount.minus(unCompoundedAmount);
+ public void addUnCompoundedAmount(Money unCompoundedAmount) {
+ if (this.unCompoundedAmount != null) {
+ this.unCompoundedAmount =
this.unCompoundedAmount.plus(unCompoundedAmount);
+ } else {
+ this.unCompoundedAmount = unCompoundedAmount;
+ }
}
- public void setUnCompoundedAmount(Money unCompoundedAmount) {
- this.unCompoundedAmount = unCompoundedAmount;
+ public void minusUnCompoundedAmount(Money unCompoundedAmount) {
+ if (this.unCompoundedAmount != null) {
+ this.unCompoundedAmount =
this.unCompoundedAmount.minus(unCompoundedAmount);
+ }
}
public boolean isFirstPeriod() {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
index 957ede516..d2acafeee 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
@@ -132,18 +132,7 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
loanApplicationTerms.getLoanCalendar(),
loanApplicationTerms.getHolidayDetailDTO(), loanApplicationTerms);
if (!scheduleParams.isPartialUpdate()) {
- Money downPaymentAmount = Money.zero(currency);
- if (loanApplicationTerms.isDownPaymentEnabled()) {
- downPaymentAmount = Money.of(currency,
MathUtil.percentageOf(scheduleParams.getOutstandingBalance().getAmount(),
-
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
- if (loanApplicationTerms.getInstallmentAmountInMultiplesOf()
!= null) {
- downPaymentAmount =
Money.roundToMultiplesOf(downPaymentAmount,
-
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
- }
-
- }
- Money calculatedAmortizableAmount =
loanApplicationTerms.getPrincipal().minus(downPaymentAmount);
- scheduleParams.reduceOutstandingBalance(downPaymentAmount);
+ Money calculatedAmortizableAmount =
loanApplicationTerms.getPrincipal().minus(loanApplicationTerms.getDownPaymentAmount());
// Set Fixed Principal Amount
updateAmortization(mc, loanApplicationTerms,
scheduleParams.getPeriodNumber(), calculatedAmortizableAmount);
@@ -161,9 +150,9 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
}
Money remainingPrincipalAmt =
disburseAmt.minus(downPaymentAmt);
scheduleParams.setPrincipalToBeScheduled(remainingPrincipalAmt);
- loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
scheduleParams.setOutstandingBalance(remainingPrincipalAmt);
scheduleParams.setOutstandingBalanceAsPerRest(remainingPrincipalAmt);
+ loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
}
}
@@ -305,7 +294,7 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
scheduleParams.getTotalCumulativePrincipal().minus(scheduleParams.getReducePrincipal()),
scheduleParams.getTotalCumulativeInterest(),
loanApplicationTerms.getTotalInterestDue(),
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(),
scheduleParams.getOutstandingBalanceAsPerRest(),
- loanApplicationTerms, scheduleParams.getPeriodNumber(),
mc, mergeVariationsToMap(scheduleParams),
+ loanApplicationTerms, scheduleParams.getPeriodNumber(),
mc, mergeVariationsToMap(loanApplicationTerms, scheduleParams),
scheduleParams.getCompoundingMap(),
periodStartDateApplicableForInterest, scheduledDueDate, interestRates);
// will check for EMI amount greater than interest calculated
@@ -427,10 +416,11 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
updateCompoundingDetails(periods, scheduleParams,
loanApplicationTerms);
return LoanScheduleModel.from(periods, applicationCurrency,
scheduleParams.getLoanTermInDays(),
- scheduleParams.getPrincipalToBeScheduled(),
scheduleParams.getTotalCumulativePrincipal().getAmount(), totalPrincipalPaid,
- scheduleParams.getTotalCumulativeInterest().getAmount(),
scheduleParams.getTotalFeeChargesCharged().getAmount(),
- scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
scheduleParams.getTotalRepaymentExpected().getAmount(),
- totalOutstanding);
+
scheduleParams.getPrincipalToBeScheduled().plus(loanApplicationTerms.getDownPaymentAmount()),
+
scheduleParams.getTotalCumulativePrincipal().plus(loanApplicationTerms.getDownPaymentAmount()).getAmount(),
+ totalPrincipalPaid,
scheduleParams.getTotalCumulativeInterest().getAmount(),
+ scheduleParams.getTotalFeeChargesCharged().getAmount(),
scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
+ scheduleParams.getTotalRepaymentExpected().getAmount(),
totalOutstanding);
}
private void updateCompoundingDetails(final
Collection<LoanScheduleModelPeriod> periods, final LoanScheduleParams params,
@@ -510,7 +500,7 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
updateCompoundingMap(loanApplicationTerms, holidayDetailDTO,
scheduleParams, lastRestDate, scheduledDueDate);
// update outstanding balance for interest calculation
- updateOutstandingBalanceAsPerRest(scheduleParams, scheduledDueDate);
+ updateOutstandingBalanceAsPerRest(loanApplicationTerms,
scheduleParams, scheduledDueDate);
}
private LoanScheduleModelPeriod handleRecalculationForTransactions(final
MathContext mc,
@@ -630,8 +620,8 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
interestCalculationGraceOnRepaymentPeriodFraction,
scheduleParams.getTotalCumulativePrincipal(),
scheduleParams.getTotalCumulativeInterest(),
totalInterestChargedForFullLoanTerm,
lastTotalOutstandingInterestPaymentDueToGrace,
scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms,
- scheduleParams.getPeriodNumber(), mc,
mergeVariationsToMap(scheduleParams), scheduleParams.getCompoundingMap(),
- periodStartDateApplicableForInterest, calculateTill,
interestRates);
+ scheduleParams.getPeriodNumber(), mc,
mergeVariationsToMap(loanApplicationTerms, scheduleParams),
+ scheduleParams.getCompoundingMap(),
periodStartDateApplicableForInterest, calculateTill, interestRates);
loanApplicationTerms.updateAnnualNominalInterestRate(currentInterestRate);
// applies charges for the period
@@ -767,7 +757,7 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
scheduleParams.getTotalCumulativeInterest(),
totalInterestChargedForFullLoanTerm,
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(),
scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms,
- scheduleParams.getPeriodNumber(), mc,
mergeVariationsToMap(scheduleParams),
+ scheduleParams.getPeriodNumber(), mc,
mergeVariationsToMap(loanApplicationTerms, scheduleParams),
scheduleParams.getCompoundingMap(),
periodStartDateApplicableForInterest, transactionDate,
interestRates);
interestForCurrentInstallment =
principalInterestForThisPeriod.interest();
@@ -805,7 +795,7 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
// update outstanding balance for interest
// calculation as per the rest
- updateOutstandingBalanceAsPerRest(scheduleParams,
transactionDate);
+
updateOutstandingBalanceAsPerRest(loanApplicationTerms, scheduleParams,
transactionDate);
// handle cumulative fields
scheduleParams.addLoanTermInDays(periodDays);
@@ -898,9 +888,9 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
scheduleParams.getTotalCumulativeInterest(),
totalInterestChargedForFullLoanTerm,
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(),
scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms,
- scheduleParams.getPeriodNumber(),
mc, mergeVariationsToMap(scheduleParams),
-
scheduleParams.getCompoundingMap(), periodStartDateApplicableForInterest,
transactionDate,
- interestRates);
+ scheduleParams.getPeriodNumber(),
mc,
+
mergeVariationsToMap(loanApplicationTerms, scheduleParams),
scheduleParams.getCompoundingMap(),
+
periodStartDateApplicableForInterest, transactionDate, interestRates);
if
(!principalInterestForThisPeriod.interest()
.plus(principalInterestForThisPeriod.interestPaymentDueToGrace())
.plus(scheduleParams.getOutstandingBalance()).isGreaterThan(unprocessed)) {
@@ -971,11 +961,37 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
scheduleParams.addTotalCumulativePrincipal(unprocessed.plus(addToPrincipal));
}
- private void updateOutstandingBalanceAsPerRest(final LoanScheduleParams
scheduleParams, final LocalDate scheduledDueDate) {
+ private void updateOutstandingBalanceAsPerRest(LoanApplicationTerms
loanApplicationTerms, final LoanScheduleParams scheduleParams,
+ final LocalDate scheduledDueDate) {
scheduleParams.setOutstandingBalanceAsPerRest(updateBalanceForInterestCalculation(scheduleParams.getPrincipalPortionMap(),
- scheduledDueDate,
scheduleParams.getOutstandingBalanceAsPerRest(), false));
-
scheduleParams.setOutstandingBalanceAsPerRest(updateBalanceForInterestCalculation(scheduleParams.getDisburseDetailMap(),
- scheduledDueDate,
scheduleParams.getOutstandingBalanceAsPerRest(), true));
+ scheduledDueDate,
scheduleParams.getOutstandingBalanceAsPerRest()));
+
scheduleParams.setOutstandingBalanceAsPerRest(calculateOutstandingBalanceAsPerRest(loanApplicationTerms,
+ scheduleParams.getDisburseDetailMap(), scheduledDueDate,
scheduleParams.getOutstandingBalanceAsPerRest()));
+ }
+
+ private Money calculateOutstandingBalanceAsPerRest(LoanApplicationTerms
loanApplicationTerms, Map<LocalDate, Money> disburseDetailMap,
+ LocalDate scheduledDueDate, Money outstandingBalance) {
+ List<LocalDate> removeFromMap = new ArrayList<>();
+ for (Map.Entry<LocalDate, Money> entry : disburseDetailMap.entrySet())
{
+ if (!DateUtils.isAfter(entry.getKey(), scheduledDueDate)) {
+ Money downPaymentAmount =
Money.zero(loanApplicationTerms.getCurrency());
+ if (loanApplicationTerms.isDownPaymentEnabled()) {
+ downPaymentAmount =
Money.of(loanApplicationTerms.getCurrency(),
MathUtil.percentageOf(entry.getValue().getAmount(),
+
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
+ if
(loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
+ downPaymentAmount =
Money.roundToMultiplesOf(downPaymentAmount,
+
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+ }
+ }
+ outstandingBalance =
outstandingBalance.plus(entry.getValue()).minus(downPaymentAmount);
+
+ removeFromMap.add(entry.getKey());
+ }
+ }
+ for (LocalDate date : removeFromMap) {
+ disburseDetailMap.remove(date);
+ }
+ return outstandingBalance;
}
/**
@@ -1305,7 +1321,7 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
} else {
principalToBeScheduled = loanApplicationTerms.getPrincipal();
}
- return principalToBeScheduled;
+ return
principalToBeScheduled.minus(loanApplicationTerms.getDownPaymentAmount());
}
private boolean updateFixedInstallmentAmount(final MathContext mc, final
LoanApplicationTerms loanApplicationTerms, int periodNumber,
@@ -1389,8 +1405,8 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
PrincipalInterest principalInterestForThisPeriod =
calculatePrincipalInterestComponentsForPeriod(
getPaymentPeriodsInOneYearCalculator(),
interestCalculationGraceOnRepaymentPeriodFraction, totalInterest.zero(),
totalInterest.zero(), totalInterest.zero(),
totalInterest.zero(), outstanding, loanApplicationTerms,
- periodNumberTemp, mc,
mergeVariationsToMap(params), params.getCompoundingMap(),
params.getPeriodStartDate(),
- transactionDate, applicableVariations);
+ periodNumberTemp, mc,
mergeVariationsToMap(loanApplicationTerms, params), params.getCompoundingMap(),
+ params.getPeriodStartDate(), transactionDate,
applicableVariations);
Money interest = principalInterestForThisPeriod.interest();
totalInterest = totalInterest.plus(interest);
@@ -1421,7 +1437,7 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
outstanding = outstanding.zero();
} else {
outstanding =
updateBalanceForInterestCalculation(params.getPrincipalPortionMap(),
params.getPeriodStartDate(),
- outstanding, false);
+ outstanding);
}
if (params.getLatePaymentMap().isEmpty() &&
outstanding.isZero()) {
break;
@@ -1432,8 +1448,8 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
PrincipalInterest principalInterestForThisPeriod =
calculatePrincipalInterestComponentsForPeriod(
getPaymentPeriodsInOneYearCalculator(),
interestCalculationGraceOnRepaymentPeriodFraction, totalInterest.zero(),
totalInterest.zero(), totalInterest.zero(),
totalInterest.zero(), outstanding, loanApplicationTerms,
- periodNumberTemp, mc, mergeVariationsToMap(params),
params.getCompoundingMap(), params.getPeriodStartDate(),
- params.getActualRepaymentDate(), applicableVariations);
+ periodNumberTemp, mc,
mergeVariationsToMap(loanApplicationTerms, params), params.getCompoundingMap(),
+ params.getPeriodStartDate(),
params.getActualRepaymentDate(), applicableVariations);
Money interest = principalInterestForThisPeriod.interest();
totalInterest = totalInterest.plus(interest);
@@ -1562,16 +1578,12 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
* Identifies all the past date principal changes and apply them on
outstanding balance for future calculations
*/
private Money updateBalanceForInterestCalculation(final Map<LocalDate,
Money> principalPortionMap, final LocalDate scheduledDueDate,
- final Money outstandingBalanceAsPerRest, boolean addMapDetails) {
+ final Money outstandingBalanceAsPerRest) {
List<LocalDate> removeFromPrincipalPortionMap = new ArrayList<>();
Money outstandingBalance = outstandingBalanceAsPerRest;
for (Map.Entry<LocalDate, Money> principal :
principalPortionMap.entrySet()) {
if (!DateUtils.isAfter(principal.getKey(), scheduledDueDate)) {
- if (addMapDetails) {
- outstandingBalance =
outstandingBalance.plus(principal.getValue());
- } else {
- outstandingBalance =
outstandingBalance.minus(principal.getValue());
- }
+ outstandingBalance =
outstandingBalance.minus(principal.getValue());
removeFromPrincipalPortionMap.add(principal.getKey());
}
}
@@ -1852,13 +1864,22 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
* as per rest) changes to single map for interest calculation
*
*/
- private TreeMap<LocalDate, Money> mergeVariationsToMap(final
LoanScheduleParams params) {
+ private TreeMap<LocalDate, Money>
mergeVariationsToMap(LoanApplicationTerms loanApplicationTerms, final
LoanScheduleParams params) {
TreeMap<LocalDate, Money> map = new
TreeMap<>(params.getLatePaymentMap());
for (Map.Entry<LocalDate, Money> mapEntry :
params.getDisburseDetailMap().entrySet()) {
Money value = mapEntry.getValue();
if (map.containsKey(mapEntry.getKey())) {
value = value.plus(map.get(mapEntry.getKey()));
}
+ if (loanApplicationTerms.isDownPaymentEnabled()) {
+ Money downPaymentAmount =
Money.of(loanApplicationTerms.getCurrency(),
+ MathUtil.percentageOf(value.getAmount(),
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
+ if (loanApplicationTerms.getInstallmentAmountInMultiplesOf()
!= null) {
+ downPaymentAmount =
Money.roundToMultiplesOf(downPaymentAmount,
+
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+ }
+ value = value.minus(downPaymentAmount);
+ }
map.put(mapEntry.getKey(), value);
}
@@ -2235,33 +2256,30 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
LocalDate periodStartDate =
RepaymentStartDateType.DISBURSEMENT_DATE.equals(loanApplicationTerms.getRepaymentStartDateType())
? loanApplicationTerms.getExpectedDisbursementDate()
: loanApplicationTerms.getSubmittedOnDate();
- Money downPaymentAmount = Money.zero(currency);
- if (loanApplicationTerms.isDownPaymentEnabled()) {
- downPaymentAmount = Money.of(currency,
MathUtil.percentageOf(loanScheduleParams.getOutstandingBalance().getAmount(),
-
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
- if (loanApplicationTerms.getInstallmentAmountInMultiplesOf()
!= null) {
- downPaymentAmount =
Money.roundToMultiplesOf(downPaymentAmount,
-
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
- }
- }
- Money calculatedAmortizableAmount =
principalToBeScheduled.minus(downPaymentAmount);
-
loanScheduleParams.setOutstandingBalance(calculatedAmortizableAmount);
// Set fixed Amortization Amounts(either EMI or Principal )
- updateAmortization(mc, loanApplicationTerms, periodNumber,
calculatedAmortizableAmount);
+ updateAmortization(mc, loanApplicationTerms, periodNumber,
outstandingBalance);
// count periods without interest grace to exclude for flat loan
// calculations
final Map<LocalDate, Money> disburseDetailMap = new HashMap<>();
if (loanApplicationTerms.isMultiDisburseLoan()) {
- // fetches the first tranche amount and also updates other
- // tranche
- // details to map
- BigDecimal disburseAmt =
getDisbursementAmount(loanApplicationTerms,
loanApplicationTerms.getExpectedDisbursementDate(),
- disburseDetailMap, true);
- outstandingBalance =
outstandingBalance.zero().plus(disburseAmt);
- outstandingBalanceAsPerRest = outstandingBalance;
- principalToBeScheduled =
principalToBeScheduled.zero().plus(disburseAmt);
+ /* fetches the first tranche amount and also updates other
tranche details to map */
+ Money disburseAmt = Money.of(currency,
+ getDisbursementAmount(loanApplicationTerms,
loanApplicationTerms.getExpectedDisbursementDate(), disburseDetailMap,
+
loanScheduleParams.applyInterestRecalculation()));
+ Money downPaymentAmt = Money.zero(currency);
+ if (loanApplicationTerms.isDownPaymentEnabled()) {
+ downPaymentAmt = Money.of(currency,
MathUtil.percentageOf(disburseAmt.getAmount(),
+
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
+ if
(loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
+ downPaymentAmt =
Money.roundToMultiplesOf(downPaymentAmt,
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+ }
+ }
+ Money remainingPrincipalAmt =
disburseAmt.minus(downPaymentAmt);
+ outstandingBalance = remainingPrincipalAmt;
+ outstandingBalanceAsPerRest = remainingPrincipalAmt;
+ principalToBeScheduled = remainingPrincipalAmt;
}
int loanTermInDays = 0;
@@ -2279,6 +2297,12 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
// This will create the recalculation details by applying the
// transactions
for (LoanRepaymentScheduleInstallment installment :
processInstallmentsInstallments) {
+ if (installment.isDownPayment()) {
+ instalmentNumber++;
+
periods.add(createLoanScheduleModelDownPaymentPeriod(installment,
outstandingBalance));
+ newRepaymentScheduleInstallments.add(installment);
+ continue;
+ }
// this will generate the next schedule due date and allows to
// process the installment only if recalculate from date is
// greater than due date
@@ -2442,9 +2466,9 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
// update outstanding balance for interest calculation
outstandingBalanceAsPerRest =
updateBalanceForInterestCalculation(principalPortionMap,
installment.getDueDate(),
- outstandingBalanceAsPerRest, false);
- outstandingBalanceAsPerRest =
updateBalanceForInterestCalculation(disburseDetailMap, installment.getDueDate(),
- outstandingBalanceAsPerRest, true);
+ outstandingBalanceAsPerRest);
+ outstandingBalanceAsPerRest =
calculateOutstandingBalanceAsPerRest(loanApplicationTerms, disburseDetailMap,
+ installment.getDueDate(),
outstandingBalanceAsPerRest);
// updates the map with over due amounts
updateLatePaymentsToMap(loanApplicationTerms,
holidayDetailDTO, currency, latePaymentMap, lastInstallmentDate,
newRepaymentScheduleInstallments, true,
lastRestDate);
@@ -2692,6 +2716,13 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
return installment;
}
+ private LoanScheduleModelPeriod
createLoanScheduleModelDownPaymentPeriod(final LoanRepaymentScheduleInstallment
installment,
+ final Money outstandingPrincipal) {
+ final MonetaryCurrency currency = outstandingPrincipal.getCurrency();
+ return
LoanScheduleModelDownPaymentPeriod.downPayment(installment.getInstallmentNumber(),
installment.getDueDate(),
+ installment.getPrincipal(currency), outstandingPrincipal);
+ }
+
private LoanScheduleModelPeriod createLoanScheduleModelPeriod(final
LoanRepaymentScheduleInstallment installment,
final Money outstandingPrincipal) {
final MonetaryCurrency currency = outstandingPrincipal.getCurrency();
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
index 2399093a6..a5738aec0 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
@@ -188,10 +188,11 @@ public abstract class
AbstractProgressiveLoanScheduleGenerator implements LoanSc
final BigDecimal totalOutstanding = BigDecimal.ZERO;
return LoanScheduleModel.from(periods, applicationCurrency,
scheduleParams.getLoanTermInDays(),
- scheduleParams.getPrincipalToBeScheduled(),
scheduleParams.getTotalCumulativePrincipal().getAmount(), totalPrincipalPaid,
- scheduleParams.getTotalCumulativeInterest().getAmount(),
scheduleParams.getTotalFeeChargesCharged().getAmount(),
- scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
scheduleParams.getTotalRepaymentExpected().getAmount(),
- totalOutstanding);
+
scheduleParams.getPrincipalToBeScheduled().plus(loanApplicationTerms.getDownPaymentAmount()),
+
scheduleParams.getTotalCumulativePrincipal().plus(loanApplicationTerms.getDownPaymentAmount()).getAmount(),
+ totalPrincipalPaid,
scheduleParams.getTotalCumulativeInterest().getAmount(),
+ scheduleParams.getTotalFeeChargesCharged().getAmount(),
scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
+ scheduleParams.getTotalRepaymentExpected().getAmount(),
totalOutstanding);
}
@Override
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index f34269cf7..b6c15d85f 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -23,7 +23,6 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.math.BigDecimal;
import java.math.MathContext;
-import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
@@ -675,8 +674,7 @@ public class LoanScheduleAssembler {
final Set<LoanCharge> loanCharges =
this.loanChargeAssembler.fromParsedJson(element, disbursementDetails);
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mc = new MathContext(8, roundingMode);
+ final MathContext mc = MoneyHelper.getMathContext();
HolidayDetailDTO detailDTO = new HolidayDetailDTO(isHolidayEnabled,
holidays, workingDays);
LoanScheduleGenerator loanScheduleGenerator =
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
@@ -703,8 +701,8 @@ public class LoanScheduleAssembler {
public LoanScheduleModel assembleForInterestRecalculation(final
LoanApplicationTerms loanApplicationTerms, final Long officeId,
Loan loan, final LoanRepaymentScheduleTransactionProcessor
loanRepaymentScheduleTransactionProcessor,
final LocalDate rescheduleFrom) {
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mc = new MathContext(8, roundingMode);
+
+ final MathContext mc = MoneyHelper.getMathContext();
final boolean isHolidayEnabled =
this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
final List<Holiday> holidays =
this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId,
@@ -723,8 +721,8 @@ public class LoanScheduleAssembler {
final LoanRepaymentScheduleTransactionProcessor
loanRepaymentScheduleTransactionProcessor) {
final LoanScheduleGenerator loanScheduleGenerator =
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
loanApplicationTerms.getInterestMethod());
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mc = new MathContext(8, roundingMode);
+
+ final MathContext mc = MoneyHelper.getMathContext();
final boolean isHolidayEnabled =
this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
final List<Holiday> holidays =
this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId,
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
index d326f5a7c..e8df96f89 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
@@ -19,7 +19,6 @@
package org.apache.fineract.portfolio.loanaccount.rescheduleloan.service;
import java.math.MathContext;
-import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
@@ -127,8 +126,8 @@ public class LoanReschedulePreviewPlatformServiceImpl
implements LoanRescheduleP
}
loanApplicationTerms.getLoanTermVariations().updateLoanTermVariationsData(loanTermVariationsData);
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mathContext = new MathContext(8, roundingMode);
+
+ final MathContext mathContext = MoneyHelper.getMathContext();
final LoanRepaymentScheduleTransactionProcessor
loanRepaymentScheduleTransactionProcessor =
this.loanRepaymentScheduleTransactionProcessorFactory
.determineProcessor(loan.transactionProcessingStrategy());
final LoanScheduleGenerator loanScheduleGenerator =
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
index 3c0d41236..05a98e07e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
@@ -20,7 +20,6 @@ package
org.apache.fineract.portfolio.loanaccount.rescheduleloan.service;
import java.math.BigDecimal;
import java.math.MathContext;
-import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@@ -432,8 +431,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl
implements LoanResche
* loanTermVariation.setApplicableFromDate(adjustedDate); } } }
*/
- final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
- final MathContext mathContext = new MathContext(8, roundingMode);
+ final MathContext mathContext = MoneyHelper.getMathContext();
final LoanRepaymentScheduleTransactionProcessor
loanRepaymentScheduleTransactionProcessor =
this.loanRepaymentScheduleTransactionProcessorFactory
.determineProcessor(loan.transactionProcessingStrategy());
final LoanScheduleGenerator loanScheduleGenerator =
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
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 e587e126d..e47ed1dcc 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
@@ -124,7 +124,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -192,7 +192,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -259,7 +259,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -327,7 +327,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -414,7 +414,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -498,7 +498,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -580,7 +580,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -666,7 +666,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -735,7 +735,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -818,7 +818,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -878,7 +878,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -947,7 +947,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1030,7 +1030,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1115,7 +1115,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1197,7 +1197,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1253,7 +1253,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1309,7 +1309,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1365,7 +1365,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1458,7 +1458,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1572,7 +1572,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1645,7 +1645,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1724,7 +1724,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1815,7 +1815,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1881,7 +1881,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1960,7 +1960,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -2065,15 +2065,16 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
CallFailedRuntimeException exception =
assertThrows(CallFailedRuntimeException.class,
- () -> applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
- "01 January 2023", "01 January 2023",
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE,
- LoanScheduleType.PROGRESSIVE.name(),
LoanScheduleProcessingType.VERTICAL.name()));
+ () -> applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
+ BigDecimal.ZERO, "01 January 2023", "01 January
2023",
+
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE,
LoanScheduleType.PROGRESSIVE.name(),
+ LoanScheduleProcessingType.VERTICAL.name()));
assertEquals(400, exception.getResponse().code());
assertTrue(exception.getMessage().contains("supported.only.with.advanced.payment.allocation.strategy"));
exception = assertThrows(CallFailedRuntimeException.class,
- () -> applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
- "01 January 2023", "01 January 2023",
+ () -> applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
+ BigDecimal.ZERO, "01 January 2023", "01 January
2023",
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
LoanScheduleType.PROGRESSIVE.name(),
LoanScheduleProcessingType.HORIZONTAL.name()));
assertEquals(400, exception.getResponse().code());
@@ -2099,7 +2100,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000), 45,
- 15, 3, 0, "01 January 2023", "01 January 2023");
+ 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January
2023");
GetLoansLoanIdResponse loanDetails =
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16),
333.33, 0.0, 333.33, 0.0, 0.0);
@@ -2128,8 +2129,8 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15),
333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
- loanResponse = applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
- "01 January 2023", "01 January 2023");
+ loanResponse = applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
+ BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanDetails =
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16),
166.67, 0.0, 166.67, 0.0, 0.0);
@@ -2187,7 +2188,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000), 45,
- 15, 3, 0, "01 January 2023", "01 January 2023");
+ 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January
2023");
GetLoansLoanIdResponse loanDetails =
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16),
333.33, 0.0, 333.33, 0.0, 0.0);
@@ -2216,8 +2217,8 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15),
333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
- loanResponse = applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
- "01 January 2023", "01 January 2023");
+ loanResponse = applyForLoanApplication(client.getClientId(),
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
+ BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanDetails =
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16),
166.67, 0.0, 166.67, 0.0, 0.0);
@@ -2275,7 +2276,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(40.50),
- 45, 15, 3, 0, "01 January 2023", "01 January 2023");
+ 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January
2023");
GetLoansLoanIdResponse loanDetails =
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1),
10.12, 0.0, 10.12, 0.0, 0.0);
@@ -2326,7 +2327,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(40.50),
- 45, 15, 3, 0, "01 January 2023", "01 January 2023");
+ 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January
2023");
GetLoansLoanIdResponse loanDetails =
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1),
10.12, 0.0, 10.12, 0.0, 0.0);
@@ -2380,7 +2381,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September
2023", "01 September 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2486,7 +2487,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September
2023", "01 September 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2591,7 +2592,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September
2023", "01 September 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2696,7 +2697,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September
2023", "01 September 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2795,7 +2796,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2881,7 +2882,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2970,7 +2971,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January
2023", "01 January 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -3205,7 +3206,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
}
private static PostLoansResponse applyForLoanApplication(final Long
clientId, final Integer loanProductId, final BigDecimal principal,
- final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final int interestRate,
+ final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String
submittedOnDate, String transactionProcessorCode, String loanScheduleType,
String loanScheduleProcessingType) {
LOG.info("--------------------------------APPLYING FOR LOAN
APPLICATION--------------------------------");
@@ -3220,7 +3221,7 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
}
private static PostLoansResponse applyForLoanApplication(final Long
clientId, final Integer loanProductId, final BigDecimal principal,
- final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final int interestRate,
+ final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String
submittedOnDate) {
LOG.info("--------------------------------APPLYING FOR LOAN
APPLICATION--------------------------------");
return applyForLoanApplication(clientId, loanProductId, principal,
loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
index a510eaf23..12a7a81de 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
@@ -128,14 +128,14 @@ public abstract class BaseLoanIntegrationTest {
.useBorrowerCycle(false)//
.minPrincipal(100.0)//
.principal(1000.0)//
- .maxPrincipal(10000.0)//
+ .maxPrincipal(100000.0)//
.minNumberOfRepayments(1)//
.numberOfRepayments(1)//
.maxNumberOfRepayments(30)//
.isLinkedToFloatingInterestRates(false)//
.minInterestRatePerPeriod((double) 0)//
.interestRatePerPeriod((double) 0)//
- .maxInterestRatePerPeriod((double) 0)//
+ .maxInterestRatePerPeriod((double) 100)//
.interestRateFrequencyType(2)//
.repaymentEvery(30)//
.repaymentFrequencyType(0L)//
@@ -412,8 +412,8 @@ public abstract class BaseLoanIntegrationTest {
PostLoansRequest postLoansRequest = new
PostLoansRequest().clientId(clientId).productId(loanProductId)
.expectedDisbursementDate(loanDisbursementDate).dateFormat(DATETIME_PATTERN)
.transactionProcessingStrategyCode(DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_STRATEGY)
-
.locale("en").submittedOnDate(loanDisbursementDate).amortizationType(1).interestRatePerPeriod(0)
-
.interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0).repaymentEvery(30).repaymentFrequencyType(0)
+
.locale("en").submittedOnDate(loanDisbursementDate).amortizationType(1).interestRatePerPeriod(BigDecimal.ZERO)
+
.interestCalculationPeriodType(1).interestType(0).repaymentEvery(30).repaymentFrequencyType(0)
.numberOfRepayments(numberOfRepayments).loanTermFrequency(numberOfRepayments *
30).loanTermFrequencyType(0)
.maxOutstandingLoanBalance(BigDecimal.valueOf(amount)).principal(BigDecimal.valueOf(amount)).loanType("individual");
if (customizer != null) {
@@ -422,9 +422,9 @@ public abstract class BaseLoanIntegrationTest {
return postLoansRequest;
}
- protected PostLoansLoanIdRequest approveLoanRequest(Double amount) {
+ protected PostLoansLoanIdRequest approveLoanRequest(Double amount, String
approvalDate) {
return new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(amount)).dateFormat(DATETIME_PATTERN)
- .approvedOnDate("01 January 2023").locale("en");
+ .approvedOnDate(approvalDate).locale("en");
}
protected Long applyAndApproveLoan(Long clientId, Long loanProductId,
String loanDisbursementDate, Double amount,
@@ -438,7 +438,7 @@ public abstract class BaseLoanIntegrationTest {
.applyLoan(applyLoanRequest(clientId, loanProductId,
loanDisbursementDate, amount, numberOfRepayments, customizer));
PostLoansLoanIdResponse approvedLoanResult =
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
- approveLoanRequest(amount));
+ approveLoanRequest(amount, loanDisbursementDate));
return approvedLoanResult.getLoanId();
}
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 4ca9fedfa..b0287e94a 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
@@ -8041,9 +8041,9 @@ public class ClientLoanIntegrationTest {
return LOAN_TRANSACTION_HELPER.applyLoan(new
PostLoansRequest().clientId(clientId.longValue()).productId(loanProductId)
.expectedDisbursementDate(loanDisbursementDate).dateFormat(DATETIME_PATTERN)
.transactionProcessingStrategyCode(repaymentStrategyCode).locale("en").submittedOnDate(loanDisbursementDate)
-
.amortizationType(1).interestRatePerPeriod(0).interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0)
-
.repaymentEvery(30).repaymentFrequencyType(0).numberOfRepayments(1).loanTermFrequency(30).loanTermFrequencyType(0)
- .principal(BigDecimal.valueOf(1000.0)).loanType("individual"));
+
.amortizationType(1).interestRatePerPeriod(BigDecimal.ZERO).interestCalculationPeriodType(1).interestType(0)
+
.repaymentFrequencyType(0).repaymentEvery(30).repaymentFrequencyType(0).numberOfRepayments(1).loanTermFrequency(30)
+
.loanTermFrequencyType(0).principal(BigDecimal.valueOf(1000.0)).loanType("individual"));
}
private PostLoanProductsRequest
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct() {
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
index d5824bdc6..2ca0a6611 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
@@ -935,10 +935,11 @@ public class ExternalIdSupportIntegrationTest extends
IntegrationTest {
"modify",
new PutLoansLoanIdRequest().submittedOnDate("31 August
2022").dateFormat("dd MMMM yyyy").locale("en")
.loanType("individual").productId(loanProductID.longValue()).clientId(client.getClientId()).interestType(0)
-
.interestCalculationPeriodType(1).interestRatePerPeriod(0).isEqualAmortization(false).loanTermFrequency(30)
-
.loanTermFrequencyType(0).maxOutstandingLoanBalance(10000L).numberOfRepayments(1).principal(10000L)
-
.repaymentEvery(30).repaymentFrequencyType(0).transactionProcessingStrategyCode("mifos-standard-strategy")
- .expectedDisbursementDate("2 September
2022").amortizationType(1));
+
.interestCalculationPeriodType(1).interestRatePerPeriod(BigDecimal.ZERO).isEqualAmortization(false)
+
.loanTermFrequency(30).loanTermFrequencyType(0).maxOutstandingLoanBalance(10000L).numberOfRepayments(1)
+
.principal(10000L).repaymentEvery(30).repaymentFrequencyType(0)
+
.transactionProcessingStrategyCode("mifos-standard-strategy").expectedDisbursementDate("2
September 2022")
+ .amortizationType(1));
assertEquals(loanExternalIdStr2,
modifyLoanApplicationResult.getResourceExternalId());
DeleteLoansLoanIdResponse deleteLoanApplicationResult =
this.loanTransactionHelper.deleteLoanApplication(loanExternalIdStr2);
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
index 33601c650..737d6c55c 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
@@ -163,8 +163,8 @@ public class
LoanChargePaymentWithAdvancedPaymentAllocationTest {
savingsAccountHelper.depositToSavingsAccount(savingsId, "10000",
startDate, CommonConstants.RESPONSE_RESOURCE_ID);
- final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 45,
15, 3, 0,
- "01 January 2023", "01 January 2023");
+ final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 45,
15, 3,
+ BigDecimal.ZERO, "01 January 2023", "01 January 2023");
int loanId = loanResponse.getLoanId().intValue();
@@ -266,7 +266,7 @@ public class
LoanChargePaymentWithAdvancedPaymentAllocationTest {
}
private static PostLoansResponse applyForLoanApplication(final Long
clientId, final Integer loanProductId, final Long principal,
- final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final int interestRate,
+ final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String
submittedOnDate) {
log.info("--------------------------------APPLYING FOR LOAN
APPLICATION--------------------------------");
return loanTransactionHelper.applyLoan(new
PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
index b7cd5c5d1..9d72e8a61 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
@@ -71,7 +71,7 @@ public class LoanInstallmentMultiplesOfTest extends
BaseLoanIntegrationTest {
PostLoansResponse postLoansResponse =
loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult =
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
- approveLoanRequest(amount));
+ approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
@@ -130,12 +130,12 @@ public class LoanInstallmentMultiplesOfTest extends
BaseLoanIntegrationTest {
.interestType(interestType)//
.amortizationType(amortizationType)//
.interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
- .interestRatePerPeriod(12);
+ .interestRatePerPeriod(BigDecimal.valueOf(12));
PostLoansResponse postLoansResponse =
loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult =
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
- approveLoanRequest(amount));
+ approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
@@ -193,12 +193,12 @@ public class LoanInstallmentMultiplesOfTest extends
BaseLoanIntegrationTest {
.interestType(interestType)//
.amortizationType(amortizationType)//
.interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
- .interestRatePerPeriod(12);
+ .interestRatePerPeriod(BigDecimal.valueOf(12));
PostLoansResponse postLoansResponse =
loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult =
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
- approveLoanRequest(amount));
+ approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
index a17929c17..d54a60d20 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
@@ -36,13 +36,15 @@ import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(LoanTestLifecycleExtension.class)
public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest
{
- public static final BigDecimal DOWN_PAYMENT_PERCENTAGE = new
BigDecimal(25);
+ public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_20 = new
BigDecimal(20);
+ public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_25 = new
BigDecimal(25);
+ public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_33 = new
BigDecimal(33);
private final LoanRescheduleRequestHelper loanRescheduleRequestHelper =
new LoanRescheduleRequestHelper(this.requestSpec,
this.responseSpec);
@Test
- public void testRescheduleWithDownpayment() {
+ public void testRescheduleWithDownPayment() {
runAt("01 January 2023", () -> {
// Create Client
Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
@@ -105,6 +107,342 @@ public class LoanRescheduleTestWithDownpayment extends
BaseLoanIntegrationTest {
});
}
+ @Test
+ public void testRescheduleAddExtraInstallmentsWithDownPayment() {
+ runAt("01 November 2023", () -> {
+ // Create Client
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ // Create Loan Product
+ Long loanProductId = createLoanProductWith33PctDownPayment(true,
true);
+
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, "02
October 2023", 1000.0, 3);
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(1000.0, null, "02 October 2023"), //
+ installment(330.0, false, "02 October 2023"), //
+ installment(223.33, false, "01 November 2023"), //
+ installment(223.33, false, "01 December 2023"), //
+ installment(223.34, false, "31 December 2023") //
+ );
+
+ // 1st Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(1000.00), "02 October
2023");
+
+ // verify transactions
+ verifyTransactions(loanId, //
+ transaction(330.0, "Down Payment", "02 October 2023"), //
+ transaction(1000.0, "Disbursement", "02 October 2023") //
+ );
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(1000.0, null, "02 October 2023"), //
+ installment(330.0, true, "02 October 2023"), //
+ installment(223.33, false, "01 November 2023"), //
+ installment(223.33, false, "01 December 2023"), //
+ installment(223.34, false, "31 December 2023") //
+ );
+
+ String requestJSON = new
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01
November 2023")
+ .updateAdjustedDueDate(null).updateSubmittedOnDate("01
November 2023").updateRescheduleReasonId("1")
+ .build(loanId.toString());
+
+ Integer loanRescheduleRequest =
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+ requestJSON = new
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 November 2023")
+ .getApproveLoanRescheduleRequestJSON();
+ Integer approveLoanRescheduleRequest =
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+ requestJSON);
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(1000.0, null, "02 October 2023"), //
+ installment(330.0, true, "02 October 2023"), //
+ installment(134.0, false, "01 November 2023"), //
+ installment(134.0, false, "01 December 2023"), //
+ installment(134.0, false, "31 December 2023"), //
+ installment(134.0, false, "30 January 2024"), //
+ installment(134.0, false, "29 February 2024") //
+ );
+ });
+ }
+
+ @Test
+ public void
testRescheduleAddExtraInstallmentsMultipleDisbursementWithDownPayment() {
+ runAt("31 December 2023", () -> {
+ // Create Client
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ // Create Loan Product
+ Long loanProductId = createLoanProductWith33PctDownPayment(true,
true);
+
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, "02
October 2023", 1000.0, 3);
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(1000.0, null, "02 October 2023"), //
+ installment(330.0, false, "02 October 2023"), //
+ installment(223.33, false, "01 November 2023"), //
+ installment(223.33, false, "01 December 2023"), //
+ installment(223.34, false, "31 December 2023") //
+ );
+
+ // 1st Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(1000.00), "02 October
2023");
+
+ // verify transactions
+ verifyTransactions(loanId, //
+ transaction(330.0, "Down Payment", "02 October 2023"), //
+ transaction(1000.0, "Disbursement", "02 October 2023") //
+ );
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(1000.0, null, "02 October 2023"), //
+ installment(330.0, true, "02 October 2023"), //
+ installment(223.33, false, "01 November 2023"), //
+ installment(223.33, false, "01 December 2023"), //
+ installment(223.34, false, "31 December 2023") //
+ );
+
+ // 2nd Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(200.00), "02 December
2023");
+
+ // verify transactions
+ verifyTransactions(loanId, //
+ transaction(330.0, "Down Payment", "02 October 2023"), //
+ transaction(1000.0, "Disbursement", "02 October 2023"), //
+ transaction(200.0, "Disbursement", "02 December 2023"), //
+ transaction(66.0, "Down Payment", "02 December 2023") //
+ );
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(1000.0, null, "02 October 2023"), //
+ installment(330.0, true, "02 October 2023"), //
+ installment(268.0, false, "01 November 2023"), //
+ installment(268.0, false, "01 December 2023"), //
+ installment(200.0, null, "02 December 2023"), //
+ installment(66.0, false, "02 December 2023"), //
+ installment(268.0, false, "31 December 2023") //
+ );
+
+ String requestJSON = new
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("31
December 2023")
+ .updateAdjustedDueDate(null).updateSubmittedOnDate("31
December 2023").updateRescheduleReasonId("1")
+ .build(loanId.toString());
+
+ Integer loanRescheduleRequest =
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+ requestJSON = new
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("31 December 2023")
+ .getApproveLoanRescheduleRequestJSON();
+ Integer approveLoanRescheduleRequest =
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+ requestJSON);
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(1000.0, null, "02 October 2023"), //
+ installment(330.0, true, "02 October 2023"), //
+ installment(268, false, "01 November 2023"), //
+ installment(268, false, "01 December 2023"), //
+ installment(200.0, null, "02 December 2023"), //
+ installment(66.0, false, "02 December 2023"), //
+ installment(89.33, false, "31 December 2023"), //
+ installment(89.33, false, "30 January 2024"), //
+ installment(89.34, false, "29 February 2024") //
+ );
+ });
+ }
+
+ @Test
+ public void
testRescheduleAddExtraInstallmentsDisbursementWithDownPaymentWithInterest() {
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ // Create Loan Product
+ Long loanProductId =
createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(true, true,
5.0);
+
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, "01
January 2023", 15000.0, 6, postLoansRequest -> {
+ postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+ postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+ postLoansRequest.repaymentEvery(1);
+
postLoansRequest.loanTermFrequencyType(RepaymentFrequencyType.MONTHS);
+
postLoansRequest.repaymentFrequencyType(RepaymentFrequencyType.MONTHS);
+ postLoansRequest.loanTermFrequency(6);
+ });
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(12000.0, null, "01 January 2023"), //
+ installment(3000.00, false, "01 January 2023"), //
+ installment(1764.21, false, "01 February 2023"), //
+ installment(1852.42, false, "01 March 2023"), //
+ installment(1945.04, false, "01 April 2023"), //
+ installment(2042.29, false, "01 May 2023"), //
+ installment(2144.41, false, "01 June 2023"), //
+ installment(2251.63, false, "01 July 2023") //
+ );
+
+ // 1st Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(12000.00), "01 January
2023");
+
+ // verify transactions
+ verifyTransactions(loanId, //
+ transaction(2400.0, "Down Payment", "01 January 2023"), //
+ transaction(12000.0, "Disbursement", "01 January 2023") //
+ );
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(12000.0, null, "01 January 2023"), //
+ installment(2400.00, true, "01 January 2023"), //
+ installment(1411.37, false, "01 February 2023"), //
+ installment(1481.94, false, "01 March 2023"), //
+ installment(1556.04, false, "01 April 2023"), //
+ installment(1633.84, false, "01 May 2023"), //
+ installment(1715.53, false, "01 June 2023"), //
+ installment(1801.28, false, "01 July 2023") //
+ );
+
+ updateBusinessDate("01 June 2023");
+ String requestJSON = new
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01
June 2023").updateAdjustedDueDate(null)
+ .updateSubmittedOnDate("01 June
2023").updateRescheduleReasonId("1").build(loanId.toString());
+
+ Integer loanRescheduleRequest =
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+ requestJSON = new
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 June 2023")
+ .getApproveLoanRescheduleRequestJSON();
+ Integer approveLoanRescheduleRequest =
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+ requestJSON);
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(12000.0, null, "01 January 2023"), //
+ installment(2400.00, true, "01 January 2023"), //
+ installment(1411.37, false, "01 February 2023"), //
+ installment(1481.94, false, "01 March 2023"), //
+ installment(1556.04, false, "01 April 2023"), //
+ installment(1633.84, false, "01 May 2023"), //
+ installment(815.94, false, "01 June 2023"), //
+ installment(856.74, false, "01 July 2023"), //
+ installment(899.57, false, "01 August 2023"), //
+ installment(944.56, false, "01 September 2023") //
+ );
+ });
+ }
+
+ @Test
+ public void
testRescheduleAddExtraInstallmentsMultipleDisbursementWithDownPaymentWithInterest()
{
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ // Create Loan Product
+ Long loanProductId =
createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(true, true,
5.0);
+
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, "01
January 2023", 15000.0, 6, postLoansRequest -> {
+ postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+ postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+ postLoansRequest.repaymentEvery(1);
+
postLoansRequest.loanTermFrequencyType(RepaymentFrequencyType.MONTHS);
+
postLoansRequest.repaymentFrequencyType(RepaymentFrequencyType.MONTHS);
+ postLoansRequest.loanTermFrequency(6);
+ });
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(12000.0, null, "01 January 2023"), //
+ installment(3000.00, false, "01 January 2023"), //
+ installment(1764.21, false, "01 February 2023"), //
+ installment(1852.42, false, "01 March 2023"), //
+ installment(1945.04, false, "01 April 2023"), //
+ installment(2042.29, false, "01 May 2023"), //
+ installment(2144.41, false, "01 June 2023"), //
+ installment(2251.63, false, "01 July 2023") //
+ );
+
+ // 1st Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(12000.00), "01 January
2023");
+
+ // verify transactions
+ verifyTransactions(loanId, //
+ transaction(2400.0, "Down Payment", "01 January 2023"), //
+ transaction(12000.0, "Disbursement", "01 January 2023") //
+ );
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(12000.0, null, "01 January 2023"), //
+ installment(2400.00, true, "01 January 2023"), //
+ installment(1411.37, false, "01 February 2023"), //
+ installment(1481.94, false, "01 March 2023"), //
+ installment(1556.04, false, "01 April 2023"), //
+ installment(1633.84, false, "01 May 2023"), //
+ installment(1715.53, false, "01 June 2023"), //
+ installment(1801.28, false, "01 July 2023") //
+ );
+
+ updateBusinessDate("02 May 2023");
+ // 2nd Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(3000.00), "02 May 2023");
+
+ // verify transactions
+ verifyTransactions(loanId, //
+ transaction(2400.0, "Down Payment", "01 January 2023"), //
+ transaction(12000.0, "Disbursement", "01 January 2023"), //
+ transaction(3000.00, "Disbursement", "02 May 2023"), //
+ transaction(600.0, "Down Payment", "02 May 2023") //
+ );
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(12000.0, null, "01 January 2023"), //
+ installment(2400.00, true, "01 January 2023"), //
+ installment(1884.21, false, "01 February 2023"), //
+ installment(1978.42, false, "01 March 2023"), //
+ installment(2077.34, false, "01 April 2023"), //
+ installment(2181.21, false, "01 May 2023"), //
+ installment(3000.0, null, "02 May 2023"), //
+ installment(600.0, false, "02 May 2023"), //
+ installment(2174.14, false, "01 June 2023"), //
+ installment(1704.68, false, "01 July 2023") //
+ );
+
+ updateBusinessDate("01 June 2023");
+ String requestJSON = new
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01
June 2023").updateAdjustedDueDate(null)
+ .updateSubmittedOnDate("01 June
2023").updateRescheduleReasonId("1").build(loanId.toString());
+
+ Integer loanRescheduleRequest =
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+ requestJSON = new
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 June 2023")
+ .getApproveLoanRescheduleRequestJSON();
+ Integer approveLoanRescheduleRequest =
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+ requestJSON);
+
+ // Verify Repayment Schedule
+ verifyRepaymentSchedule(loanId, //
+ installment(12000.0, null, "01 January 2023"), //
+ installment(2400.00, true, "01 January 2023"), //
+ installment(1884.21, false, "01 February 2023"), //
+ installment(1978.42, false, "01 March 2023"), //
+ installment(2077.34, false, "01 April 2023"), //
+ installment(2181.21, false, "01 May 2023"), //
+ installment(3000.0, null, "02 May 2023"), //
+ installment(600.0, false, "02 May 2023"), //
+ installment(903.80, false, "01 June 2023"), //
+ installment(945.12, false, "01 July 2023"), //
+ installment(992.37, false, "01 August 2023"), //
+ installment(1037.53, false, "01 September 2023")//
+ );
+ });
+ }
+
private Long createLoanProductWith25PctDownPayment(boolean
autoDownPaymentEnabled, boolean multiDisburseEnabled) {
PostLoanProductsRequest product =
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
product.setMultiDisburseLoan(multiDisburseEnabled);
@@ -117,7 +455,75 @@ public class LoanRescheduleTestWithDownpayment extends
BaseLoanIntegrationTest {
}
product.setEnableDownPayment(true);
-
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE);
+
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_25);
+ product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
+
+ PostLoanProductsResponse loanProductResponse =
loanProductHelper.createLoanProduct(product);
+ GetLoanProductsProductIdResponse getLoanProductsProductIdResponse =
loanProductHelper
+ .retrieveLoanProductById(loanProductResponse.getResourceId());
+
+ Long loanProductId = loanProductResponse.getResourceId();
+
+ assertEquals(TRUE,
getLoanProductsProductIdResponse.getEnableDownPayment());
+
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
+ assertEquals(0,
+
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_25));
+ assertEquals(autoDownPaymentEnabled,
getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
+ assertEquals(multiDisburseEnabled,
getLoanProductsProductIdResponse.getMultiDisburseLoan());
+ return loanProductId;
+ }
+
+ private Long createLoanProductWith33PctDownPayment(boolean
autoDownPaymentEnabled, boolean multiDisburseEnabled) {
+ PostLoanProductsRequest product =
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
+ product.setMultiDisburseLoan(multiDisburseEnabled);
+ product.repaymentEvery(1);
+
product.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue());
+ product.installmentAmountInMultiplesOf(null);
+
+ if (!multiDisburseEnabled) {
+ product.disallowExpectedDisbursements(null);
+ product.setAllowApprovedDisbursedAmountsOverApplied(null);
+ product.overAppliedCalculationType(null);
+ product.overAppliedNumber(null);
+ }
+
+ product.setEnableDownPayment(true);
+
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_33);
+ product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
+
+ PostLoanProductsResponse loanProductResponse =
loanProductHelper.createLoanProduct(product);
+ GetLoanProductsProductIdResponse getLoanProductsProductIdResponse =
loanProductHelper
+ .retrieveLoanProductById(loanProductResponse.getResourceId());
+
+ Long loanProductId = loanProductResponse.getResourceId();
+
+ assertEquals(TRUE,
getLoanProductsProductIdResponse.getEnableDownPayment());
+
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
+ assertEquals(0,
+
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_33));
+ assertEquals(autoDownPaymentEnabled,
getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
+ assertEquals(multiDisburseEnabled,
getLoanProductsProductIdResponse.getMultiDisburseLoan());
+ return loanProductId;
+ }
+
+ private Long
createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(boolean
autoDownPaymentEnabled,
+ boolean multiDisburseEnabled, double interestRate) {
+ PostLoanProductsRequest product =
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
+ product.setMultiDisburseLoan(multiDisburseEnabled);
+ product.repaymentEvery(1);
+
product.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue());
+ product.installmentAmountInMultiplesOf(null);
+ product.interestRatePerPeriod(interestRate);
+
+ if (!multiDisburseEnabled) {
+ product.disallowExpectedDisbursements(null);
+ product.setAllowApprovedDisbursedAmountsOverApplied(null);
+ product.overAppliedCalculationType(null);
+ product.overAppliedNumber(null);
+ }
+
+ product.setEnableDownPayment(true);
+
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_20);
product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
PostLoanProductsResponse loanProductResponse =
loanProductHelper.createLoanProduct(product);
@@ -128,7 +534,8 @@ public class LoanRescheduleTestWithDownpayment extends
BaseLoanIntegrationTest {
assertEquals(TRUE,
getLoanProductsProductIdResponse.getEnableDownPayment());
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
- assertEquals(0,
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE));
+ assertEquals(0,
+
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_20));
assertEquals(autoDownPaymentEnabled,
getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
assertEquals(multiDisburseEnabled,
getLoanProductsProductIdResponse.getMultiDisburseLoan());
return loanProductId;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
index 7efe0be71..660f7e19b 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
@@ -446,8 +446,8 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
.currencyCode("USD").name(Utils.randomStringGenerator("PENALTY_" +
Calendar.getInstance().getTimeInMillis(), 5))
.chargeAppliesTo(1).locale("en").active(true));
- final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 30,
30, 1, 0,
- "01 September 2023", "01 September 2023");
+ final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 30,
30, 1,
+ BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -548,7 +548,7 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
}
private static PostLoansResponse applyForLoanApplication(final Long
clientId, final Integer loanProductId, final Long principal,
- final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final int interestRate,
+ final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String
submittedOnDate) {
LOG.info("--------------------------------APPLYING FOR LOAN
APPLICATION--------------------------------");
return loanTransactionHelper.applyLoan(new
PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
index 12377c465..9d631d87f 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
@@ -80,7 +80,7 @@ public class LoanWaiveChargeTest extends
BaseLoanIntegrationTest {
PostLoansResponse postLoansResponse =
loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult =
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
- approveLoanRequest(amount));
+ approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
appliedLoanId.set(loanId);
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
index 58c884679..29c9817fd 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
@@ -104,8 +104,8 @@ public class
RefundForActiveLoansWithAdvancedPaymentAllocationTest {
Integer loanProductId = createLoanProduct("1000", "30", "4",
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount,
expenseAccount, overpaymentAccount);
- final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
0,
- "01 January 2023", "01 January 2023");
+ final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
+ BigDecimal.ZERO, "01 January 2023", "01 January 2023");
int loanId = loanResponse.getLoanId().intValue();
@@ -303,8 +303,8 @@ public class
RefundForActiveLoansWithAdvancedPaymentAllocationTest {
Integer loanProductId = createLoanProduct("1000", "30", "4",
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount,
expenseAccount, overpaymentAccount);
- final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
0,
- "01 January 2023", "01 January 2023");
+ final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
+ BigDecimal.ZERO, "01 January 2023", "01 January 2023");
int loanId = loanResponse.getLoanId().intValue();
@@ -529,7 +529,7 @@ public class
RefundForActiveLoansWithAdvancedPaymentAllocationTest {
}
private static PostLoansResponse applyForLoanApplication(final Long
clientId, final Integer loanProductId, final Long principal,
- final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final int interestRate,
+ final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String
submittedOnDate) {
log.info("--------------------------------APPLYING FOR LOAN
APPLICATION--------------------------------");
return loanTransactionHelper.applyLoan(new
PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())