fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nazeer1100...@apache.org
Subject [2/5] incubator-fineract git commit: FINERACT-94: Flexible morotorium(only principal portion)
Date Tue, 26 Apr 2016 05:43:26 GMT
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/437de26c/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index d2341ba..7be11d3 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -57,1424 +57,1864 @@ import org.joda.time.Years;
 
 public final class LoanApplicationTerms {
 
-    private final ApplicationCurrency currency;
-
-    private final Calendar loanCalendar;
-    private Integer loanTermFrequency;
-    private final PeriodFrequencyType loanTermPeriodFrequencyType;
-    private Integer numberOfRepayments;
-    private Integer actualNumberOfRepayments;
-    private final Integer repaymentEvery;
-    private final PeriodFrequencyType repaymentPeriodFrequencyType;
-    private final Integer nthDay;
+	private final ApplicationCurrency currency;
+
+	private final Calendar loanCalendar;
+	private Integer loanTermFrequency;
+	private final PeriodFrequencyType loanTermPeriodFrequencyType;
+	private Integer numberOfRepayments;
+	private Integer actualNumberOfRepayments;
+	private final Integer repaymentEvery;
+	private final PeriodFrequencyType repaymentPeriodFrequencyType;
+	private final Integer nthDay;
 
-    private final DayOfWeekType weekDayType;
-    private final AmortizationMethod amortizationMethod;
+	private final DayOfWeekType weekDayType;
+	private final AmortizationMethod amortizationMethod;
 
-    private final InterestMethod interestMethod;
-    private BigDecimal interestRatePerPeriod;
-    private final PeriodFrequencyType interestRatePeriodFrequencyType;
-    private BigDecimal annualNominalInterestRate;
-    private final InterestCalculationPeriodMethod interestCalculationPeriodMethod;
-    private final boolean allowPartialPeriodInterestCalcualtion;
+	private final InterestMethod interestMethod;
+	private BigDecimal interestRatePerPeriod;
+	private final PeriodFrequencyType interestRatePeriodFrequencyType;
+	private BigDecimal annualNominalInterestRate;
+	private final InterestCalculationPeriodMethod interestCalculationPeriodMethod;
+	private final boolean allowPartialPeriodInterestCalcualtion;
 
-    private Money principal;
-    private final LocalDate expectedDisbursementDate;
-    private final LocalDate repaymentsStartingFromDate;
-    private final LocalDate calculatedRepaymentsStartingFromDate;
-    /**
-     * Integer representing the number of 'repayment frequencies' or
-     * installments where 'grace' should apply to the principal component of a
-     * loans repayment period (installment).
-     */
-    private Integer principalGrace;
+	private Money principal;
+	private final LocalDate expectedDisbursementDate;
+	private final LocalDate repaymentsStartingFromDate;
+	private final LocalDate calculatedRepaymentsStartingFromDate;
+	/**
+	 * Integer representing the number of 'repayment frequencies' or
+	 * installments where 'grace' should apply to the principal component of a
+	 * loans repayment period (installment).
+	 */
+	private Integer principalGrace;
+	private Integer recurringMoratoriumOnPrincipalPeriods;
 
-    /**
-     * Integer representing the number of 'repayment frequencies' or
-     * installments where 'grace' should apply to the payment of interest in a
-     * loans repayment period (installment).
-     * 
-     * <b>Note:</b> Interest is still calculated taking into account the full
-     * loan term, the interest is simply offset to a later period.
-     */
-    private Integer interestPaymentGrace;
+	/**
+	 * Integer representing the number of 'repayment frequencies' or
+	 * installments where 'grace' should apply to the payment of interest in a
+	 * loans repayment period (installment).
+	 * 
+	 * <b>Note:</b> Interest is still calculated taking into account the full
+	 * loan term, the interest is simply offset to a later period.
+	 */
+	private Integer interestPaymentGrace;
 
-    /**
-     * Integer representing the number of 'repayment frequencies' or
-     * installments where 'grace' should apply to the charging of interest in a
-     * loans repayment period (installment).
-     * 
-     * <b>Note:</b> The loan is <i>interest-free</i> for the period of time
-     * indicated.
-     */
-    private final Integer interestChargingGrace;
+	/**
+	 * Integer representing the number of 'repayment frequencies' or
+	 * installments where 'grace' should apply to the charging of interest in a
+	 * loans repayment period (installment).
+	 * 
+	 * <b>Note:</b> The loan is <i>interest-free</i> for the period of time
+	 * indicated.
+	 */
+	private final Integer interestChargingGrace;
 
-    /**
-     * Legacy method of support 'grace' on the charging of interest on a loan.
-     * 
-     * <p>
-     * For the typical structured loan, its reasonable to use an integer to
-     * indicate the number of 'repayment frequency' periods the 'grace' should
-     * apply to but for slightly <b>irregular</b> loans where the period between
-     * disbursement and the date of the 'first repayment period' isnt doest
-     * match the 'repayment frequency' but can be less (15days instead of 1
-     * month) or more (6 weeks instead of 1 month) - The idea was to use a date
-     * to indicate from whence interest should be charged.
-     * </p>
-     */
-    private LocalDate interestChargedFromDate;
-    private final Money inArrearsTolerance;
-
-    private final Integer graceOnArrearsAgeing;
-
-    // added
-    private LocalDate loanEndDate;
-
-    private final List<DisbursementData> disbursementDatas;
-
-    private final boolean multiDisburseLoan;
-
-    private BigDecimal fixedEmiAmount;
-
-    private BigDecimal fixedPrincipalAmount;
-
-    private BigDecimal currentPeriodFixedEmiAmount;
-
-    private BigDecimal currentPeriodFixedPrincipalAmount;
-
-    private final BigDecimal actualFixedEmiAmount;
-
-    private final BigDecimal maxOutstandingBalance;
-
-    private Money totalInterestDue;
-
-    private final DaysInMonthType daysInMonthType;
-
-    private final DaysInYearType daysInYearType;
-
-    private final boolean interestRecalculationEnabled;
-
-    private final LoanRescheduleStrategyMethod rescheduleStrategyMethod;
-
-    private final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod;
-
-    private final CalendarInstance restCalendarInstance;
-
-    private final RecalculationFrequencyType recalculationFrequencyType;
-
-    private final CalendarInstance compoundingCalendarInstance;
-
-    private final RecalculationFrequencyType compoundingFrequencyType;
-
-    private final BigDecimal principalThresholdForLastInstalment;
-    private final Integer installmentAmountInMultiplesOf;
-
-    private final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy;
-
-    private Money approvedPrincipal = null;
-
-    private final LoanTermVariationsDataWrapper variationsDataWrapper;
-
-    private Money adjustPrincipalForFlatLoans;
-
-    private final LocalDate seedDate;
-
-    private final CalendarHistoryDataWrapper calendarHistoryDataWrapper;
-    
-    private final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled;
-
-    private final Integer numberOfDays;
-
-    private final boolean isSkipRepaymentOnFirstDayOfMonth;
-
-    public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
-            final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
-            final PeriodFrequencyType repaymentPeriodFrequencyType, Integer nthDay, DayOfWeekType weekDayType,
-            final AmortizationMethod amortizationMethod, final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod,
-            final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualNominalInterestRate,
-            final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final boolean allowPartialPeriodInterestCalcualtion,
-            final Money principalMoney, final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
-            final LocalDate calculatedRepaymentsStartingFromDate, final Integer graceOnPrincipalPayment,
-            final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate,
-            final Money inArrearsTolerance, final boolean multiDisburseLoan, final BigDecimal emiAmount,
-            final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance, final Integer graceOnArrearsAgeing,
-            final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType, final boolean isInterestRecalculationEnabled,
-            final RecalculationFrequencyType recalculationFrequencyType, final CalendarInstance restCalendarInstance,
-            final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
-            final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
-            final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar,
-            BigDecimal approvedAmount, List<LoanTermVariationsData> loanTermVariations, Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled,
-            final Integer numberOfdays,boolean isSkipRepaymentOnFirstDayofMonth) {
-
-           
-    	final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
-        final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
-        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
-        return new LoanApplicationTerms(currency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery,
-                repaymentPeriodFrequencyType, nthDay, weekDayType, amortizationMethod, interestMethod, interestRatePerPeriod,
-                interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod,
-                allowPartialPeriodInterestCalcualtion, principalMoney, expectedDisbursementDate, repaymentsStartingFromDate,
-                calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
-                interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance,
-                graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, rescheduleStrategyMethod,
-                interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType, compoundingCalendarInstance,
-                compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
-                preClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper,
-                isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfdays, isSkipRepaymentOnFirstDayofMonth);
-
-    }
-
-    public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
-            final PeriodFrequencyType loanTermPeriodFrequencyType, NthDayType nthDay, DayOfWeekType dayOfWeek,
-            final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
-            final LocalDate calculatedRepaymentsStartingFromDate, final Money inArrearsTolerance,
-            final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan, final BigDecimal emiAmount,
-            final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
-            final LocalDate interestChargedFromDate, final BigDecimal principalThresholdForLastInstalment,
-            final Integer installmentAmountInMultiplesOf, final RecalculationFrequencyType recalculationFrequencyType,
-            final CalendarInstance restCalendarInstance, final InterestRecalculationCompoundingMethod compoundingMethod,
-            final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
-            final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy,
-            final LoanRescheduleStrategyMethod rescheduleStrategyMethod, BigDecimal approvedAmount, BigDecimal annualNominalInterestRate,
-            List<LoanTermVariationsData> loanTermVariations, final Integer numberOfdays, final boolean isSkipRepaymentOnFirstDayofMonth) {
-        final Calendar loanCalendar = null;
-        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
-
-        return assembleFrom(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, nthDay, dayOfWeek,
-                expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, inArrearsTolerance,
-                loanProductRelatedDetail, multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance, interestChargedFromDate,
-                principalThresholdForLastInstalment, installmentAmountInMultiplesOf, recalculationFrequencyType, restCalendarInstance,
-                compoundingMethod, compoundingCalendarInstance, compoundingFrequencyType, loanPreClosureInterestCalculationStrategy,
-                rescheduleStrategyMethod, loanCalendar, approvedAmount, annualNominalInterestRate, loanTermVariations,
-                calendarHistoryDataWrapper, numberOfdays, isSkipRepaymentOnFirstDayofMonth);
-    }
-
-    public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
-            final PeriodFrequencyType loanTermPeriodFrequencyType, NthDayType nthDay, DayOfWeekType dayOfWeek,
-            final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
-            final LocalDate calculatedRepaymentsStartingFromDate, final Money inArrearsTolerance,
-            final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan, final BigDecimal emiAmount,
-            final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
-            final LocalDate interestChargedFromDate, final BigDecimal principalThresholdForLastInstalment,
-            final Integer installmentAmountInMultiplesOf, final RecalculationFrequencyType recalculationFrequencyType,
-            final CalendarInstance restCalendarInstance, final InterestRecalculationCompoundingMethod compoundingMethod,
-            final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
-            final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy,
-            final LoanRescheduleStrategyMethod rescheduleStrategyMethod, final Calendar loanCalendar, BigDecimal approvedAmount,
-            BigDecimal annualNominalInterestRate, final List<LoanTermVariationsData> loanTermVariations,
-            final CalendarHistoryDataWrapper calendarHistoryDataWrapper, final Integer numberOfdays,
-            final boolean isSkipRepaymentOnFirstDayofMonth) {
-
-        final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
-        final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
-        final PeriodFrequencyType repaymentPeriodFrequencyType = loanProductRelatedDetail.getRepaymentPeriodFrequencyType();
-        final AmortizationMethod amortizationMethod = loanProductRelatedDetail.getAmortizationMethod();
-        final InterestMethod interestMethod = loanProductRelatedDetail.getInterestMethod();
-        final BigDecimal interestRatePerPeriod = loanProductRelatedDetail.getNominalInterestRatePerPeriod();
-        final PeriodFrequencyType interestRatePeriodFrequencyType = loanProductRelatedDetail.getInterestPeriodFrequencyType();
-        final InterestCalculationPeriodMethod interestCalculationPeriodMethod = loanProductRelatedDetail
-                .getInterestCalculationPeriodMethod();
-        final boolean allowPartialPeriodInterestCalcualtion = loanProductRelatedDetail.isAllowPartialPeriodInterestCalcualtion();
-        final Money principalMoney = loanProductRelatedDetail.getPrincipal();
-
-        //
-        final Integer graceOnPrincipalPayment = loanProductRelatedDetail.graceOnPrincipalPayment();
-        final Integer graceOnInterestPayment = loanProductRelatedDetail.graceOnInterestPayment();
-        final Integer graceOnInterestCharged = loanProductRelatedDetail.graceOnInterestCharged();
-
-        // Interest recalculation settings
-        final DaysInMonthType daysInMonthType = loanProductRelatedDetail.fetchDaysInMonthType();
-        final DaysInYearType daysInYearType = loanProductRelatedDetail.fetchDaysInYearType();
-        final boolean isInterestRecalculationEnabled = loanProductRelatedDetail.isInterestRecalculationEnabled();
-        final boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = false;
-        return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
-                repaymentEvery, repaymentPeriodFrequencyType, nthDay.getValue(), dayOfWeek, amortizationMethod, interestMethod,
-                interestRatePerPeriod, interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod,
-                allowPartialPeriodInterestCalcualtion, principalMoney, expectedDisbursementDate, repaymentsStartingFromDate,
-                calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
-                interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance,
-                loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
-                rescheduleStrategyMethod, compoundingMethod, restCalendarInstance, recalculationFrequencyType, compoundingCalendarInstance,
-                compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
-                loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper,
-                isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfdays, isSkipRepaymentOnFirstDayofMonth);
-    }
-
-    public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
-            final PeriodFrequencyType loanTermPeriodFrequencyType, final LocalDate expectedDisbursementDate,
-            final LocalDate repaymentsStartingFromDate, final LocalDate calculatedRepaymentsStartingFromDate,
-            final Money inArrearsTolerance, final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan,
-            final BigDecimal emiAmount, final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
-            final LocalDate interestChargedFromDate, final LoanInterestRecalculationDetails interestRecalculationDetails,
-            final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType,
-            final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
-            final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
-            final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy, final Calendar loanCalendar,
-            BigDecimal approvedAmount, final BigDecimal annualNominalInterestRate, final List<LoanTermVariationsData> loanTermVariations,
-            Integer numberOfdays, boolean isSkipRepaymentOnFirstDayofMonth) {
-
-        final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
-        final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
-        final PeriodFrequencyType repaymentPeriodFrequencyType = loanProductRelatedDetail.getRepaymentPeriodFrequencyType();
-        final AmortizationMethod amortizationMethod = loanProductRelatedDetail.getAmortizationMethod();
-        final InterestMethod interestMethod = loanProductRelatedDetail.getInterestMethod();
-        final BigDecimal interestRatePerPeriod = loanProductRelatedDetail.getNominalInterestRatePerPeriod();
-        final PeriodFrequencyType interestRatePeriodFrequencyType = loanProductRelatedDetail.getInterestPeriodFrequencyType();
-        final InterestCalculationPeriodMethod interestCalculationPeriodMethod = loanProductRelatedDetail
-                .getInterestCalculationPeriodMethod();
-        final boolean allowPartialPeriodInterestCalcualtion = loanProductRelatedDetail.isAllowPartialPeriodInterestCalcualtion();
-        final Money principalMoney = loanProductRelatedDetail.getPrincipal();
-
-        //
-        final Integer graceOnPrincipalPayment = loanProductRelatedDetail.graceOnPrincipalPayment();
-        final Integer graceOnInterestPayment = loanProductRelatedDetail.graceOnInterestPayment();
-        final Integer graceOnInterestCharged = loanProductRelatedDetail.graceOnInterestCharged();
-
-        // Interest recalculation settings
-        final DaysInMonthType daysInMonthType = loanProductRelatedDetail.fetchDaysInMonthType();
-        final DaysInYearType daysInYearType = loanProductRelatedDetail.fetchDaysInYearType();
-        final boolean isInterestRecalculationEnabled = loanProductRelatedDetail.isInterestRecalculationEnabled();
-        LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
-        InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
-        if (isInterestRecalculationEnabled) {
-            rescheduleStrategyMethod = interestRecalculationDetails.getRescheduleStrategyMethod();
-            interestRecalculationCompoundingMethod = interestRecalculationDetails.getInterestRecalculationCompoundingMethod();
-        }
-        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
-        final boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = false;
-
-        return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
-                repaymentEvery, repaymentPeriodFrequencyType, null, null, amortizationMethod, interestMethod, interestRatePerPeriod,
-                interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod,
-                allowPartialPeriodInterestCalcualtion, principalMoney, expectedDisbursementDate, repaymentsStartingFromDate,
-                calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
-                interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance,
-                loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
-                rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType,
-                compoundingCalendarInstance, compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
-                loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper,
-                isInterestChargedFromDateSameAsDisbursalDateEnabled,  numberOfdays, isSkipRepaymentOnFirstDayofMonth);
-
-    }
-
-    public static LoanApplicationTerms assembleFrom(final LoanApplicationTerms applicationTerms,
-            final List<LoanTermVariationsData> loanTermVariations) {
-        return new LoanApplicationTerms(applicationTerms.currency, applicationTerms.loanTermFrequency,
-                applicationTerms.loanTermPeriodFrequencyType, applicationTerms.numberOfRepayments, applicationTerms.repaymentEvery,
-                applicationTerms.repaymentPeriodFrequencyType, applicationTerms.nthDay, applicationTerms.weekDayType,
-                applicationTerms.amortizationMethod, applicationTerms.interestMethod, applicationTerms.interestRatePerPeriod,
-                applicationTerms.interestRatePeriodFrequencyType, applicationTerms.annualNominalInterestRate,
-                applicationTerms.interestCalculationPeriodMethod, applicationTerms.allowPartialPeriodInterestCalcualtion,
-                applicationTerms.principal, applicationTerms.expectedDisbursementDate, applicationTerms.repaymentsStartingFromDate,
-                applicationTerms.calculatedRepaymentsStartingFromDate, applicationTerms.principalGrace,
-                applicationTerms.interestPaymentGrace, applicationTerms.interestChargingGrace, applicationTerms.interestChargedFromDate,
-                applicationTerms.inArrearsTolerance, applicationTerms.multiDisburseLoan, applicationTerms.actualFixedEmiAmount,
-                applicationTerms.disbursementDatas, applicationTerms.maxOutstandingBalance, applicationTerms.graceOnArrearsAgeing,
-                applicationTerms.daysInMonthType, applicationTerms.daysInYearType, applicationTerms.interestRecalculationEnabled,
-                applicationTerms.rescheduleStrategyMethod, applicationTerms.interestRecalculationCompoundingMethod,
-                applicationTerms.restCalendarInstance, applicationTerms.recalculationFrequencyType,
-                applicationTerms.compoundingCalendarInstance, applicationTerms.compoundingFrequencyType,
-                applicationTerms.principalThresholdForLastInstalment, applicationTerms.installmentAmountInMultiplesOf,
-                applicationTerms.preClosureInterestCalculationStrategy, applicationTerms.loanCalendar,
-                applicationTerms.approvedPrincipal.getAmount(), loanTermVariations, applicationTerms.calendarHistoryDataWrapper,
-                applicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled, applicationTerms.numberOfDays, 
-                applicationTerms.isSkipRepaymentOnFirstDayOfMonth);
- }
-
-    private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
-            final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
-            final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer nthDay, final DayOfWeekType weekDayType,
-            final AmortizationMethod amortizationMethod, final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod,
-            final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualNominalInterestRate,
-            final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final boolean allowPartialPeriodInterestCalcualtion,
-            final Money principal, final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
-            final LocalDate calculatedRepaymentsStartingFromDate, final Integer principalGrace, final Integer interestPaymentGrace,
-            final Integer interestChargingGrace, final LocalDate interestChargedFromDate, final Money inArrearsTolerance,
-            final boolean multiDisburseLoan, final BigDecimal emiAmount, final List<DisbursementData> disbursementDatas,
-            final BigDecimal maxOutstandingBalance, final Integer graceOnArrearsAgeing, final DaysInMonthType daysInMonthType,
-            final DaysInYearType daysInYearType, final boolean isInterestRecalculationEnabled,
-            final LoanRescheduleStrategyMethod rescheduleStrategyMethod,
-            final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod,
-            final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType,
-            final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
-            final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
-            final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar,
-            BigDecimal approvedAmount, List<LoanTermVariationsData> loanTermVariations,
-            final CalendarHistoryDataWrapper calendarHistoryDataWrapper, Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled, 
-            final Integer numberOfdays, final boolean isSkipRepaymentOnFirstDayofMonth) {
-
-        this.currency = currency;
-        this.loanTermFrequency = loanTermFrequency;
-        this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
-        this.numberOfRepayments = numberOfRepayments;
-        this.repaymentEvery = repaymentEvery;
-        this.repaymentPeriodFrequencyType = repaymentPeriodFrequencyType;
-        this.nthDay = nthDay;
-        this.weekDayType = weekDayType;
-        this.amortizationMethod = amortizationMethod;
-
-        this.interestMethod = interestMethod;
-        this.interestRatePerPeriod = interestRatePerPeriod;
-        this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType;
-        this.annualNominalInterestRate = annualNominalInterestRate;
-        this.interestCalculationPeriodMethod = interestCalculationPeriodMethod;
-        this.allowPartialPeriodInterestCalcualtion = allowPartialPeriodInterestCalcualtion;
-
-        this.principal = principal;
-        this.expectedDisbursementDate = expectedDisbursementDate;
-        this.repaymentsStartingFromDate = repaymentsStartingFromDate;
-        this.calculatedRepaymentsStartingFromDate = calculatedRepaymentsStartingFromDate;
-
-        this.principalGrace = principalGrace;
-        this.interestPaymentGrace = interestPaymentGrace;
-        this.interestChargingGrace = interestChargingGrace;
-        this.interestChargedFromDate = interestChargedFromDate;
-
-        this.inArrearsTolerance = inArrearsTolerance;
-        this.multiDisburseLoan = multiDisburseLoan;
-        this.fixedEmiAmount = emiAmount;
-        this.actualFixedEmiAmount = emiAmount;
-        this.disbursementDatas = disbursementDatas;
-        this.maxOutstandingBalance = maxOutstandingBalance;
-        this.graceOnArrearsAgeing = graceOnArrearsAgeing;
-        this.daysInMonthType = daysInMonthType;
-        this.daysInYearType = daysInYearType;
-        this.interestRecalculationEnabled = isInterestRecalculationEnabled;
-        this.rescheduleStrategyMethod = rescheduleStrategyMethod;
-        this.interestRecalculationCompoundingMethod = interestRecalculationCompoundingMethod;
-        this.restCalendarInstance = restCalendarInstance;
-        this.compoundingCalendarInstance = compoundingCalendarInstance;
-        this.recalculationFrequencyType = recalculationFrequencyType;
-        this.compoundingFrequencyType = compoundingFrequencyType;
-        this.principalThresholdForLastInstalment = principalThresholdForLastInstalment;
-        this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
-        this.preClosureInterestCalculationStrategy = preClosureInterestCalculationStrategy;
-        this.isSkipRepaymentOnFirstDayOfMonth = isSkipRepaymentOnFirstDayofMonth;
-        this.numberOfDays = numberOfdays;
-
-        this.loanCalendar = loanCalendar;
-        this.approvedPrincipal = Money.of(principal.getCurrency(), approvedAmount);
-        this.variationsDataWrapper = new LoanTermVariationsDataWrapper(loanTermVariations);
-        this.actualNumberOfRepayments = numberOfRepayments + getLoanTermVariations().adjustNumberOfRepayments();
-        this.adjustPrincipalForFlatLoans = principal.zero();
-        if (this.calculatedRepaymentsStartingFromDate == null) {
-            this.seedDate = this.expectedDisbursementDate;
-        } else {
-            this.seedDate = this.calculatedRepaymentsStartingFromDate;
-        }
-        this.calendarHistoryDataWrapper = calendarHistoryDataWrapper;
-        this.isInterestChargedFromDateSameAsDisbursalDateEnabled = isInterestChargedFromDateSameAsDisbursalDateEnabled;
-    }
-
-    public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
-            final int periodNumber) {
-
-        Money adjusted = principalForPeriod;
-
-        final Money totalPrincipalRemaining = this.principal.minus(totalCumulativePrincipalToDate);
-        if (totalPrincipalRemaining.isLessThanZero()) {
-            // paid too much principal, subtract amount that overpays from
-            // principal paid for period.
-            adjusted = principalForPeriod.minus(totalPrincipalRemaining.abs());
-        } else if (this.actualFixedEmiAmount != null) {
-            final Money difference = this.principal.minus(totalCumulativePrincipalToDate);
-            final Money principalThreshold = principalForPeriod.multipliedBy(this.principalThresholdForLastInstalment).dividedBy(100,
-                    MoneyHelper.getRoundingMode());
-            if (difference.isLessThan(principalThreshold)) {
-                adjusted = principalForPeriod.plus(difference.abs());
-            }
-        } else if (isLastRepaymentPeriod(this.actualNumberOfRepayments, periodNumber)) {
-
-            final Money difference = totalCumulativePrincipalToDate.minus(this.principal);
-            if (difference.isLessThanZero()) {
-                adjusted = principalForPeriod.plus(difference.abs());
-            } else if (difference.isGreaterThanZero()) {
-                adjusted = principalForPeriod.minus(difference.abs());
-            }
-        }
-
-        return adjusted;
-    }
-
-    public Money adjustInterestIfLastRepaymentPeriod(final Money interestForThisPeriod, final Money totalCumulativeInterestToDate,
-            final Money totalInterestDueForLoan, final int periodNumber) {
-
-        Money adjusted = interestForThisPeriod;
-
-        final Money totalInterestRemaining = totalInterestDueForLoan.minus(totalCumulativeInterestToDate);
-        if (totalInterestRemaining.isLessThanZero()) {
-            // paid too much interest, subtract amount that overpays from
-            // interest paid for period.
-            adjusted = interestForThisPeriod.minus(totalInterestRemaining.abs());
-        } else if (isLastRepaymentPeriod(this.actualNumberOfRepayments, periodNumber)) {
-            final Money interestDifference = totalCumulativeInterestToDate.minus(totalInterestDueForLoan);
-            if (interestDifference.isLessThanZero()) {
-                adjusted = interestForThisPeriod.plus(interestDifference.abs());
-            } else if (interestDifference.isGreaterThanZero()) {
-                adjusted = interestForThisPeriod.minus(interestDifference.abs());
-            }
-        }
-        if (adjusted.isLessThanZero()) {
-            adjusted = adjusted.plus(adjusted);
-        }
-        return adjusted;
-    }
-
-    /**
-     * Calculates the total interest to be charged on loan taking into account
-     * grace settings.
-     * 
-     */
-    public Money calculateTotalInterestCharged(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc) {
-
-        Money totalInterestCharged = this.principal.zero();
-
-        switch (this.interestMethod) {
-            case FLAT:
-                final Money totalInterestChargedForLoanTerm = calculateTotalFlatInterestDueWithoutGrace(calculator, mc);
-
-                final Money totalInterestPerInstallment = calculateTotalInterestPerInstallmentWithoutGrace(calculator, mc);
-
-                final Money totalGraceOnInterestCharged = totalInterestPerInstallment.multiplyRetainScale(getInterestChargingGrace(),
-                        mc.getRoundingMode());
-
-                totalInterestCharged = totalInterestChargedForLoanTerm.minus(totalGraceOnInterestCharged);
-            break;
-            case DECLINING_BALANCE:
-            case INVALID:
-            break;
-        }
-
-        return totalInterestCharged;
-    }
-
-    public Money calculateTotalPrincipalForPeriod(final PaymentPeriodsInOneYearCalculator calculator, final Money outstandingBalance,
-            final int periodNumber, final MathContext mc, Money interestForThisInstallment) {
-
-        Money principalForInstallment = this.principal.zero();
-
-        switch (this.interestMethod) {
-            case FLAT:
-                principalForInstallment = calculateTotalPrincipalPerPeriodWithoutGrace(mc, periodNumber);
-            break;
-            case DECLINING_BALANCE:
-                switch (this.amortizationMethod) {
-                    case EQUAL_INSTALLMENTS:
-                        Money totalPmtForThisInstallment = pmtForInstallment(calculator, outstandingBalance, periodNumber, mc);
-                        principalForInstallment = calculatePrincipalDueForInstallment(periodNumber, totalPmtForThisInstallment,
-                                interestForThisInstallment);
-                    break;
-                    case EQUAL_PRINCIPAL:
-                        principalForInstallment = calculateEqualPrincipalDueForInstallment(mc, periodNumber);
-                    break;
-                    case INVALID:
-                    break;
-                }
-            break;
-            case INVALID:
-            break;
-        }
-
-        return principalForInstallment;
-    }
-
-    public Money pmtForInstallment(final PaymentPeriodsInOneYearCalculator calculator, final Money outstandingBalance,
-            final int periodNumber, final MathContext mc) {
-        // Calculate exact period from disbursement date
-        final LocalDate periodStartDate = getExpectedDisbursementDate().withDayOfMonth(1);
-        final LocalDate periodEndDate = getPeriodEndDate(periodStartDate);
-        // equal installments
-        final int periodsElapsed = periodNumber - 1;
-        // with periodic interest for default month and year for
-        // equal installment
-        final BigDecimal periodicInterestRateForRepaymentPeriod = periodicInterestRate(calculator, mc, DaysInMonthType.DAYS_30,
-                DaysInYearType.DAYS_365, periodStartDate, periodEndDate);
-        Money totalPmtForThisInstallment = calculateTotalDueForEqualInstallmentRepaymentPeriod(periodicInterestRateForRepaymentPeriod,
-                outstandingBalance, periodsElapsed);
-        return totalPmtForThisInstallment;
-    }
-
-    private LocalDate getPeriodEndDate(final LocalDate startDate) {
-        LocalDate dueRepaymentPeriodDate = startDate;
-        switch (this.repaymentPeriodFrequencyType) {
-            case DAYS:
-                dueRepaymentPeriodDate = startDate.plusDays(this.repaymentEvery);
-            break;
-            case WEEKS:
-                dueRepaymentPeriodDate = startDate.plusWeeks(this.repaymentEvery);
-            break;
-            case MONTHS:
-                dueRepaymentPeriodDate = startDate.plusMonths(this.repaymentEvery);
-            break;
-            case YEARS:
-                dueRepaymentPeriodDate = startDate.plusYears(this.repaymentEvery);
-            break;
-            case INVALID:
-            break;
-        }
-        return dueRepaymentPeriodDate;
-    }
-
-    public PrincipalInterest calculateTotalInterestForPeriod(final PaymentPeriodsInOneYearCalculator calculator,
-            final double interestCalculationGraceOnRepaymentPeriodFraction, final int periodNumber, final MathContext mc,
-            final Money cumulatingInterestPaymentDueToGrace, final Money outstandingBalance, final LocalDate periodStartDate,
-            final LocalDate periodEndDate) {
-
-        Money interestForInstallment = this.principal.zero();
-        Money interestBroughtForwardDueToGrace = cumulatingInterestPaymentDueToGrace.copy();
-
-        switch (this.interestMethod) {
-            case FLAT:
-
-                switch (this.amortizationMethod) {
-                    case EQUAL_INSTALLMENTS:
-                        // average out outstanding interest over remaining
-                        // instalments where interest is applicable
-                        interestForInstallment = calculateTotalFlatInterestForInstallmentAveragingOutGracePeriods(calculator, periodNumber,
-                                mc);
-                    break;
-                    case EQUAL_PRINCIPAL:
-                        // interest follows time-value of money and is brought
-                        // forward to next applicable interest payment period
-                        final PrincipalInterest result = calculateTotalFlatInterestForPeriod(calculator, periodNumber, mc,
-                                interestBroughtForwardDueToGrace);
-                        interestForInstallment = result.interest();
-                        interestBroughtForwardDueToGrace = result.interestPaymentDueToGrace();
-                    break;
-                    case INVALID:
-                    break;
-                }
-            break;
-            case DECLINING_BALANCE:
-
-                final Money interestForThisInstallmentBeforeGrace = calculateDecliningInterestDueForInstallmentBeforeApplyingGrace(
-                        calculator, mc, outstandingBalance, periodStartDate, periodEndDate);
-
-                final Money interestForThisInstallmentAfterGrace = calculateDecliningInterestDueForInstallmentAfterApplyingGrace(
-                        calculator, interestCalculationGraceOnRepaymentPeriodFraction, mc, outstandingBalance, periodNumber,
-                        periodStartDate, periodEndDate);
-
-                interestForInstallment = interestForThisInstallmentAfterGrace;
-                if (interestForThisInstallmentAfterGrace.isGreaterThanZero()) {
-                    interestForInstallment = interestBroughtForwardDueToGrace.plus(interestForThisInstallmentAfterGrace);
-                    interestBroughtForwardDueToGrace = interestBroughtForwardDueToGrace.zero();
-                } else if (isInterestFreeGracePeriod(periodNumber)) {
-                    interestForInstallment = interestForInstallment.zero();
-                } else if (isInterestFreeGracePeriodFromDate(interestCalculationGraceOnRepaymentPeriodFraction)) {
-                    interestForInstallment = interestForThisInstallmentAfterGrace;
-                } else {
-                    interestBroughtForwardDueToGrace = interestBroughtForwardDueToGrace.plus(interestForThisInstallmentBeforeGrace);
-                }
-            break;
-            case INVALID:
-            break;
-        }
-
-        return new PrincipalInterest(null, interestForInstallment, interestBroughtForwardDueToGrace);
-    }
-
-    private final boolean isLastRepaymentPeriod(final int numberOfRepayments, final int periodNumber) {
-        return periodNumber == numberOfRepayments;
-    }
-
-    /**
-     * general method to calculate totalInterestDue discounting any grace
-     * settings
-     */
-    private Money calculateTotalFlatInterestDueWithoutGrace(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc) {
-
-        Money totalInterestDue = this.principal.zero();
-
-        switch (this.interestMethod) {
-            case FLAT:
-                final BigDecimal interestRateForLoanTerm = calculateFlatInterestRateForLoanTerm(calculator, mc);
-                totalInterestDue = this.principal.multiplyRetainScale(interestRateForLoanTerm, mc.getRoundingMode());
-
-            break;
-            case DECLINING_BALANCE:
-            break;
-            case INVALID:
-            break;
-        }
-
-        if (this.totalInterestDue != null) {
-            totalInterestDue = this.totalInterestDue;
-        }
-
-        return totalInterestDue;
-    }
-
-    private BigDecimal calculateFlatInterestRateForLoanTerm(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc) {
-
-        final BigDecimal divisor = BigDecimal.valueOf(Double.valueOf("100.0"));
-
-        final long loanTermPeriodsInOneYear = calculatePeriodsInOneYear(calculator);
-        final BigDecimal loanTermPeriodsInYearBigDecimal = BigDecimal.valueOf(loanTermPeriodsInOneYear);
-
-        final BigDecimal loanTermFrequencyBigDecimal = calculatePeriodsInLoanTerm();
-
-        return this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc).divide(divisor, mc)
-                .multiply(loanTermFrequencyBigDecimal);
-    }
-
-    private BigDecimal calculatePeriodsInLoanTerm() {
-
-        BigDecimal periodsInLoanTerm = BigDecimal.valueOf(this.loanTermFrequency);
-        switch (this.interestCalculationPeriodMethod) {
-            case DAILY:
-                // number of days from 'ideal disbursement' to final date
-
-                LocalDate loanStartDate = getExpectedDisbursementDate();
-                if (getInterestChargedFromDate() != null && loanStartDate.isBefore(getInterestChargedFromLocalDate())) {
-                    loanStartDate = getInterestChargedFromLocalDate();
-                }
-
-                final int periodsInLoanTermInteger = Days.daysBetween(loanStartDate, this.loanEndDate).getDays();
-                periodsInLoanTerm = BigDecimal.valueOf(periodsInLoanTermInteger);
-            break;
-            case INVALID:
-            break;
-            case SAME_AS_REPAYMENT_PERIOD:
-                if (this.allowPartialPeriodInterestCalcualtion) {
-                    LocalDate startDate = getExpectedDisbursementDate();
-                    if (getInterestChargedFromDate() != null) {
-                        startDate = getInterestChargedFromLocalDate();
-                    }
-                    periodsInLoanTerm = calculatePeriodsBetweenDates(startDate, this.loanEndDate);
-                }
-            break;
-        }
-
-        return periodsInLoanTerm;
-    }
-
-    public BigDecimal calculatePeriodsBetweenDates(final LocalDate startDate, final LocalDate endDate) {
-        BigDecimal numberOfPeriods = BigDecimal.ZERO;
-        switch (this.repaymentPeriodFrequencyType) {
-            case DAYS:
-                int numberOfDays = Days.daysBetween(startDate, endDate).getDays();
-                numberOfPeriods = BigDecimal.valueOf((double) numberOfDays);
-            break;
-            case WEEKS:
-                int numberOfWeeks = Weeks.weeksBetween(startDate, endDate).getWeeks();
-                int daysLeftAfterWeeks = Days.daysBetween(startDate.plusWeeks(numberOfWeeks), endDate).getDays();
-                numberOfPeriods = numberOfPeriods.add(BigDecimal.valueOf(numberOfWeeks)).add(
-                        BigDecimal.valueOf((double) daysLeftAfterWeeks / 7));
-            break;
-            case MONTHS:
-                int numberOfMonths = Months.monthsBetween(startDate, endDate).getMonths();
-                LocalDate startDateAfterConsideringMonths = startDate.plusMonths(numberOfMonths);
-                LocalDate endDateAfterConsideringMonths = startDate.plusMonths(numberOfMonths + 1);
-                int daysLeftAfterMonths = Days.daysBetween(startDateAfterConsideringMonths, endDate).getDays();
-                int daysInPeriodAfterMonths = Days.daysBetween(startDateAfterConsideringMonths, endDateAfterConsideringMonths).getDays();
-                numberOfPeriods = numberOfPeriods.add(BigDecimal.valueOf(numberOfMonths)).add(
-                        BigDecimal.valueOf((double) daysLeftAfterMonths / daysInPeriodAfterMonths));
-            break;
-            case YEARS:
-                int numberOfYears = Years.yearsBetween(startDate, endDate).getYears();
-                LocalDate startDateAfterConsideringYears = startDate.plusYears(numberOfYears);
-                LocalDate endDateAfterConsideringYears = startDate.plusYears(numberOfYears + 1);
-                int daysLeftAfterYears = Days.daysBetween(startDateAfterConsideringYears, endDate).getDays();
-                int daysInPeriodAfterYears = Days.daysBetween(startDateAfterConsideringYears, endDateAfterConsideringYears).getDays();
-                numberOfPeriods = numberOfPeriods.add(BigDecimal.valueOf(numberOfYears)).add(
-                        BigDecimal.valueOf((double) daysLeftAfterYears / daysInPeriodAfterYears));
-            break;
-            default:
-            break;
-        }
-        return numberOfPeriods;
-    }
-
-    public void updateLoanEndDate(final LocalDate loanEndDate) {
-        this.loanEndDate = loanEndDate;
-    }
-
-    private Money calculateTotalInterestPerInstallmentWithoutGrace(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc) {
-
-        final Money totalInterestForLoanTerm = calculateTotalFlatInterestDueWithoutGrace(calculator, mc);
-
-        return totalInterestForLoanTerm.dividedBy(Long.valueOf(this.actualNumberOfRepayments), mc.getRoundingMode());
-    }
-
-    private Money calculateTotalPrincipalPerPeriodWithoutGrace(final MathContext mc, final int periodNumber) {
-        final int totalRepaymentsWithCapitalPayment = calculateNumberOfRepaymentsWithPrincipalPayment();
-        Money principalPerPeriod = this.principal.dividedBy(totalRepaymentsWithCapitalPayment, mc.getRoundingMode()).plus(
-                this.adjustPrincipalForFlatLoans);
-        if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) {
-            principalPerPeriod = principalPerPeriod.zero();
-        }
-        if (!isPrincipalGraceApplicableForThisPeriod(periodNumber) && currentPeriodFixedPrincipalAmount != null) {
-            this.adjustPrincipalForFlatLoans = this.adjustPrincipalForFlatLoans.plus(principalPerPeriod.minus(
-                    currentPeriodFixedPrincipalAmount).dividedBy(this.actualNumberOfRepayments - periodNumber, mc.getRoundingMode()));
-            principalPerPeriod = this.principal.zero().plus(currentPeriodFixedPrincipalAmount);
-
-        }
-        return principalPerPeriod;
-    }
-
-    private PrincipalInterest calculateTotalFlatInterestForPeriod(final PaymentPeriodsInOneYearCalculator calculator,
-            final int periodNumber, final MathContext mc, final Money cumulatingInterestPaymentDueToGrace) {
-
-        Money interestBroughtForwardDueToGrace = cumulatingInterestPaymentDueToGrace.copy();
-
-        Money interestForInstallment = calculateTotalInterestPerInstallmentWithoutGrace(calculator, mc);
-        if (isInterestPaymentGraceApplicableForThisPeriod(periodNumber)) {
-            interestBroughtForwardDueToGrace = interestBroughtForwardDueToGrace.plus(interestForInstallment);
-            interestForInstallment = interestForInstallment.zero();
-        } else if (isInterestFreeGracePeriod(periodNumber)) {
-            interestForInstallment = interestForInstallment.zero();
-        } else if (isFirstPeriodAfterInterestPaymentGracePeriod(periodNumber)) {
-            interestForInstallment = cumulatingInterestPaymentDueToGrace.plus(interestForInstallment);
-            interestBroughtForwardDueToGrace = interestBroughtForwardDueToGrace.zero();
-        }
-
-        return new PrincipalInterest(null, interestForInstallment, interestBroughtForwardDueToGrace);
-    }
-
-    /*
-     * calculates the interest that should be due for a given scheduled loan
-     * repayment period. It takes into account GRACE periods and calculates how
-     * much interest is due per period by averaging the number of periods where
-     * interest is due and should be paid against the total known interest that
-     * is due without grace.
-     */
-    private Money calculateTotalFlatInterestForInstallmentAveragingOutGracePeriods(final PaymentPeriodsInOneYearCalculator calculator,
-            final int periodNumber, final MathContext mc) {
-
-        Money interestForInstallment = calculateTotalInterestPerInstallmentWithoutGrace(calculator, mc);
-        if (isInterestPaymentGraceApplicableForThisPeriod(periodNumber)) {
-            interestForInstallment = interestForInstallment.zero();
-        } else if (isInterestFreeGracePeriod(periodNumber)) {
-            interestForInstallment = interestForInstallment.zero();
-        } else {
-
-            final Money totalInterestForLoanTerm = calculateTotalFlatInterestDueWithoutGrace(calculator, mc);
-
-            final Money interestPerGracePeriod = calculateTotalInterestPerInstallmentWithoutGrace(calculator, mc);
-
-            final Money totalInterestFree = interestPerGracePeriod.multipliedBy(getInterestChargingGrace());
-            final Money realTotalInterestForLoan = totalInterestForLoanTerm.minus(totalInterestFree);
-
-            final Integer interestPaymentDuePeriods = calculateNumberOfRepaymentPeriodsWhereInterestPaymentIsDue(this.actualNumberOfRepayments);
-
-            interestForInstallment = realTotalInterestForLoan
-                    .dividedBy(BigDecimal.valueOf(interestPaymentDuePeriods), mc.getRoundingMode());
-        }
-
-        return interestForInstallment;
-    }
-
-    private BigDecimal periodicInterestRate(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc,
-            final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType, LocalDate periodStartDate, LocalDate periodEndDate) {
-
-        final long loanTermPeriodsInOneYear = calculatePeriodsInOneYear(calculator);
-
-        final BigDecimal divisor = BigDecimal.valueOf(Double.valueOf("100.0"));
-        final BigDecimal loanTermPeriodsInYearBigDecimal = BigDecimal.valueOf(loanTermPeriodsInOneYear);
-
-        BigDecimal periodicInterestRate = BigDecimal.ZERO;
-        BigDecimal loanTermFrequencyBigDecimal = calculateLoanTermFrequency(periodStartDate, periodEndDate);
-        switch (this.interestCalculationPeriodMethod) {
-            case INVALID:
-            break;
-            case DAILY:
-                // For daily work out number of days in the period
-                BigDecimal numberOfDaysInPeriod = BigDecimal.valueOf(Days.daysBetween(periodStartDate, periodEndDate).getDays());
-
-                final BigDecimal oneDayOfYearInterestRate = this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc)
-                        .divide(divisor, mc);
-
-                switch (this.repaymentPeriodFrequencyType) {
-                    case INVALID:
-                    break;
-                    case DAYS:
-                        periodicInterestRate = oneDayOfYearInterestRate.multiply(numberOfDaysInPeriod, mc);
-                    break;
-                    case WEEKS:
-                        periodicInterestRate = oneDayOfYearInterestRate.multiply(numberOfDaysInPeriod, mc);
-                    break;
-                    case MONTHS:
-                        if (daysInMonthType.isDaysInMonth_30()) {
-                            numberOfDaysInPeriod = loanTermFrequencyBigDecimal.multiply(BigDecimal.valueOf(30), mc);
-                        }
-                        periodicInterestRate = oneDayOfYearInterestRate.multiply(numberOfDaysInPeriod, mc);
-                    break;
-                    case YEARS:
-                        switch (daysInYearType) {
-                            case DAYS_360:
-                                numberOfDaysInPeriod = loanTermFrequencyBigDecimal.multiply(BigDecimal.valueOf(360), mc);
-                            break;
-                            case DAYS_364:
-                                numberOfDaysInPeriod = loanTermFrequencyBigDecimal.multiply(BigDecimal.valueOf(364), mc);
-                            break;
-                            case DAYS_365:
-                                numberOfDaysInPeriod = loanTermFrequencyBigDecimal.multiply(BigDecimal.valueOf(365), mc);
-                            break;
-                            default:
-                            break;
-                        }
-                        periodicInterestRate = oneDayOfYearInterestRate.multiply(numberOfDaysInPeriod, mc);
-                    break;
-                }
-            break;
-            case SAME_AS_REPAYMENT_PERIOD:
-                periodicInterestRate = this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc).divide(divisor, mc)
-                        .multiply(loanTermFrequencyBigDecimal);
-            break;
-        }
-
-        return periodicInterestRate;
-    }
-
-    private BigDecimal calculateLoanTermFrequency(final LocalDate periodStartDate, final LocalDate periodEndDate) {
-        BigDecimal loanTermFrequencyBigDecimal = BigDecimal.valueOf(this.repaymentEvery);
-        if (this.interestCalculationPeriodMethod.isDaily() || this.allowPartialPeriodInterestCalcualtion) {
-            loanTermFrequencyBigDecimal = calculatePeriodsBetweenDates(periodStartDate, periodEndDate);
-        }
-        return loanTermFrequencyBigDecimal;
-    }
-
-    public BigDecimal interestRateFor(final PaymentPeriodsInOneYearCalculator calculator, final MathContext mc,
-            final Money outstandingBalance, final LocalDate fromDate, final LocalDate toDate) {
-
-        long loanTermPeriodsInOneYear = calculator.calculate(PeriodFrequencyType.DAYS).longValue();
-        int repaymentEvery = Days.daysBetween(fromDate, toDate).getDays();
-        if (isFallingInRepaymentPeriod(fromDate, toDate)) {
-            loanTermPeriodsInOneYear = calculatePeriodsInOneYear(calculator);
-            repaymentEvery = getPeriodsBetween(fromDate, toDate);
-        }
-
-        final BigDecimal divisor = BigDecimal.valueOf(Double.valueOf("100.0"));
-        final BigDecimal loanTermPeriodsInYearBigDecimal = BigDecimal.valueOf(loanTermPeriodsInOneYear);
-        final BigDecimal oneDayOfYearInterestRate = this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc).divide(
-                divisor, mc);
-        BigDecimal interestRate = oneDayOfYearInterestRate.multiply(BigDecimal.valueOf(repaymentEvery), mc);
-        return outstandingBalance.getAmount().multiply(interestRate, mc);
-    }
-
-    private long calculatePeriodsInOneYear(final PaymentPeriodsInOneYearCalculator calculator) {
-
-        // check if daysInYears is set if so change periodsInOneYear to days set
-        // in db
-        long periodsInOneYear;
-        boolean daysInYearToUse = (this.repaymentPeriodFrequencyType.getCode().equalsIgnoreCase("periodFrequencyType.days") && !this.daysInYearType
-                .getCode().equalsIgnoreCase("DaysInYearType.actual"));
-        if (daysInYearToUse) {
-            periodsInOneYear = this.daysInYearType.getValue().longValue();
-        } else {
-            periodsInOneYear = calculator.calculate(this.repaymentPeriodFrequencyType).longValue();
-        }
-        switch (this.interestCalculationPeriodMethod) {
-            case DAILY:
-                periodsInOneYear = (!this.daysInYearType.getCode().equalsIgnoreCase("DaysInYearType.actual")) ? this.daysInYearType
-                        .getValue().longValue() : calculator.calculate(PeriodFrequencyType.DAYS).longValue();
-            break;
-            case INVALID:
-            break;
-            case SAME_AS_REPAYMENT_PERIOD:
-            break;
-        }
-
-        return periodsInOneYear;
-    }
-
-    private int calculateNumberOfRepaymentsWithPrincipalPayment() {
-        return this.actualNumberOfRepayments - getPrincipalGrace();
-    }
-
-    private Integer calculateNumberOfRepaymentPeriodsWhereInterestPaymentIsDue(final Integer totalNumberOfRepaymentPeriods) {
-        return totalNumberOfRepaymentPeriods - Math.max(getInterestChargingGrace(), getInterestPaymentGrace());
-    }
-
-    private Integer calculateNumberOfPrincipalPaymentPeriods(final Integer totalNumberOfRepaymentPeriods) {
-        return totalNumberOfRepaymentPeriods - getPrincipalGrace();
-    }
-
-    public boolean isPrincipalGraceApplicableForThisPeriod(final int periodNumber) {
-        return periodNumber > 0 && periodNumber <= getPrincipalGrace();
-    }
-
-    private boolean isInterestPaymentGraceApplicableForThisPeriod(final int periodNumber) {
-        return periodNumber > 0 && periodNumber <= getInterestPaymentGrace();
-    }
-
-    private boolean isFirstPeriodAfterInterestPaymentGracePeriod(final int periodNumber) {
-        return periodNumber > 0 && periodNumber == getInterestPaymentGrace() + 1;
-    }
-
-    private boolean isInterestFreeGracePeriod(final int periodNumber) {
-        return periodNumber > 0 && periodNumber <= getInterestChargingGrace();
-    }
-
-    public Integer getPrincipalGrace() {
-        Integer graceOnPrincipalPayments = Integer.valueOf(0);
-        if (this.principalGrace != null) {
-            graceOnPrincipalPayments = this.principalGrace;
-        }
-        return graceOnPrincipalPayments;
-    }
-
-    public Integer getInterestPaymentGrace() {
-        Integer graceOnInterestPayments = Integer.valueOf(0);
-        if (this.interestPaymentGrace != null) {
-            graceOnInterestPayments = this.interestPaymentGrace;
-        }
-        return graceOnInterestPayments;
-    }
-
-    public Integer getInterestChargingGrace() {
-        Integer graceOnInterestCharged = Integer.valueOf(0);
-        if (this.interestChargingGrace != null) {
-            graceOnInterestCharged = this.interestChargingGrace;
-        }
-        return graceOnInterestCharged;
-    }
-
-    private double paymentPerPeriod(final BigDecimal periodicInterestRate, final Money balance, final int periodsElapsed) {
-
-        if (getFixedEmiAmount() == null) {
-            final double futureValue = 0;
-            final double principalDouble = balance.getAmount().multiply(BigDecimal.valueOf(-1)).doubleValue();
-
-            final Integer periodsRemaining = this.actualNumberOfRepayments - periodsElapsed;
-
-            double installmentAmount = FinanicalFunctions.pmt(periodicInterestRate.doubleValue(), periodsRemaining.doubleValue(),
-                    principalDouble, futureValue, false);
-
-            if (this.installmentAmountInMultiplesOf != null) {
-                installmentAmount = Money.roundToMultiplesOf(installmentAmount, this.installmentAmountInMultiplesOf);
-            }
-            setFixedEmiAmount(BigDecimal.valueOf(installmentAmount));
-        }
-        return getFixedEmiAmount().doubleValue();
-    }
-
-    private Money calculateDecliningInterestDueForInstallmentBeforeApplyingGrace(final PaymentPeriodsInOneYearCalculator calculator,
-            final MathContext mc, final Money outstandingBalance, LocalDate periodStartDate, LocalDate periodEndDate) {
-
-        Money interestDue = Money.zero(outstandingBalance.getCurrency());
-
-        final BigDecimal periodicInterestRate = periodicInterestRate(calculator, mc, this.daysInMonthType, this.daysInYearType,
-                periodStartDate, periodEndDate);
-        interestDue = outstandingBalance.multiplyRetainScale(periodicInterestRate, mc.getRoundingMode());
-
-        return interestDue;
-    }
-
-    private Money calculateDecliningInterestDueForInstallmentAfterApplyingGrace(final PaymentPeriodsInOneYearCalculator calculator,
-            final double interestCalculationGraceOnRepaymentPeriodFraction, final MathContext mc, final Money outstandingBalance,
-            final int periodNumber, LocalDate periodStartDate, LocalDate periodEndDate) {
-
-        Money interest = calculateDecliningInterestDueForInstallmentBeforeApplyingGrace(calculator, mc, outstandingBalance,
-                periodStartDate, periodEndDate);
-
-        if (isInterestPaymentGraceApplicableForThisPeriod(periodNumber)) {
-            interest = interest.zero();
-        }
-
-        Double fraction = interestCalculationGraceOnRepaymentPeriodFraction;
-
-        if (isInterestFreeGracePeriod(periodNumber)) {
-            interest = interest.zero();
-        } else if (isInterestFreeGracePeriodFromDate(interestCalculationGraceOnRepaymentPeriodFraction)) {
-
-            if (interestCalculationGraceOnRepaymentPeriodFraction >= Integer.valueOf(1).doubleValue()) {
-                interest = interest.zero();
-                fraction = fraction - Integer.valueOf(1).doubleValue();
-
-            } else if (interestCalculationGraceOnRepaymentPeriodFraction > Double.valueOf("0.25")
-                    && interestCalculationGraceOnRepaymentPeriodFraction < Integer.valueOf(1).doubleValue()) {
-
-                final Money graceOnInterestForRepaymentPeriod = interest.multipliedBy(interestCalculationGraceOnRepaymentPeriodFraction);
-                interest = interest.minus(graceOnInterestForRepaymentPeriod);
-                fraction = Double.valueOf("0");
-            }
-        }
-
-        return interest;
-    }
-
-    private boolean isInterestFreeGracePeriodFromDate(final double interestCalculationGraceOnRepaymentPeriodFraction) {
-        return this.interestChargedFromDate != null && interestCalculationGraceOnRepaymentPeriodFraction > Double.valueOf("0.0");
-    }
-
-    private Money calculateEqualPrincipalDueForInstallment(final MathContext mc, final int periodNumber) {
-        Money principal = this.principal;
-        if (this.fixedPrincipalAmount == null) {
-            final Integer numberOfPrincipalPaymentPeriods = calculateNumberOfPrincipalPaymentPeriods(this.actualNumberOfRepayments);
-            principal = this.principal.dividedBy(numberOfPrincipalPaymentPeriods, mc.getRoundingMode());
-            this.fixedPrincipalAmount = principal.getAmount();
-        }
-        principal = Money.of(getCurrency(), getFixedPrincipalAmount());
-
-        if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) {
-            principal = principal.zero();
-        }
-        return principal;
-    }
-
-    public void updateFixedPrincipalAmount(final MathContext mc, final int periodNumber, final Money outstandingAmount) {
-        final Integer numberOfPrincipalPaymentPeriods = calculateNumberOfPrincipalPaymentPeriods(this.actualNumberOfRepayments);
-        Money principal = outstandingAmount.dividedBy(numberOfPrincipalPaymentPeriods - periodNumber + 1, mc.getRoundingMode());
-        this.fixedPrincipalAmount = principal.getAmount();
-    }
-
-    public void setFixedPrincipalAmount(BigDecimal fixedPrincipalAmount) {
-        this.fixedPrincipalAmount = fixedPrincipalAmount;
-    }
-
-    private Money calculatePrincipalDueForInstallment(final int periodNumber, final Money totalDuePerInstallment, final Money periodInterest) {
-
-        Money principal = totalDuePerInstallment.minus(periodInterest);
-        if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) {
-            principal = principal.zero();
-        }
-        return principal;
-    }
-
-    private Money calculateTotalDueForEqualInstallmentRepaymentPeriod(final BigDecimal periodicInterestRate, final Money balance,
-            final int periodsElapsed) {
-
-        final double paymentPerRepaymentPeriod = paymentPerPeriod(periodicInterestRate, balance, periodsElapsed);
-
-        return Money.of(balance.getCurrency(), BigDecimal.valueOf(paymentPerRepaymentPeriod));
-    }
-
-    public LoanProductRelatedDetail toLoanProductRelatedDetail() {
-        final MonetaryCurrency currency = new MonetaryCurrency(this.currency.getCode(), this.currency.getDecimalPlaces(),
-                this.currency.getCurrencyInMultiplesOf());
-
-        return LoanProductRelatedDetail.createFrom(currency, this.principal.getAmount(), this.interestRatePerPeriod,
-                this.interestRatePeriodFrequencyType, this.annualNominalInterestRate, this.interestMethod,
-                this.interestCalculationPeriodMethod, this.allowPartialPeriodInterestCalcualtion, this.repaymentEvery,
-                this.repaymentPeriodFrequencyType, this.numberOfRepayments, this.principalGrace, this.interestPaymentGrace,
-                this.interestChargingGrace, this.amortizationMethod, this.inArrearsTolerance.getAmount(), this.graceOnArrearsAgeing,
-                this.daysInMonthType.getValue(), this.daysInYearType.getValue(), this.interestRecalculationEnabled);
-    }
-
-    public Integer getLoanTermFrequency() {
-        return this.loanTermFrequency;
-    }
-
-    public PeriodFrequencyType getLoanTermPeriodFrequencyType() {
-        return this.loanTermPeriodFrequencyType;
-    }
-
-    public Integer getRepaymentEvery() {
-        return this.repaymentEvery;
-    }
-
-    public PeriodFrequencyType getRepaymentPeriodFrequencyType() {
-        return this.repaymentPeriodFrequencyType;
-    }
-
-    public Date getRepaymentStartFromDate() {
-        Date dateValue = null;
-        if (this.repaymentsStartingFromDate != null) {
-            dateValue = this.repaymentsStartingFromDate.toDate();
-        }
-        return dateValue;
-    }
-
-    public Date getInterestChargedFromDate() {
-        Date dateValue = null;
-        if (this.interestChargedFromDate != null) {
-            dateValue = this.interestChargedFromDate.toDate();
-        }
-        return dateValue;
-    }
-
-    public void setPrincipal(Money principal) {
-        this.principal = principal;
-    }
-
-    public LocalDate getInterestChargedFromLocalDate() {
-        return this.interestChargedFromDate;
-    }
-
-    public InterestMethod getInterestMethod() {
-        return this.interestMethod;
-    }
-
-    public AmortizationMethod getAmortizationMethod() {
-        return this.amortizationMethod;
-    }
-
-    public MonetaryCurrency getCurrency() {
-        return this.principal.getCurrency();
-    }
-
-    public Integer getNumberOfRepayments() {
-        return this.numberOfRepayments;
-    }
-
-    public LocalDate getExpectedDisbursementDate() {
-        return this.expectedDisbursementDate;
-    }
-
-    public LocalDate getRepaymentsStartingFromLocalDate() {
-        return this.repaymentsStartingFromDate;
-    }
-
-    public LocalDate getCalculatedRepaymentsStartingFromLocalDate() {
-        return this.calculatedRepaymentsStartingFromDate;
-    }
-
-    public Money getPrincipal() {
-        return this.principal;
-    }
-
-    public Money getApprovedPrincipal() {
-        return this.approvedPrincipal;
-    }
-
-    public List<DisbursementData> getDisbursementDatas() {
-        return this.disbursementDatas;
-    }
-
-    public boolean isMultiDisburseLoan() {
-        return this.multiDisburseLoan;
-    }
-
-    public Money getMaxOutstandingBalance() {
-        return Money.of(getCurrency(), this.maxOutstandingBalance);
-    }
-
-    public BigDecimal getFixedEmiAmount() {
-        BigDecimal fixedEmiAmount = this.fixedEmiAmount;
-        if (getCurrentPeriodFixedEmiAmount() != null) {
-            fixedEmiAmount = getCurrentPeriodFixedEmiAmount();
-        }
-        return fixedEmiAmount;
-    }
-
-    public Integer getNthDay() {
-        return this.nthDay;
-    }
-
-    public DayOfWeekType getWeekDayType() {
-        return this.weekDayType;
-    }
-
-    public void setFixedEmiAmount(BigDecimal fixedEmiAmount) {
-        this.fixedEmiAmount = fixedEmiAmount;
-    }
-
-    public void resetFixedEmiAmount() {
-        this.fixedEmiAmount = this.actualFixedEmiAmount;
-    }
-
-    public LoanRescheduleStrategyMethod getLoanRescheduleStrategyMethod() {
-        return LoanRescheduleStrategyMethod.REDUCE_EMI_AMOUNT;
-    }
-
-    public boolean isInterestRecalculationEnabled() {
-        return this.interestRecalculationEnabled;
-    }
-
-    public LoanRescheduleStrategyMethod getRescheduleStrategyMethod() {
-        return this.rescheduleStrategyMethod;
-    }
-
-    public InterestRecalculationCompoundingMethod getInterestRecalculationCompoundingMethod() {
-        return this.interestRecalculationCompoundingMethod;
-    }
-
-    public CalendarInstance getRestCalendarInstance() {
-        return this.restCalendarInstance;
-    }
-
-    private boolean isFallingInRepaymentPeriod(LocalDate fromDate, LocalDate toDate) {
-        boolean isSameAsRepaymentPeriod = false;
-        if (this.interestCalculationPeriodMethod.getValue().equals(InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD.getValue())) {
-            switch (this.repaymentPeriodFrequencyType) {
-                case WEEKS:
-                    int days = Days.daysBetween(fromDate, toDate).getDays();
-                    isSameAsRepaymentPeriod = (days % 7) == 0;
-                break;
-                case MONTHS:
-                    boolean isFromDateOnEndDate = false;
-                    if (fromDate.getDayOfMonth() > fromDate.plusDays(1).getDayOfMonth()) {
-                        isFromDateOnEndDate = true;
-                    }
-                    boolean isToDateOnEndDate = false;
-                    if (toDate.getDayOfMonth() > toDate.plusDays(1).getDayOfMonth()) {
-                        isToDateOnEndDate = true;
-                    }
-
-                    if (isFromDateOnEndDate && isToDateOnEndDate) {
-                        isSameAsRepaymentPeriod = true;
-                    } else {
-
-                        int months = getPeriodsBetween(fromDate, toDate);
-                        fromDate = fromDate.plusMonths(months);
-                        isSameAsRepaymentPeriod = fromDate.isEqual(toDate);
-                    }
-
-                break;
-                default:
-                break;
-            }
-        }
-        return isSameAsRepaymentPeriod;
-    }
-
-    private Integer getPeriodsBetween(LocalDate fromDate, LocalDate toDate) {
-        Integer numberOfPeriods = 0;
-        PeriodType periodType = PeriodType.yearMonthDay();
-        Period difference = new Period(fromDate, toDate, periodType);
-        switch (this.repaymentPeriodFrequencyType) {
-            case DAYS:
-                numberOfPeriods = difference.getDays();
-            break;
-            case WEEKS:
-                periodType = PeriodType.weeks();
-                difference = new Period(fromDate, toDate, periodType);
-                numberOfPeriods = difference.getWeeks();
-            break;
-            case MONTHS:
-                numberOfPeriods = difference.getMonths();
-            break;
-            case YEARS:
-                numberOfPeriods = difference.getYears();
-            break;
-            default:
-            break;
-        }
-        return numberOfPeriods;
-    }
-
-    public RecalculationFrequencyType getRecalculationFrequencyType() {
-        return this.recalculationFrequencyType;
-    }
-
-    public void updateNumberOfRepayments(final Integer numberOfRepayments) {
-        this.numberOfRepayments = numberOfRepayments;
-        this.actualNumberOfRepayments = numberOfRepayments + getLoanTermVariations().adjustNumberOfRepayments();
-
-    }
-
-    public void updatePrincipalGrace(final Integer principalGrace) {
-        this.principalGrace = principalGrace;
-    }
-
-    public void updateInterestPaymentGrace(final Integer interestPaymentGrace) {
-        this.interestPaymentGrace = interestPaymentGrace;
-    }
-
-    public void updateInterestRatePerPeriod(BigDecimal interestRatePerPeriod) {
-        if (interestRatePerPeriod != null) {
-            this.interestRatePerPeriod = interestRatePerPeriod;
-        }
-    }
-
-    public void updateAnnualNominalInterestRate(BigDecimal annualNominalInterestRate) {
-        if (annualNominalInterestRate != null) {
-            this.annualNominalInterestRate = annualNominalInterestRate;
-        }
-    }
-
-    public BigDecimal getAnnualNominalInterestRate() {
-        return this.annualNominalInterestRate;
-    }
-
-    public void updateInterestChargedFromDate(LocalDate interestChargedFromDate) {
-        if (interestChargedFromDate != null) {
-            this.interestChargedFromDate = interestChargedFromDate;
-        }
-    }
-
-    public void updateLoanTermFrequency(Integer loanTermFrequency) {
-        if (loanTermFrequency != null) {
-            this.loanTermFrequency = loanTermFrequency;
-        }
-    }
-
-    public void updateTotalInterestDue(Money totalInterestDue) {
-
-        if (totalInterestDue != null) {
-            this.totalInterestDue = totalInterestDue;
-        }
-    }
-
-    public ApplicationCurrency getApplicationCurrency() {
-        return this.currency;
-    }
-
-    public InterestCalculationPeriodMethod getInterestCalculationPeriodMethod() {
-        return this.interestCalculationPeriodMethod;
-    }
-
-    public LoanPreClosureInterestCalculationStrategy getPreClosureInterestCalculationStrategy() {
-        return this.preClosureInterestCalculationStrategy;
-    }
-
-    public CalendarInstance getCompoundingCalendarInstance() {
-        return this.compoundingCalendarInstance;
-    }
-
-    public RecalculationFrequencyType getCompoundingFrequencyType() {
-        return this.compoundingFrequencyType;
-    }
-
-    public BigDecimal getActualFixedEmiAmount() {
-        return this.actualFixedEmiAmount;
-    }
-
-    public Calendar getLoanCalendar() {
-        return loanCalendar;
-    }
-
-    public BigDecimal getFixedPrincipalAmount() {
-        BigDecimal fixedPrincipalAmount = this.fixedPrincipalAmount;
-        if (getCurrentPeriodFixedPrincipalAmount() != null) {
-            fixedPrincipalAmount = getCurrentPeriodFixedPrincipalAmount();
-        }
-        return fixedPrincipalAmount;
-    }
-
-    public LoanTermVariationsDataWrapper getLoanTermVariations() {
-        return this.variationsDataWrapper;
-    }
-
-    public BigDecimal getCurrentPeriodFixedEmiAmount() {
-        return this.currentPeriodFixedEmiAmount;
-    }
-
-    public void setCurrentPeriodFixedEmiAmount(BigDecimal currentPeriodFixedEmiAmount) {
-        this.currentPeriodFixedEmiAmount = currentPeriodFixedEmiAmount;
-    }
-
-    public BigDecimal getCurrentPeriodFixedPrincipalAmount() {
-        return this.currentPeriodFixedPrincipalAmount;
-    }
-
-    public void setCurrentPeriodFixedPrincipalAmount(BigDecimal currentPeriodFixedPrincipalAmount) {
-        this.currentPeriodFixedPrincipalAmount = currentPeriodFixedPrincipalAmount;
-    }
-
-    public Integer fetchNumberOfRepaymentsAfterExceptions() {
-        return this.actualNumberOfRepayments;
-    }
-
-    public LocalDate getSeedDate() {
-        return this.seedDate;
-    }
-
-    public CalendarHistoryDataWrapper getCalendarHistoryDataWrapper() {
-        return this.calendarHistoryDataWrapper;
-    }
-    
-    public Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled(){
-        return this.isInterestChargedFromDateSameAsDisbursalDateEnabled;
-    }
-
-    public Integer getNumberOfdays() {
-        return numberOfDays;
-    }
-
-    public boolean isSkipRepaymentOnFirstDayofMonth() {
-        return isSkipRepaymentOnFirstDayOfMonth;
-    }
+	/**
+	 * Legacy method of support 'grace' on the charging of interest on a loan.
+	 * 
+	 * <p>
+	 * For the typical structured loan, its reasonable to use an integer to
+	 * indicate the number of 'repayment frequency' periods the 'grace' should
+	 * apply to but for slightly <b>irregular</b> loans where the period between
+	 * disbursement and the date of the 'first repayment period' isnt doest
+	 * match the 'repayment frequency' but can be less (15days instead of 1
+	 * month) or more (6 weeks instead of 1 month) - The idea was to use a date
+	 * to indicate from whence interest should be charged.
+	 * </p>
+	 */
+	private LocalDate interestChargedFromDate;
+	private final Money inArrearsTolerance;
+
+	private final Integer graceOnArrearsAgeing;
+
+	// added
+	private LocalDate loanEndDate;
+
+	private final List<DisbursementData> disbursementDatas;
+
+	private final boolean multiDisburseLoan;
+
+	private BigDecimal fixedEmiAmount;
+
+	private BigDecimal fixedPrincipalAmount;
+
+	private BigDecimal currentPeriodFixedEmiAmount;
+
+	private BigDecimal currentPeriodFixedPrincipalAmount;
+
+	private final BigDecimal actualFixedEmiAmount;
+
+	private final BigDecimal maxOutstandingBalance;
+
+	private Money totalInterestDue;
+
+	private final DaysInMonthType daysInMonthType;
+
+	private final DaysInYearType daysInYearType;
+
+	private final boolean interestRecalculationEnabled;
+
+	private final LoanRescheduleStrategyMethod rescheduleStrategyMethod;
+
+	private final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod;
+
+	private final CalendarInstance restCalendarInstance;
+
+	private final RecalculationFrequencyType recalculationFrequencyType;
+
+	private final CalendarInstance compoundingCalendarInstance;
+
+	private final RecalculationFrequencyType compoundingFrequencyType;
+
+	private final BigDecimal principalThresholdForLastInstalment;
+	private final Integer installmentAmountInMultiplesOf;
+
+	private final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy;
+
+	private Money approvedPrincipal = null;
+
+	private final LoanTermVariationsDataWrapper variationsDataWrapper;
+
+	private Money adjustPrincipalForFlatLoans;
+
+	private final LocalDate seedDate;
+
+	private final CalendarHistoryDataWrapper calendarHistoryDataWrapper;
+
+	private final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled;
+
+	private final Integer numberOfDays;
+
+	private final boolean isSkipRepaymentOnFirstDayOfMonth;
+
+	public static LoanApplicationTerms assembleFrom(
+			final ApplicationCurrency currency,
+			final Integer loanTermFrequency,
+			final PeriodFrequencyType loanTermPeriodFrequencyType,
+			final Integer numberOfRepayments,
+			final Integer repaymentEvery,
+			final PeriodFrequencyType repaymentPeriodFrequencyType,
+			Integer nthDay,
+			DayOfWeekType weekDayType,
+			final AmortizationMethod amortizationMethod,
+			final InterestMethod interestMethod,
+			final BigDecimal interestRatePerPeriod,
+			final PeriodFrequencyType interestRatePeriodFrequencyType,
+			final BigDecimal annualNominalInterestRate,
+			final InterestCalculationPeriodMethod interestCalculationPeriodMethod,
+			final boolean allowPartialPeriodInterestCalcualtion,
+			final Money principalMoney,
+			final LocalDate expectedDisbursementDate,
+			final LocalDate repaymentsStartingFromDate,
+			final LocalDate calculatedRepaymentsStartingFromDate,
+			final Integer graceOnPrincipalPayment,
+			final Integer recurringMoratoriumOnPrincipalPeriods,
+			final Integer graceOnInterestPayment,
+			final Integer graceOnInterestCharged,
+			final LocalDate interestChargedFromDate,
+			final Money inArrearsTolerance,
+			final boolean multiDisburseLoan,
+			final BigDecimal emiAmount,
+			final List<DisbursementData> disbursementDatas,
+			final BigDecimal maxOutstandingBalance,
+			final Integer graceOnArrearsAgeing,
+			final DaysInMonthType daysInMonthType,
+			final DaysInYearType daysInYearType,
+			final boolean isInterestRecalculationEnabled,
+			final RecalculationFrequencyType recalculationFrequencyType,
+			final CalendarInstance restCalendarInstance,
+			final CalendarInstance compoundingCalendarInstance,
+			final RecalculationFrequencyType compoundingFrequencyType,
+			final BigDecimal principalThresholdForLastInstalment,
+			final Integer installmentAmountInMultiplesOf,
+			final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy,
+			final Calendar loanCalendar, BigDecimal approvedAmount,
+			List<LoanTermVariationsData> loanTermVariations,
+			Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled,
+			final Integer numberOfdays, boolean isSkipRepaymentOnFirstDayofMonth) {
+
+		final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
+		final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
+		final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
+		return new LoanApplicationTerms(currency, loanTermFrequency,
+				loanTermPeriodFrequencyType, numberOfRepayments,
+				repaymentEvery, repaymentPeriodFrequencyType, nthDay,
+				weekDayType, amortizationMethod, interestMethod,
+				interestRatePerPeriod, interestRatePeriodFrequencyType,
+				annualNominalInterestRate, interestCalculationPeriodMethod,
+				allowPartialPeriodInterestCalcualtion, principalMoney,
+				expectedDisbursementDate, repaymentsStartingFromDate,
+				calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment,
+				recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment,
+				graceOnInterestCharged, interestChargedFromDate,
+				inArrearsTolerance, multiDisburseLoan, emiAmount,
+				disbursementDatas, maxOutstandingBalance, graceOnArrearsAgeing,
+				daysInMonthType, daysInYearType,
+				isInterestRecalculationEnabled, rescheduleStrategyMethod,
+				interestRecalculationCompoundingMethod, restCalendarInstance,
+				recalculationFrequencyType, compoundingCalendarInstance,
+				compoundingFrequencyType, principalThresholdForLastInstalment,
+				installmentAmountInMultiplesOf,
+				preClosureInterestCalculationStrategy, loanCalendar,
+				approvedAmount, loanTermVariations, calendarHistoryDataWrapper,
+				isInterestChargedFromDateSameAsDisbursalDateEnabled,
+				numberOfdays, isSkipRepaymentOnFirstDayofMonth);
+
+	}
+
+	public static LoanApplicationTerms assembleFrom(
+			final ApplicationCurrency applicationCurrency,
+			final Integer loanTermFrequency,
+			final PeriodFrequencyType loanTermPeriodFrequencyType,
+			NthDayType nthDay,
+			DayOfWeekType dayOfWeek,
+			final LocalDate expectedDisbursementDate,
+			final LocalDate repaymentsStartingFromDate,
+			final LocalDate calculatedRepaymentsStartingFromDate,
+			final Money inArrearsTolerance,
+			final LoanProductRelatedDetail loanProductRelatedDetail,
+			final boolean multiDisburseLoan,
+			final BigDecimal emiAmount,
+			final List<DisbursementData> disbursementDatas,
+			final BigDecimal maxOutstandingBalance,
+			final LocalDate interestChargedFromDate,
+			final BigDecimal principalThresholdForLastInstalment,
+			final Integer installmentAmountInMultiplesOf,
+			final RecalculationFrequencyType recalculationFrequencyType,
+			final CalendarInstance restCalendarInstance,
+			final InterestRecalculationCompoundingMethod compoundingMethod,
+			final CalendarInstance compoundingCalendarInstance,
+			final RecalculationFrequencyType compoundingFrequencyType,
+			final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy,
+			final LoanRescheduleStrategyMethod rescheduleStrategyMethod,
+			BigDecimal approvedAmount, BigDecimal annualNominalInterestRate,
+			List<LoanTermVariationsData> loanTermVariations,
+			final Integer numberOfdays,
+			final boolean isSkipRepaymentOnFirstDayofMonth) {
+		final Calendar loanCalendar = null;
+		final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
+
+		return assembleFrom(applicationCurrency, loanTermFrequency,
+				loanTermPeriodFrequencyType, nthDay, dayOfWeek,
+				expectedDisbursementDate, repaymentsStartingFromDate,
+				calculatedRepaymentsStartingFromDate, inArrearsTolerance,
+				loanProductRelatedDetail, multiDisburseLoan, emiAmount,
+				disbursementDatas, maxOutstandingBalance,
+				interestChargedFromDate, principalThresholdForLastInstalment,
+				installmentAmountInMultiplesOf, recalculationFrequencyType,
+				restCalendarInstance, compoundingMethod,
+				compoundingCalendarInstance, compoundingFrequencyType,
+				loanPreClosureInterestCalculationStrategy,
+				rescheduleStrategyMethod, loanCalendar, approvedAmount,
+				annualNominalInterestRate, loanTermVariations,
+				calendarHistoryDataWrapper, numberOfdays,
+				isSkipRepaymentOnFirstDayofMonth);
+	}
+
+	public static LoanApplicationTerms assembleFrom(
+			final ApplicationCurrency applicationCurrency,
+			final Integer loanTermFrequency,
+			final PeriodFrequencyType loanTermPeriodFrequencyType,
+			NthDayType nthDay,
+			DayOfWeekType dayOfWeek,
+			final LocalDate expectedDisbursementDate,
+			final LocalDate repaymentsStartingFromDate,
+			final LocalDate calculatedRepaymentsStartingFromDate,
+			final Money inArrearsTolerance,
+			final LoanProductRelatedDetail loanProductRelatedDetail,
+			final boolean multiDisburseLoan,
+			final BigDecimal emiAmount,
+			final List<DisbursementData> disbursementDatas,
+			final BigDecimal maxOutstandingBalance,
+			final LocalDate interestChargedFromDate,
+			final BigDecimal principalThresholdForLastInstalment,
+			final Integer installmentAmountInMultiplesOf,
+			final RecalculationFrequencyType recalculationFrequencyType,
+			final CalendarInstance restCalendarInstance,
+			final InterestRecalculationCompoundingMethod compoundingMethod,
+			final CalendarInstance compoundingCalendarInstance,
+			final RecalculationFrequencyType compoundingFrequencyType,
+			final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy,
+			final LoanRescheduleStrategyMethod res

<TRUNCATED>


Mime
View raw message