diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java index f00a9d94a..dc6612469 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java @@ -65,10 +65,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener this.paymentPeriodsInOneYearCalculator, mc); // 5. loop over the known set of 'scheduled due dates' - LocalDate repaymentPeriodStartDate = this.scheduledDateGenerator.idealDisbursementDateBasedOnFirstRepaymentDate( + final LocalDate idealDisbursementDate = this.scheduledDateGenerator.idealDisbursementDateBasedOnFirstRepaymentDate( loanApplicationTerms.getLoanTermPeriodFrequencyType(), loanApplicationTerms.getRepaymentEvery(), scheduledDates); - LocalDate startDate = loanApplicationTerms.getExpectedDisbursementDate(); + LocalDate periodStartDate = loanApplicationTerms.getExpectedDisbursementDate(); + LocalDate periodStartDateApplicableForInterest = periodStartDate; int periodNumber = 1; Money totalCumulativePrincipal = principalDisbursed.zero(); Money totalCumulativeInterest = principalDisbursed.zero(); @@ -76,18 +77,24 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener Money outstandingBalance = principalDisbursed; for (final LocalDate scheduledDueDate : scheduledDates) { - final int daysInPeriod = Days.daysBetween(startDate, scheduledDueDate).getDays(); + final int daysInPeriod = Days.daysBetween(periodStartDate, scheduledDueDate).getDays(); + int daysInPeriodApplicableForInterest = daysInPeriod; + + if (periodStartDate.isBefore(idealDisbursementDate)) { + periodStartDateApplicableForInterest = idealDisbursementDate; + daysInPeriodApplicableForInterest = Days.daysBetween(periodStartDateApplicableForInterest, scheduledDueDate).getDays(); + } final double interestCalculationGraceOnRepaymentPeriodFraction = this.paymentPeriodsInOneYearCalculator - .calculatePortionOfRepaymentPeriodInterestChargingGrace(repaymentPeriodStartDate, scheduledDueDate, + .calculatePortionOfRepaymentPeriodInterestChargingGrace(periodStartDateApplicableForInterest, scheduledDueDate, loanApplicationTerms.getInterestChargedFromLocalDate(), loanApplicationTerms.getLoanTermPeriodFrequencyType(), loanApplicationTerms.getRepaymentEvery()); // 5 determine principal,interest of repayment period final PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod( this.paymentPeriodsInOneYearCalculator, interestCalculationGraceOnRepaymentPeriodFraction, totalCumulativePrincipal, - totalCumulativeInterest, totalInterestChargedForFullLoanTerm, totalOutstandingInterestPaymentDueToGrace, daysInPeriod, - outstandingBalance, loanApplicationTerms, periodNumber, mc); + totalCumulativeInterest, totalInterestChargedForFullLoanTerm, totalOutstandingInterestPaymentDueToGrace, + daysInPeriodApplicableForInterest, outstandingBalance, loanApplicationTerms, periodNumber, mc); // update cumulative fields for principal & interest totalCumulativePrincipal = totalCumulativePrincipal.plus(principalInterestForThisPeriod.principal()); @@ -98,8 +105,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener outstandingBalance = outstandingBalance.minus(principalInterestForThisPeriod.principal()); // 7. determine fees and penalties - final Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(startDate, scheduledDueDate, loanCharges, currency); - final Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(startDate, scheduledDueDate, loanCharges, currency); + final Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, currency); + final Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, + currency); // 8. sum up real totalInstallmentDue from components final Money totalInstallmentDue = principalInterestForThisPeriod.principal() // @@ -108,7 +116,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener .plus(penaltyChargesForInstallment); // 9. create repayment period from parts - final LoanScheduleModelPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(periodNumber, startDate, + final LoanScheduleModelPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(periodNumber, periodStartDate, scheduledDueDate, principalInterestForThisPeriod.principal(), outstandingBalance, principalInterestForThisPeriod.interest(), feeChargesForInstallment, penaltyChargesForInstallment, totalInstallmentDue); periods.add(installment); @@ -120,8 +128,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener totalFeeChargesCharged = totalFeeChargesCharged.add(feeChargesForInstallment.getAmount()); totalPenaltyChargesCharged = totalPenaltyChargesCharged.add(penaltyChargesForInstallment.getAmount()); totalRepaymentExpected = totalRepaymentExpected.add(totalInstallmentDue.getAmount()); - startDate = scheduledDueDate; - repaymentPeriodStartDate = startDate; + periodStartDate = scheduledDueDate; + periodStartDateApplicableForInterest = periodStartDate; periodNumber++; } @@ -133,7 +141,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener public abstract PrincipalInterest calculatePrincipalInterestComponentsForPeriod(PaymentPeriodsInOneYearCalculator calculator, double interestCalculationGraceOnRepaymentPeriodFraction, Money totalCumulativePrincipal, Money totalCumulativeInterest, - Money totalInterestDueForLoan, Money cumulatingInterestPaymentDueToGrace, int daysInPeriod, Money outstandingBalance, + Money totalInterestDueForLoan, Money cumulatingInterestPaymentDueToGrace, int daysInPeriodApplicableForInterest, Money outstandingBalance, LoanApplicationTerms loanApplicationTerms, int periodNumber, MathContext mc); protected final boolean isLastRepaymentPeriod(final int numberOfRepayments, final int periodNumber) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java index 09437f6e4..0ce3e671e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java @@ -19,14 +19,14 @@ import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod; *
* When amortized using equal principal payments, the principal * component of each installment is fixed and interest due is * calculated from the outstanding principal balance resulting in a * different total payment due for each installment. *
- * + * ** When amortized using equal installments, the total payment due * for each installment is fixed and is calculated using the excel like @@ -42,17 +42,17 @@ public class DecliningBalanceInterestLoanScheduleGenerator extends AbstractLoanS final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal, @SuppressWarnings("unused") final Money totalCumulativeInterest, @SuppressWarnings("unused") final Money totalInterestDueForLoan, final Money cumulatingInterestPaymentDueToGrace, - final int daysInPeriod, final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, + final int daysInPeriodApplicableForInterest, final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, final int periodNumber, final MathContext mc) { final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator, - interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace, daysInPeriod, - outstandingBalance); + interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace, + daysInPeriodApplicableForInterest, outstandingBalance); final Money interestForThisInstallment = result.interest(); - Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, daysInPeriod, - outstandingBalance, periodNumber, mc); + Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, + daysInPeriodApplicableForInterest, outstandingBalance, periodNumber, mc); // update cumulative fields for principal & interest final Money interestBroughtFowardDueToGrace = result.interestPaymentDueToGrace(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatInterestLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatInterestLoanScheduleGenerator.java index ee3eb4dbc..e7fbe6be2 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatInterestLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatInterestLoanScheduleGenerator.java @@ -15,14 +15,14 @@ public class FlatInterestLoanScheduleGenerator extends AbstractLoanScheduleGener public PrincipalInterest calculatePrincipalInterestComponentsForPeriod(final PaymentPeriodsInOneYearCalculator calculator, final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal, final Money totalCumulativeInterest, final Money totalInterestDueForLoan, final Money cumulatingInterestPaymentDueToGrace, - final int daysInPeriod, final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, + final int daysInPeriodApplicableForInterest, final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, final int periodNumber, final MathContext mc) { - Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, daysInPeriod, + Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, daysInPeriodApplicableForInterest, outstandingBalance, periodNumber, mc); final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator, - interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace, daysInPeriod, + interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace, daysInPeriodApplicableForInterest, outstandingBalance); Money interestForThisInstallment = result.interest(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java index 4dd8cca6c..5399600c8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java @@ -288,7 +288,7 @@ public final class LoanApplicationTerms { public PrincipalInterest calculateTotalInterestForPeriod(final PaymentPeriodsInOneYearCalculator calculator, final double interestCalculationGraceOnRepaymentPeriodFraction, final int periodNumber, final MathContext mc, - final Money cumulatingInterestPaymentDueToGrace, final int daysInPeriod, final Money outstandingBalance) { + final Money cumulatingInterestPaymentDueToGrace, final int daysInPeriodApplicableForInterest, final Money outstandingBalance) { Money interestForInstallment = this.principal.zero(); Money interestBroughtForwardDueToGrace = cumulatingInterestPaymentDueToGrace.copy(); @@ -318,10 +318,10 @@ public final class LoanApplicationTerms { case DECLINING_BALANCE: final Money interestForThisInstallmentBeforeGrace = calculateDecliningInterestDueForInstallmentBeforeApplyingGrace( - calculator, mc, daysInPeriod, outstandingBalance); + calculator, mc, daysInPeriodApplicableForInterest, outstandingBalance); final Money interestForThisInstallmentAfterGrace = calculateDecliningInterestDueForInstallmentAfterApplyingGrace( - calculator, interestCalculationGraceOnRepaymentPeriodFraction, mc, daysInPeriod, outstandingBalance, periodNumber); + calculator, interestCalculationGraceOnRepaymentPeriodFraction, mc, daysInPeriodApplicableForInterest, outstandingBalance, periodNumber); interestForInstallment = interestForThisInstallmentAfterGrace; if (interestForThisInstallmentAfterGrace.isGreaterThanZero()) {