You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ra...@apache.org on 2016/05/04 14:26:16 UTC

[04/10] incubator-fineract git commit: FINERACT-60 : Interest compounding, nth day rest frequency and meeting calendar date changes

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/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
old mode 100755
new mode 100644
index 7be11d3..c1f91ea
--- 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
@@ -30,12 +30,14 @@ import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
 import org.apache.fineract.portfolio.calendar.data.CalendarHistoryDataWrapper;
 import org.apache.fineract.portfolio.calendar.domain.Calendar;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
+import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
 import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
 import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
 import org.apache.fineract.portfolio.common.domain.DaysInYearType;
 import org.apache.fineract.portfolio.common.domain.NthDayType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
+import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrapper;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
@@ -57,1864 +59,1521 @@ import org.joda.time.Years;
 
 public final class LoanApplicationTerms {
 
-	private final ApplicationCurrency currency;
+    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 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 Integer recurringMoratoriumOnPrincipalPeriods;
+    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 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 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 recurringMoratoriumOnPrincipalPeriods = loanProductRelatedDetail
-				.recurringMoratoriumOnPrincipalPeriods();
-		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,
-				recurringMoratoriumOnPrincipalPeriods, 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 recurringMoratoriumOnPrincipalPeriods = loanProductRelatedDetail
-				.recurringMoratoriumOnPrincipalPeriods();
-		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,
-				recurringMoratoriumOnPrincipalPeriods, 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.recurringMoratoriumOnPrincipalPeriods,
-				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 recurringMoratoriumOnPrincipalPeriods,
-			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.recurringMoratoriumOnPrincipalPeriods = recurringMoratoriumOnPrincipalPeriods;
-		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() {
-		int numPeriods = calculateNumberOfRemainingPrincipalPaymentPeriods(
-				this.actualNumberOfRepayments,
-				this.getRecurringMoratoriumOnPrincipalPeriods(),
-				this.getPrincipalGrace(), 0);
-		return numPeriods;
-	}
-
-	private Integer calculateNumberOfRepaymentPeriodsWhereInterestPaymentIsDue(
-			final Integer totalNumberOfRepaymentPeriods) {
-		return totalNumberOfRepaymentPeriods
-				- Math.max(getInterestChargingGrace(),
-						getInterestPaymentGrace());
-	}
-
-	public boolean isPrincipalGraceApplicableForThisPeriod(
-			final int periodNumber) {
-		if (this.getRecurringMoratoriumOnPrincipalPeriods() > 0) {
-			return ((periodNumber > 0 && periodNumber <= getPrincipalGrace()) || (periodNumber > 0 && (((periodNumber - getPrincipalGrace()) % (this
-					.getRecurringMoratoriumOnPrincipalPeriods() + 1)) != 1)));
-		} else {
-			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 getRecurringMoratoriumOnPrincipalPeriods() {
-		Integer recurringMoratoriumOnPrincipalPeriods = Integer.valueOf(0);
-		if (this.recurringMoratoriumOnPrincipalPeriods != null) {
-			recurringMoratoriumOnPrincipalPeriods = this.recurringMoratoriumOnPrincipalPeriods;
-		}
-		return recurringMoratoriumOnPrincipalPeriods;
-	}
-
-	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 = calculateNumberOfRemainingPrincipalPaymentPeriods(
-					this.actualNumberOfRepayments,
-					this.getRecurringMoratoriumOnPrincipalPeriods(),
-					this.getPrincipalGrace(), 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 = calculateNumberOfRemainingPrincipalPaymentPeriods(
-					this.actualNumberOfRepayments,
-					this.getRecurringMoratoriumOnPrincipalPeriods(),
-					this.getPrincipalGrace(), periodNumber);
-			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 = calculateNumberOfRemainingPrincipalPaymentPeriods(
-				this.actualNumberOfRepayments,
-				this.getRecurringMoratoriumOnPrincipalPeriods(),
-				this.getPrincipalGrace(), periodNumber - 1);
-		Money principal = outstandingAmount.dividedBy(
-				numberOfPrincipalPaymentPeriods, mc.getRoundingMode());
-		this.fixedPrincipalAmount = principal.getAmount();
-	}
-
-	private static Integer calculateNumberOfRemainingPrincipalPaymentPeriods(
-			final Integer totalNumberOfRepaymentPeriods,
-			final int recurringMoratoriumOnPrincipalPeriods,
-			final int PrincipalGrace, int periodsElapsed) {
-		if (PrincipalGrace > periodsElapsed) {
-			periodsElapsed = PrincipalGrace;
-		}
-		Integer periodsRemaining = totalNumberOfRepaymentPeriods
-				- periodsElapsed;
-		if (recurringMoratoriumOnPrincipalPeriods > 0) {
-			double periodsRemainingDouble = ((double) periodsRemaining / ((double) (recurringMoratoriumOnPrincipalPeriods + 1)));
-			periodsRemaining = (int) Math.ceil(periodsRemainingDouble);
-		}
-		return periodsRemaining;
-	}
-
-	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.recurringMoratoriumOnPrincipalPeriods,
-				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 boolean allowCompoundingOnEod;
+
+    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;
+
+    private final HolidayDetailDTO holidayDetailDTO;
+
+    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 InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod,
+            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 HolidayDetailDTO holidayDetailDTO, final boolean allowCompoundingOnEod) {
+
+        final LoanRescheduleStrategyMethod rescheduleStrategyMethod = 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, holidayDetailDTO,
+                allowCompoundingOnEod);
+
+    }
+
+    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, final HolidayDetailDTO holidayDetailDTO, final boolean allowCompoundingOnEod) {
+        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, holidayDetailDTO, allowCompoundingOnEod);
+    }
+
+    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 HolidayDetailDTO holidayDetailDTO, final boolean allowCompoundingOnEod) {
+
+        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 recurringMoratoriumOnPrincipalPeriods = loanProductRelatedDetail.recurringMoratoriumOnPrincipalPeriods();
+        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 LoanApplicatio

<TRUNCATED>