MIFOSX-721: fix issue with daily interest calculation when using interest charged from date feature.
This commit is contained in:
+20
-12
@@ -65,10 +65,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
this.paymentPeriodsInOneYearCalculator, mc);
|
this.paymentPeriodsInOneYearCalculator, mc);
|
||||||
|
|
||||||
// 5. loop over the known set of 'scheduled due dates'
|
// 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);
|
loanApplicationTerms.getLoanTermPeriodFrequencyType(), loanApplicationTerms.getRepaymentEvery(), scheduledDates);
|
||||||
|
|
||||||
LocalDate startDate = loanApplicationTerms.getExpectedDisbursementDate();
|
LocalDate periodStartDate = loanApplicationTerms.getExpectedDisbursementDate();
|
||||||
|
LocalDate periodStartDateApplicableForInterest = periodStartDate;
|
||||||
int periodNumber = 1;
|
int periodNumber = 1;
|
||||||
Money totalCumulativePrincipal = principalDisbursed.zero();
|
Money totalCumulativePrincipal = principalDisbursed.zero();
|
||||||
Money totalCumulativeInterest = principalDisbursed.zero();
|
Money totalCumulativeInterest = principalDisbursed.zero();
|
||||||
@@ -76,18 +77,24 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
Money outstandingBalance = principalDisbursed;
|
Money outstandingBalance = principalDisbursed;
|
||||||
for (final LocalDate scheduledDueDate : scheduledDates) {
|
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
|
final double interestCalculationGraceOnRepaymentPeriodFraction = this.paymentPeriodsInOneYearCalculator
|
||||||
.calculatePortionOfRepaymentPeriodInterestChargingGrace(repaymentPeriodStartDate, scheduledDueDate,
|
.calculatePortionOfRepaymentPeriodInterestChargingGrace(periodStartDateApplicableForInterest, scheduledDueDate,
|
||||||
loanApplicationTerms.getInterestChargedFromLocalDate(), loanApplicationTerms.getLoanTermPeriodFrequencyType(),
|
loanApplicationTerms.getInterestChargedFromLocalDate(), loanApplicationTerms.getLoanTermPeriodFrequencyType(),
|
||||||
loanApplicationTerms.getRepaymentEvery());
|
loanApplicationTerms.getRepaymentEvery());
|
||||||
|
|
||||||
// 5 determine principal,interest of repayment period
|
// 5 determine principal,interest of repayment period
|
||||||
final PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod(
|
final PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod(
|
||||||
this.paymentPeriodsInOneYearCalculator, interestCalculationGraceOnRepaymentPeriodFraction, totalCumulativePrincipal,
|
this.paymentPeriodsInOneYearCalculator, interestCalculationGraceOnRepaymentPeriodFraction, totalCumulativePrincipal,
|
||||||
totalCumulativeInterest, totalInterestChargedForFullLoanTerm, totalOutstandingInterestPaymentDueToGrace, daysInPeriod,
|
totalCumulativeInterest, totalInterestChargedForFullLoanTerm, totalOutstandingInterestPaymentDueToGrace,
|
||||||
outstandingBalance, loanApplicationTerms, periodNumber, mc);
|
daysInPeriodApplicableForInterest, outstandingBalance, loanApplicationTerms, periodNumber, mc);
|
||||||
|
|
||||||
// update cumulative fields for principal & interest
|
// update cumulative fields for principal & interest
|
||||||
totalCumulativePrincipal = totalCumulativePrincipal.plus(principalInterestForThisPeriod.principal());
|
totalCumulativePrincipal = totalCumulativePrincipal.plus(principalInterestForThisPeriod.principal());
|
||||||
@@ -98,8 +105,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
outstandingBalance = outstandingBalance.minus(principalInterestForThisPeriod.principal());
|
outstandingBalance = outstandingBalance.minus(principalInterestForThisPeriod.principal());
|
||||||
|
|
||||||
// 7. determine fees and penalties
|
// 7. determine fees and penalties
|
||||||
final Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(startDate, scheduledDueDate, loanCharges, currency);
|
final Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges, currency);
|
||||||
final Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(startDate, scheduledDueDate, loanCharges, currency);
|
final Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(periodStartDate, scheduledDueDate, loanCharges,
|
||||||
|
currency);
|
||||||
|
|
||||||
// 8. sum up real totalInstallmentDue from components
|
// 8. sum up real totalInstallmentDue from components
|
||||||
final Money totalInstallmentDue = principalInterestForThisPeriod.principal() //
|
final Money totalInstallmentDue = principalInterestForThisPeriod.principal() //
|
||||||
@@ -108,7 +116,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
.plus(penaltyChargesForInstallment);
|
.plus(penaltyChargesForInstallment);
|
||||||
|
|
||||||
// 9. create repayment period from parts
|
// 9. create repayment period from parts
|
||||||
final LoanScheduleModelPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(periodNumber, startDate,
|
final LoanScheduleModelPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(periodNumber, periodStartDate,
|
||||||
scheduledDueDate, principalInterestForThisPeriod.principal(), outstandingBalance,
|
scheduledDueDate, principalInterestForThisPeriod.principal(), outstandingBalance,
|
||||||
principalInterestForThisPeriod.interest(), feeChargesForInstallment, penaltyChargesForInstallment, totalInstallmentDue);
|
principalInterestForThisPeriod.interest(), feeChargesForInstallment, penaltyChargesForInstallment, totalInstallmentDue);
|
||||||
periods.add(installment);
|
periods.add(installment);
|
||||||
@@ -120,8 +128,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
totalFeeChargesCharged = totalFeeChargesCharged.add(feeChargesForInstallment.getAmount());
|
totalFeeChargesCharged = totalFeeChargesCharged.add(feeChargesForInstallment.getAmount());
|
||||||
totalPenaltyChargesCharged = totalPenaltyChargesCharged.add(penaltyChargesForInstallment.getAmount());
|
totalPenaltyChargesCharged = totalPenaltyChargesCharged.add(penaltyChargesForInstallment.getAmount());
|
||||||
totalRepaymentExpected = totalRepaymentExpected.add(totalInstallmentDue.getAmount());
|
totalRepaymentExpected = totalRepaymentExpected.add(totalInstallmentDue.getAmount());
|
||||||
startDate = scheduledDueDate;
|
periodStartDate = scheduledDueDate;
|
||||||
repaymentPeriodStartDate = startDate;
|
periodStartDateApplicableForInterest = periodStartDate;
|
||||||
|
|
||||||
periodNumber++;
|
periodNumber++;
|
||||||
}
|
}
|
||||||
@@ -133,7 +141,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
|
|
||||||
public abstract PrincipalInterest calculatePrincipalInterestComponentsForPeriod(PaymentPeriodsInOneYearCalculator calculator,
|
public abstract PrincipalInterest calculatePrincipalInterestComponentsForPeriod(PaymentPeriodsInOneYearCalculator calculator,
|
||||||
double interestCalculationGraceOnRepaymentPeriodFraction, Money totalCumulativePrincipal, Money totalCumulativeInterest,
|
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);
|
LoanApplicationTerms loanApplicationTerms, int periodNumber, MathContext mc);
|
||||||
|
|
||||||
protected final boolean isLastRepaymentPeriod(final int numberOfRepayments, final int periodNumber) {
|
protected final boolean isLastRepaymentPeriod(final int numberOfRepayments, final int periodNumber) {
|
||||||
|
|||||||
+5
-5
@@ -42,17 +42,17 @@ public class DecliningBalanceInterestLoanScheduleGenerator extends AbstractLoanS
|
|||||||
final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal,
|
final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal,
|
||||||
@SuppressWarnings("unused") final Money totalCumulativeInterest,
|
@SuppressWarnings("unused") final Money totalCumulativeInterest,
|
||||||
@SuppressWarnings("unused") final Money totalInterestDueForLoan, final Money cumulatingInterestPaymentDueToGrace,
|
@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 int periodNumber, final MathContext mc) {
|
||||||
|
|
||||||
final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator,
|
final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator,
|
||||||
interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace, daysInPeriod,
|
interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace,
|
||||||
outstandingBalance);
|
daysInPeriodApplicableForInterest, outstandingBalance);
|
||||||
|
|
||||||
final Money interestForThisInstallment = result.interest();
|
final Money interestForThisInstallment = result.interest();
|
||||||
|
|
||||||
Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, daysInPeriod,
|
Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator,
|
||||||
outstandingBalance, periodNumber, mc);
|
daysInPeriodApplicableForInterest, outstandingBalance, periodNumber, mc);
|
||||||
|
|
||||||
// update cumulative fields for principal & interest
|
// update cumulative fields for principal & interest
|
||||||
final Money interestBroughtFowardDueToGrace = result.interestPaymentDueToGrace();
|
final Money interestBroughtFowardDueToGrace = result.interestPaymentDueToGrace();
|
||||||
|
|||||||
+3
-3
@@ -15,14 +15,14 @@ public class FlatInterestLoanScheduleGenerator extends AbstractLoanScheduleGener
|
|||||||
public PrincipalInterest calculatePrincipalInterestComponentsForPeriod(final PaymentPeriodsInOneYearCalculator calculator,
|
public PrincipalInterest calculatePrincipalInterestComponentsForPeriod(final PaymentPeriodsInOneYearCalculator calculator,
|
||||||
final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal,
|
final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal,
|
||||||
final Money totalCumulativeInterest, final Money totalInterestDueForLoan, final Money cumulatingInterestPaymentDueToGrace,
|
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) {
|
final int periodNumber, final MathContext mc) {
|
||||||
|
|
||||||
Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, daysInPeriod,
|
Money principalForThisInstallment = loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, daysInPeriodApplicableForInterest,
|
||||||
outstandingBalance, periodNumber, mc);
|
outstandingBalance, periodNumber, mc);
|
||||||
|
|
||||||
final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator,
|
final PrincipalInterest result = loanApplicationTerms.calculateTotalInterestForPeriod(calculator,
|
||||||
interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace, daysInPeriod,
|
interestCalculationGraceOnRepaymentPeriodFraction, periodNumber, mc, cumulatingInterestPaymentDueToGrace, daysInPeriodApplicableForInterest,
|
||||||
outstandingBalance);
|
outstandingBalance);
|
||||||
Money interestForThisInstallment = result.interest();
|
Money interestForThisInstallment = result.interest();
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -288,7 +288,7 @@ public final class LoanApplicationTerms {
|
|||||||
|
|
||||||
public PrincipalInterest calculateTotalInterestForPeriod(final PaymentPeriodsInOneYearCalculator calculator,
|
public PrincipalInterest calculateTotalInterestForPeriod(final PaymentPeriodsInOneYearCalculator calculator,
|
||||||
final double interestCalculationGraceOnRepaymentPeriodFraction, final int periodNumber, final MathContext mc,
|
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 interestForInstallment = this.principal.zero();
|
||||||
Money interestBroughtForwardDueToGrace = cumulatingInterestPaymentDueToGrace.copy();
|
Money interestBroughtForwardDueToGrace = cumulatingInterestPaymentDueToGrace.copy();
|
||||||
@@ -318,10 +318,10 @@ public final class LoanApplicationTerms {
|
|||||||
case DECLINING_BALANCE:
|
case DECLINING_BALANCE:
|
||||||
|
|
||||||
final Money interestForThisInstallmentBeforeGrace = calculateDecliningInterestDueForInstallmentBeforeApplyingGrace(
|
final Money interestForThisInstallmentBeforeGrace = calculateDecliningInterestDueForInstallmentBeforeApplyingGrace(
|
||||||
calculator, mc, daysInPeriod, outstandingBalance);
|
calculator, mc, daysInPeriodApplicableForInterest, outstandingBalance);
|
||||||
|
|
||||||
final Money interestForThisInstallmentAfterGrace = calculateDecliningInterestDueForInstallmentAfterApplyingGrace(
|
final Money interestForThisInstallmentAfterGrace = calculateDecliningInterestDueForInstallmentAfterApplyingGrace(
|
||||||
calculator, interestCalculationGraceOnRepaymentPeriodFraction, mc, daysInPeriod, outstandingBalance, periodNumber);
|
calculator, interestCalculationGraceOnRepaymentPeriodFraction, mc, daysInPeriodApplicableForInterest, outstandingBalance, periodNumber);
|
||||||
|
|
||||||
interestForInstallment = interestForThisInstallmentAfterGrace;
|
interestForInstallment = interestForThisInstallmentAfterGrace;
|
||||||
if (interestForThisInstallmentAfterGrace.isGreaterThanZero()) {
|
if (interestForThisInstallmentAfterGrace.isGreaterThanZero()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user