From 5b0dc5b77ba18f536c97cd9298ef91bc497e19b8 Mon Sep 17 00:00:00 2001 From: Pramod Nuthakki Date: Wed, 17 Sep 2014 20:19:59 +0530 Subject: [PATCH] MIFOSX-1541 : corrected prepayment and interest calculation on date change --- .../portfolio/loanaccount/domain/Loan.java | 31 ++++++++------ .../LoanAccrualWritePlatformServiceImpl.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 40 +++++++++++++------ 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index b9f8153fc..53a4deab0 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -1820,24 +1820,11 @@ public class Loan extends AbstractPersistable { validateDisbursementDateIsOnNonWorkingDay(workingDays, allowTransactionsOnNonWorkingDay); validateDisbursementDateIsOnHoliday(allowTransactionsOnHoliday, holidays); - BigDecimal emiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName); - boolean isEmiAmountChanged = false; - if (this.loanProduct.isMultiDisburseLoan() && emiAmount != null && emiAmount.compareTo(retriveLastEmiAmount()) != 0) { - LoanTermVariations loanVariationTerms = new LoanTermVariations(LoanTermVariationType.EMI_AMOUNT.getValue(), - actualDisbursementDate.toDate(), emiAmount, this); - this.loanTermVariations.add(loanVariationTerms); - isEmiAmountChanged = true; - } - if (this.repaymentScheduleDetail().isInterestRecalculationEnabled() && (fetchRepaymentScheduleInstallment(1).getDueDate().isBefore(LocalDate.now()) || isDisbursementMissed())) { LocalDate recalculateFrom = null; regenerateRepaymentScheduleWithInterestRecalculation(loanScheduleFactory, currency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, workingDays, calendarInstanceForInterestRecalculation, recalculateFrom); - } else if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule - || isEmiAmountChanged) { - regenerateRepaymentSchedule(loanScheduleFactory, currency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, - workingDays); } updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); @@ -1863,6 +1850,24 @@ public class Loan extends AbstractPersistable { } + public void regenerateScheduleOnDisbursement(final LoanScheduleGeneratorFactory loanScheduleFactory, + final ApplicationCurrency currency, final LocalDate calculatedRepaymentsStartingFromDate, final boolean isHolidayEnabled, + final List holidays, final WorkingDays workingDays, final boolean recalculateSchedule, + final LocalDate actualDisbursementDate, BigDecimal emiAmount) { + boolean isEmiAmountChanged = false; + if (this.loanProduct.isMultiDisburseLoan() && emiAmount != null && emiAmount.compareTo(retriveLastEmiAmount()) != 0) { + LoanTermVariations loanVariationTerms = new LoanTermVariations(LoanTermVariationType.EMI_AMOUNT.getValue(), + actualDisbursementDate.toDate(), emiAmount, this); + this.loanTermVariations.add(loanVariationTerms); + isEmiAmountChanged = true; + } + + if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule || isEmiAmountChanged) { + regenerateRepaymentSchedule(loanScheduleFactory, currency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, + workingDays); + } + } + public boolean canDisburse(final LocalDate actualDisbursementDate) { Date lastDusburseDate = this.actualDisbursementDate; final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java index 1b45df998..583094ae8 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java @@ -156,7 +156,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat } int daysToBeAccrued = Days.daysBetween(startDate, tilldate).getDays(); // if (daysToBeAccrued < 1) { return; } - int daysInSchedule = Days.daysBetween(interestStartDate, tilldate).getDays(); +// int daysInSchedule = Days.daysBetween(interestStartDate, tilldate).getDays(); /* * switch (accrualData.getRepaymentFrequency()) { case MONTHS: int * numberOfDaysInMonth = @@ -175,7 +175,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat BigDecimal interestportion = null; BigDecimal feeportion = accrualData.getDueDateFeeIncome(); BigDecimal penaltyportion = accrualData.getDueDatePenaltyIncome(); - if (daysInSchedule >= totalNumberOfDays) { + if (daysToBeAccrued >= totalNumberOfDays) { interestportion = accrualData.getInterestIncome(); } else { double iterest = interestPerDay * daysToBeAccrued; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index e28e38414..b9e3c610c 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -83,6 +83,7 @@ import org.mifosplatform.portfolio.collectionsheet.command.SingleRepaymentComman import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.group.domain.Group; import org.mifosplatform.portfolio.group.exception.GroupNotActiveException; +import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants; import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand; import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.mifosplatform.portfolio.loanaccount.data.LoanInstallmentChargeData; @@ -280,7 +281,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf ChangedTransactionDetail changedTransactionDetail = null; if (canDisburse) { Money disburseAmount = loan.adjustDisburseAmount(command, actualDisbursementDate); - boolean recalcualteSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincpal()); + boolean recalculateSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincpal()); final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId"); if (isAccountTransfer) { disburseLoanToSavings(loan, command, disburseAmount, paymentDetail); @@ -301,9 +302,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf CalendarEntityType.LOAN_RECALCULATION_DETAIL.getValue()); } + regenerateScheduleOnDisbursement(command, loan, applicationCurrency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, + workingDays, recalculateSchedule); + if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { + this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(loan.fetchRepaymentScheduleInstallments(), + loan, null); + } changedTransactionDetail = loan.disburse(this.loanScheduleFactory, currentUser, command, applicationCurrency, changes, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, - allowTransactionsOnNonWorkingDay, recalcualteSchedule, restCalendarInstance); + allowTransactionsOnNonWorkingDay, recalculateSchedule, restCalendarInstance); } if (!changes.isEmpty()) { saveAndFlushLoanWithDataIntegrityViolationChecks(loan); @@ -322,10 +329,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue()); } } - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - createLoanScheduleArchive(loan, applicationCurrency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, - workingDays); - } + postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); } @@ -476,7 +480,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (canDisburse) { Money amountBeforeAdjust = loan.getPrincpal(); Money disburseAmount = loan.adjustDisburseAmount(command, actualDisbursementDate); - boolean recalcualteSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincpal()); + boolean recalculateSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincpal()); final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId"); if (isAccountTransfer) { disburseLoanToSavings(loan, command, disburseAmount, paymentDetail); @@ -496,10 +500,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_DETAIL.getValue()); } - + regenerateScheduleOnDisbursement(command, loan, applicationCurrency, firstRepaymentOnDate, isHolidayEnabled, holidays, + workingDays, recalculateSchedule); + if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { + this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(loan.fetchRepaymentScheduleInstallments(), + loan, null); + } changedTransactionDetail = loan.disburse(this.loanScheduleFactory, currentUser, command, applicationCurrency, changes, firstRepaymentOnDate, isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, - allowTransactionsOnNonWorkingDay, recalcualteSchedule, restCalendarInstance); + allowTransactionsOnNonWorkingDay, recalculateSchedule, restCalendarInstance); } if (!changes.isEmpty()) { @@ -518,10 +527,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue()); } } - - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - createLoanScheduleArchive(loan, applicationCurrency, firstRepaymentOnDate, isHolidayEnabled, holidays, workingDays); - } postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); } final Set loanCharges = loan.charges(); @@ -2315,6 +2320,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } + private void regenerateScheduleOnDisbursement(final JsonCommand command, final Loan loan, final ApplicationCurrency applicationCurrency, + final LocalDate calculatedRepaymentsStartingFromDate, final boolean isHolidayEnabled, final List holidays, + final WorkingDays workingDays, final boolean recalculateSchedule) { + final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate"); + BigDecimal emiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName); + loan.regenerateScheduleOnDisbursement(loanScheduleFactory, applicationCurrency, calculatedRepaymentsStartingFromDate, + isHolidayEnabled, holidays, workingDays, recalculateSchedule, actualDisbursementDate, emiAmount); + } + private List retrieveRepaymentScheduleFromModel(LoanScheduleModel model) { final List installments = new ArrayList<>(); for (final LoanScheduleModelPeriod scheduledLoanInstallment : model.getPeriods()) {