FINERACT-1981: Order disbursements and repayment periods properly
This commit is contained in:
+12
-2
@@ -23,6 +23,7 @@ import java.time.LocalDate;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object representing disbursement information.
|
* Immutable data object representing disbursement information.
|
||||||
@@ -89,9 +90,12 @@ public final class DisbursementData implements Comparable<DisbursementData> {
|
|||||||
return DateUtils.compare(obj.expectedDisbursementDate, this.expectedDisbursementDate);
|
return DateUtils.compare(obj.expectedDisbursementDate, this.expectedDisbursementDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDueForDisbursement(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
public boolean isDueForDisbursement(LoanScheduleType loanScheduleType, final LocalDate fromDate, final LocalDate toDate) {
|
||||||
final LocalDate dueDate = disbursementDate();
|
final LocalDate dueDate = disbursementDate();
|
||||||
return occursOnDayFromAndUpToAndIncluding(fromNotInclusive, upToAndInclusive, dueDate);
|
return switch (loanScheduleType) {
|
||||||
|
case CUMULATIVE -> occursOnDayFromAndUpToAndIncluding(fromDate, toDate, dueDate);
|
||||||
|
case PROGRESSIVE -> occursOnDayFromAndIncludingAndUpTo(fromDate, toDate, dueDate);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
||||||
@@ -99,6 +103,12 @@ public final class DisbursementData implements Comparable<DisbursementData> {
|
|||||||
return DateUtils.isAfter(target, fromNotInclusive) && !DateUtils.isAfter(target, upToAndInclusive);
|
return DateUtils.isAfter(target, fromNotInclusive) && !DateUtils.isAfter(target, upToAndInclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean occursOnDayFromAndIncludingAndUpTo(final LocalDate fromInclusive, final LocalDate upToNotInclusive,
|
||||||
|
final LocalDate target) {
|
||||||
|
return (DateUtils.isEqual(target, fromInclusive) || DateUtils.isAfter(target, fromInclusive))
|
||||||
|
&& DateUtils.isBefore(target, upToNotInclusive);
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal getWaivedChargeAmount() {
|
public BigDecimal getWaivedChargeAmount() {
|
||||||
return this.waivedChargeAmount == null ? BigDecimal.ZERO : this.waivedChargeAmount;
|
return this.waivedChargeAmount == null ? BigDecimal.ZERO : this.waivedChargeAmount;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -282,7 +282,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
List<LoanRepaymentScheduleInstallment> installments) {
|
List<LoanRepaymentScheduleInstallment> installments) {
|
||||||
final MathContext mc = MoneyHelper.getMathContext();
|
final MathContext mc = MoneyHelper.getMathContext();
|
||||||
List<LoanRepaymentScheduleInstallment> candidateRepaymentInstallments = installments.stream().filter(
|
List<LoanRepaymentScheduleInstallment> candidateRepaymentInstallments = installments.stream().filter(
|
||||||
i -> !i.getDueDate().isBefore(disbursementTransaction.getTransactionDate()) && !i.isDownPayment() && !i.isAdditional())
|
i -> i.getDueDate().isAfter(disbursementTransaction.getTransactionDate()) && !i.isDownPayment() && !i.isAdditional())
|
||||||
.toList();
|
.toList();
|
||||||
int noCandidateRepaymentInstallments = candidateRepaymentInstallments.size();
|
int noCandidateRepaymentInstallments = candidateRepaymentInstallments.size();
|
||||||
LoanProductRelatedDetail loanProductRelatedDetail = disbursementTransaction.getLoan().getLoanRepaymentScheduleDetail();
|
LoanProductRelatedDetail loanProductRelatedDetail = disbursementTransaction.getLoan().getLoanRepaymentScheduleDetail();
|
||||||
|
|||||||
+7
@@ -39,4 +39,11 @@ public enum LoanScheduleType {
|
|||||||
public EnumOptionData asEnumOptionData() {
|
public EnumOptionData asEnumOptionData() {
|
||||||
return new EnumOptionData((long) this.ordinal(), this.name(), this.humanReadableName);
|
return new EnumOptionData((long) this.ordinal(), this.name(), this.humanReadableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LoanScheduleType fromEnumOptionData(EnumOptionData enumOptionData) {
|
||||||
|
if (enumOptionData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return valueOf(enumOptionData.getCode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -47,7 +47,6 @@ import jakarta.ws.rs.core.MediaType;
|
|||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
import jakarta.ws.rs.core.UriInfo;
|
import jakarta.ws.rs.core.UriInfo;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -953,7 +952,7 @@ public class LoansApiResource {
|
|||||||
loanBasicDetails.getFeeChargesAtDisbursementCharged());
|
loanBasicDetails.getFeeChargesAtDisbursementCharged());
|
||||||
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(resolvedLoanId, repaymentScheduleRelatedData,
|
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(resolvedLoanId, repaymentScheduleRelatedData,
|
||||||
disbursementData, loanBasicDetails.isInterestRecalculationEnabled(),
|
disbursementData, loanBasicDetails.isInterestRecalculationEnabled(),
|
||||||
loanBasicDetails.getSummary() != null ? loanBasicDetails.getSummary().getFeeChargesPaid() : BigDecimal.ZERO);
|
LoanScheduleType.fromEnumOptionData(loanBasicDetails.getLoanScheduleType()));
|
||||||
|
|
||||||
if (associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName)
|
if (associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName)
|
||||||
&& loanBasicDetails.isInterestRecalculationEnabled()) {
|
&& loanBasicDetails.isInterestRecalculationEnabled()) {
|
||||||
@@ -965,8 +964,9 @@ public class LoansApiResource {
|
|||||||
&& loanBasicDetails.isInterestRecalculationEnabled()
|
&& loanBasicDetails.isInterestRecalculationEnabled()
|
||||||
&& LoanStatus.fromInt(loanBasicDetails.getStatus().getId().intValue()).isActive()) {
|
&& LoanStatus.fromInt(loanBasicDetails.getStatus().getId().intValue()).isActive()) {
|
||||||
mandatoryResponseParameters.add(DataTableApiConstant.originalScheduleAssociateParamName);
|
mandatoryResponseParameters.add(DataTableApiConstant.originalScheduleAssociateParamName);
|
||||||
LoanScheduleData loanScheduleData = this.loanScheduleHistoryReadPlatformService
|
LoanScheduleData loanScheduleData = this.loanScheduleHistoryReadPlatformService.retrieveRepaymentArchiveSchedule(
|
||||||
.retrieveRepaymentArchiveSchedule(resolvedLoanId, repaymentScheduleRelatedData, disbursementData);
|
resolvedLoanId, repaymentScheduleRelatedData, disbursementData,
|
||||||
|
LoanScheduleType.fromEnumOptionData(loanBasicDetails.getLoanScheduleType()));
|
||||||
loanBasicDetails = LoanAccountData.withOriginalSchedule(loanBasicDetails, loanScheduleData);
|
loanBasicDetails = LoanAccountData.withOriginalSchedule(loanBasicDetails, loanScheduleData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-82
@@ -28,7 +28,6 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||||
@@ -85,26 +84,6 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
|
|
||||||
boolean isFirstRepayment = true;
|
boolean isFirstRepayment = true;
|
||||||
|
|
||||||
if (loanApplicationTerms.isMultiDisburseLoan()) {
|
|
||||||
/* fetches the first tranche amount and also updates other tranche details to map */
|
|
||||||
Money disburseAmt = Money.of(currency, getDisbursementAmount(loanApplicationTerms, scheduleParams.getPeriodStartDate(),
|
|
||||||
scheduleParams.getDisburseDetailMap(), scheduleParams.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);
|
|
||||||
scheduleParams.setPrincipalToBeScheduled(remainingPrincipalAmt);
|
|
||||||
loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
|
|
||||||
scheduleParams.setOutstandingBalance(remainingPrincipalAmt);
|
|
||||||
scheduleParams.setOutstandingBalanceAsPerRest(remainingPrincipalAmt);
|
|
||||||
loanApplicationTerms.resetFixedEmiAmount();
|
|
||||||
}
|
|
||||||
|
|
||||||
// charges which depends on total loan interest will be added to this
|
// charges which depends on total loan interest will be added to this
|
||||||
// set and handled separately after all installments generated
|
// set and handled separately after all installments generated
|
||||||
final Set<LoanCharge> nonCompoundingCharges = separateTotalCompoundingPercentageCharges(loanCharges);
|
final Set<LoanCharge> nonCompoundingCharges = separateTotalCompoundingPercentageCharges(loanCharges);
|
||||||
@@ -134,13 +113,8 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5 determine principal,interest of repayment period
|
// 5 determine principal,interest of repayment period
|
||||||
PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod(
|
PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod(loanApplicationTerms,
|
||||||
getPaymentPeriodsInOneYearCalculator(), currentPeriodParams.getInterestCalculationGraceOnRepaymentPeriodFraction(),
|
scheduleParams, mc);
|
||||||
scheduleParams.getTotalCumulativePrincipal().minus(scheduleParams.getReducePrincipal()),
|
|
||||||
scheduleParams.getTotalCumulativeInterest(), loanApplicationTerms.getTotalInterestDue(),
|
|
||||||
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(), scheduleParams.getOutstandingBalanceAsPerRest(),
|
|
||||||
loanApplicationTerms, scheduleParams.getPeriodNumber(), mc, null, scheduleParams.getCompoundingMap(), null,
|
|
||||||
scheduledDueDate, null);
|
|
||||||
|
|
||||||
// update cumulative fields for principal
|
// update cumulative fields for principal
|
||||||
currentPeriodParams.setPrincipalForThisPeriod(principalInterestForThisPeriod.principal());
|
currentPeriodParams.setPrincipalForThisPeriod(principalInterestForThisPeriod.principal());
|
||||||
@@ -241,12 +215,8 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
|
|
||||||
public abstract PaymentPeriodsInOneYearCalculator getPaymentPeriodsInOneYearCalculator();
|
public abstract PaymentPeriodsInOneYearCalculator getPaymentPeriodsInOneYearCalculator();
|
||||||
|
|
||||||
public abstract PrincipalInterest calculatePrincipalInterestComponentsForPeriod(PaymentPeriodsInOneYearCalculator calculator,
|
public abstract PrincipalInterest calculatePrincipalInterestComponentsForPeriod(LoanApplicationTerms loanApplicationTerms,
|
||||||
BigDecimal interestCalculationGraceOnRepaymentPeriodFraction, Money totalCumulativePrincipal, Money totalCumulativeInterest,
|
LoanScheduleParams loanScheduleParams, MathContext mc);
|
||||||
Money totalInterestDueForLoan, Money cumulatingInterestPaymentDueToGrace, Money outstandingBalance,
|
|
||||||
LoanApplicationTerms loanApplicationTerms, int periodNumber, MathContext mc, TreeMap<LocalDate, Money> principalVariation,
|
|
||||||
Map<LocalDate, Money> compoundingMap, LocalDate periodStartDate, LocalDate periodEndDate,
|
|
||||||
Collection<LoanTermVariationsData> termVariations);
|
|
||||||
|
|
||||||
// Private, internal methods
|
// Private, internal methods
|
||||||
private BigDecimal deriveTotalChargesDueAtTimeOfDisbursement(final Set<LoanCharge> loanCharges) {
|
private BigDecimal deriveTotalChargesDueAtTimeOfDisbursement(final Set<LoanCharge> loanCharges) {
|
||||||
@@ -266,7 +236,8 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
Money principalToBeScheduled;
|
Money principalToBeScheduled;
|
||||||
if (loanApplicationTerms.isMultiDisburseLoan()) {
|
if (loanApplicationTerms.isMultiDisburseLoan()) {
|
||||||
if (loanApplicationTerms.getTotalDisbursedAmount().isGreaterThanZero()) {
|
if (loanApplicationTerms.getTotalDisbursedAmount().isGreaterThanZero()) {
|
||||||
principalToBeScheduled = loanApplicationTerms.getTotalMultiDisbursedAmount();
|
principalToBeScheduled = Money.of(loanApplicationTerms.getCurrency(),
|
||||||
|
loanApplicationTerms.getDisbursementDatas().get(0).getPrincipal());
|
||||||
} else if (loanApplicationTerms.getApprovedPrincipal().isGreaterThanZero()) {
|
} else if (loanApplicationTerms.getApprovedPrincipal().isGreaterThanZero()) {
|
||||||
principalToBeScheduled = loanApplicationTerms.getApprovedPrincipal();
|
principalToBeScheduled = loanApplicationTerms.getApprovedPrincipal();
|
||||||
} else {
|
} else {
|
||||||
@@ -300,6 +271,9 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
loanScheduleParams, loanApplicationTerms.getExpectedDisbursementDate(), disbursementData.getPrincipal());
|
loanScheduleParams, loanApplicationTerms.getExpectedDisbursementDate(), disbursementData.getPrincipal());
|
||||||
periods.add(downPaymentPeriod);
|
periods.add(downPaymentPeriod);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
loanScheduleParams.getDisburseDetailMap().put(disbursementData.disbursementDate(),
|
||||||
|
Money.of(loanApplicationTerms.getCurrency(), disbursementData.getPrincipal()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,14 +287,19 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
|
if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
|
||||||
downPaymentAmount = Money.roundToMultiplesOf(downPaymentAmount, loanApplicationTerms.getInstallmentAmountInMultiplesOf());
|
downPaymentAmount = Money.roundToMultiplesOf(downPaymentAmount, loanApplicationTerms.getInstallmentAmountInMultiplesOf());
|
||||||
}
|
}
|
||||||
LoanScheduleModelDownPaymentPeriod installment = LoanScheduleModelDownPaymentPeriod
|
LoanScheduleModelDownPaymentPeriod installment = LoanScheduleModelDownPaymentPeriod.downPayment(
|
||||||
.downPayment(scheduleParams.getInstalmentNumber(), date, downPaymentAmount, scheduleParams.getOutstandingBalance());
|
scheduleParams.getInstalmentNumber(), date, downPaymentAmount,
|
||||||
|
scheduleParams.getOutstandingBalance().minus(downPaymentAmount));
|
||||||
|
|
||||||
addLoanRepaymentScheduleInstallment(scheduleParams.getInstallments(), installment);
|
addLoanRepaymentScheduleInstallment(scheduleParams.getInstallments(), installment);
|
||||||
|
|
||||||
scheduleParams.incrementInstalmentNumber();
|
scheduleParams.incrementInstalmentNumber();
|
||||||
scheduleParams.addTotalRepaymentExpected(downPaymentAmount);
|
scheduleParams.addTotalRepaymentExpected(downPaymentAmount);
|
||||||
|
scheduleParams.reduceOutstandingBalance(downPaymentAmount);
|
||||||
|
scheduleParams.reduceOutstandingBalanceAsPerRest(downPaymentAmount);
|
||||||
|
scheduleParams.setPrincipalToBeScheduled(scheduleParams.getPrincipalToBeScheduled().minus(downPaymentAmount));
|
||||||
|
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().minus(downPaymentAmount));
|
||||||
|
loanApplicationTerms.resetFixedEmiAmount();
|
||||||
return installment;
|
return installment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,8 +324,9 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
private void processDisbursements(final LoanApplicationTerms loanApplicationTerms, final BigDecimal chargesDueAtTimeOfDisbursement,
|
private void processDisbursements(final LoanApplicationTerms loanApplicationTerms, final BigDecimal chargesDueAtTimeOfDisbursement,
|
||||||
LoanScheduleParams scheduleParams, final Collection<LoanScheduleModelPeriod> periods, final LocalDate scheduledDueDate) {
|
LoanScheduleParams scheduleParams, final Collection<LoanScheduleModelPeriod> periods, final LocalDate scheduledDueDate) {
|
||||||
for (Map.Entry<LocalDate, Money> disburseDetail : scheduleParams.getDisburseDetailMap().entrySet()) {
|
for (Map.Entry<LocalDate, Money> disburseDetail : scheduleParams.getDisburseDetailMap().entrySet()) {
|
||||||
if (disburseDetail.getKey().isAfter(scheduleParams.getPeriodStartDate())
|
if ((disburseDetail.getKey().isEqual(scheduleParams.getPeriodStartDate())
|
||||||
&& !disburseDetail.getKey().isAfter(scheduledDueDate)) {
|
|| disburseDetail.getKey().isAfter(scheduleParams.getPeriodStartDate()))
|
||||||
|
&& disburseDetail.getKey().isBefore(scheduledDueDate)) {
|
||||||
// validation check for amount not exceeds specified max
|
// validation check for amount not exceeds specified max
|
||||||
// amount as per the configuration
|
// amount as per the configuration
|
||||||
loanApplicationTerms.getMaxOutstandingBalance();
|
loanApplicationTerms.getMaxOutstandingBalance();
|
||||||
@@ -378,11 +358,10 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
}
|
}
|
||||||
// updates actual outstanding balance with new
|
// updates actual outstanding balance with new
|
||||||
// disbursement detail
|
// disbursement detail
|
||||||
Money remainingPrincipal = disburseDetail.getValue().minus(downPaymentAmt);
|
scheduleParams.addOutstandingBalance(disburseDetail.getValue());
|
||||||
scheduleParams.addOutstandingBalance(remainingPrincipal);
|
scheduleParams.addOutstandingBalanceAsPerRest(disburseDetail.getValue());
|
||||||
scheduleParams.addOutstandingBalanceAsPerRest(remainingPrincipal);
|
scheduleParams.addPrincipalToBeScheduled(disburseDetail.getValue());
|
||||||
scheduleParams.addPrincipalToBeScheduled(remainingPrincipal);
|
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().plus(disburseDetail.getValue()));
|
||||||
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().plus(remainingPrincipal));
|
|
||||||
loanApplicationTerms.resetFixedEmiAmount();
|
loanApplicationTerms.resetFixedEmiAmount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -585,43 +564,6 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
|
|||||||
return interestCharges;
|
return interestCharges;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal getDisbursementAmount(final LoanApplicationTerms loanApplicationTerms, LocalDate disbursementDate,
|
|
||||||
final Map<LocalDate, Money> disburseDetails, final boolean excludePastUnDisbursed) {
|
|
||||||
|
|
||||||
// this method relates to multi-disbursement loans
|
|
||||||
BigDecimal principal = BigDecimal.ZERO;
|
|
||||||
if (loanApplicationTerms.getDisbursementDatas().size() == 0) {
|
|
||||||
// non tranche loans have no disbursement data entries in submitted and approved status
|
|
||||||
// the appropriate approved amount or applied for amount is used to show a proposed schedule
|
|
||||||
if (loanApplicationTerms.getApprovedPrincipal().getAmount().compareTo(BigDecimal.ZERO) > 0) {
|
|
||||||
principal = loanApplicationTerms.getApprovedPrincipal().getAmount();
|
|
||||||
} else {
|
|
||||||
principal = loanApplicationTerms.getPrincipal().getAmount();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MonetaryCurrency currency = loanApplicationTerms.getPrincipal().getCurrency();
|
|
||||||
for (DisbursementData disbursementData : loanApplicationTerms.getDisbursementDatas()) {
|
|
||||||
if (disbursementData.disbursementDate().equals(disbursementDate)) {
|
|
||||||
principal = principal.add(disbursementData.getPrincipal());
|
|
||||||
} else if (!excludePastUnDisbursed || disbursementData.isDisbursed()
|
|
||||||
|| !disbursementData.disbursementDate().isBefore(DateUtils.getBusinessLocalDate())) {
|
|
||||||
/*
|
|
||||||
* JW: sums up amounts by disbursal date in case of side-effect issues. Original assumed that there
|
|
||||||
* were no duplicate disbursal dates and 'put' each amount into the map keyed by date
|
|
||||||
*/
|
|
||||||
Money previousSum = disburseDetails.get(disbursementData.disbursementDate());
|
|
||||||
BigDecimal sumToNow = BigDecimal.ZERO;
|
|
||||||
if (previousSum != null) {
|
|
||||||
sumToNow = previousSum.getAmount();
|
|
||||||
}
|
|
||||||
sumToNow = sumToNow.add(disbursementData.getPrincipal());
|
|
||||||
disburseDetails.put(disbursementData.disbursementDate(), Money.of(currency, sumToNow));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return principal;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateOutstandingBalance(LoanScheduleParams scheduleParams, ScheduleCurrentPeriodParams currentPeriodParams) {
|
private void updateOutstandingBalance(LoanScheduleParams scheduleParams, ScheduleCurrentPeriodParams currentPeriodParams) {
|
||||||
// update outstandingLoanBlance using current period
|
// update outstandingLoanBlance using current period
|
||||||
// 'principalDue'
|
// 'principalDue'
|
||||||
|
|||||||
+22
-17
@@ -20,13 +20,9 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleParams;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -47,21 +43,30 @@ public class ProgressiveLoanScheduleGenerator extends AbstractProgressiveLoanSch
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PrincipalInterest calculatePrincipalInterestComponentsForPeriod(PaymentPeriodsInOneYearCalculator calculator,
|
public PrincipalInterest calculatePrincipalInterestComponentsForPeriod(LoanApplicationTerms loanApplicationTerms,
|
||||||
BigDecimal interestCalculationGraceOnRepaymentPeriodFraction, Money totalCumulativePrincipal, Money totalCumulativeInterest,
|
LoanScheduleParams loanScheduleParams, MathContext mc) {
|
||||||
Money totalInterestDueForLoan, Money cumulatingInterestPaymentDueToGrace, Money outstandingBalance,
|
|
||||||
LoanApplicationTerms loanApplicationTerms, int periodNumber, MathContext mc, TreeMap<LocalDate, Money> principalVariation,
|
|
||||||
Map<LocalDate, Money> compoundingMap, LocalDate periodStartDate, LocalDate periodEndDate,
|
|
||||||
Collection<LoanTermVariationsData> termVariations) {
|
|
||||||
// TODO: handle interest calculation
|
// TODO: handle interest calculation
|
||||||
Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, outstandingBalance,
|
int periodNumber = loanScheduleParams.getPeriodNumber();
|
||||||
periodNumber, mc, Money.zero(loanApplicationTerms.getCurrency()));
|
BigDecimal fixedEMIAmount = loanApplicationTerms.getFixedEmiAmount();
|
||||||
final Money totalCumulativePrincipalToDate = totalCumulativePrincipal.plus(principalForThisInstallment);
|
Money calculatedPrincipal;
|
||||||
|
if (fixedEMIAmount == null) {
|
||||||
|
int noRemainingPeriod = loanApplicationTerms.getActualNoOfRepaymnets() - periodNumber + 1;
|
||||||
|
calculatedPrincipal = loanScheduleParams.getOutstandingBalance().dividedBy(noRemainingPeriod, mc.getRoundingMode());
|
||||||
|
if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
|
||||||
|
calculatedPrincipal = Money.roundToMultiplesOf(calculatedPrincipal,
|
||||||
|
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
|
||||||
|
}
|
||||||
|
loanApplicationTerms.setFixedEmiAmount(calculatedPrincipal.getAmount());
|
||||||
|
} else {
|
||||||
|
calculatedPrincipal = Money.of(loanApplicationTerms.getCurrency(), fixedEMIAmount);
|
||||||
|
}
|
||||||
// adjust if needed
|
// adjust if needed
|
||||||
principalForThisInstallment = loanApplicationTerms.adjustPrincipalIfLastRepaymentPeriod(principalForThisInstallment,
|
if (periodNumber == loanApplicationTerms.getActualNoOfRepaymnets()) {
|
||||||
totalCumulativePrincipalToDate, periodNumber);
|
Money remainingAmount = loanScheduleParams.getOutstandingBalance().minus(calculatedPrincipal);
|
||||||
|
calculatedPrincipal = calculatedPrincipal.plus(remainingAmount);
|
||||||
|
}
|
||||||
|
|
||||||
return new PrincipalInterest(principalForThisInstallment, Money.zero(loanApplicationTerms.getCurrency()),
|
return new PrincipalInterest(calculatedPrincipal, Money.zero(loanApplicationTerms.getCurrency()),
|
||||||
Money.zero(loanApplicationTerms.getCurrency()));
|
Money.zero(loanApplicationTerms.getCurrency()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -23,13 +23,14 @@ import java.util.Map;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
|
import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||||
|
|
||||||
public interface LoanScheduleHistoryReadPlatformService {
|
public interface LoanScheduleHistoryReadPlatformService {
|
||||||
|
|
||||||
Integer fetchCurrentVersionNumber(Long loanId);
|
Integer fetchCurrentVersionNumber(Long loanId);
|
||||||
|
|
||||||
LoanScheduleData retrieveRepaymentArchiveSchedule(Long loanId, RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
|
LoanScheduleData retrieveRepaymentArchiveSchedule(Long loanId, RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
|
||||||
Collection<DisbursementData> disbursementData);
|
Collection<DisbursementData> disbursementData, LoanScheduleType loanScheduleType);
|
||||||
|
|
||||||
Map<String, Object> fetchOldAuditDates(Long id);
|
Map<String, Object> fetchOldAuditDates(Long id);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -37,6 +37,7 @@ import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLo
|
|||||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.EmptyResultDataAccessException;
|
import org.springframework.dao.EmptyResultDataAccessException;
|
||||||
@@ -68,7 +69,8 @@ public class LoanScheduleHistoryReadPlatformServiceImpl implements LoanScheduleH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanScheduleData retrieveRepaymentArchiveSchedule(final Long loanId,
|
public LoanScheduleData retrieveRepaymentArchiveSchedule(final Long loanId,
|
||||||
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection<DisbursementData> disbursementData) {
|
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection<DisbursementData> disbursementData,
|
||||||
|
LoanScheduleType loanScheduleType) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
@@ -77,7 +79,7 @@ public class LoanScheduleHistoryReadPlatformServiceImpl implements LoanScheduleH
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final LoanScheduleArchiveResultSetExtractor fullResultsetExtractor = new LoanScheduleArchiveResultSetExtractor(
|
final LoanScheduleArchiveResultSetExtractor fullResultsetExtractor = new LoanScheduleArchiveResultSetExtractor(
|
||||||
repaymentScheduleRelatedLoanData, disbursementData);
|
repaymentScheduleRelatedLoanData, disbursementData, loanScheduleType);
|
||||||
final String sql = "select " + fullResultsetExtractor.schema()
|
final String sql = "select " + fullResultsetExtractor.schema()
|
||||||
+ " where ls.loan_id = ? and ls.version = ? order by ls.loan_id, ls.installment";
|
+ " where ls.loan_id = ? and ls.version = ? order by ls.loan_id, ls.installment";
|
||||||
|
|
||||||
@@ -99,17 +101,19 @@ public class LoanScheduleHistoryReadPlatformServiceImpl implements LoanScheduleH
|
|||||||
private final DisbursementData disbursement;
|
private final DisbursementData disbursement;
|
||||||
private final BigDecimal totalFeeChargesDueAtDisbursement;
|
private final BigDecimal totalFeeChargesDueAtDisbursement;
|
||||||
private final Collection<DisbursementData> disbursementData;
|
private final Collection<DisbursementData> disbursementData;
|
||||||
|
private final LoanScheduleType loanScheduleType;
|
||||||
private LocalDate lastDueDate;
|
private LocalDate lastDueDate;
|
||||||
private BigDecimal outstandingLoanPrincipalBalance;
|
private BigDecimal outstandingLoanPrincipalBalance;
|
||||||
|
|
||||||
LoanScheduleArchiveResultSetExtractor(final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
|
LoanScheduleArchiveResultSetExtractor(final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
|
||||||
Collection<DisbursementData> disbursementData) {
|
Collection<DisbursementData> disbursementData, LoanScheduleType loanScheduleType) {
|
||||||
this.currency = repaymentScheduleRelatedLoanData.getCurrency();
|
this.currency = repaymentScheduleRelatedLoanData.getCurrency();
|
||||||
this.disbursement = repaymentScheduleRelatedLoanData.disbursementData();
|
this.disbursement = repaymentScheduleRelatedLoanData.disbursementData();
|
||||||
this.totalFeeChargesDueAtDisbursement = repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement();
|
this.totalFeeChargesDueAtDisbursement = repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement();
|
||||||
this.lastDueDate = this.disbursement.disbursementDate();
|
this.lastDueDate = this.disbursement.disbursementDate();
|
||||||
this.outstandingLoanPrincipalBalance = this.disbursement.getPrincipal();
|
this.outstandingLoanPrincipalBalance = this.disbursement.getPrincipal();
|
||||||
this.disbursementData = disbursementData;
|
this.disbursementData = disbursementData;
|
||||||
|
this.loanScheduleType = loanScheduleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String schema() {
|
public String schema() {
|
||||||
@@ -163,7 +167,7 @@ public class LoanScheduleHistoryReadPlatformServiceImpl implements LoanScheduleH
|
|||||||
data.getPrincipal(), this.totalFeeChargesDueAtDisbursement, data.isDisbursed());
|
data.getPrincipal(), this.totalFeeChargesDueAtDisbursement, data.isDisbursed());
|
||||||
periods.add(periodData);
|
periods.add(periodData);
|
||||||
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
|
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
|
||||||
} else if (data.isDueForDisbursement(fromDate, dueDate)
|
} else if (data.isDueForDisbursement(loanScheduleType, fromDate, dueDate)
|
||||||
&& this.outstandingLoanPrincipalBalance.compareTo(BigDecimal.ZERO) > 0) {
|
&& this.outstandingLoanPrincipalBalance.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
principal = principal.add(data.getPrincipal());
|
principal = principal.add(data.getPrincipal());
|
||||||
final LoanSchedulePeriodData periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(),
|
final LoanSchedulePeriodData periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(),
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.service;
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -43,6 +42,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||||
|
|
||||||
public interface LoanReadPlatformService {
|
public interface LoanReadPlatformService {
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public interface LoanReadPlatformService {
|
|||||||
LoanAccountData fetchRepaymentScheduleData(LoanAccountData accountData);
|
LoanAccountData fetchRepaymentScheduleData(LoanAccountData accountData);
|
||||||
|
|
||||||
LoanScheduleData retrieveRepaymentSchedule(Long loanId, RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData,
|
LoanScheduleData retrieveRepaymentSchedule(Long loanId, RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData,
|
||||||
Collection<DisbursementData> disbursementData, boolean isInterestRecalculationEnabled, BigDecimal totalPaidFeeCharges);
|
Collection<DisbursementData> disbursementData, boolean isInterestRecalculationEnabled, LoanScheduleType loanScheduleType);
|
||||||
|
|
||||||
Collection<LoanTransactionData> retrieveLoanTransactions(Long loanId);
|
Collection<LoanTransactionData> retrieveLoanTransactions(Long loanId);
|
||||||
|
|
||||||
|
|||||||
+48
-58
@@ -245,7 +245,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
final Collection<DisbursementData> disbursementData = retrieveLoanDisbursementDetails(accountData.getId());
|
final Collection<DisbursementData> disbursementData = retrieveLoanDisbursementDetails(accountData.getId());
|
||||||
final LoanScheduleData repaymentSchedule = retrieveRepaymentSchedule(accountData.getId(), repaymentScheduleRelatedData,
|
final LoanScheduleData repaymentSchedule = retrieveRepaymentSchedule(accountData.getId(), repaymentScheduleRelatedData,
|
||||||
disbursementData, accountData.isInterestRecalculationEnabled(),
|
disbursementData, accountData.isInterestRecalculationEnabled(),
|
||||||
accountData.getSummary() != null ? accountData.getSummary().getFeeChargesPaid() : BigDecimal.ZERO);
|
LoanScheduleType.fromEnumOptionData(accountData.getLoanScheduleType()));
|
||||||
accountData.setRepaymentSchedule(repaymentSchedule);
|
accountData.setRepaymentSchedule(repaymentSchedule);
|
||||||
return accountData;
|
return accountData;
|
||||||
}
|
}
|
||||||
@@ -253,13 +253,13 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
@Override
|
@Override
|
||||||
public LoanScheduleData retrieveRepaymentSchedule(final Long loanId,
|
public LoanScheduleData retrieveRepaymentSchedule(final Long loanId,
|
||||||
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection<DisbursementData> disbursementData,
|
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection<DisbursementData> disbursementData,
|
||||||
boolean isInterestRecalculationEnabled, BigDecimal totalPaidFeeCharges) {
|
boolean isInterestRecalculationEnabled, LoanScheduleType loanScheduleType) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
final LoanScheduleResultSetExtractor fullResultsetExtractor = new LoanScheduleResultSetExtractor(
|
final LoanScheduleResultSetExtractor fullResultsetExtractor = new LoanScheduleResultSetExtractor(
|
||||||
repaymentScheduleRelatedLoanData, disbursementData, isInterestRecalculationEnabled);
|
repaymentScheduleRelatedLoanData, disbursementData, isInterestRecalculationEnabled, loanScheduleType);
|
||||||
final String sql = "select " + fullResultsetExtractor.schema() + " where ls.loan_id = ? order by ls.loan_id, ls.installment";
|
final String sql = "select " + fullResultsetExtractor.schema() + " where ls.loan_id = ? order by ls.loan_id, ls.installment";
|
||||||
|
|
||||||
return this.jdbcTemplate.query(sql, fullResultsetExtractor, loanId); // NOSONAR
|
return this.jdbcTemplate.query(sql, fullResultsetExtractor, loanId); // NOSONAR
|
||||||
@@ -1123,19 +1123,21 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
private final DisbursementData disbursement;
|
private final DisbursementData disbursement;
|
||||||
private final BigDecimal totalFeeChargesDueAtDisbursement;
|
private final BigDecimal totalFeeChargesDueAtDisbursement;
|
||||||
private final Collection<DisbursementData> disbursementData;
|
private final Collection<DisbursementData> disbursementData;
|
||||||
|
private final LoanScheduleType loanScheduleType;
|
||||||
private LocalDate lastDueDate;
|
private LocalDate lastDueDate;
|
||||||
private BigDecimal outstandingLoanPrincipalBalance;
|
private BigDecimal outstandingLoanPrincipalBalance;
|
||||||
private boolean excludePastUndisbursed;
|
private boolean excludePastUnDisbursed;
|
||||||
|
|
||||||
LoanScheduleResultSetExtractor(final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
|
LoanScheduleResultSetExtractor(final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
|
||||||
Collection<DisbursementData> disbursementData, boolean isInterestRecalculationEnabled) {
|
Collection<DisbursementData> disbursementData, boolean isInterestRecalculationEnabled, LoanScheduleType loanScheduleType) {
|
||||||
this.currency = repaymentScheduleRelatedLoanData.getCurrency();
|
this.currency = repaymentScheduleRelatedLoanData.getCurrency();
|
||||||
this.disbursement = repaymentScheduleRelatedLoanData.disbursementData();
|
this.disbursement = repaymentScheduleRelatedLoanData.disbursementData();
|
||||||
this.totalFeeChargesDueAtDisbursement = repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement();
|
this.totalFeeChargesDueAtDisbursement = repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement();
|
||||||
this.lastDueDate = this.disbursement.disbursementDate();
|
this.lastDueDate = this.disbursement.disbursementDate();
|
||||||
this.outstandingLoanPrincipalBalance = this.disbursement.getPrincipal();
|
this.outstandingLoanPrincipalBalance = this.disbursement.getPrincipal();
|
||||||
this.disbursementData = disbursementData;
|
this.disbursementData = disbursementData;
|
||||||
this.excludePastUndisbursed = isInterestRecalculationEnabled;
|
this.excludePastUnDisbursed = isInterestRecalculationEnabled;
|
||||||
|
this.loanScheduleType = loanScheduleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String schema() {
|
public String schema() {
|
||||||
@@ -1160,7 +1162,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
this.disbursement.disbursementDate(), this.disbursement.getPrincipal(), this.totalFeeChargesDueAtDisbursement,
|
this.disbursement.disbursementDate(), this.disbursement.getPrincipal(), this.totalFeeChargesDueAtDisbursement,
|
||||||
this.disbursement.isDisbursed());
|
this.disbursement.isDisbursed());
|
||||||
|
|
||||||
final Collection<LoanSchedulePeriodData> periods = new ArrayList<>();
|
final List<LoanSchedulePeriodData> periods = new ArrayList<>();
|
||||||
final MonetaryCurrency monCurrency = new MonetaryCurrency(this.currency.getCode(), this.currency.getDecimalPlaces(),
|
final MonetaryCurrency monCurrency = new MonetaryCurrency(this.currency.getCode(), this.currency.getDecimalPlaces(),
|
||||||
this.currency.getInMultiplesOf());
|
this.currency.getInMultiplesOf());
|
||||||
BigDecimal totalPrincipalDisbursed = BigDecimal.ZERO;
|
BigDecimal totalPrincipalDisbursed = BigDecimal.ZERO;
|
||||||
@@ -1170,7 +1172,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
totalPrincipalDisbursed = Money.of(monCurrency, this.disbursement.getPrincipal()).getAmount();
|
totalPrincipalDisbursed = Money.of(monCurrency, this.disbursement.getPrincipal()).getAmount();
|
||||||
} else {
|
} else {
|
||||||
if (!this.disbursement.isDisbursed()) {
|
if (!this.disbursement.isDisbursed()) {
|
||||||
excludePastUndisbursed = false;
|
excludePastUnDisbursed = false;
|
||||||
}
|
}
|
||||||
for (DisbursementData data : disbursementData) {
|
for (DisbursementData data : disbursementData) {
|
||||||
if (data.getChargeAmount() != null) {
|
if (data.getChargeAmount() != null) {
|
||||||
@@ -1211,56 +1213,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
final LocalDate obligationsMetOnDate = JdbcSupport.getLocalDate(rs, "obligationsMetOnDate");
|
final LocalDate obligationsMetOnDate = JdbcSupport.getLocalDate(rs, "obligationsMetOnDate");
|
||||||
final boolean complete = rs.getBoolean("complete");
|
final boolean complete = rs.getBoolean("complete");
|
||||||
final boolean isAdditional = rs.getBoolean("isAdditional");
|
final boolean isAdditional = rs.getBoolean("isAdditional");
|
||||||
BigDecimal principal = BigDecimal.ZERO;
|
BigDecimal disbursedAmount = BigDecimal.ZERO;
|
||||||
if (!isAdditional) {
|
if (!isAdditional) {
|
||||||
for (final DisbursementData data : disbursementData) {
|
disbursedAmount = processDisbursementData(loanScheduleType, disbursementData, fromDate, dueDate, disbursementPeriodIds,
|
||||||
if (fromDate.equals(this.disbursement.disbursementDate()) && data.disbursementDate().equals(fromDate)
|
disbursementChargeAmount, waivedChargeAmount, periods);
|
||||||
&& !disbursementPeriodIds.contains(data.getId())) {
|
|
||||||
principal = principal.add(data.getPrincipal());
|
|
||||||
LoanSchedulePeriodData periodData = null;
|
|
||||||
if (data.getChargeAmount() == null) {
|
|
||||||
periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), data.getPrincipal(),
|
|
||||||
disbursementChargeAmount, data.isDisbursed());
|
|
||||||
} else {
|
|
||||||
periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), data.getPrincipal(),
|
|
||||||
disbursementChargeAmount.add(data.getChargeAmount()).subtract(waivedChargeAmount),
|
|
||||||
data.isDisbursed());
|
|
||||||
}
|
|
||||||
periods.add(periodData);
|
|
||||||
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
|
|
||||||
disbursementPeriodIds.add(data.getId());
|
|
||||||
} else if (data.isDueForDisbursement(fromDate, dueDate) && !disbursementPeriodIds.contains(data.getId())) {
|
|
||||||
if (!excludePastUndisbursed || data.isDisbursed() || !DateUtils.isBeforeBusinessDate(data.disbursementDate())) {
|
|
||||||
principal = principal.add(data.getPrincipal());
|
|
||||||
LoanSchedulePeriodData periodData;
|
|
||||||
if (data.getChargeAmount() == null) {
|
|
||||||
periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), data.getPrincipal(),
|
|
||||||
BigDecimal.ZERO, data.isDisbursed());
|
|
||||||
} else {
|
|
||||||
periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), data.getPrincipal(),
|
|
||||||
data.getChargeAmount(), data.isDisbursed());
|
|
||||||
}
|
|
||||||
periods.add(periodData);
|
|
||||||
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
|
|
||||||
disbursementPeriodIds.add(data.getId());
|
|
||||||
}
|
|
||||||
} else if (fromDate.equals(dueDate) && data.disbursementDate().equals(fromDate)
|
|
||||||
&& !disbursementPeriodIds.contains(data.getId())) {
|
|
||||||
principal = principal.add(data.getPrincipal());
|
|
||||||
LoanSchedulePeriodData periodData = null;
|
|
||||||
if (data.getChargeAmount() == null) {
|
|
||||||
periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), data.getPrincipal(),
|
|
||||||
disbursementChargeAmount, data.isDisbursed());
|
|
||||||
} else {
|
|
||||||
periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), data.getPrincipal(),
|
|
||||||
disbursementChargeAmount.add(data.getChargeAmount()).subtract(waivedChargeAmount),
|
|
||||||
data.isDisbursed());
|
|
||||||
}
|
|
||||||
periods.add(periodData);
|
|
||||||
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
|
|
||||||
disbursementPeriodIds.add(data.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Add the Charge back or Credits to the initial amount to avoid negative balance
|
// Add the Charge back or Credits to the initial amount to avoid negative balance
|
||||||
final BigDecimal credits = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalCredits");
|
final BigDecimal credits = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalCredits");
|
||||||
@@ -1268,7 +1225,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(credits);
|
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(credits);
|
||||||
}
|
}
|
||||||
|
|
||||||
totalPrincipalDisbursed = totalPrincipalDisbursed.add(principal);
|
totalPrincipalDisbursed = totalPrincipalDisbursed.add(disbursedAmount);
|
||||||
|
|
||||||
Integer daysInPeriod = 0;
|
Integer daysInPeriod = 0;
|
||||||
if (fromDate != null) {
|
if (fromDate != null) {
|
||||||
@@ -1379,6 +1336,39 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
totalPaidLate.getAmount(), totalOutstanding.getAmount(), totalCredits.getAmount());
|
totalPaidLate.getAmount(), totalOutstanding.getAmount(), totalCredits.getAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BigDecimal processDisbursementData(LoanScheduleType loanScheduleType, Collection<DisbursementData> disbursementData,
|
||||||
|
LocalDate fromDate, LocalDate dueDate, Set<Long> disbursementPeriodIds, BigDecimal disbursementChargeAmount,
|
||||||
|
BigDecimal waivedChargeAmount, List<LoanSchedulePeriodData> periods) {
|
||||||
|
BigDecimal disbursedAmount = BigDecimal.ZERO;
|
||||||
|
for (final DisbursementData data : disbursementData) {
|
||||||
|
boolean isDueForDisbursement = data.isDueForDisbursement(loanScheduleType, fromDate, dueDate);
|
||||||
|
if (((fromDate.equals(this.disbursement.disbursementDate()) && data.disbursementDate().equals(fromDate))
|
||||||
|
|| (fromDate.equals(dueDate) && data.disbursementDate().equals(fromDate))
|
||||||
|
|| canAddDisbursementData(data, isDueForDisbursement, excludePastUnDisbursed))
|
||||||
|
&& !disbursementPeriodIds.contains(data.getId())) {
|
||||||
|
disbursedAmount = disbursedAmount.add(data.getPrincipal());
|
||||||
|
LoanSchedulePeriodData periodData = createLoanSchedulePeriodData(data, disbursementChargeAmount, waivedChargeAmount);
|
||||||
|
periods.add(periodData);
|
||||||
|
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(periodData.getPrincipalDisbursed());
|
||||||
|
disbursementPeriodIds.add(data.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return disbursedAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoanSchedulePeriodData createLoanSchedulePeriodData(final DisbursementData data, BigDecimal disbursementChargeAmount,
|
||||||
|
BigDecimal waivedChargeAmount) {
|
||||||
|
BigDecimal chargeAmount = data.getChargeAmount() == null ? disbursementChargeAmount
|
||||||
|
: disbursementChargeAmount.add(data.getChargeAmount()).subtract(waivedChargeAmount);
|
||||||
|
return LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), data.getPrincipal(), chargeAmount,
|
||||||
|
data.isDisbursed());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canAddDisbursementData(DisbursementData data, boolean isDueForDisbursement, boolean excludePastUnDisbursed) {
|
||||||
|
return (!excludePastUnDisbursed || data.isDisbursed() || !DateUtils.isBeforeBusinessDate(data.disbursementDate()))
|
||||||
|
&& isDueForDisbursement;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class LoanTransactionsMapper implements RowMapper<LoanTransactionData> {
|
private static final class LoanTransactionsMapper implements RowMapper<LoanTransactionData> {
|
||||||
|
|||||||
+327
-254
File diff suppressed because it is too large
Load Diff
+5
@@ -498,4 +498,9 @@ public abstract class BaseLoanIntegrationTest {
|
|||||||
public static final Integer MONTHS = 2;
|
public static final Integer MONTHS = 2;
|
||||||
public static final Integer YEARS = 3;
|
public static final Integer YEARS = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateBusinessDate(String date) {
|
||||||
|
businessDateHelper.updateBusinessDate(
|
||||||
|
new BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-25
@@ -18,9 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.integrationtests;
|
package org.apache.fineract.integrationtests;
|
||||||
|
|
||||||
import static java.lang.Boolean.FALSE;
|
|
||||||
import static java.lang.Boolean.TRUE;
|
|
||||||
import static org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.BUSINESS_DATE;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
@@ -42,7 +39,6 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.apache.fineract.client.models.AdvancedPaymentData;
|
import org.apache.fineract.client.models.AdvancedPaymentData;
|
||||||
import org.apache.fineract.client.models.AllowAttributeOverrides;
|
import org.apache.fineract.client.models.AllowAttributeOverrides;
|
||||||
import org.apache.fineract.client.models.BusinessDateRequest;
|
|
||||||
import org.apache.fineract.client.models.ChargeData;
|
import org.apache.fineract.client.models.ChargeData;
|
||||||
import org.apache.fineract.client.models.ChargeToGLAccountMapper;
|
import org.apache.fineract.client.models.ChargeToGLAccountMapper;
|
||||||
import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
|
import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
|
||||||
@@ -61,7 +57,6 @@ import org.apache.fineract.client.models.PostPaymentTypesRequest;
|
|||||||
import org.apache.fineract.client.models.PostPaymentTypesResponse;
|
import org.apache.fineract.client.models.PostPaymentTypesResponse;
|
||||||
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
||||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
|
|
||||||
import org.apache.fineract.integrationtests.common.PaymentTypeHelper;
|
import org.apache.fineract.integrationtests.common.PaymentTypeHelper;
|
||||||
import org.apache.fineract.integrationtests.common.Utils;
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
import org.apache.fineract.integrationtests.common.accounting.Account;
|
import org.apache.fineract.integrationtests.common.accounting.Account;
|
||||||
@@ -83,7 +78,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
@ExtendWith(LoanTestLifecycleExtension.class)
|
@ExtendWith(LoanTestLifecycleExtension.class)
|
||||||
public class LoanAccountChargeOffWithAdvancedPaymentAllocationTest {
|
public class LoanAccountChargeOffWithAdvancedPaymentAllocationTest extends BaseLoanIntegrationTest {
|
||||||
|
|
||||||
private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
|
private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
|
||||||
private ResponseSpecification responseSpec;
|
private ResponseSpecification responseSpec;
|
||||||
@@ -777,23 +772,4 @@ public class LoanAccountChargeOffWithAdvancedPaymentAllocationTest {
|
|||||||
return paymentAllocationOrder;
|
return paymentAllocationOrder;
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runAt(String date, Runnable runnable) {
|
|
||||||
try {
|
|
||||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, 42, true);
|
|
||||||
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, TRUE);
|
|
||||||
businessDateHelper.updateBusinessDate(
|
|
||||||
new BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
|
|
||||||
runnable.run();
|
|
||||||
} finally {
|
|
||||||
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, FALSE);
|
|
||||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, 42, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateBusinessDate(String date) {
|
|
||||||
businessDateHelper.updateBusinessDate(
|
|
||||||
new BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-27
@@ -724,16 +724,16 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
|
|||||||
// down payment period [1]
|
// down payment period [1]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
||||||
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
|
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
|
||||||
// disbursement period [2]
|
// regular installment [2]
|
||||||
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 200.0);
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 75.0, 50.0, 50.0, 25.0, 0.0, 0.0, 0.0, 0.0,
|
||||||
// down payment period [3]
|
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 2, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
|
||||||
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
|
||||||
// regular installment [4]
|
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 150.0, 0.0, 0.0, 150.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
|
false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
|
||||||
|
// disbursement period [3]
|
||||||
|
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0);
|
||||||
|
// down payment period [4]
|
||||||
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 50.0, 0.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, false,
|
||||||
|
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
||||||
// regular installment [5]
|
// regular installment [5]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 150.0, 0.0, 0.0, 150.0, 0.0, 0.0, 0.0, 0.0,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
|
||||||
false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
|
false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
|
||||||
|
|
||||||
// same day third disbursement with overlapping installment i.e same due date as regular repayment due date
|
// same day third disbursement with overlapping installment i.e same due date as regular repayment due date
|
||||||
@@ -758,21 +758,21 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
|
|||||||
// down payment period [1]
|
// down payment period [1]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
||||||
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
|
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
|
||||||
// disbursement period [2]
|
// regular installment [2]
|
||||||
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 200.0);
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 75.0, 75.0, 75.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
||||||
|
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
|
||||||
// disbursement period [3]
|
// disbursement period [3]
|
||||||
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0);
|
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0);
|
||||||
// down payment period [4]
|
// disbursement period [4]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(4), LocalDate.of(2023, 4, 3), 200.0);
|
||||||
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
|
||||||
// down payment period [5]
|
// down payment period [5]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 50.0, 25.0, 25.0, 25.0, 0.0, 0.0, 0.0, 0.0,
|
||||||
|
false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
||||||
|
// down payment period [6]
|
||||||
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 50.0, 0.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, false,
|
||||||
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
||||||
// regular installment [6]
|
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
|
|
||||||
// regular installment [7]
|
// regular installment [7]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 375.0, 0.0, 0.0, 375.0, 0.0, 0.0, 0.0, 0.0,
|
||||||
false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
|
false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
|
||||||
|
|
||||||
// make repayment for fully paying and verify that regular installment gets fully paid on 3rd april
|
// make repayment for fully paying and verify that regular installment gets fully paid on 3rd april
|
||||||
@@ -791,21 +791,21 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
|
|||||||
// down payment period [1]
|
// down payment period [1]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
||||||
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
|
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
|
||||||
// disbursement period [2]
|
// regular installment [2]
|
||||||
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 200.0);
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 75.0, 75.0, 75.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
||||||
|
LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
|
||||||
// disbursement period [3]
|
// disbursement period [3]
|
||||||
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0);
|
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0);
|
||||||
// down payment period [4]
|
// disbursement period [4]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(4), LocalDate.of(2023, 4, 3), 200.0);
|
||||||
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
|
||||||
// down payment period [5]
|
// down payment period [5]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
||||||
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
||||||
// regular installment [6]
|
// down payment period [6]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 225.0, 225.0, 225.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
|
||||||
true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
|
LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
|
||||||
// regular installment [7]
|
// regular installment [7]
|
||||||
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
|
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 375.0, 150.0, 150.0, 225.0, 0.0, 0.0, 0.0, 0.0,
|
||||||
false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
|
false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
+42
-42
@@ -124,7 +124,7 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
// Set business date
|
// Set business date
|
||||||
LocalDate businessDate = LocalDate.of(2023, 03, 3);
|
LocalDate businessDate = LocalDate.of(2023, 3, 3);
|
||||||
|
|
||||||
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
|
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
|
||||||
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
|
||||||
@@ -169,25 +169,25 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
|
|
||||||
// first period [2023-03-03 to 2023-04-03]
|
// first period [2023-03-03 to 2023-04-03]
|
||||||
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 03, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 04, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
||||||
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second period [2023-04-03 to 2023-05-03]
|
// second period [2023-04-03 to 2023-05-03]
|
||||||
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 04, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 05, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
||||||
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// third period [2023-05-03 to 2023-06-03]
|
// third period [2023-05-03 to 2023-06-03]
|
||||||
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 05, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 06, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
assertEquals(LocalDate.of(2023, 6, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
||||||
assertEquals(333.34, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.34, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// first disbursement on a future date (7 March 2023)
|
// first disbursement on a future date (7 March 2023)
|
||||||
|
|
||||||
LocalDate disbursementDate = LocalDate.of(2023, 03, 7);
|
LocalDate disbursementDate = LocalDate.of(2023, 3, 7);
|
||||||
|
|
||||||
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
||||||
|
|
||||||
@@ -208,25 +208,25 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
|
|
||||||
// first period [2023-03-03 to 2023-04-03]
|
// first period [2023-03-03 to 2023-04-03]
|
||||||
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 03, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 04, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
||||||
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second period [2023-04-03 to 2023-05-03]
|
// second period [2023-04-03 to 2023-05-03]
|
||||||
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 04, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 05, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
||||||
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// third period [2023-05-03 to 2023-06-03]
|
// third period [2023-05-03 to 2023-06-03]
|
||||||
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 05, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 06, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
assertEquals(LocalDate.of(2023, 6, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
||||||
assertEquals(166.66, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
assertEquals(166.66, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second disbursement next month (7 April 2023)
|
// second disbursement next month (7 April 2023)
|
||||||
|
|
||||||
disbursementDate = LocalDate.of(2023, 04, 7);
|
disbursementDate = LocalDate.of(2023, 4, 7);
|
||||||
|
|
||||||
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
||||||
|
|
||||||
@@ -248,20 +248,20 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
|
|
||||||
// first period [2023-03-03 to 2023-04-03]
|
// first period [2023-03-03 to 2023-04-03]
|
||||||
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 03, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 04, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
||||||
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second period [2023-04-03 to 2023-05-03]
|
// second period [2023-04-03 to 2023-05-03]
|
||||||
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 04, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 05, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
||||||
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// third period [2023-05-03 to 2023-06-03]
|
// third period [2023-05-03 to 2023-06-03]
|
||||||
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod());
|
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 05, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
|
assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 06, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
|
assertEquals(LocalDate.of(2023, 6, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
|
||||||
assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod());
|
assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
@@ -278,7 +278,7 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
// Set business date
|
// Set business date
|
||||||
LocalDate businessDate = LocalDate.of(2023, 03, 3);
|
LocalDate businessDate = LocalDate.of(2023, 3, 3);
|
||||||
|
|
||||||
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
|
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
|
||||||
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
|
||||||
@@ -324,25 +324,25 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
|
|
||||||
// first period [2023-03-07 to 2023-04-07]
|
// first period [2023-03-07 to 2023-04-07]
|
||||||
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 03, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
assertEquals(LocalDate.of(2023, 3, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 04, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
||||||
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second period [2023-04-07 to 2023-05-07]
|
// second period [2023-04-07 to 2023-05-07]
|
||||||
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 04, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 05, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
||||||
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// third period [2023-05-07 to 2023-06-07]
|
// third period [2023-05-07 to 2023-06-07]
|
||||||
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 05, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 06, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
assertEquals(LocalDate.of(2023, 6, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
||||||
assertEquals(333.34, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.34, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// first disbursement (7 March 2023)
|
// first disbursement (7 March 2023)
|
||||||
|
|
||||||
LocalDate disbursementDate = LocalDate.of(2023, 03, 7);
|
LocalDate disbursementDate = LocalDate.of(2023, 3, 7);
|
||||||
|
|
||||||
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
||||||
|
|
||||||
@@ -364,25 +364,25 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
|
|
||||||
// first period [2023-03-07 to 2023-04-07]
|
// first period [2023-03-07 to 2023-04-07]
|
||||||
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 03, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
assertEquals(LocalDate.of(2023, 3, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 04, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
|
||||||
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second period [2023-04-07 to 2023-05-07]
|
// second period [2023-04-07 to 2023-05-07]
|
||||||
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 04, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 05, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
||||||
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
assertEquals(166.67, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// third period [2023-05-07 to 2023-06-07]
|
// third period [2023-05-07 to 2023-06-07]
|
||||||
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 05, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 06, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
assertEquals(LocalDate.of(2023, 6, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
||||||
assertEquals(166.66, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
assertEquals(166.66, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second disbursement next month (7 April 2023)
|
// second disbursement next month (7 April 2023)
|
||||||
|
|
||||||
disbursementDate = LocalDate.of(2023, 04, 7);
|
disbursementDate = LocalDate.of(2023, 4, 7);
|
||||||
|
|
||||||
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate);
|
||||||
|
|
||||||
@@ -405,20 +405,20 @@ public class LoanProductRepaymentStartDateConfigurationTest {
|
|||||||
|
|
||||||
// first period [2023-03-07 to 2023-04-07]
|
// first period [2023-03-07 to 2023-04-07]
|
||||||
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 03, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
assertEquals(LocalDate.of(2023, 3, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 04, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
||||||
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// second period [2023-04-07 to 2023-05-07]
|
// second period [2023-04-07 to 2023-05-07]
|
||||||
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 04, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 05, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
|
||||||
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.33, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
// third period [2023-05-07 to 2023-06-07]
|
// third period [2023-05-07 to 2023-06-07]
|
||||||
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod());
|
assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 05, 7), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
|
assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
|
||||||
assertEquals(LocalDate.of(2023, 06, 7), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
|
assertEquals(LocalDate.of(2023, 6, 7), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
|
||||||
assertEquals(333.34, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod());
|
assertEquals(333.34, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user