diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java index b62aaf4bd..75aefb219 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java @@ -77,4 +77,6 @@ public interface ConfigurationDomainService { Long retreivePeroidInNumberOfDaysForSkipMeetingDate(); + boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled(); + } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java index db853d47b..356d098e7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java @@ -255,6 +255,13 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName); return property.isEnabled(); } + + @Override + public boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled() { + final String propertyName = "change-emi-if-repaymentdate-same-as-disbursementdate"; + final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName); + return property.isEnabled(); + } } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java index ee6461aaf..b437af711 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java @@ -42,15 +42,16 @@ public class ScheduleGeneratorDTO { final Boolean isInterestChargedFromDateAsDisbursementDateEnabled; final Integer numberOfdays; final boolean isSkipRepaymentOnFirstDayofMonth; + final Boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled; 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 Boolean isInterestChargedFromDateAsDisbursementDateEnabled, final Integer numberOfdays, final boolean isSkipRepaymentOnFirstDayofMonth) { + final Boolean isInterestChargedFromDateAsDisbursementDateEnabled, final Integer numberOfdays, final boolean isSkipRepaymentOnFirstDayofMonth, + final Boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled) { this.loanScheduleFactory = loanScheduleFactory; this.applicationCurrency = applicationCurrency; @@ -64,9 +65,9 @@ public class ScheduleGeneratorDTO { this.calendar = calendar; this.calendarHistoryDataWrapper = calendarHistoryDataWrapper; this.isInterestChargedFromDateAsDisbursementDateEnabled = isInterestChargedFromDateAsDisbursementDateEnabled; - this.numberOfdays = numberOfdays; this.isSkipRepaymentOnFirstDayofMonth = isSkipRepaymentOnFirstDayofMonth; + this.isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled = isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled; } public LoanScheduleGeneratorFactory getLoanScheduleFactory() { @@ -136,5 +137,9 @@ public class ScheduleGeneratorDTO { public boolean isSkipRepaymentOnFirstDayofMonth() { return isSkipRepaymentOnFirstDayofMonth; } + + public Boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled() { + return this.isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 6d5b75086..13fd9ce22 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -2359,8 +2359,13 @@ public class Loan extends AbstractPersistable { if (this.loanProduct.isMultiDisburseLoan()) { final Date dateValue = null; final boolean isSpecificToInstallment = false; + final Boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled = scheduleGeneratorDTO.isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled(); + Date effectiveDateFrom = actualDisbursementDate.toDate(); + if(!isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled && actualDisbursementDate.equals(nextPossibleRepaymentDate)){ + effectiveDateFrom = nextPossibleRepaymentDate.plusDays(1).toDate(); + } LoanTermVariations loanVariationTerms = new LoanTermVariations(LoanTermVariationType.EMI_AMOUNT.getValue(), - actualDisbursementDate.toDate(), emiAmount, dateValue, isSpecificToInstallment, this, LoanStatus.ACTIVE.getValue()); + effectiveDateFrom, emiAmount, dateValue, isSpecificToInstallment, this, LoanStatus.ACTIVE.getValue()); this.loanTermVariations.add(loanVariationTerms); } else { this.fixedEmiAmount = emiAmount; @@ -5082,7 +5087,7 @@ public class Loan extends AbstractPersistable { this.loanProduct.getInstallmentAmountInMultiplesOf(), recalculationFrequencyType, restCalendarInstance, compoundingMethod, compoundingCalendarInstance, compoundingFrequencyType, this.loanProduct.preCloseInterestCalculationStrategy(), rescheduleStrategyMethod, calendar, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations, calendarHistoryDataWrapper, - scheduleGeneratorDTO.getNumberOfdays(), scheduleGeneratorDTO.isSkipRepaymentOnFirstDayofMonth()); + scheduleGeneratorDTO.getNumberOfdays(), scheduleGeneratorDTO.isSkipRepaymentOnFirstDayofMonth()); return loanApplicationTerms; } @@ -5239,6 +5244,7 @@ public class Loan extends AbstractPersistable { * TODO * @param floatingRateDTO * TODO + * @param isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled * @param loanCalendarInstance * Used for accessing the loan's calendar object * @return application terms of the Loan object diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java index ce06ca4cc..e17312eb6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java @@ -136,11 +136,12 @@ public class LoanUtilService { isSkipRepaymentOnFirstMonth = isLoanRepaymentsSyncWithMeeting(loan.group(), calendar); if(isSkipRepaymentOnFirstMonth) { numberOfDays = configurationDomainService.retreivePeroidInNumberOfDaysForSkipMeetingDate().intValue(); } } + final Boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled = this.configurationDomainService.isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled(); ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, calculatedRepaymentsStartingFromDate, holidayDetails, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, overdurPenaltyWaitPeriod, floatingRateDTO, calendar, calendarHistoryDataWrapper, isInterestChargedFromDateAsDisbursementDateEnabled, - numberOfDays, isSkipRepaymentOnFirstMonth); + numberOfDays, isSkipRepaymentOnFirstMonth, isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled); return scheduleGeneratorDTO; } diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V300__configuration_for_allow_changing_of_emi_amount.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V300__configuration_for_allow_changing_of_emi_amount.sql new file mode 100644 index 000000000..dc784ca46 --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V300__configuration_for_allow_changing_of_emi_amount.sql @@ -0,0 +1,4 @@ +ALTER TABLE `c_configuration` + CHANGE COLUMN `name` `name` VARCHAR(100) NULL DEFAULT NULL AFTER `id`; + +INSERT INTO `c_configuration` (`name`, `value`, `date_value`, `enabled`, `is_trap_door`, `description`) VALUES ( 'change-emi-if-repaymentdate-same-as-disbursementdate', 0, NULL, 1, 0, 'In tranche loans, if repayment date is same as tranche disbursement date then allow to change the emi amount');