Merge pull request #1494 from pramodn02/develop

MIFOSX-2123 : added fix to change the principal amount
This commit is contained in:
Vishwas Babu A J
2015-09-11 15:32:15 +05:30
3 changed files with 44 additions and 23 deletions
@@ -520,7 +520,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
BigDecimal fixedEmiAmount = loanApplicationTerms.getFixedEmiAmount(); BigDecimal fixedEmiAmount = loanApplicationTerms.getFixedEmiAmount();
reducePrincipal = applyEarlyPaymentStrategy(loanApplicationTerms, reducePrincipal, totalCumulativePrincipal, reducePrincipal = applyEarlyPaymentStrategy(loanApplicationTerms, reducePrincipal, totalCumulativePrincipal,
periodNumber + 1, mc, holidayDetailDTO); periodNumber + 1, mc, holidayDetailDTO);
if (fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) { if (loanApplicationTerms.getAmortizationMethod().isEqualInstallment() && fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) {
isEmiAmountChanged = true; isEmiAmountChanged = true;
} }
principalForThisPeriod = principalForThisPeriod.plus(earlyPaidAmount); principalForThisPeriod = principalForThisPeriod.plus(earlyPaidAmount);
@@ -643,7 +643,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
reducePrincipal = applyEarlyPaymentStrategy(loanApplicationTerms, reducePrincipal, reducePrincipal = applyEarlyPaymentStrategy(loanApplicationTerms, reducePrincipal,
totalCumulativePrincipal.plus(principalForThisPeriod.minus(principalProcessed)), periodNumber + 1, mc, totalCumulativePrincipal.plus(principalForThisPeriod.minus(principalProcessed)), periodNumber + 1, mc,
holidayDetailDTO); holidayDetailDTO);
if (fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) { if (loanApplicationTerms.getAmortizationMethod().isEqualInstallment() && fixedEmiAmount.compareTo(loanApplicationTerms.getFixedEmiAmount()) != 0) {
isEmiAmountChanged = true; isEmiAmountChanged = true;
} }
@@ -943,6 +943,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
updateFixedInstallmentAmount(mc, loanApplicationTerms, loanApplicationTerms.getExpectedDisbursementDate(), updateFixedInstallmentAmount(mc, loanApplicationTerms, loanApplicationTerms.getExpectedDisbursementDate(),
periodNumber, loanApplicationTerms.getPrincipal().minus(totalCumulativePrincipal), holidayDetailDTO); periodNumber, loanApplicationTerms.getPrincipal().minus(totalCumulativePrincipal), holidayDetailDTO);
} }
if(loanApplicationTerms.getAmortizationMethod().isEqualPrincipal()){
loanApplicationTerms.updateFixedPrincipalAmount(mc, periodNumber, loanApplicationTerms.getPrincipal().minus(totalCumulativePrincipal));
}
reducePrincipal = reducePrincipal.zero(); reducePrincipal = reducePrincipal.zero();
break; break;
case REDUCE_NUMBER_OF_INSTALLMENTS: case REDUCE_NUMBER_OF_INSTALLMENTS:
@@ -7,7 +7,6 @@ package org.mifosplatform.portfolio.loanaccount.loanschedule.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.MathContext; import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -117,6 +116,8 @@ public final class LoanApplicationTerms {
private BigDecimal fixedEmiAmount; private BigDecimal fixedEmiAmount;
private BigDecimal fixedPrincipalAmount;
private final BigDecimal actualFixedEmiAmount; private final BigDecimal actualFixedEmiAmount;
private final BigDecimal maxOutstandingBalance; private final BigDecimal maxOutstandingBalance;
@@ -148,8 +149,8 @@ public final class LoanApplicationTerms {
private final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy; private final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy;
private Money approvedPrincipal = null ; private Money approvedPrincipal = null;
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, Integer nthDay, DayOfWeekType weekDayType, final PeriodFrequencyType repaymentPeriodFrequencyType, Integer nthDay, DayOfWeekType weekDayType,
@@ -166,7 +167,8 @@ public final class LoanApplicationTerms {
final RecalculationFrequencyType recalculationFrequencyType, final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType, final CalendarInstance restCalendarInstance,
final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType, final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf, final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar, BigDecimal approvedAmount) { final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar,
BigDecimal approvedAmount) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null; final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null; final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
@@ -341,7 +343,8 @@ public final class LoanApplicationTerms {
final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType, final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType,
final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType, final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf, final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar, BigDecimal approvedAmount) { final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar,
BigDecimal approvedAmount) {
this.currency = currency; this.currency = currency;
this.loanTermFrequency = loanTermFrequency; this.loanTermFrequency = loanTermFrequency;
this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType; this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
@@ -390,7 +393,7 @@ public final class LoanApplicationTerms {
this.preClosureInterestCalculationStrategy = preClosureInterestCalculationStrategy; this.preClosureInterestCalculationStrategy = preClosureInterestCalculationStrategy;
this.loanCalendar = loanCalendar; this.loanCalendar = loanCalendar;
this.approvedPrincipal = Money.of(principal.getCurrency(), approvedAmount) ; this.approvedPrincipal = Money.of(principal.getCurrency(), approvedAmount);
} }
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate, public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -490,8 +493,7 @@ public final class LoanApplicationTerms {
case DECLINING_BALANCE: case DECLINING_BALANCE:
switch (this.amortizationMethod) { switch (this.amortizationMethod) {
case EQUAL_INSTALLMENTS: case EQUAL_INSTALLMENTS:
Money totalPmtForThisInstallment = pmtForInstallment(calculator, daysInPeriod, outstandingBalance, periodNumber, Money totalPmtForThisInstallment = pmtForInstallment(calculator, daysInPeriod, outstandingBalance, periodNumber, mc);
mc);
principalForInstallment = calculatePrincipalDueForInstallment(periodNumber, totalPmtForThisInstallment, principalForInstallment = calculatePrincipalDueForInstallment(periodNumber, totalPmtForThisInstallment,
interestForThisInstallment); interestForThisInstallment);
break; break;
@@ -556,9 +558,9 @@ public final class LoanApplicationTerms {
final Money interestForThisInstallmentBeforeGrace = calculateDecliningInterestDueForInstallmentBeforeApplyingGrace( final Money interestForThisInstallmentBeforeGrace = calculateDecliningInterestDueForInstallmentBeforeApplyingGrace(
calculator, mc, daysInPeriodApplicableForInterest, outstandingBalance); calculator, mc, daysInPeriodApplicableForInterest, outstandingBalance);
final Money interestForThisInstallmentAfterGrace = calculateDecliningInterestDueForInstallmentAfterApplyingGrace(calculator, final Money interestForThisInstallmentAfterGrace = calculateDecliningInterestDueForInstallmentAfterApplyingGrace(
interestCalculationGraceOnRepaymentPeriodFraction, mc, daysInPeriodApplicableForInterest, outstandingBalance, calculator, interestCalculationGraceOnRepaymentPeriodFraction, mc, daysInPeriodApplicableForInterest,
periodNumber); outstandingBalance, periodNumber);
interestForInstallment = interestForThisInstallmentAfterGrace; interestForInstallment = interestForThisInstallmentAfterGrace;
if (interestForThisInstallmentAfterGrace.isGreaterThanZero()) { if (interestForThisInstallmentAfterGrace.isGreaterThanZero()) {
@@ -651,8 +653,7 @@ public final class LoanApplicationTerms {
this.loanEndDate = loanEndDate; this.loanEndDate = loanEndDate;
} }
private Money calculateTotalInterestPerInstallmentWithoutGrace(final PaymentPeriodsInOneYearCalculator calculator, private Money calculateTotalInterestPerInstallmentWithoutGrace(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc) {
final MathContext mc) {
final Money totalInterestForLoanTerm = calculateTotalFlatInterestDueWithoutGrace(calculator, mc); final Money totalInterestForLoanTerm = calculateTotalFlatInterestDueWithoutGrace(calculator, mc);
@@ -709,8 +710,8 @@ public final class LoanApplicationTerms {
final Integer interestPaymentDuePeriods = calculateNumberOfRepaymentPeriodsWhereInterestPaymentIsDue(this.numberOfRepayments); final Integer interestPaymentDuePeriods = calculateNumberOfRepaymentPeriodsWhereInterestPaymentIsDue(this.numberOfRepayments);
interestForInstallment = realTotalInterestForLoan.dividedBy(BigDecimal.valueOf(interestPaymentDuePeriods), interestForInstallment = realTotalInterestForLoan
mc.getRoundingMode()); .dividedBy(BigDecimal.valueOf(interestPaymentDuePeriods), mc.getRoundingMode());
} }
return interestForInstallment; return interestForInstallment;
@@ -792,8 +793,8 @@ public final class LoanApplicationTerms {
final BigDecimal divisor = BigDecimal.valueOf(Double.valueOf("100.0")); final BigDecimal divisor = BigDecimal.valueOf(Double.valueOf("100.0"));
final BigDecimal loanTermPeriodsInYearBigDecimal = BigDecimal.valueOf(loanTermPeriodsInOneYear); final BigDecimal loanTermPeriodsInYearBigDecimal = BigDecimal.valueOf(loanTermPeriodsInOneYear);
final BigDecimal oneDayOfYearInterestRate = this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc) final BigDecimal oneDayOfYearInterestRate = this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc).divide(
.divide(divisor, mc); divisor, mc);
BigDecimal interestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(repaymentEvery), mc); BigDecimal interestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(repaymentEvery), mc);
return outstandingBalance.getAmount().multiply(interestRate, mc); return outstandingBalance.getAmount().multiply(interestRate, mc);
} }
@@ -936,16 +937,27 @@ public final class LoanApplicationTerms {
private Money calculateEqualPrincipalDueForInstallment(final MathContext mc, final int periodNumber) { private Money calculateEqualPrincipalDueForInstallment(final MathContext mc, final int periodNumber) {
final Integer numberOfPrincipalPaymentPeriods = calculateNumberOfPrincipalPaymentPeriods(this.numberOfRepayments); final Integer numberOfPrincipalPaymentPeriods = calculateNumberOfPrincipalPaymentPeriods(this.numberOfRepayments);
Money principal = this.principal;
if (this.fixedPrincipalAmount == null) {
principal = this.principal.dividedBy(numberOfPrincipalPaymentPeriods, mc.getRoundingMode());
this.fixedPrincipalAmount = principal.getAmount();
} else {
principal = Money.of(getCurrency(), this.fixedPrincipalAmount);
}
Money principal = this.principal.dividedBy(numberOfPrincipalPaymentPeriods, mc.getRoundingMode());
if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) { if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) {
principal = principal.zero(); principal = principal.zero();
} }
return principal; return principal;
} }
private Money calculatePrincipalDueForInstallment(final int periodNumber, final Money totalDuePerInstallment, public void updateFixedPrincipalAmount(final MathContext mc, final int periodNumber, final Money outstandingAmount) {
final Money periodInterest) { final Integer numberOfPrincipalPaymentPeriods = calculateNumberOfPrincipalPaymentPeriods(this.numberOfRepayments);
Money principal = outstandingAmount.dividedBy(numberOfPrincipalPaymentPeriods - periodNumber + 1, mc.getRoundingMode());
this.fixedPrincipalAmount = principal.getAmount();
}
private Money calculatePrincipalDueForInstallment(final int periodNumber, final Money totalDuePerInstallment, final Money periodInterest) {
Money principal = totalDuePerInstallment.minus(periodInterest); Money principal = totalDuePerInstallment.minus(periodInterest);
if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) { if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) {
@@ -1047,8 +1059,9 @@ public final class LoanApplicationTerms {
} }
public Money getApprovedPrincipal() { public Money getApprovedPrincipal() {
return this.approvedPrincipal ; return this.approvedPrincipal;
} }
public List<DisbursementData> getDisbursementDatas() { public List<DisbursementData> getDisbursementDatas() {
return this.disbursementDatas; return this.disbursementDatas;
} }
@@ -1256,4 +1269,5 @@ public final class LoanApplicationTerms {
public Calendar getLoanCalendar() { public Calendar getLoanCalendar() {
return loanCalendar; return loanCalendar;
} }
} }
@@ -48,4 +48,8 @@ public enum AmortizationMethod {
public boolean isEqualInstallment() { public boolean isEqualInstallment() {
return this.value.equals(AmortizationMethod.EQUAL_INSTALLMENTS.getValue()); return this.value.equals(AmortizationMethod.EQUAL_INSTALLMENTS.getValue());
} }
public boolean isEqualPrincipal() {
return this.value.equals(AmortizationMethod.EQUAL_PRINCIPAL.getValue());
}
} }