MIFOSX-1422 : added number of days configuration for loan schedule
This commit is contained in:
+6
-2
@@ -12,8 +12,8 @@ import java.util.List;
|
|||||||
* <ul>
|
* <ul>
|
||||||
* People typically use either of the following settings when calculating there
|
* People typically use either of the following settings when calculating there
|
||||||
* interest using the daily method:
|
* interest using the daily method:
|
||||||
* <li>360 and</li>
|
* <li>Actual or</li>
|
||||||
* <li>365</li>
|
* <li>30</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public enum DaysInMonthType {
|
public enum DaysInMonthType {
|
||||||
@@ -64,4 +64,8 @@ public enum DaysInMonthType {
|
|||||||
}
|
}
|
||||||
return repaymentFrequencyType;
|
return repaymentFrequencyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDaysInMonth_30() {
|
||||||
|
return DaysInMonthType.DAYS_30.getValue().equals(this.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+7
-1
@@ -12,7 +12,9 @@ import java.util.List;
|
|||||||
* <ul>
|
* <ul>
|
||||||
* People typically use either of the following settings when calculating there
|
* People typically use either of the following settings when calculating there
|
||||||
* interest using the daily method:
|
* interest using the daily method:
|
||||||
* <li>360 and</li>
|
* <li>Actual or</li>
|
||||||
|
* <li>360 or</li>
|
||||||
|
* <li>364 or</li>
|
||||||
* <li>365</li>
|
* <li>365</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@@ -71,4 +73,8 @@ public enum DaysInYearType {
|
|||||||
}
|
}
|
||||||
return repaymentFrequencyType;
|
return repaymentFrequencyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActual() {
|
||||||
|
return DaysInYearType.ACTUAL.getValue().equals(this.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+17
-25
@@ -66,8 +66,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
final Collection<LoanScheduleModelPeriod> periods = createNewLoanScheduleListWithDisbursementDetails(numberOfRepayments,
|
final Collection<LoanScheduleModelPeriod> periods = createNewLoanScheduleListWithDisbursementDetails(numberOfRepayments,
|
||||||
loanApplicationTerms, chargesDueAtTimeOfDisbursement);
|
loanApplicationTerms, chargesDueAtTimeOfDisbursement);
|
||||||
|
|
||||||
// 4. Determine the total interest owed over the full loan.
|
// 4. Determine the total interest owed over the full loan for FLAT interest method .
|
||||||
final Money totalInterestChargedForFullLoanTerm = loanApplicationTerms.calculateTotalInterestCharged(
|
Money totalInterestChargedForFullLoanTerm = loanApplicationTerms.calculateTotalInterestCharged(
|
||||||
this.paymentPeriodsInOneYearCalculator, mc);
|
this.paymentPeriodsInOneYearCalculator, mc);
|
||||||
|
|
||||||
LocalDate periodStartDate = loanApplicationTerms.getExpectedDisbursementDate();
|
LocalDate periodStartDate = loanApplicationTerms.getExpectedDisbursementDate();
|
||||||
@@ -150,13 +150,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
|
|
||||||
Money feeChargesForInstallment = principalDisbursed.zero();
|
Money feeChargesForInstallment = principalDisbursed.zero();
|
||||||
Money penaltyChargesForInstallment = principalDisbursed.zero();
|
Money penaltyChargesForInstallment = principalDisbursed.zero();
|
||||||
if (!(loanApplicationTerms.isMultiDisburseLoan() && loanApplicationTerms.getFixedEmiAmount() != null)) {
|
|
||||||
// 7. determine fees and penalties
|
|
||||||
feeChargesForInstallment = cumulativeFeeChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, currency,
|
|
||||||
principalInterestForThisPeriod, principalDisbursed, totalInterestChargedForFullLoanTerm, numberOfRepayments);
|
|
||||||
penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, currency,
|
|
||||||
principalInterestForThisPeriod, principalDisbursed, totalInterestChargedForFullLoanTerm, numberOfRepayments);
|
|
||||||
}
|
|
||||||
// 8. sum up real totalInstallmentDue from components
|
// 8. sum up real totalInstallmentDue from components
|
||||||
final Money totalInstallmentDue = principalInterestForThisPeriod.principal() //
|
final Money totalInstallmentDue = principalInterestForThisPeriod.principal() //
|
||||||
.plus(principalInterestForThisPeriod.interest()) //
|
.plus(principalInterestForThisPeriod.interest()) //
|
||||||
@@ -187,22 +181,20 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
throw new MultiDisbursementDisbursementDateException(errorMsg);
|
throw new MultiDisbursementDisbursementDateException(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loanApplicationTerms.isMultiDisburseLoan() && loanApplicationTerms.getFixedEmiAmount() != null && !loanCharges.isEmpty()) {
|
// 7. determine fees and penalties
|
||||||
// 7. determine fees and penalties
|
for (LoanScheduleModelPeriod loanScheduleModelPeriod : periods) {
|
||||||
for (LoanScheduleModelPeriod loanScheduleModelPeriod : periods) {
|
if (loanScheduleModelPeriod.isRepaymentPeriod()) {
|
||||||
if (loanScheduleModelPeriod.isRepaymentPeriod()) {
|
PrincipalInterest principalInterest = new PrincipalInterest(Money.of(currency, loanScheduleModelPeriod.principalDue()),
|
||||||
PrincipalInterest principalInterest = new PrincipalInterest(Money.of(currency, loanScheduleModelPeriod.principalDue()),
|
Money.of(currency, loanScheduleModelPeriod.interestDue()), null);
|
||||||
Money.of(currency, loanScheduleModelPeriod.interestDue()), null);
|
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
||||||
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
loanScheduleModelPeriod.periodDueDate(), loanCharges, currency, principalInterest, principalDisbursed,
|
||||||
loanScheduleModelPeriod.periodDueDate(), loanCharges, currency, principalInterest, principalDisbursed,
|
totalCumulativeInterest, numberOfRepayments);
|
||||||
totalCumulativeInterest, numberOfRepayments);
|
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
||||||
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
loanScheduleModelPeriod.periodDueDate(), loanCharges, currency, principalInterest, principalDisbursed,
|
||||||
loanScheduleModelPeriod.periodDueDate(), loanCharges, currency, principalInterest, principalDisbursed,
|
totalCumulativeInterest, numberOfRepayments);
|
||||||
totalCumulativeInterest, numberOfRepayments);
|
totalFeeChargesCharged = totalFeeChargesCharged.add(feeChargesForInstallment.getAmount());
|
||||||
totalFeeChargesCharged = totalFeeChargesCharged.add(feeChargesForInstallment.getAmount());
|
totalPenaltyChargesCharged = totalPenaltyChargesCharged.add(penaltyChargesForInstallment.getAmount());
|
||||||
totalPenaltyChargesCharged = totalPenaltyChargesCharged.add(penaltyChargesForInstallment.getAmount());
|
loanScheduleModelPeriod.addLoanCharges(feeChargesForInstallment.getAmount(), penaltyChargesForInstallment.getAmount());
|
||||||
loanScheduleModelPeriod.addLoanCharges(feeChargesForInstallment.getAmount(), penaltyChargesForInstallment.getAmount());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+47
-47
@@ -16,6 +16,8 @@ import org.joda.time.LocalDate;
|
|||||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
import org.mifosplatform.portfolio.common.domain.DaysInMonthType;
|
||||||
|
import org.mifosplatform.portfolio.common.domain.DaysInYearType;
|
||||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||||
import org.mifosplatform.portfolio.loanaccount.data.DisbursementData;
|
import org.mifosplatform.portfolio.loanaccount.data.DisbursementData;
|
||||||
import org.mifosplatform.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.mifosplatform.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||||
@@ -102,6 +104,10 @@ public final class LoanApplicationTerms {
|
|||||||
|
|
||||||
private List<LoanTermVariationsData> emiAmountVariations;
|
private List<LoanTermVariationsData> emiAmountVariations;
|
||||||
|
|
||||||
|
private final DaysInMonthType daysInMonthType;
|
||||||
|
|
||||||
|
private final DaysInYearType daysInYearType;
|
||||||
|
|
||||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
||||||
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
|
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
|
||||||
final PeriodFrequencyType repaymentPeriodFrequencyType, final AmortizationMethod amortizationMethod,
|
final PeriodFrequencyType repaymentPeriodFrequencyType, final AmortizationMethod amortizationMethod,
|
||||||
@@ -113,22 +119,23 @@ public final class LoanApplicationTerms {
|
|||||||
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate,
|
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate,
|
||||||
final Money inArrearsTolerance, final boolean multiDisburseLoan, final BigDecimal emiAmount,
|
final Money inArrearsTolerance, final boolean multiDisburseLoan, final BigDecimal emiAmount,
|
||||||
final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
|
final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
|
||||||
final List<LoanTermVariationsData> emiAmountVariations, final Integer graceOnArrearsAgeing) {
|
final List<LoanTermVariationsData> emiAmountVariations, final Integer graceOnArrearsAgeing,
|
||||||
|
final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType) {
|
||||||
|
|
||||||
return new LoanApplicationTerms(currency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery,
|
return new LoanApplicationTerms(currency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery,
|
||||||
repaymentPeriodFrequencyType, amortizationMethod, interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType,
|
repaymentPeriodFrequencyType, amortizationMethod, interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType,
|
||||||
annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney, expectedDisbursementDate,
|
annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney, expectedDisbursementDate,
|
||||||
repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment,
|
repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment,
|
||||||
graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount, disbursementDatas,
|
graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount, disbursementDatas,
|
||||||
maxOutstandingBalance, emiAmountVariations, graceOnArrearsAgeing);
|
maxOutstandingBalance, emiAmountVariations, graceOnArrearsAgeing, daysInMonthType, daysInYearType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
|
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
|
||||||
final PeriodFrequencyType loanTermPeriodFrequencyType, final LocalDate expectedDisbursementDate,
|
final PeriodFrequencyType loanTermPeriodFrequencyType, final LocalDate expectedDisbursementDate,
|
||||||
final LocalDate repaymentsStartingFromDate, final LocalDate calculatedRepaymentsStartingFromDate,
|
final LocalDate repaymentsStartingFromDate, final LocalDate calculatedRepaymentsStartingFromDate,
|
||||||
final Money inArrearsTolerance, final LoanProductRelatedDetail loanProductRelatedDetail,
|
final Money inArrearsTolerance, final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan,
|
||||||
final boolean multiDisburseLoan,final BigDecimal emiAmount,final List<DisbursementData> disbursementDatas,
|
final BigDecimal emiAmount, final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
|
||||||
final BigDecimal maxOutstandingBalance,final List<LoanTermVariationsData> emiAmountVariations, final LocalDate interestChargedFromDate) {
|
final List<LoanTermVariationsData> emiAmountVariations, final LocalDate interestChargedFromDate) {
|
||||||
|
|
||||||
final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
|
final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
|
||||||
final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
|
final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
|
||||||
@@ -143,8 +150,8 @@ public final class LoanApplicationTerms {
|
|||||||
final Money principalMoney = loanProductRelatedDetail.getPrincipal();
|
final Money principalMoney = loanProductRelatedDetail.getPrincipal();
|
||||||
|
|
||||||
//
|
//
|
||||||
final Integer graceOnPrincipalPayment = loanProductRelatedDetail.graceOnPrincipalPayment() ;
|
final Integer graceOnPrincipalPayment = loanProductRelatedDetail.graceOnPrincipalPayment();
|
||||||
final Integer graceOnInterestPayment = loanProductRelatedDetail.graceOnInterestPayment() ;
|
final Integer graceOnInterestPayment = loanProductRelatedDetail.graceOnInterestPayment();
|
||||||
final Integer graceOnInterestCharged = loanProductRelatedDetail.graceOnInterestCharged();
|
final Integer graceOnInterestCharged = loanProductRelatedDetail.graceOnInterestCharged();
|
||||||
|
|
||||||
return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
|
return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
|
||||||
@@ -152,7 +159,8 @@ public final class LoanApplicationTerms {
|
|||||||
interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney,
|
interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney,
|
||||||
expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment,
|
expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment,
|
||||||
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
|
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
|
||||||
disbursementDatas, maxOutstandingBalance, emiAmountVariations, loanProductRelatedDetail.getGraceOnDueDate());
|
disbursementDatas, maxOutstandingBalance, emiAmountVariations, loanProductRelatedDetail.getGraceOnDueDate(),
|
||||||
|
loanProductRelatedDetail.fetchDaysInMonthType(), loanProductRelatedDetail.fetchDaysInYearType());
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
||||||
@@ -165,7 +173,8 @@ public final class LoanApplicationTerms {
|
|||||||
final LocalDate calculatedRepaymentsStartingFromDate, final Integer principalGrace, final Integer interestPaymentGrace,
|
final LocalDate calculatedRepaymentsStartingFromDate, final Integer principalGrace, final Integer interestPaymentGrace,
|
||||||
final Integer interestChargingGrace, final LocalDate interestChargedFromDate, final Money inArrearsTolerance,
|
final Integer interestChargingGrace, final LocalDate interestChargedFromDate, final Money inArrearsTolerance,
|
||||||
final boolean multiDisburseLoan, final BigDecimal emiAmount, final List<DisbursementData> disbursementDatas,
|
final boolean multiDisburseLoan, final BigDecimal emiAmount, final List<DisbursementData> disbursementDatas,
|
||||||
final BigDecimal maxOutstandingBalance, final List<LoanTermVariationsData> emiAmountVariations, final Integer graceOnArrearsAgeing) {
|
final BigDecimal maxOutstandingBalance, final List<LoanTermVariationsData> emiAmountVariations,
|
||||||
|
final Integer graceOnArrearsAgeing, final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType) {
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.loanTermFrequency = loanTermFrequency;
|
this.loanTermFrequency = loanTermFrequency;
|
||||||
this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
|
this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
|
||||||
@@ -197,6 +206,8 @@ public final class LoanApplicationTerms {
|
|||||||
this.maxOutstandingBalance = maxOutstandingBalance;
|
this.maxOutstandingBalance = maxOutstandingBalance;
|
||||||
this.emiAmountVariations = emiAmountVariations;
|
this.emiAmountVariations = emiAmountVariations;
|
||||||
this.graceOnArrearsAgeing = graceOnArrearsAgeing;
|
this.graceOnArrearsAgeing = graceOnArrearsAgeing;
|
||||||
|
this.daysInMonthType = daysInMonthType;
|
||||||
|
this.daysInYearType = daysInYearType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
|
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
|
||||||
@@ -273,12 +284,6 @@ public final class LoanApplicationTerms {
|
|||||||
totalInterestCharged = totalInterestChargedForLoanTerm.minus(totalGraceOnInterestCharged);
|
totalInterestCharged = totalInterestChargedForLoanTerm.minus(totalGraceOnInterestCharged);
|
||||||
break;
|
break;
|
||||||
case DECLINING_BALANCE:
|
case DECLINING_BALANCE:
|
||||||
final BigDecimal periodicInterestRateForRepaymentPeriod = periodicInterestRate(calculator, mc);
|
|
||||||
|
|
||||||
final Money totalRepaymentDueForLoanTerm = calculateTotalDueForEqualInstallmentLoan(periodicInterestRateForRepaymentPeriod);
|
|
||||||
|
|
||||||
totalInterestCharged = totalRepaymentDueForLoanTerm.minus(this.principal);
|
|
||||||
break;
|
|
||||||
case INVALID:
|
case INVALID:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -303,7 +308,10 @@ public final class LoanApplicationTerms {
|
|||||||
case EQUAL_INSTALLMENTS:
|
case EQUAL_INSTALLMENTS:
|
||||||
// equal installments
|
// equal installments
|
||||||
final int periodsElapsed = periodNumber - 1;
|
final int periodsElapsed = periodNumber - 1;
|
||||||
final BigDecimal periodicInterestRateForRepaymentPeriod = periodicInterestRate(calculator, mc);
|
// with periodic interest for default month and year for
|
||||||
|
// equal installment
|
||||||
|
final BigDecimal periodicInterestRateForRepaymentPeriod = periodicInterestRate(calculator, mc, daysInPeriod,
|
||||||
|
DaysInMonthType.DAYS_30, DaysInYearType.DAYS_365);
|
||||||
Money totalPmtForThisInstallment = calculateTotalDueForEqualInstallmentRepaymentPeriod(
|
Money totalPmtForThisInstallment = calculateTotalDueForEqualInstallmentRepaymentPeriod(
|
||||||
periodicInterestRateForRepaymentPeriod, outstandingBalance, periodsElapsed);
|
periodicInterestRateForRepaymentPeriod, outstandingBalance, periodsElapsed);
|
||||||
principalForInstallment = calculatePrincipalDueForInstallment(calculator, mc, periodNumber,
|
principalForInstallment = calculatePrincipalDueForInstallment(calculator, mc, periodNumber,
|
||||||
@@ -384,15 +392,6 @@ public final class LoanApplicationTerms {
|
|||||||
return periodNumber == numberOfRepayments;
|
return periodNumber == numberOfRepayments;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Money calculateTotalDueForEqualInstallmentLoan(final BigDecimal periodicInterestRate) {
|
|
||||||
|
|
||||||
final int periodsElapsed = 0;
|
|
||||||
final double paymentPerRepaymentPeriod = paymentPerPeriod(periodicInterestRate, this.principal, periodsElapsed);
|
|
||||||
final double totalRepayment = paymentPerRepaymentPeriod * this.numberOfRepayments;
|
|
||||||
|
|
||||||
return Money.of(this.principal.getCurrency(), BigDecimal.valueOf(totalRepayment));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* general method to calculate totalInterestDue discounting any grace
|
* general method to calculate totalInterestDue discounting any grace
|
||||||
* settings
|
* settings
|
||||||
@@ -521,7 +520,8 @@ public final class LoanApplicationTerms {
|
|||||||
return interestForInstallment;
|
return interestForInstallment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal periodicInterestRate(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc) {
|
private BigDecimal periodicInterestRate(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc, final int actualDays,
|
||||||
|
final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType) {
|
||||||
|
|
||||||
final long loanTermPeriodsInOneYear = calculatePeriodsInOneYear(calculator);
|
final long loanTermPeriodsInOneYear = calculatePeriodsInOneYear(calculator);
|
||||||
|
|
||||||
@@ -535,7 +535,8 @@ public final class LoanApplicationTerms {
|
|||||||
break;
|
break;
|
||||||
case DAILY:
|
case DAILY:
|
||||||
// For daily work out number of days in the period
|
// For daily work out number of days in the period
|
||||||
int numberOfDaysInPeriod = this.repaymentEvery;
|
int numberOfDaysInPeriod = actualDays;
|
||||||
|
|
||||||
final BigDecimal oneDayOfYearInterestRate = this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc)
|
final BigDecimal oneDayOfYearInterestRate = this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc)
|
||||||
.divide(divisor, mc);
|
.divide(divisor, mc);
|
||||||
|
|
||||||
@@ -547,15 +548,28 @@ public final class LoanApplicationTerms {
|
|||||||
periodicInterestRate = oneDayOfYearInterestRate.multiply(loanTermFrequencyBigDecimal, mc);
|
periodicInterestRate = oneDayOfYearInterestRate.multiply(loanTermFrequencyBigDecimal, mc);
|
||||||
break;
|
break;
|
||||||
case WEEKS:
|
case WEEKS:
|
||||||
numberOfDaysInPeriod = this.repaymentEvery * 7;
|
|
||||||
periodicInterestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(numberOfDaysInPeriod), mc);
|
periodicInterestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(numberOfDaysInPeriod), mc);
|
||||||
break;
|
break;
|
||||||
case MONTHS:
|
case MONTHS:
|
||||||
numberOfDaysInPeriod = this.repaymentEvery * 30;
|
if (daysInMonthType.isDaysInMonth_30()) {
|
||||||
|
numberOfDaysInPeriod = this.repaymentEvery * 30;
|
||||||
|
}
|
||||||
periodicInterestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(numberOfDaysInPeriod), mc);
|
periodicInterestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(numberOfDaysInPeriod), mc);
|
||||||
break;
|
break;
|
||||||
case YEARS:
|
case YEARS:
|
||||||
numberOfDaysInPeriod = this.repaymentEvery * 365;
|
switch (daysInYearType) {
|
||||||
|
case DAYS_360:
|
||||||
|
numberOfDaysInPeriod = this.repaymentEvery * 360;
|
||||||
|
break;
|
||||||
|
case DAYS_364:
|
||||||
|
numberOfDaysInPeriod = this.repaymentEvery * 364;
|
||||||
|
break;
|
||||||
|
case DAYS_365:
|
||||||
|
numberOfDaysInPeriod = this.repaymentEvery * 365;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
periodicInterestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(numberOfDaysInPeriod), mc);
|
periodicInterestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(numberOfDaysInPeriod), mc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -655,23 +669,9 @@ public final class LoanApplicationTerms {
|
|||||||
|
|
||||||
Money interestDue = Money.zero(outstandingBalance.getCurrency());
|
Money interestDue = Money.zero(outstandingBalance.getCurrency());
|
||||||
|
|
||||||
switch (this.interestCalculationPeriodMethod) {
|
final BigDecimal periodicInterestRate = periodicInterestRate(calculator, mc, daysInPeriod, this.daysInMonthType,
|
||||||
case DAILY:
|
this.daysInYearType);
|
||||||
final BigDecimal dailyInterestRate = this.annualNominalInterestRate.divide(BigDecimal.valueOf(Long.valueOf(365)), mc)
|
interestDue = outstandingBalance.multiplyRetainScale(periodicInterestRate, mc.getRoundingMode());
|
||||||
.divide(BigDecimal.valueOf(Double.valueOf("100.0")), mc);
|
|
||||||
|
|
||||||
final BigDecimal equivalentInterestRateForPeriod = dailyInterestRate
|
|
||||||
.multiply(BigDecimal.valueOf(Long.valueOf(daysInPeriod)));
|
|
||||||
|
|
||||||
interestDue = outstandingBalance.multiplyRetainScale(equivalentInterestRateForPeriod, mc.getRoundingMode());
|
|
||||||
break;
|
|
||||||
case SAME_AS_REPAYMENT_PERIOD:
|
|
||||||
final BigDecimal periodicInterestRate = periodicInterestRate(calculator, mc);
|
|
||||||
interestDue = outstandingBalance.multiplyRetainScale(periodicInterestRate, mc.getRoundingMode());
|
|
||||||
break;
|
|
||||||
case INVALID:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return interestDue;
|
return interestDue;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -221,7 +221,7 @@ public class LoanScheduleAssembler {
|
|||||||
expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment,
|
expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment,
|
||||||
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsToleranceMoney,
|
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsToleranceMoney,
|
||||||
loanProduct.isMultiDisburseLoan(), emiAmount, disbursementDatas, maxOutstandingBalance, loanVariationTermsData,
|
loanProduct.isMultiDisburseLoan(), emiAmount, disbursementDatas, maxOutstandingBalance, loanVariationTermsData,
|
||||||
graceOnArrearsAgeing);
|
graceOnArrearsAgeing, loanProduct.fetchDaysInMonthType(), loanProduct.fetchDaysInYearType());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DisbursementData> fetchDisbursementData(final JsonObject command) {
|
private List<DisbursementData> fetchDisbursementData(final JsonObject command) {
|
||||||
|
|||||||
+11
@@ -38,6 +38,8 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
|||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||||
|
import org.mifosplatform.portfolio.common.domain.DaysInMonthType;
|
||||||
|
import org.mifosplatform.portfolio.common.domain.DaysInYearType;
|
||||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||||
import org.mifosplatform.portfolio.fund.domain.Fund;
|
import org.mifosplatform.portfolio.fund.domain.Fund;
|
||||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||||
@@ -839,4 +841,13 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
return borrowerCycleVariations;
|
return borrowerCycleVariations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DaysInMonthType fetchDaysInMonthType() {
|
||||||
|
return this.loanProductRelatedDetail.fetchDaysInMonthType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DaysInYearType fetchDaysInYearType() {
|
||||||
|
return this.loanProductRelatedDetail.fetchDaysInYearType();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+13
-3
@@ -23,6 +23,8 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
import org.mifosplatform.portfolio.common.domain.DaysInMonthType;
|
||||||
|
import org.mifosplatform.portfolio.common.domain.DaysInYearType;
|
||||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||||
@@ -164,15 +166,15 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
|||||||
public void setPrincipal(BigDecimal principal) {
|
public void setPrincipal(BigDecimal principal) {
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer graceOnInterestCharged() {
|
public Integer graceOnInterestCharged() {
|
||||||
return this.graceOnInterestCharged;
|
return this.graceOnInterestCharged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer graceOnInterestPayment() {
|
public Integer graceOnInterestPayment() {
|
||||||
return this.graceOnInterestPayment;
|
return this.graceOnInterestPayment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer graceOnPrincipalPayment() {
|
public Integer graceOnPrincipalPayment() {
|
||||||
return this.graceOnPrincipalPayment;
|
return this.graceOnPrincipalPayment;
|
||||||
}
|
}
|
||||||
@@ -431,4 +433,12 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
|||||||
public Integer getGraceOnDueDate() {
|
public Integer getGraceOnDueDate() {
|
||||||
return this.graceOnArrearsAgeing;
|
return this.graceOnArrearsAgeing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DaysInMonthType fetchDaysInMonthType() {
|
||||||
|
return DaysInMonthType.ACTUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DaysInYearType fetchDaysInYearType() {
|
||||||
|
return DaysInYearType.ACTUAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user