adding global config for interest charged from date same as disbursement date

This commit is contained in:
sachinkulkarni12
2016-03-15 18:06:24 +05:30
parent bf6d0eaa5b
commit 04fe104dde
11 changed files with 140 additions and 16 deletions
@@ -0,0 +1,79 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.integrationtests;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
public class GlobalConfigInterestChargedFromDateSameAsDisbursalDateTest {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private GlobalConfigurationHelper globalConfigurationHelper;
@Before
public void setup() {
Utils.initializeRESTAssured();
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
}
@SuppressWarnings( {"static-access", "rawtypes", "unchecked"})
@Test
public void testInterestChargedFromDateSameAsDisbursalDate(){
this.globalConfigurationHelper = new GlobalConfigurationHelper(this.requestSpec, this.responseSpec);
// Retrieving All Global Configuration details
final ArrayList<HashMap> globalConfig = this.globalConfigurationHelper
.getAllGlobalConfigurations(this.requestSpec, this.responseSpec);
Assert.assertNotNull(globalConfig);
String configName = "interest-charged-from-date-same-as-disbursal-date";
boolean newBooleanValue = true;
for (Integer configIndex = 0; configIndex < (globalConfig.size()); configIndex++) {
if (globalConfig.get(configIndex).get("name")
.equals(configName)) {
String configId = (globalConfig.get(configIndex).get("id"))
.toString();
Integer updateConfigId = this.globalConfigurationHelper
.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec,
configId.toString(), newBooleanValue);;
Assert.assertNotNull(updateConfigId);
break;
}
}
}
}
@@ -70,4 +70,6 @@ public interface ConfigurationDomainService {
Date retrieveOrganisationStartDate();
boolean isPaymnetypeApplicableforDisbursementCharge();
boolean isInterestChargedFromDateSameAsDisbursementDate();
}
@@ -236,4 +236,12 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
return property.isEnabled();
}
@Override
public boolean isInterestChargedFromDateSameAsDisbursementDate() {
final String propertyName = "interest-charged-from-date-same-as-disbursal-date";
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
return property.isEnabled();
}
}
@@ -39,12 +39,14 @@ public class ScheduleGeneratorDTO {
final FloatingRateDTO floatingRateDTO;
final Calendar calendar;
final CalendarHistoryDataWrapper calendarHistoryDataWrapper;
final Boolean isInterestChargedFromDateAsDisbursementDateEnabled;
public ScheduleGeneratorDTO(final LoanScheduleGeneratorFactory loanScheduleFactory, final ApplicationCurrency applicationCurrency,
final LocalDate calculatedRepaymentsStartingFromDate, final HolidayDetailDTO holidayDetailDTO,
final CalendarInstance calendarInstanceForInterestRecalculation, final CalendarInstance compoundingCalendarInstance,
final LocalDate recalculateFrom, final Long overdurPenaltyWaitPeriod, final FloatingRateDTO floatingRateDTO,
final Calendar calendar, final CalendarHistoryDataWrapper calendarHistoryDataWrapper) {
final Calendar calendar, final CalendarHistoryDataWrapper calendarHistoryDataWrapper,
final Boolean isInterestChargedFromDateAsDisbursementDateEnabled) {
this.loanScheduleFactory = loanScheduleFactory;
this.applicationCurrency = applicationCurrency;
@@ -57,6 +59,7 @@ public class ScheduleGeneratorDTO {
this.floatingRateDTO = floatingRateDTO;
this.calendar = calendar;
this.calendarHistoryDataWrapper = calendarHistoryDataWrapper;
this.isInterestChargedFromDateAsDisbursementDateEnabled = isInterestChargedFromDateAsDisbursementDateEnabled;
}
@@ -115,5 +118,9 @@ public class ScheduleGeneratorDTO {
public CalendarHistoryDataWrapper getCalendarHistoryDataWrapper(){
return this.calendarHistoryDataWrapper;
}
public Boolean isInterestChargedFromDateAsDisbursementDateEnabled(){
return this.isInterestChargedFromDateAsDisbursementDateEnabled;
}
}
@@ -5052,12 +5052,16 @@ public class Loan extends AbstractPersistable<Long> {
FloatingRateDTO floatingRateDTO = scheduleGeneratorDTO.getFloatingRateDTO();
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
annualNominalInterestRate = constructLoanTermVariations(floatingRateDTO, annualNominalInterestRate, loanTermVariations);
LocalDate interestChargedFromDate = getInterestChargedFromDate();
if(interestChargedFromDate == null && scheduleGeneratorDTO.isInterestChargedFromDateAsDisbursementDateEnabled()){
interestChargedFromDate = getDisbursementDate();
}
final LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(scheduleGeneratorDTO.getApplicationCurrency(),
loanTermFrequency, loanTermPeriodFrequencyType, nthDayType, dayOfWeekType, getDisbursementDate(),
getExpectedFirstRepaymentOnDate(), scheduleGeneratorDTO.getCalculatedRepaymentsStartingFromDate(), getInArrearsTolerance(),
this.loanRepaymentScheduleDetail, this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, disbursementData,
this.maxOutstandingLoanBalance, getInterestChargedFromDate(), this.loanProduct.getPrincipalThresholdForLastInstallment(),
this.maxOutstandingLoanBalance, interestChargedFromDate, this.loanProduct.getPrincipalThresholdForLastInstallment(),
this.loanProduct.getInstallmentAmountInMultiplesOf(), recalculationFrequencyType, restCalendarInstance, compoundingMethod,
compoundingCalendarInstance, compoundingFrequencyType, this.loanProduct.preCloseInterestCalculationStrategy(),
rescheduleStrategyMethod, calendar, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations, calendarHistoryDataWrapper);
@@ -185,7 +185,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
// calculated interest start date for the period
LocalDate periodStartDateApplicableForInterest = calculateInterestStartDateForPeriod(loanApplicationTerms,
scheduleParams.getPeriodStartDate(), idealDisbursementDate, firstRepaymentdate);
scheduleParams.getPeriodStartDate(), idealDisbursementDate, firstRepaymentdate,
loanApplicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled(), loanApplicationTerms.getExpectedDisbursementDate());
// Loan Schedule Exceptions that need to be applied for Loan Account
LoanTermVariationParams termVariationParams = applyLoanTermVariations(loanApplicationTerms, scheduleParams,
@@ -249,7 +250,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
continue;
}
periodStartDateApplicableForInterest = calculateInterestStartDateForPeriod(loanApplicationTerms,
scheduleParams.getPeriodStartDate(), idealDisbursementDate, firstRepaymentdate);
scheduleParams.getPeriodStartDate(), idealDisbursementDate, firstRepaymentdate,
loanApplicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled(), loanApplicationTerms.getExpectedDisbursementDate());
// backup for pre-close transaction
updateCompoundingDetails(scheduleParams, periodStartDateApplicableForInterest);
@@ -632,7 +634,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
// calculates period start date for interest
// calculation as per the configuration
periodStartDateApplicableForInterest = calculateInterestStartDateForPeriod(loanApplicationTerms,
scheduleParams.getPeriodStartDate(), idealDisbursementDate, firstRepaymentdate);
scheduleParams.getPeriodStartDate(), idealDisbursementDate, firstRepaymentdate,
loanApplicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled(), loanApplicationTerms.getExpectedDisbursementDate());
int daysInPeriodApplicable = Days.daysBetween(periodStartDateApplicableForInterest, transactionDate).getDays();
Money interestForThisinstallment = Money.zero(currency);
@@ -1534,9 +1537,12 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
*
* @param firstRepaymentdate
* TODO
* @param boolean1
* @param localDate
*/
private LocalDate calculateInterestStartDateForPeriod(final LoanApplicationTerms loanApplicationTerms, LocalDate periodStartDate,
final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate) {
final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate, final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled,
final LocalDate expectedDisbursementDate) {
LocalDate periodStartDateApplicableForInterest = periodStartDate;
if (periodStartDate.isBefore(idealDisbursementDate) || firstRepaymentdate.isAfter(periodStartDate)) {
if (loanApplicationTerms.getInterestChargedFromLocalDate() != null) {
@@ -1544,9 +1550,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|| loanApplicationTerms.getInterestChargedFromLocalDate().isAfter(periodStartDate)) {
periodStartDateApplicableForInterest = loanApplicationTerms.getInterestChargedFromLocalDate();
}
} else if(loanApplicationTerms.getInterestChargedFromLocalDate() == null && isInterestChargedFromDateSameAsDisbursalDateEnabled) {
periodStartDateApplicableForInterest = expectedDisbursementDate;
} else if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())) {
periodStartDateApplicableForInterest = idealDisbursementDate;
}
}
}
return periodStartDateApplicableForInterest;
}
@@ -180,6 +180,8 @@ public final class LoanApplicationTerms {
private final LocalDate seedDate;
private final CalendarHistoryDataWrapper calendarHistoryDataWrapper;
private final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled;
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
@@ -197,7 +199,7 @@ public final class LoanApplicationTerms {
final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar,
BigDecimal approvedAmount, List<LoanTermVariationsData> loanTermVariations) {
BigDecimal approvedAmount, List<LoanTermVariationsData> loanTermVariations, Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
@@ -211,7 +213,8 @@ public final class LoanApplicationTerms {
graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, rescheduleStrategyMethod,
interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType, compoundingCalendarInstance,
compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
preClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper);
preClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper,
isInterestChargedFromDateSameAsDisbursalDateEnabled);
}
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
@@ -275,6 +278,7 @@ public final class LoanApplicationTerms {
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,
@@ -284,7 +288,8 @@ public final class LoanApplicationTerms {
loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
rescheduleStrategyMethod, compoundingMethod, restCalendarInstance, recalculationFrequencyType, compoundingCalendarInstance,
compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper);
loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper,
isInterestChargedFromDateSameAsDisbursalDateEnabled);
}
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
@@ -327,6 +332,7 @@ public final class LoanApplicationTerms {
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,
@@ -337,7 +343,8 @@ public final class LoanApplicationTerms {
loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType,
compoundingCalendarInstance, compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper);
loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper,
isInterestChargedFromDateSameAsDisbursalDateEnabled);
}
public static LoanApplicationTerms assembleFrom(final LoanApplicationTerms applicationTerms,
@@ -359,7 +366,8 @@ public final class LoanApplicationTerms {
applicationTerms.compoundingCalendarInstance, applicationTerms.compoundingFrequencyType,
applicationTerms.principalThresholdForLastInstalment, applicationTerms.installmentAmountInMultiplesOf,
applicationTerms.preClosureInterestCalculationStrategy, applicationTerms.loanCalendar,
applicationTerms.approvedPrincipal.getAmount(), loanTermVariations, applicationTerms.calendarHistoryDataWrapper);
applicationTerms.approvedPrincipal.getAmount(), loanTermVariations, applicationTerms.calendarHistoryDataWrapper,
applicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled);
}
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
@@ -381,7 +389,7 @@ public final class LoanApplicationTerms {
final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar,
BigDecimal approvedAmount, List<LoanTermVariationsData> loanTermVariations,
final CalendarHistoryDataWrapper calendarHistoryDataWrapper) {
final CalendarHistoryDataWrapper calendarHistoryDataWrapper, Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled) {
this.currency = currency;
this.loanTermFrequency = loanTermFrequency;
this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
@@ -440,6 +448,7 @@ public final class LoanApplicationTerms {
this.seedDate = this.calculatedRepaymentsStartingFromDate;
}
this.calendarHistoryDataWrapper = calendarHistoryDataWrapper;
this.isInterestChargedFromDateSameAsDisbursalDateEnabled = isInterestChargedFromDateSameAsDisbursalDateEnabled;
}
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1440,5 +1449,9 @@ public final class LoanApplicationTerms {
public CalendarHistoryDataWrapper getCalendarHistoryDataWrapper() {
return this.calendarHistoryDataWrapper;
}
public Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled(){
return this.isInterestChargedFromDateSameAsDisbursalDateEnabled;
}
}
@@ -289,6 +289,7 @@ public class LoanScheduleAssembler {
final Integer graceOnInterestPayment = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestPayment", element);
final Integer graceOnInterestCharged = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestCharged", element);
final LocalDate interestChargedFromDate = this.fromApiJsonHelper.extractLocalDateNamed("interestChargedFromDate", element);
final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = this.configurationDomainService.isInterestChargedFromDateSameAsDisbursementDate();
final Integer graceOnArrearsAgeing = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(
LoanProductConstants.graceOnArrearsAgeingParameterName, element);
@@ -396,7 +397,7 @@ public class LoanScheduleAssembler {
maxOutstandingBalance, graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
recalculationFrequencyType, restCalendarInstance, compoundingCalendarInstance, compoundingFrequencyType,
principalThresholdForLastInstalment, installmentAmountInMultiplesOf, loanProduct.preCloseInterestCalculationStrategy(),
calendar, BigDecimal.ZERO, loanTermVariations);
calendar, BigDecimal.ZERO, loanTermVariations, isInterestChargedFromDateSameAsDisbursalDateEnabled);
}
private CalendarInstance createCalendarForSameAsRepayment(final Integer repaymentEvery,
@@ -550,7 +550,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
}
}
}
final Set<LoanCollateral> possiblyModifedLoanCollateralItems = this.loanCollateralAssembler
.fromParsedJson(command.parsedJson());
@@ -123,10 +123,11 @@ public class LoanUtilService {
loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue());
overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod();
}
final Boolean isInterestChargedFromDateAsDisbursementDateEnabled = this.configurationDomainService.isInterestChargedFromDateSameAsDisbursementDate();
FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan);
ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency,
calculatedRepaymentsStartingFromDate, holidayDetails, restCalendarInstance, compoundingCalendarInstance, recalculateFrom,
overdurPenaltyWaitPeriod, floatingRateDTO, calendar, calendarHistoryDataWrapper);
overdurPenaltyWaitPeriod, floatingRateDTO, calendar, calendarHistoryDataWrapper, isInterestChargedFromDateAsDisbursementDateEnabled);
return scheduleGeneratorDTO;
}
@@ -0,0 +1 @@
INSERT INTO `c_configuration` (`name`, `value`, `date_value`, `enabled`, `is_trap_door`, `description`) VALUES ('interest-charged-from-date-same-as-disbursal-date', 0, NULL, 0, 0, NULL);