From 7c45056f88ebf2367ea86f03c17f59f985726057 Mon Sep 17 00:00:00 2001 From: pramod Date: Wed, 13 Jan 2016 15:27:50 +0530 Subject: [PATCH] MIFOSX-2437: fix for prepay of loan --- .../data/ScheduleGeneratorDTO.java | 18 - .../portfolio/loanaccount/domain/Loan.java | 324 ++++------ .../domain/LoanAccountDomainService.java | 20 +- .../domain/LoanAccountDomainServiceJpa.java | 159 +---- .../domain/AbstractLoanScheduleGenerator.java | 46 +- .../domain/LoanScheduleGenerator.java | 10 +- .../service/LoanScheduleAssembler.java | 33 +- ...cheduleCalculationPlatformServiceImpl.java | 66 +- .../LoanScheduleWritePlatformServiceImpl.java | 4 +- ...heduleRequestWritePlatformServiceImpl.java | 86 ++- ...WritePlatformServiceJpaRepositoryImpl.java | 34 +- .../service/LoanReadPlatformServiceImpl.java | 71 +-- .../loanaccount/service/LoanUtilService.java | 135 ++-- ...WritePlatformServiceJpaRepositoryImpl.java | 578 +++--------------- 14 files changed, 447 insertions(+), 1137 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/ScheduleGeneratorDTO.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/ScheduleGeneratorDTO.java index 046452e5c..32b3ff2b0 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/ScheduleGeneratorDTO.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/ScheduleGeneratorDTO.java @@ -23,23 +23,6 @@ public class ScheduleGeneratorDTO { final Long overdurPenaltyWaitPeriod; final FloatingRateDTO floatingRateDTO; - public ScheduleGeneratorDTO(final LoanScheduleGeneratorFactory loanScheduleFactory, final ApplicationCurrency applicationCurrency, - final LocalDate calculatedRepaymentsStartingFromDate, final HolidayDetailDTO holidayDetailDTO, - final CalendarInstance calendarInstanceForInterestRecalculation, final CalendarInstance compoundingCalendarInstance, - final FloatingRateDTO floatingRateDTO) { - - this.loanScheduleFactory = loanScheduleFactory; - this.applicationCurrency = applicationCurrency; - this.calculatedRepaymentsStartingFromDate = calculatedRepaymentsStartingFromDate; - this.calendarInstanceForInterestRecalculation = calendarInstanceForInterestRecalculation; - this.compoundingCalendarInstance = compoundingCalendarInstance; - this.recalculateFrom = null; - this.overdurPenaltyWaitPeriod = null; - this.holidayDetailDTO = holidayDetailDTO; - this.floatingRateDTO = floatingRateDTO; - - } - public ScheduleGeneratorDTO(final LoanScheduleGeneratorFactory loanScheduleFactory, final ApplicationCurrency applicationCurrency, final LocalDate calculatedRepaymentsStartingFromDate, final HolidayDetailDTO holidayDetailDTO, final CalendarInstance calendarInstanceForInterestRecalculation, final CalendarInstance compoundingCalendarInstance, @@ -100,7 +83,6 @@ public class ScheduleGeneratorDTO { return this.compoundingCalendarInstance; } - public FloatingRateDTO getFloatingRateDTO() { return this.floatingRateDTO; } 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 2e3a2e3f0..27003d44b 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 @@ -103,10 +103,8 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator; -import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod; -import org.mifosplatform.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest; import org.mifosplatform.portfolio.loanproduct.LoanProductConstants; import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod; import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod; @@ -838,9 +836,7 @@ public class Loan extends AbstractPersistable { */ private BigDecimal calculateAmountPercentageAppliedTo(final LoanCharge loanCharge) { BigDecimal amount = BigDecimal.ZERO; - if(loanCharge.isOverdueInstallmentCharge()){ - return loanCharge.getAmountPercentageAppliedTo(); - } + if (loanCharge.isOverdueInstallmentCharge()) { return loanCharge.getAmountPercentageAppliedTo(); } switch (loanCharge.getChargeCalculation()) { case PERCENT_OF_AMOUNT: amount = getPrincpal().getAmount(); @@ -2561,50 +2557,14 @@ public class Loan extends AbstractPersistable { } public LoanScheduleModel regenerateScheduleModel(final ScheduleGeneratorDTO scheduleGeneratorDTO) { - final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod(); - final LoanScheduleGenerator loanScheduleGenerator = scheduleGeneratorDTO.getLoanScheduleFactory().create(interestMethod); final RoundingMode roundingMode = MoneyHelper.getRoundingMode(); final MathContext mc = new MathContext(8, roundingMode); - final Integer loanTermFrequency = this.termFrequency; - final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType); - final NthDayType nthDayType = NthDayType.fromInt(this.repaymentFrequencyNthDayType); - final DayOfWeekType dayOfWeekType = DayOfWeekType.fromInt(this.repaymentFrequencyDayOfWeekType); - final List disbursementData = new ArrayList<>(); - for (LoanDisbursementDetails disbursementDetails : this.disbursementDetails) { - disbursementData.add(disbursementDetails.toData()); - } - - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - RecalculationFrequencyType recalculationFrequencyType = null; - InterestRecalculationCompoundingMethod compoundingMethod = null; - RecalculationFrequencyType compoundingFrequencyType = null; - LoanRescheduleStrategyMethod rescheduleStrategyMethod = null; - if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = scheduleGeneratorDTO.getCalendarInstanceForInterestRecalculation(); - compoundingCalendarInstance = scheduleGeneratorDTO.getCompoundingCalendarInstance(); - recalculationFrequencyType = this.loanInterestRecalculationDetails.getRestFrequencyType(); - compoundingMethod = this.loanInterestRecalculationDetails.getInterestRecalculationCompoundingMethod(); - compoundingFrequencyType = this.loanInterestRecalculationDetails.getCompoundingFrequencyType(); - rescheduleStrategyMethod = this.loanInterestRecalculationDetails.getRescheduleStrategyMethod(); - } - - BigDecimal annualNominalInterestRate = this.loanRepaymentScheduleDetail.getAnnualNominalInterestRate(); - FloatingRateDTO floatingRateDTO = scheduleGeneratorDTO.getFloatingRateDTO(); - List loanTermVariations = new ArrayList<>(); - annualNominalInterestRate = constructLoanTermVariations(floatingRateDTO, annualNominalInterestRate, loanTermVariations); - - 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.loanProduct.getInstallmentAmountInMultiplesOf(), recalculationFrequencyType, restCalendarInstance, compoundingMethod, - compoundingCalendarInstance, compoundingFrequencyType, this.loanProduct.preCloseInterestCalculationStrategy(), - rescheduleStrategyMethod, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations); + final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod(); + final LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(scheduleGeneratorDTO); + final LoanScheduleGenerator loanScheduleGenerator = scheduleGeneratorDTO.getLoanScheduleFactory().create(interestMethod); final LoanScheduleModel loanSchedule = loanScheduleGenerator.generate(mc, loanApplicationTerms, charges(), scheduleGeneratorDTO.getHolidayDetailDTO()); return loanSchedule; @@ -2837,6 +2797,7 @@ public class Loan extends AbstractPersistable { return changedTransactionDetail; } + @SuppressWarnings("null") public ChangedTransactionDetail makeRepayment(final LoanTransaction repaymentTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine, final List existingTransactionIds, final List existingReversedTransactionIds, boolean isRecoveryRepayment, final ScheduleGeneratorDTO scheduleGeneratorDTO, @@ -3087,9 +3048,7 @@ public class Loan extends AbstractPersistable { private List retreiveListOfTransactionsPostDisbursement() { final List repaymentsOrWaivers = new ArrayList<>(); for (final LoanTransaction transaction : this.loanTransactions) { - if (transaction.isNotReversed() - && !(transaction.isDisbursement() - || transaction.isNonMonetaryTransaction())) { + if (transaction.isNotReversed() && !(transaction.isDisbursement() || transaction.isNonMonetaryTransaction())) { repaymentsOrWaivers.add(transaction); } } @@ -3101,11 +3060,9 @@ public class Loan extends AbstractPersistable { public List retreiveListOfTransactionsPostDisbursementExcludeAccruals() { final List repaymentsOrWaivers = new ArrayList<>(); for (final LoanTransaction transaction : this.loanTransactions) { - if (transaction.isNotReversed() - && !(transaction.isDisbursement() - || transaction.isAccrual() - || transaction.isRepaymentAtDisbursement() - || transaction.isNonMonetaryTransaction())) { + if (transaction.isNotReversed() + && !(transaction.isDisbursement() || transaction.isAccrual() || transaction.isRepaymentAtDisbursement() || transaction + .isNonMonetaryTransaction())) { repaymentsOrWaivers.add(transaction); } } @@ -3117,9 +3074,7 @@ public class Loan extends AbstractPersistable { private List retreiveListOfTransactionsExcludeAccruals() { final List repaymentsOrWaivers = new ArrayList<>(); for (final LoanTransaction transaction : this.loanTransactions) { - if (transaction.isNotReversed() - && !(transaction.isAccrual() - || transaction.isNonMonetaryTransaction())) { + if (transaction.isNotReversed() && !(transaction.isAccrual() || transaction.isNonMonetaryTransaction())) { repaymentsOrWaivers.add(transaction); } } @@ -4520,9 +4475,10 @@ public class Loan extends AbstractPersistable { postfix = "cannot.be.made.before.client.transfer.date"; break; case LOAN_DISBURSAL_UNDO_LAST: - errorMessage = "Cannot undo a last disbursal in another branch"; + errorMessage = "Cannot undo a last disbursal in another branch"; action = "disbursal"; postfix = "cannot.be.undone.before.client.transfer.date"; + break; default: break; } @@ -4573,7 +4529,7 @@ public class Loan extends AbstractPersistable { } return currentTransactionDate; } - + public LocalDate getLastRepaymentDate() { LocalDate currentTransactionDate = getDisbursementDate(); for (final LoanTransaction previousTransaction : this.loanTransactions) { @@ -4756,13 +4712,14 @@ public class Loan extends AbstractPersistable { dataValidationErrors.add(error); } break; - case LOAN_DISBURSAL_UNDO_LAST: - if (!isOpen()) { - final String defaultUserMessage = "Loan Undo last disbursal is not allowed. Loan Account is not active."; - final ApiParameterError error = ApiParameterError.generalError("error.msg.loan.undo.last.disbursal.account.is.not.active", - defaultUserMessage); - dataValidationErrors.add(error); - } + case LOAN_DISBURSAL_UNDO_LAST: + if (!isOpen()) { + final String defaultUserMessage = "Loan Undo last disbursal is not allowed. Loan Account is not active."; + final ApiParameterError error = ApiParameterError.generalError( + "error.msg.loan.undo.last.disbursal.account.is.not.active", defaultUserMessage); + dataValidationErrors.add(error); + } + break; default: break; } @@ -5007,9 +4964,7 @@ public class Loan extends AbstractPersistable { final RoundingMode roundingMode = MoneyHelper.getRoundingMode(); final MathContext mc = new MathContext(8, roundingMode); - final LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(generatorDTO.getApplicationCurrency(), - generatorDTO.getCalculatedRepaymentsStartingFromDate(), generatorDTO.getCalendarInstanceForInterestRecalculation(), - generatorDTO.getCompoundingCalendarInstance(), generatorDTO.getFloatingRateDTO()); + final LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(generatorDTO); final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); @@ -5019,91 +4974,69 @@ public class Loan extends AbstractPersistable { repaymentScheduleInstallments, generatorDTO.getRecalculateFrom()); } - public LoanApplicationTerms constructLoanApplicationTerms(final ApplicationCurrency applicationCurrency, - final LocalDate calculatedRepaymentsStartingFromDate, final CalendarInstance calendarInstanceForInterestRecalculation, - final CalendarInstance compoundingCalendarInstance, final FloatingRateDTO floatingRateDTO) { + public LoanRepaymentScheduleInstallment fetchPrepaymentDetail(final ScheduleGeneratorDTO scheduleGeneratorDTO, final LocalDate onDate) { + LoanRepaymentScheduleInstallment installment = null; + + if (this.loanRepaymentScheduleDetail.isInterestRecalculationEnabled()) { + final RoundingMode roundingMode = MoneyHelper.getRoundingMode(); + final MathContext mc = new MathContext(8, roundingMode); + + final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod(); + final LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(scheduleGeneratorDTO); + + final LoanScheduleGenerator loanScheduleGenerator = scheduleGeneratorDTO.getLoanScheduleFactory().create(interestMethod); + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory + .determineProcessor(this.transactionProcessingStrategy); + installment = loanScheduleGenerator.calculatePrepaymentAmount(getCurrency(), onDate, loanApplicationTerms, mc, charges(), + scheduleGeneratorDTO.getHolidayDetailDTO(), retreiveListOfTransactionsPostDisbursementExcludeAccruals(), + loanRepaymentScheduleTransactionProcessor, this.fetchRepaymentScheduleInstallments()); + } else { + installment = this.getTotalOutstandingOnLoan(); + } + return installment; + } + + public LoanApplicationTerms constructLoanApplicationTerms(final ScheduleGeneratorDTO scheduleGeneratorDTO) { final Integer loanTermFrequency = this.termFrequency; final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType); + final NthDayType nthDayType = NthDayType.fromInt(this.repaymentFrequencyNthDayType); + final DayOfWeekType dayOfWeekType = DayOfWeekType.fromInt(this.repaymentFrequencyDayOfWeekType); final List disbursementData = new ArrayList<>(); for (LoanDisbursementDetails disbursementDetails : this.disbursementDetails) { disbursementData.add(disbursementDetails.toData()); } - RecalculationFrequencyType recalculationFrequencyType = this.loanInterestRecalculationDetails().getRestFrequencyType(); - RecalculationFrequencyType compoundingFrequencyType = this.loanInterestRecalculationDetails().getCompoundingFrequencyType(); + CalendarInstance restCalendarInstance = null; + CalendarInstance compoundingCalendarInstance = null; + RecalculationFrequencyType recalculationFrequencyType = null; + InterestRecalculationCompoundingMethod compoundingMethod = null; + RecalculationFrequencyType compoundingFrequencyType = null; + LoanRescheduleStrategyMethod rescheduleStrategyMethod = null; + if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) { + restCalendarInstance = scheduleGeneratorDTO.getCalendarInstanceForInterestRecalculation(); + compoundingCalendarInstance = scheduleGeneratorDTO.getCompoundingCalendarInstance(); + recalculationFrequencyType = this.loanInterestRecalculationDetails.getRestFrequencyType(); + compoundingMethod = this.loanInterestRecalculationDetails.getInterestRecalculationCompoundingMethod(); + compoundingFrequencyType = this.loanInterestRecalculationDetails.getCompoundingFrequencyType(); + rescheduleStrategyMethod = this.loanInterestRecalculationDetails.getRescheduleStrategyMethod(); + } BigDecimal annualNominalInterestRate = this.loanRepaymentScheduleDetail.getAnnualNominalInterestRate(); + FloatingRateDTO floatingRateDTO = scheduleGeneratorDTO.getFloatingRateDTO(); List loanTermVariations = new ArrayList<>(); annualNominalInterestRate = constructLoanTermVariations(floatingRateDTO, annualNominalInterestRate, loanTermVariations); - final LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency, - loanTermPeriodFrequencyType, getDisbursementDate(), getExpectedFirstRepaymentOnDate(), - calculatedRepaymentsStartingFromDate, getInArrearsTolerance(), this.loanRepaymentScheduleDetail, - this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, disbursementData, this.maxOutstandingLoanBalance, - getInterestChargedFromDate(), this.loanInterestRecalculationDetails, calendarInstanceForInterestRecalculation, - recalculationFrequencyType, compoundingCalendarInstance, compoundingFrequencyType, - this.loanProduct.getPrincipalThresholdForLastInstallment(), this.loanProduct.getInstallmentAmountInMultiplesOf(), - this.loanProduct.preCloseInterestCalculationStrategy(), getApprovedPrincipal(), annualNominalInterestRate, - loanTermVariations); + 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.loanProduct.getInstallmentAmountInMultiplesOf(), recalculationFrequencyType, restCalendarInstance, compoundingMethod, + compoundingCalendarInstance, compoundingFrequencyType, this.loanProduct.preCloseInterestCalculationStrategy(), + rescheduleStrategyMethod, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations); return loanApplicationTerms; } - public LoanRepaymentScheduleInstallment fetchPrepaymentDetail(final LoanScheduleGeneratorFactory loanScheduleFactory, - final CalendarInstance restCalendarInstance, final CalendarInstance compoundingCalendarInstance, - final HolidayDetailDTO holidayDetailDTO, final LocalDate onDate, FloatingRateDTO floatingRateDTO) { - LoanRepaymentScheduleInstallment installment = null; - - if (this.loanRepaymentScheduleDetail.isInterestRecalculationEnabled()) { - final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod(); - final LoanScheduleGenerator loanScheduleGenerator = loanScheduleFactory.create(interestMethod); - - final RoundingMode roundingMode = MoneyHelper.getRoundingMode(); - final MathContext mc = new MathContext(8, roundingMode); - - final Integer loanTermFrequency = this.termFrequency; - final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType); - final NthDayType nthDayType = NthDayType.fromInt(this.repaymentFrequencyNthDayType); - final DayOfWeekType dayOfWeekType = DayOfWeekType.fromInt(this.repaymentFrequencyDayOfWeekType); - - final List disbursementData = new ArrayList<>(); - for (LoanDisbursementDetails disbursementDetails : this.disbursementDetails) { - disbursementData.add(disbursementDetails.toData()); - } - - RecalculationFrequencyType recalculationFrequencyType = null; - InterestRecalculationCompoundingMethod compoundingMethod = null; - RecalculationFrequencyType compoundingFrequencyType = null; - LoanRescheduleStrategyMethod rescheduleStrategyMethod = null; - if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - recalculationFrequencyType = this.loanInterestRecalculationDetails.getRestFrequencyType(); - compoundingMethod = this.loanInterestRecalculationDetails.getInterestRecalculationCompoundingMethod(); - compoundingFrequencyType = this.loanInterestRecalculationDetails.getCompoundingFrequencyType(); - rescheduleStrategyMethod = this.loanInterestRecalculationDetails.getRescheduleStrategyMethod(); - } - - BigDecimal annualNominalInterestRate = this.loanRepaymentScheduleDetail.getAnnualNominalInterestRate(); - List loanTermVariations = new ArrayList<>(); - annualNominalInterestRate = constructLoanTermVariations(floatingRateDTO, annualNominalInterestRate, loanTermVariations); - - final LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(null, loanTermFrequency, - loanTermPeriodFrequencyType, nthDayType, dayOfWeekType, getDisbursementDate(), getExpectedFirstRepaymentOnDate(), null, - getInArrearsTolerance(), this.loanRepaymentScheduleDetail, this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, - disbursementData, this.maxOutstandingLoanBalance, getInterestChargedFromDate(), - this.loanProduct.getPrincipalThresholdForLastInstallment(), this.loanProduct.getInstallmentAmountInMultiplesOf(), - recalculationFrequencyType, restCalendarInstance, compoundingMethod, compoundingCalendarInstance, - compoundingFrequencyType, this.loanProduct.preCloseInterestCalculationStrategy(), rescheduleStrategyMethod, - getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations); - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory - .determineProcessor(this.transactionProcessingStrategy); - installment = loanScheduleGenerator.calculatePrepaymentAmount(getCurrency(), onDate, loanApplicationTerms, mc, charges(), - holidayDetailDTO, retreiveListOfTransactionsPostDisbursementExcludeAccruals(), - loanRepaymentScheduleTransactionProcessor); - } else { - installment = this.getTotalOutstandingOnLoan(); - } - return installment; - } - private BigDecimal constructLoanTermVariations(FloatingRateDTO floatingRateDTO, BigDecimal annualNominalInterestRate, List loanTermVariations) { for (LoanTermVariations variationTerms : this.loanTermVariations) { @@ -5575,76 +5508,79 @@ public class Loan extends AbstractPersistable { trancheCharges.add(new LoanTrancheCharge(charge, this)); } } - - public Map undoLastDisbursal(ScheduleGeneratorDTO scheduleGeneratorDTO, List existingTransactionIds, - List existingReversedTransactionIds, AppUser currentUser, Loan loan) { - validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO_LAST); - existingTransactionIds.addAll(findExistingTransactionIds()); + public Map undoLastDisbursal(ScheduleGeneratorDTO scheduleGeneratorDTO, List existingTransactionIds, + List existingReversedTransactionIds, AppUser currentUser, Loan loan) { + + validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO_LAST); + existingTransactionIds.addAll(findExistingTransactionIds()); existingReversedTransactionIds.addAll(findExistingReversedTransactionIds()); final Map actualChanges = new LinkedHashMap<>(); validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_DISBURSAL_UNDO_LAST, getDisbursementDate()); LocalDate actualDisbursementDate = null; - LocalDate lastTransactionDate = getDisbursementDate(); - List loanTransactions = retreiveListOfTransactionsExcludeAccruals(); - Collections.reverse(loanTransactions); - for (final LoanTransaction previousTransaction : loanTransactions) { + LocalDate lastTransactionDate = getDisbursementDate(); + List loanTransactions = retreiveListOfTransactionsExcludeAccruals(); + Collections.reverse(loanTransactions); + for (final LoanTransaction previousTransaction : loanTransactions) { if (lastTransactionDate.isBefore(previousTransaction.getTransactionDate())) { - if(previousTransaction.isRepayment() || previousTransaction.isWaiver() || - previousTransaction.isChargePayment()){ - throw new UndoLastTrancheDisbursementException(previousTransaction.getId()); } - } - if(previousTransaction.isDisbursement()){ - lastTransactionDate = previousTransaction.getTransactionDate(); - break; - } + if (previousTransaction.isRepayment() || previousTransaction.isWaiver() || previousTransaction.isChargePayment()) { throw new UndoLastTrancheDisbursementException( + previousTransaction.getId()); } + } + if (previousTransaction.isDisbursement()) { + lastTransactionDate = previousTransaction.getTransactionDate(); + break; + } } actualDisbursementDate = lastTransactionDate; updateLoanToLastDisbursalState(actualDisbursementDate); reverseExistingTransactionsTillLastDisbursal(actualDisbursementDate); - loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, - existingTransactionIds, existingReversedTransactionIds, currentUser); - actualChanges.put("undolastdisbursal","true"); - actualChanges.put("disbursedAmount",this.getDisbursedAmount()); + loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, existingTransactionIds, existingReversedTransactionIds, + currentUser); + actualChanges.put("undolastdisbursal", "true"); + actualChanges.put("disbursedAmount", this.getDisbursedAmount()); updateLoanSummaryDerivedFields(); return actualChanges; - } - /** - * Reverse only disbursement, accruals, and repayments at disbursal transactions - * @param actualDisbursementDate - * @return - */ - public List reverseExistingTransactionsTillLastDisbursal(LocalDate actualDisbursementDate) { - final List reversedTransactions = new ArrayList<>(); - for (final LoanTransaction transaction : this.loanTransactions) { - if((actualDisbursementDate.equals(transaction.getTransactionDate()) || actualDisbursementDate.isBefore(transaction.getTransactionDate())) - && transaction.isAllowTypeTransactionAtTheTimeOfLastUndo()){ - reversedTransactions.add(transaction); - transaction.reverse(); - } - } - return reversedTransactions; - } + } - private void updateLoanToLastDisbursalState(LocalDate actualDisbursementDate) { - - for (final LoanCharge charge : charges()) { - if (charge.isOverdueInstallmentCharge()) { - charge.setActive(false); - } else if (charge.isTrancheDisbursementCharge() && actualDisbursementDate.equals(new LocalDate - (charge.getTrancheDisbursementCharge().getloanDisbursementDetails().actualDisbursementDate()))) { - charge.resetToOriginal(loanCurrency()); - } - } - for (final LoanDisbursementDetails details : this.disbursementDetails) { - if (actualDisbursementDate.equals(new LocalDate(details.actualDisbursementDate()))) { - this.loanRepaymentScheduleDetail.setPrincipal(getDisbursedAmount().subtract(details.principal())); - details.updateActualDisbursementDate(null); - } - } - updateLoanSummaryDerivedFields(); - } + /** + * Reverse only disbursement, accruals, and repayments at disbursal + * transactions + * + * @param actualDisbursementDate + * @return + */ + public List reverseExistingTransactionsTillLastDisbursal(LocalDate actualDisbursementDate) { + final List reversedTransactions = new ArrayList<>(); + for (final LoanTransaction transaction : this.loanTransactions) { + if ((actualDisbursementDate.equals(transaction.getTransactionDate()) || actualDisbursementDate.isBefore(transaction + .getTransactionDate())) && transaction.isAllowTypeTransactionAtTheTimeOfLastUndo()) { + reversedTransactions.add(transaction); + transaction.reverse(); + } + } + return reversedTransactions; + } + + private void updateLoanToLastDisbursalState(LocalDate actualDisbursementDate) { + + for (final LoanCharge charge : charges()) { + if (charge.isOverdueInstallmentCharge()) { + charge.setActive(false); + } else if (charge.isTrancheDisbursementCharge() + && actualDisbursementDate.equals(new LocalDate(charge.getTrancheDisbursementCharge().getloanDisbursementDetails() + .actualDisbursementDate()))) { + charge.resetToOriginal(loanCurrency()); + } + } + for (final LoanDisbursementDetails details : this.disbursementDetails) { + if (actualDisbursementDate.equals(new LocalDate(details.actualDisbursementDate()))) { + this.loanRepaymentScheduleDetail.setPrincipal(getDisbursedAmount().subtract(details.principal())); + details.updateActualDisbursementDate(null); + } + } + updateLoanSummaryDerivedFields(); + } public Boolean getIsFloatingInterestRate() { return this.isFloatingInterestRate; @@ -5685,5 +5621,5 @@ public class Loan extends AbstractPersistable { public void setExpectedFirstRepaymentOnDate(Date expectedFirstRepaymentOnDate) { this.expectedFirstRepaymentOnDate = expectedFirstRepaymentOnDate; } - + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java index edf79764a..3f5b53f80 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java @@ -9,9 +9,7 @@ import java.math.BigDecimal; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; -import org.mifosplatform.portfolio.calendar.domain.CalendarInstance; import org.mifosplatform.portfolio.loanaccount.data.HolidayDetailDTO; -import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail; public interface LoanAccountDomainService { @@ -31,11 +29,8 @@ public interface LoanAccountDomainService { LoanTransaction makeDisburseTransaction(Long loanId, LocalDate transactionDate, BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId); - LocalDate getCalculatedRepaymentsStartingFromDate(LocalDate actualDisbursementDate, Loan loan, CalendarInstance calendarInstance); - - LoanTransaction makeRefundForActiveLoan(Long accountId, CommandProcessingResultBuilder builderResult, - LocalDate transactionDate, BigDecimal transactionAmount, - PaymentDetail paymentDetail, String noteText, String txnExternalId); + LoanTransaction makeRefundForActiveLoan(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate, + BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId); /** * This method is to recalculate and accrue the income till the last accrued @@ -46,17 +41,6 @@ public interface LoanAccountDomainService { */ void recalculateAccruals(Loan loan); - /** - * This method is used for building ScheduleGeneratorDTO from loan, usages - * are as, if have loan and some of the terms are modified which may impact - * the schedule, in that case need to recompute the schedule, so this method - * helps to build the ScheduleGeneratorDTO from modified loan. - * - * @param loan - */ - - public ScheduleGeneratorDTO buildScheduleGeneratorDTO(final Loan loan); - void saveLoanWithDataIntegrityViolationChecks(Loan loan); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 2aca9a7e5..d2af0970c 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -38,30 +38,20 @@ import org.mifosplatform.organisation.workingdays.domain.WorkingDays; import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; import org.mifosplatform.portfolio.account.domain.AccountTransferRepository; import org.mifosplatform.portfolio.account.domain.AccountTransferTransaction; -import org.mifosplatform.portfolio.calendar.domain.Calendar; -import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType; -import org.mifosplatform.portfolio.calendar.domain.CalendarInstance; -import org.mifosplatform.portfolio.calendar.domain.CalendarInstanceRepository; -import org.mifosplatform.portfolio.calendar.service.CalendarUtils; import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.exception.ClientNotActiveException; import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY; import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS; import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.common.service.BusinessEventNotifierService; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRateDTO; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRatePeriodData; -import org.mifosplatform.portfolio.floatingrates.exception.FloatingRateNotFoundException; -import org.mifosplatform.portfolio.floatingrates.service.FloatingRatesReadPlatformService; import org.mifosplatform.portfolio.group.domain.Group; import org.mifosplatform.portfolio.group.exception.GroupNotActiveException; import org.mifosplatform.portfolio.loanaccount.data.HolidayDetailDTO; import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData; import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO; -import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory; import org.mifosplatform.portfolio.loanaccount.service.LoanAccrualPlatformService; import org.mifosplatform.portfolio.loanaccount.service.LoanAssembler; -import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail; +import org.mifosplatform.portfolio.loanaccount.service.LoanUtilService; import org.mifosplatform.portfolio.note.domain.Note; import org.mifosplatform.portfolio.note.domain.NoteRepository; import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail; @@ -85,14 +75,12 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { private final JournalEntryWritePlatformService journalEntryWritePlatformService; private final NoteRepository noteRepository; private final AccountTransferRepository accountTransferRepository; - private final LoanScheduleGeneratorFactory loanScheduleFactory; private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository; - private final CalendarInstanceRepository calendarInstanceRepository; private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository; private final LoanAccrualPlatformService loanAccrualPlatformService; private final PlatformSecurityContext context; private final BusinessEventNotifierService businessEventNotifierService; - private final FloatingRatesReadPlatformService floatingRatesReadPlatformService; + private final LoanUtilService loanUtilService; @Autowired public LoanAccountDomainServiceJpa(final LoanAssembler loanAccountAssembler, final LoanRepository loanRepository, @@ -101,13 +89,11 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { final WorkingDaysRepositoryWrapper workingDaysRepository, final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper, final JournalEntryWritePlatformService journalEntryWritePlatformService, - final AccountTransferRepository accountTransferRepository, final LoanScheduleGeneratorFactory loanScheduleFactory, + final AccountTransferRepository accountTransferRepository, final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository, - final CalendarInstanceRepository calendarInstanceRepository, final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository, final LoanAccrualPlatformService loanAccrualPlatformService, final PlatformSecurityContext context, - final BusinessEventNotifierService businessEventNotifierService, - final FloatingRatesReadPlatformService floatingRatesReadPlatformService) { + final BusinessEventNotifierService businessEventNotifierService, final LoanUtilService loanUtilService) { this.loanAccountAssembler = loanAccountAssembler; this.loanRepository = loanRepository; this.loanTransactionRepository = loanTransactionRepository; @@ -118,31 +104,22 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper; this.journalEntryWritePlatformService = journalEntryWritePlatformService; this.accountTransferRepository = accountTransferRepository; - this.loanScheduleFactory = loanScheduleFactory; this.applicationCurrencyRepository = applicationCurrencyRepository; - this.calendarInstanceRepository = calendarInstanceRepository; this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository; this.loanAccrualPlatformService = loanAccrualPlatformService; this.context = context; this.businessEventNotifierService = businessEventNotifierService; - this.floatingRatesReadPlatformService = floatingRatesReadPlatformService; + this.loanUtilService = loanUtilService; } @Transactional @Override public LoanTransaction makeRepayment(final Loan loan, final CommandProcessingResultBuilder builderResult, final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText, - final String txnExternalId, final boolean isRecoveryRepayment, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto, Boolean isHolidayValidationDone) { + final String txnExternalId, final boolean isRecoveryRepayment, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto, + Boolean isHolidayValidationDone) { AppUser currentUser = getAppUserIfPresent(); checkClientOrGroupActive(loan); - List holidays = null; - WorkingDays workingDays = null; - boolean allowTransactionsOnHoliday = false; - boolean allowTransactionsOnNonWorkingDay = false; - HolidayDetailDTO holidayDetailDTO = null; - if(holidayDetailDto != null){ - holidayDetailDTO = holidayDetailDto; - } this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT, constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); @@ -173,48 +150,12 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { txnExternalId, currentDateTime, currentUser); } - if(!isHolidayValidationDone){ - allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); - holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), - transactionDate.toDate(), HolidayStatusType.ACTIVE.getValue()); - workingDays = this.workingDaysRepository.findOne(); - allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); - } - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - ApplicationCurrency applicationCurrency = null; - LocalDate calculatedRepaymentsStartingFromDate = null; - boolean isHolidayEnabled = false; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - - final MonetaryCurrency currency = loan.getCurrency(); - applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - calculatedRepaymentsStartingFromDate = getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan, - calendarInstance); - - if(!isHolidayValidationDone){ - isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - } - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); recalculateFrom = transactionDate; } - if(!isHolidayValidationDone){ - holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, - allowTransactionsOnNonWorkingDay); - } - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - final ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom, + holidayDetailDto); final ChangedTransactionDetail changedTransactionDetail = loan.makeRepayment(newRepaymentTransaction, defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, isRecoveryRepayment, @@ -261,25 +202,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { return newRepaymentTransaction; } - private FloatingRateDTO constructFloatingRateDTO(final Loan loan) { - FloatingRateDTO floatingRateDTO = null; - if (loan.loanProduct().isLinkedToFloatingInterestRate()) { - boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); - BigDecimal interestRateDiff = loan.getInterestRateDifferential(); - List baseLendingRatePeriods = null; - try{ - baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate() - .getRatePeriods(); - }catch(final FloatingRateNotFoundException ex){ - // Do not do anything - } - - floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, - baseLendingRatePeriods); - } - return floatingRateDTO; - } - private void saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) { try { this.loanTransactionRepository.save(newRepaymentTransaction); @@ -316,7 +238,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { "Validation errors exist.", dataValidationErrors); } } } - + @Override public void saveLoanWithDataIntegrityViolationChecks(final Loan loan) { try { @@ -492,34 +414,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { saveLoanTransactionWithDataIntegrityViolationChecks(loanTransaction); } - @Override - public LocalDate getCalculatedRepaymentsStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, - final CalendarInstance calendarInstance) { - final Calendar calendar = calendarInstance == null ? null : calendarInstance.getCalendar(); - LocalDate calculatedRepaymentsStartingFromDate = loan.getExpectedFirstRepaymentOnDate(); - if (calendar != null) {// sync repayments - - // TODO: AA - user provided first repayment date takes precedence - // over recalculated meeting date - if (calculatedRepaymentsStartingFromDate == null) { - // FIXME: AA - Possibility of having next meeting date - // immediately after disbursement date, - // need to have minimum number of days gap between disbursement - // and first repayment date. - final LoanProductRelatedDetail repaymentScheduleDetails = loan.repaymentScheduleDetail(); - if (repaymentScheduleDetails != null) {// Not expecting to be - // null - final Integer repayEvery = repaymentScheduleDetails.getRepayEvery(); - final String frequency = CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(repaymentScheduleDetails - .getRepaymentPeriodFrequencyType()); - calculatedRepaymentsStartingFromDate = CalendarUtils.getFirstRepaymentMeetingDate(calendar, actualDisbursementDate, - repayEvery, frequency); - } - } - } - return calculatedRepaymentsStartingFromDate; - } - /* * (non-Javadoc) * @@ -594,39 +488,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { } } - @Override - public ScheduleGeneratorDTO buildScheduleGeneratorDTO(final Loan loan) { - - final MonetaryCurrency currency = loan.getCurrency(); - ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - LocalDate calculatedRepaymentsStartingFromDate = this.getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan, - calendarInstance); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan - .getExpectedDisbursedOnLocalDate().toDate(), HolidayStatusType.ACTIVE.getValue()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); - final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, - allowTransactionsOnNonWorkingDay); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - } - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, floatingRateDTO); - - return scheduleGeneratorDTO; - } - private AppUser getAppUserIfPresent() { AppUser user = null; if (this.context != null) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java index a8b905a36..e4ebd1c9e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java @@ -1520,7 +1520,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener || loanApplicationTerms.getInterestChargedFromLocalDate().isAfter(periodStartDate)) { periodStartDateApplicableForInterest = loanApplicationTerms.getInterestChargedFromLocalDate(); } - } else if(periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())){ + } else if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())) { periodStartDateApplicableForInterest = idealDisbursementDate; } } @@ -2023,6 +2023,18 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final List repaymentScheduleInstallments, final LocalDate rescheduleFrom) { + // Fixed schedule End Date for generating schedule + final LocalDate scheduleTillDate = null; + return rescheduleNextInstallments(mc, loanApplicationTerms, loanCharges, holidayDetailDTO, transactions, + loanRepaymentScheduleTransactionProcessor, repaymentScheduleInstallments, rescheduleFrom, scheduleTillDate); + + } + + private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final LoanApplicationTerms loanApplicationTerms, + final Set loanCharges, final HolidayDetailDTO holidayDetailDTO, final List transactions, + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, + final List repaymentScheduleInstallments, final LocalDate rescheduleFrom, + final LocalDate scheduleTillDate) { // Loan transactions to process and find the variation on payments Collection recalculationDetails = new ArrayList<>(); for (LoanTransaction loanTransaction : transactions) { @@ -2031,8 +2043,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener } final boolean applyInterestRecalculation = loanApplicationTerms.isInterestRecalculationEnabled(); - // Fixed schedule End Date for generating schedule - final LocalDate scheduleTillDate = null; LoanScheduleParams loanScheduleParams = null; Collection periods = new ArrayList<>(); final List retainedInstallments = new ArrayList<>(); @@ -2259,7 +2269,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener periods.addAll(loanScheduleModel.getPeriods()); LoanScheduleModel loanScheduleModelwithPeriodChanges = LoanScheduleModel.withLoanScheduleModelPeriods(periods, loanScheduleModel); return LoanScheduleDTO.from(retainedInstallments, loanScheduleModelwithPeriodChanges); - } /** @@ -2368,14 +2377,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener return principalPortionCalculated; } - private List fetchInstallmentsFromScheduleModel(final LoanScheduleModel loanScheduleModel) { - final List installments = new ArrayList<>(); - for (LoanScheduleModelPeriod loanScheduleModelPeriod : loanScheduleModel.getPeriods()) { - addLoanRepaymentScheduleInstallment(installments, loanScheduleModelPeriod); - } - return installments; - } - private LoanRepaymentScheduleInstallment addLoanRepaymentScheduleInstallment(final List installments, final LoanScheduleModelPeriod scheduledLoanInstallment) { LoanRepaymentScheduleInstallment installment = null; @@ -2437,29 +2438,24 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener public LoanRepaymentScheduleInstallment calculatePrepaymentAmount(final MonetaryCurrency currency, final LocalDate onDate, final LoanApplicationTerms loanApplicationTerms, final MathContext mc, final Set charges, final HolidayDetailDTO holidayDetailDTO, final List loanTransactions, - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor) { + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, + final List repaymentScheduleInstallments) { LocalDate calculateTill = onDate; if (loanApplicationTerms.getPreClosureInterestCalculationStrategy().calculateTillRestFrequencyEnabled()) { calculateTill = getNextRestScheduleDate(onDate.minusDays(1), loanApplicationTerms, holidayDetailDTO); } - Collection recalculationDetails = new ArrayList<>(); - for (LoanTransaction loanTransaction : loanTransactions) { - recalculationDetails.add(new RecalculationDetail(loanTransaction.getTransactionDate(), LoanTransaction - .copyTransactionProperties(loanTransaction))); - } - final boolean applyInterestRecalculation = loanApplicationTerms.isInterestRecalculationEnabled(); - LoanScheduleParams loanScheduleRecalculationDTO = LoanScheduleParams.createLoanScheduleParamsForCompleteUpdate( - recalculationDetails, loanRepaymentScheduleTransactionProcessor, calculateTill, applyInterestRecalculation); - LoanScheduleModel loanScheduleModel = generate(mc, loanApplicationTerms, charges, holidayDetailDTO, loanScheduleRecalculationDTO); - List installments = fetchInstallmentsFromScheduleModel(loanScheduleModel); + + LoanScheduleDTO loanScheduleDTO = rescheduleNextInstallments(mc, loanApplicationTerms, charges, holidayDetailDTO, loanTransactions, + loanRepaymentScheduleTransactionProcessor, repaymentScheduleInstallments, onDate, calculateTill); + loanRepaymentScheduleTransactionProcessor.handleTransaction(loanApplicationTerms.getExpectedDisbursementDate(), loanTransactions, - currency, installments, charges); + currency, loanScheduleDTO.getInstallments(), charges); Money feeCharges = Money.zero(currency); Money penaltyCharges = Money.zero(currency); Money totalPrincipal = Money.zero(currency); Money totalInterest = Money.zero(currency); - for (final LoanRepaymentScheduleInstallment currentInstallment : installments) { + for (final LoanRepaymentScheduleInstallment currentInstallment : loanScheduleDTO.getInstallments()) { if (currentInstallment.isNotFullyPaidOff()) { totalPrincipal = totalPrincipal.plus(currentInstallment.getPrincipalOutstanding(currency)); totalInterest = totalInterest.plus(currentInstallment.getInterestOutstanding(currency)); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanScheduleGenerator.java index 72ee9b1d3..2b0cac0be 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanScheduleGenerator.java @@ -31,11 +31,13 @@ public interface LoanScheduleGenerator { LoanScheduleDTO rescheduleNextInstallments(MathContext mc, LoanApplicationTerms loanApplicationTerms, Set loanCharges, final HolidayDetailDTO holidayDetailDTO, List transactions, - LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, List repaymentScheduleInstallments, LocalDate rescheduleFrom); + LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, + List repaymentScheduleInstallments, LocalDate rescheduleFrom); - LoanRepaymentScheduleInstallment calculatePrepaymentAmount(MonetaryCurrency currency, - LocalDate onDate, LoanApplicationTerms loanApplicationTerms, MathContext mc, Set charges, - HolidayDetailDTO holidayDetailDTO, List loanTransactions, LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor); + LoanRepaymentScheduleInstallment calculatePrepaymentAmount(MonetaryCurrency currency, LocalDate onDate, + LoanApplicationTerms loanApplicationTerms, MathContext mc, Set charges, HolidayDetailDTO holidayDetailDTO, + List loanTransactions, LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, + List repaymentScheduleInstallments); LoanRescheduleModel reschedule(final MathContext mathContext, final LoanRescheduleRequest loanRescheduleRequest, final ApplicationCurrency applicationCurrency, final HolidayDetailDTO holidayDetailDTO, CalendarInstance restCalendarInstance, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java index abf0183fa..c942e0f34 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java @@ -307,7 +307,10 @@ public class LoanScheduleAssembler { LoanProductInterestRecalculationDetails loanProductInterestRecalculationDetails = loanProduct .getProductInterestRecalculationDetails(); recalculationFrequencyType = loanProductInterestRecalculationDetails.getRestFrequencyType(); - if (!recalculationFrequencyType.isSameAsRepayment()) { + if (recalculationFrequencyType.isSameAsRepayment()) { + restCalendarInstance = createCalendarForSameAsRepayment(repaymentEvery, repaymentPeriodFrequencyType, + expectedDisbursementDate); + } else { LocalDate calendarStartDate = this.fromApiJsonHelper.extractLocalDateNamed( LoanProductConstants.recalculationRestFrequencyDateParamName, element); if (calendarStartDate == null) { @@ -320,7 +323,10 @@ public class LoanScheduleAssembler { .fromInt(loanProductInterestRecalculationDetails.getInterestRecalculationCompoundingMethod()); if (compoundingMethod.isCompoundingEnabled()) { compoundingFrequencyType = loanProductInterestRecalculationDetails.getCompoundingFrequencyType(); - if (!compoundingFrequencyType.isSameAsRepayment()) { + if (compoundingFrequencyType.isSameAsRepayment()) { + compoundingCalendarInstance = createCalendarForSameAsRepayment(repaymentEvery, repaymentPeriodFrequencyType, + expectedDisbursementDate); + } else { LocalDate calendarStartDate = this.fromApiJsonHelper.extractLocalDateNamed( LoanProductConstants.recalculationCompoundingFrequencyDateParamName, element); if (calendarStartDate == null) { @@ -380,9 +386,16 @@ public class LoanScheduleAssembler { calendar, BigDecimal.ZERO, loanTermVariations); } + private CalendarInstance createCalendarForSameAsRepayment(final Integer repaymentEvery, + final PeriodFrequencyType repaymentPeriodFrequencyType, final LocalDate expectedDisbursementDate) { + + CalendarInstance restCalendarInstance = createInterestRecalculationCalendarInstance(expectedDisbursementDate, repaymentEvery, + CalendarFrequencyType.from(repaymentPeriodFrequencyType)); + return restCalendarInstance; + } + private CalendarInstance createInterestRecalculationCalendarInstance(final LocalDate calendarStartDate, final RecalculationFrequencyType recalculationFrequencyType, final Integer frequency) { - final Integer repeatsOnDay = calendarStartDate.getDayOfWeek(); CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.INVALID; switch (recalculationFrequencyType) { @@ -399,6 +412,12 @@ public class LoanScheduleAssembler { break; } + return createInterestRecalculationCalendarInstance(calendarStartDate, frequency, calendarFrequencyType); + } + + private CalendarInstance createInterestRecalculationCalendarInstance(final LocalDate calendarStartDate, final Integer frequency, + CalendarFrequencyType calendarFrequencyType) { + final Integer repeatsOnDay = calendarStartDate.getDayOfWeek(); final String title = "loan_recalculation_detail"; final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(), calendarFrequencyType, frequency, repeatsOnDay); @@ -549,7 +568,8 @@ public class LoanScheduleAssembler { public LoanRepaymentScheduleInstallment calculatePrepaymentAmount(MonetaryCurrency currency, LocalDate onDate, LoanApplicationTerms loanApplicationTerms, final Set loanCharges, final Long officeId, List loanTransactions, - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor) { + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, + final List repaymentScheduleInstallments) { final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory.create(loanApplicationTerms.getInterestMethod()); final RoundingMode roundingMode = MoneyHelper.getRoundingMode(); final MathContext mc = new MathContext(8, roundingMode); @@ -561,7 +581,7 @@ public class LoanScheduleAssembler { HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); return loanScheduleGenerator.calculatePrepaymentAmount(currency, onDate, loanApplicationTerms, mc, loanCharges, holidayDetailDTO, - loanTransactions, loanRepaymentScheduleTransactionProcessor); + loanTransactions, loanRepaymentScheduleTransactionProcessor, repaymentScheduleInstallments); } @@ -736,7 +756,8 @@ public class LoanScheduleAssembler { if (loan.getExpectedFirstRepaymentOnDate() == null) { loan.setExpectedFirstRepaymentOnDate(loan.fetchRepaymentScheduleInstallment(1).getDueDate().toDate()); } - ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan); + final LocalDate recalculateFrom = null; + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); AppUser currentUser = this.context.getAuthenticatedUserIfPresent(); loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java index ec5da0eb6..84c4a9106 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java @@ -22,21 +22,12 @@ import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidation import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.service.DateUtils; import org.mifosplatform.organisation.monetary.data.CurrencyData; -import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency; -import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService; import org.mifosplatform.portfolio.accountdetails.domain.AccountType; -import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType; -import org.mifosplatform.portfolio.calendar.domain.CalendarInstance; -import org.mifosplatform.portfolio.calendar.domain.CalendarInstanceRepository; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRateDTO; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRatePeriodData; -import org.mifosplatform.portfolio.floatingrates.exception.FloatingRateNotFoundException; -import org.mifosplatform.portfolio.floatingrates.service.FloatingRatesReadPlatformService; +import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.mifosplatform.portfolio.loanaccount.domain.Loan; -import org.mifosplatform.portfolio.loanaccount.domain.LoanAccountDomainService; import org.mifosplatform.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; @@ -50,6 +41,7 @@ import org.mifosplatform.portfolio.loanaccount.serialization.CalculateLoanSchedu import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonHelper; import org.mifosplatform.portfolio.loanaccount.service.LoanAssembler; import org.mifosplatform.portfolio.loanaccount.service.LoanReadPlatformService; +import org.mifosplatform.portfolio.loanaccount.service.LoanUtilService; import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct; import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository; import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException; @@ -68,25 +60,20 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC private final LoanReadPlatformService loanReadPlatformService; private final LoanApplicationCommandFromApiJsonHelper loanApiJsonDeserializer; private final LoanAssembler loanAssembler; - private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository; - private final LoanAccountDomainService accountDomainService; - private final CalendarInstanceRepository calendarInstanceRepository; private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; private final ConfigurationDomainService configurationDomainService; - private final FloatingRatesReadPlatformService floatingRatesReadPlatformService; private final CurrencyReadPlatformService currencyReadPlatformService; + private final LoanUtilService loanUtilService; @Autowired public LoanScheduleCalculationPlatformServiceImpl(final CalculateLoanScheduleQueryFromApiJsonHelper fromApiJsonDeserializer, final LoanScheduleAssembler loanScheduleAssembler, final FromJsonHelper fromJsonHelper, final LoanProductRepository loanProductRepository, final LoanProductDataValidator loanProductCommandFromApiJsonDeserializer, final LoanReadPlatformService loanReadPlatformService, final LoanApplicationCommandFromApiJsonHelper loanApiJsonDeserializer, - final LoanAssembler loanAssembler, final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository, - final LoanAccountDomainService accountDomainService, final CalendarInstanceRepository calendarInstanceRepository, + final LoanAssembler loanAssembler, final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, - final ConfigurationDomainService configurationDomainService, - final FloatingRatesReadPlatformService floatingRatesReadPlatformService, - final CurrencyReadPlatformService currencyReadPlatformService) { + final ConfigurationDomainService configurationDomainService, final CurrencyReadPlatformService currencyReadPlatformService, + final LoanUtilService loanUtilService) { this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.loanScheduleAssembler = loanScheduleAssembler; this.fromJsonHelper = fromJsonHelper; @@ -95,13 +82,10 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC this.loanReadPlatformService = loanReadPlatformService; this.loanApiJsonDeserializer = loanApiJsonDeserializer; this.loanAssembler = loanAssembler; - this.applicationCurrencyRepository = applicationCurrencyRepository; - this.accountDomainService = accountDomainService; - this.calendarInstanceRepository = calendarInstanceRepository; this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory; this.configurationDomainService = configurationDomainService; - this.floatingRatesReadPlatformService = floatingRatesReadPlatformService; this.currencyReadPlatformService = currencyReadPlatformService; + this.loanUtilService = loanUtilService; } @Override @@ -174,7 +158,8 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(loan); LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = this.loanScheduleAssembler.calculatePrepaymentAmount(currency, today, loanApplicationTerms, loan.charges(), loan.getOfficeId(), - loan.retreiveListOfTransactionsPostDisbursementExcludeAccruals(), loanRepaymentScheduleTransactionProcessor); + loan.retreiveListOfTransactionsPostDisbursementExcludeAccruals(), loanRepaymentScheduleTransactionProcessor, + loan.fetchRepaymentScheduleInstallments()); Money totalAmount = totalPrincipal.plus(loanRepaymentScheduleInstallment.getFeeChargesOutstanding(currency)).plus( loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding(currency)); Money interestDue = Money.zero(currency); @@ -278,37 +263,10 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC } private LoanApplicationTerms constructLoanApplicationTerms(final Loan loan) { - MonetaryCurrency currency = loan.getCurrency(); - final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - final CalendarInstance restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - final CalendarInstance compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - LocalDate calculatedRepaymentsStartingFromDate = accountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - LoanApplicationTerms loanApplicationTerms = loan.constructLoanApplicationTerms(applicationCurrency, - calculatedRepaymentsStartingFromDate, restCalendarInstance, compoundingCalendarInstance, floatingRateDTO); + final LocalDate recalculateFrom = null; + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); + LoanApplicationTerms loanApplicationTerms = loan.constructLoanApplicationTerms(scheduleGeneratorDTO); return loanApplicationTerms; } - private FloatingRateDTO constructFloatingRateDTO(final Loan loan) { - FloatingRateDTO floatingRateDTO = null; - if (loan.loanProduct().isLinkedToFloatingInterestRate()) { - boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); - BigDecimal interestRateDiff = loan.getInterestRateDifferential(); - List baseLendingRatePeriods = null; - try { - baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods(); - } catch (final FloatingRateNotFoundException ex) { - // Do not do anything - } - floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, - baseLendingRatePeriods); - } - return floatingRateDTO; - } - } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java index 43dacde27..86f816ecf 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; @@ -87,7 +88,8 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl final Map changes = new HashMap<>(); changes.put("removedEntityIds", deletedVariations); loan.getLoanTermVariations().clear(); - ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan); + final LocalDate recalculateFrom = null; + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); AppUser currentUser = this.context.getAuthenticatedUserIfPresent(); loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser); this.loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java index 2301f6bb8..933c7bdee 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java @@ -8,7 +8,13 @@ package org.mifosplatform.portfolio.loanaccount.rescheduleloan.service; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; @@ -43,17 +49,34 @@ import org.mifosplatform.portfolio.floatingrates.service.FloatingRatesReadPlatfo import org.mifosplatform.portfolio.loanaccount.data.HolidayDetailDTO; import org.mifosplatform.portfolio.loanaccount.data.LoanChargePaidByData; import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO; -import org.mifosplatform.portfolio.loanaccount.domain.*; +import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; +import org.mifosplatform.portfolio.loanaccount.domain.Loan; +import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; +import org.mifosplatform.portfolio.loanaccount.domain.LoanInstallmentCharge; +import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine; +import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; +import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository; +import org.mifosplatform.portfolio.loanaccount.domain.LoanRepositoryWrapper; +import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus; +import org.mifosplatform.portfolio.loanaccount.domain.LoanSummary; +import org.mifosplatform.portfolio.loanaccount.domain.LoanSummaryWrapper; +import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction; +import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository; +import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionType; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanRepaymentScheduleHistory; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanRepaymentScheduleHistoryRepository; -import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory; import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleHistoryWritePlatformService; import org.mifosplatform.portfolio.loanaccount.rescheduleloan.RescheduleLoansApiConstants; import org.mifosplatform.portfolio.loanaccount.rescheduleloan.data.LoanRescheduleRequestDataValidator; -import org.mifosplatform.portfolio.loanaccount.rescheduleloan.domain.*; +import org.mifosplatform.portfolio.loanaccount.rescheduleloan.domain.DefaultLoanReschedulerFactory; +import org.mifosplatform.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleModel; +import org.mifosplatform.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleModelRepaymentPeriod; +import org.mifosplatform.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest; +import org.mifosplatform.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository; import org.mifosplatform.portfolio.loanaccount.rescheduleloan.exception.LoanRescheduleRequestNotFoundException; import org.mifosplatform.portfolio.loanaccount.service.LoanAssembler; import org.mifosplatform.portfolio.loanaccount.service.LoanChargeReadPlatformService; +import org.mifosplatform.portfolio.loanaccount.service.LoanUtilService; import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod; import org.mifosplatform.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail; import org.mifosplatform.useradministration.domain.AppUser; @@ -81,14 +104,13 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche private final LoanRepaymentScheduleHistoryRepository loanRepaymentScheduleHistoryRepository; private final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService; private final CalendarInstanceRepository calendarInstanceRepository; - private final LoanAccountDomainService loanAccountDomainService; private final LoanChargeReadPlatformService loanChargeReadPlatformService; - private final LoanScheduleGeneratorFactory loanScheduleFactory; private final LoanTransactionRepository loanTransactionRepository; private final JournalEntryWritePlatformService journalEntryWritePlatformService; private final LoanRepository loanRepository; private final LoanAssembler loanAssembler; private final FloatingRatesReadPlatformService floatingRatesReadPlatformService; + private final LoanUtilService loanUtilService; /** * LoanRescheduleRequestWritePlatformServiceImpl constructor @@ -104,11 +126,11 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche HolidayRepositoryWrapper holidayRepository, WorkingDaysRepositoryWrapper workingDaysRepository, LoanRepaymentScheduleHistoryRepository loanRepaymentScheduleHistoryRepository, final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService, - final CalendarInstanceRepository calendarInstanceRepository, final LoanAccountDomainService loanAccountDomainService, - final LoanChargeReadPlatformService loanChargeReadPlatformService, final LoanScheduleGeneratorFactory loanScheduleFactory, + final CalendarInstanceRepository calendarInstanceRepository, final LoanChargeReadPlatformService loanChargeReadPlatformService, final LoanTransactionRepository loanTransactionRepository, final JournalEntryWritePlatformService journalEntryWritePlatformService, final LoanRepository loanRepository, - final LoanAssembler loanAssembler, final FloatingRatesReadPlatformService floatingRatesReadPlatformService) { + final LoanAssembler loanAssembler, final FloatingRatesReadPlatformService floatingRatesReadPlatformService, + final LoanUtilService loanUtilService) { this.loanRepositoryWrapper = loanRepositoryWrapper; this.codeValueRepositoryWrapper = codeValueRepositoryWrapper; this.platformSecurityContext = platformSecurityContext; @@ -121,14 +143,13 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche this.loanRepaymentScheduleHistoryRepository = loanRepaymentScheduleHistoryRepository; this.loanScheduleHistoryWritePlatformService = loanScheduleHistoryWritePlatformService; this.calendarInstanceRepository = calendarInstanceRepository; - this.loanAccountDomainService = loanAccountDomainService; this.loanChargeReadPlatformService = loanChargeReadPlatformService; - this.loanScheduleFactory = loanScheduleFactory; this.loanTransactionRepository = loanTransactionRepository; this.journalEntryWritePlatformService = journalEntryWritePlatformService; this.loanRepository = loanRepository; this.loanAssembler = loanAssembler; this.floatingRatesReadPlatformService = floatingRatesReadPlatformService; + this.loanUtilService = loanUtilService; } /** @@ -398,8 +419,8 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche for (final LoanRepaymentScheduleInstallment repaymentScheduleInstallment : repaymentScheduleInstallments) { repaymentScheduleInstallment.updateDerivedFields(currency, new LocalDate()); } - - //updates maturity date + + // updates maturity date loan.updateLoanScheduleDependentDerivedFields(); // update the loan object this.loanRepository.save(loan); @@ -448,40 +469,12 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - ApplicationCurrency applicationCurrency = null; - LocalDate calculatedRepaymentsStartingFromDate = null; - List holidays = null; - boolean isHolidayEnabled = false; - WorkingDays workingDays = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - final MonetaryCurrency currency = loan.getCurrency(); - applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate() - .toDate()); - workingDays = this.workingDaysRepository.findOne(); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); recalculateFrom = DateUtils.getLocalDateOfTenant(); } - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, - recalculateFrom, overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); Money accruedCharge = Money.zero(loan.getCurrency()); if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) { @@ -583,11 +576,10 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); BigDecimal interestRateDiff = loan.getInterestRateDifferential(); List baseLendingRatePeriods = null; - try{ - baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate() - .getRatePeriods(); - }catch(final FloatingRateNotFoundException ex){ - // Do not do anything + try { + baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods(); + } catch (final FloatingRateNotFoundException ex) { + // Do not do anything } floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, baseLendingRatePeriods); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index 228d78076..0c78ef3b7 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -5,8 +5,14 @@ */ package org.mifosplatform.portfolio.loanaccount.service; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.accountnumberformat.domain.AccountNumberFormat; @@ -56,7 +62,6 @@ import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; import org.mifosplatform.portfolio.loanaccount.domain.Loan; -import org.mifosplatform.portfolio.loanaccount.domain.LoanAccountDomainService; import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; import org.mifosplatform.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine; @@ -97,13 +102,8 @@ import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; @Service public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements LoanApplicationWritePlatformService { @@ -134,11 +134,11 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private final AccountAssociationsRepository accountAssociationsRepository; private final LoanReadPlatformService loanReadPlatformService; private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository; - private final LoanAccountDomainService loanAccountDomainService; private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository; private final BusinessEventNotifierService businessEventNotifierService; private final ConfigurationDomainService configurationDomainService; private final LoanScheduleAssembler loanScheduleAssembler; + private final LoanUtilService loanUtilService; @Autowired public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper, @@ -154,10 +154,10 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository, final SavingsAccountAssembler savingsAccountAssembler, final AccountAssociationsRepository accountAssociationsRepository, final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository, - final LoanReadPlatformService loanReadPlatformService, final LoanAccountDomainService loanAccountDomainService, + final LoanReadPlatformService loanReadPlatformService, final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final BusinessEventNotifierService businessEventNotifierService, final ConfigurationDomainService configurationDomainService, - final LoanScheduleAssembler loanScheduleAssembler) { + final LoanScheduleAssembler loanScheduleAssembler, final LoanUtilService loanUtilService) { this.context = context; this.fromJsonHelper = fromJsonHelper; this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator; @@ -182,11 +182,11 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa this.accountAssociationsRepository = accountAssociationsRepository; this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository; this.loanReadPlatformService = loanReadPlatformService; - this.loanAccountDomainService = loanAccountDomainService; this.accountNumberFormatRepository = accountNumberFormatRepository; this.businessEventNotifierService = businessEventNotifierService; this.configurationDomainService = configurationDomainService; this.loanScheduleAssembler = loanScheduleAssembler; + this.loanUtilService = loanUtilService; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -894,7 +894,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa // to recompute the schedule if (changes.containsKey(LoanApiConstants.approvedLoanAmountParameterName) || changes.containsKey("recalculateLoanSchedule") || changes.containsKey("expectedDisbursementDate")) { - ScheduleGeneratorDTO scheduleGeneratorDTO = loanAccountDomainService.buildScheduleGeneratorDTO(loan); + LocalDate recalculateFrom = null; + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser); } @@ -941,7 +942,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa if (changes.containsKey(LoanApiConstants.approvedLoanAmountParameterName) || changes.containsKey(LoanApiConstants.disbursementPrincipalParameterName)) { - ScheduleGeneratorDTO scheduleGeneratorDTO = loanAccountDomainService.buildScheduleGeneratorDTO(loan); + LocalDate recalculateFrom = null; + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 5b9673278..c01b84099 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -26,7 +26,6 @@ import org.joda.time.format.DateTimeFormatter; import org.mifosplatform.accounting.common.AccountingRuleType; import org.mifosplatform.infrastructure.codes.data.CodeValueData; import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService; -import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService; import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.service.DateUtils; @@ -35,9 +34,6 @@ import org.mifosplatform.infrastructure.core.service.PaginationHelper; import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.SearchParameters; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; -import org.mifosplatform.organisation.holiday.domain.Holiday; -import org.mifosplatform.organisation.holiday.domain.HolidayRepository; -import org.mifosplatform.organisation.holiday.domain.HolidayStatusType; import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency; import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; @@ -45,15 +41,11 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.organisation.staff.data.StaffData; import org.mifosplatform.organisation.staff.service.StaffReadPlatformService; -import org.mifosplatform.organisation.workingdays.domain.WorkingDays; -import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; import org.mifosplatform.portfolio.account.data.AccountTransferData; import org.mifosplatform.portfolio.accountdetails.domain.AccountType; import org.mifosplatform.portfolio.accountdetails.service.AccountEnumerations; import org.mifosplatform.portfolio.calendar.data.CalendarData; import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType; -import org.mifosplatform.portfolio.calendar.domain.CalendarInstance; -import org.mifosplatform.portfolio.calendar.domain.CalendarInstanceRepository; import org.mifosplatform.portfolio.calendar.service.CalendarReadPlatformService; import org.mifosplatform.portfolio.charge.data.ChargeData; import org.mifosplatform.portfolio.charge.domain.ChargeTimeType; @@ -63,10 +55,7 @@ import org.mifosplatform.portfolio.client.domain.ClientEnumerations; import org.mifosplatform.portfolio.client.service.ClientReadPlatformService; import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.common.service.CommonEnumerations; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRateDTO; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRatePeriodData; import org.mifosplatform.portfolio.floatingrates.data.InterestRatePeriodData; -import org.mifosplatform.portfolio.floatingrates.exception.FloatingRateNotFoundException; import org.mifosplatform.portfolio.floatingrates.service.FloatingRatesReadPlatformService; import org.mifosplatform.portfolio.fund.data.FundData; import org.mifosplatform.portfolio.fund.service.FundReadPlatformService; @@ -74,7 +63,6 @@ import org.mifosplatform.portfolio.group.data.GroupGeneralData; import org.mifosplatform.portfolio.group.data.GroupRoleData; import org.mifosplatform.portfolio.group.service.GroupReadPlatformService; import org.mifosplatform.portfolio.loanaccount.data.DisbursementData; -import org.mifosplatform.portfolio.loanaccount.data.HolidayDetailDTO; import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; import org.mifosplatform.portfolio.loanaccount.data.LoanApplicationTimelineData; import org.mifosplatform.portfolio.loanaccount.data.LoanApprovalData; @@ -87,6 +75,7 @@ import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData; import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionEnumData; import org.mifosplatform.portfolio.loanaccount.data.PaidInAdvanceData; import org.mifosplatform.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData; +import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.mifosplatform.portfolio.loanaccount.domain.Loan; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; @@ -101,7 +90,6 @@ import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFound import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData; -import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData; import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod; @@ -143,14 +131,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { private final LoanMapper loaanLoanMapper = new LoanMapper(); private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; private final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd"); - private final LoanScheduleGeneratorFactory loanScheduleFactory; - private final CalendarInstanceRepository calendarInstanceRepository; - private final HolidayRepository holidayRepository; - private final ConfigurationDomainService configurationDomainService; - private final WorkingDaysRepositoryWrapper workingDaysRepository; private final PaymentTypeReadPlatformService paymentTypeReadPlatformService; private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; private final FloatingRatesReadPlatformService floatingRatesReadPlatformService; + private final LoanUtilService loanUtilService; @Autowired public LoanReadPlatformServiceImpl(final PlatformSecurityContext context, final LoanRepository loanRepository, @@ -161,11 +145,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final FundReadPlatformService fundReadPlatformService, final ChargeReadPlatformService chargeReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService, final RoutingDataSource dataSource, final CalendarReadPlatformService calendarReadPlatformService, final StaffReadPlatformService staffReadPlatformService, - final LoanScheduleGeneratorFactory loanScheduleFactory, final CalendarInstanceRepository calendarInstanceRepository, - final HolidayRepository holidayRepository, final ConfigurationDomainService configurationDomainService, - final WorkingDaysRepositoryWrapper workingDaysRepository, PaymentTypeReadPlatformService paymentTypeReadPlatformService, + final PaymentTypeReadPlatformService paymentTypeReadPlatformService, final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, - final FloatingRatesReadPlatformService floatingRatesReadPlatformService) { + final FloatingRatesReadPlatformService floatingRatesReadPlatformService, final LoanUtilService loanUtilService) { this.context = context; this.loanRepository = loanRepository; this.loanTransactionRepository = loanTransactionRepository; @@ -181,14 +163,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { this.staffReadPlatformService = staffReadPlatformService; this.jdbcTemplate = new JdbcTemplate(dataSource); this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - this.loanScheduleFactory = loanScheduleFactory; - this.calendarInstanceRepository = calendarInstanceRepository; - this.holidayRepository = holidayRepository; - this.configurationDomainService = configurationDomainService; - this.workingDaysRepository = workingDaysRepository; this.paymentTypeReadPlatformService = paymentTypeReadPlatformService; this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory; this.floatingRatesReadPlatformService = floatingRatesReadPlatformService; + this.loanUtilService = loanUtilService; } @Override @@ -429,25 +407,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final CurrencyData currencyData = applicationCurrency.toData(); final LocalDate earliestUnpaidInstallmentDate = LocalDate.now(); - - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - HolidayDetailDTO holidayDetailDTO = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan - .getDisbursementDate().toDate(), HolidayStatusType.ACTIVE.getValue()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - } - - final FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = loan.fetchPrepaymentDetail(this.loanScheduleFactory, - restCalendarInstance, compoundingCalendarInstance, holidayDetailDTO, onDate, floatingRateDTO); + final LocalDate recalculateFrom = null; + final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); + final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = loan.fetchPrepaymentDetail(scheduleGeneratorDTO, onDate); final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT); final Collection paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes(); final BigDecimal outstandingLoanBalance = loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency).getAmount(); @@ -1993,23 +1955,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { null, null, null, false); } - private FloatingRateDTO constructFloatingRateDTO(final Loan loan) { - FloatingRateDTO floatingRateDTO = null; - if (loan.loanProduct().isLinkedToFloatingInterestRate()) { - boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); - BigDecimal interestRateDiff = loan.getInterestRateDifferential(); - List baseLendingRatePeriods = null; - try { - baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods(); - } catch (final FloatingRateNotFoundException ex) { - // Do not do anything - } - floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, - baseLendingRatePeriods); - } - return floatingRateDTO; - } - @Override public Collection retrieveLoanInterestRatePeriodData(Long loanId) { this.context.authenticatedUser(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanUtilService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanUtilService.java index f87d13d42..ee23857e7 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanUtilService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanUtilService.java @@ -60,9 +60,92 @@ public class LoanUtilService { this.floatingRatesReadPlatformService = floatingRatesReadPlatformService; } - public LocalDate getCalculatedRepaymentsStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, + public ScheduleGeneratorDTO buildScheduleGeneratorDTO(final Loan loan, final LocalDate recalculateFrom) { + final HolidayDetailDTO holidayDetailDTO = null; + return buildScheduleGeneratorDTO(loan, recalculateFrom, holidayDetailDTO); + } + + public ScheduleGeneratorDTO buildScheduleGeneratorDTO(final Loan loan, final LocalDate recalculateFrom, + final HolidayDetailDTO holidayDetailDTO) { + HolidayDetailDTO holidayDetails = holidayDetailDTO; + if (holidayDetailDTO == null) { + holidayDetails = constructHolidayDTO(loan); + } + final MonetaryCurrency currency = loan.getCurrency(); + ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); + final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), + CalendarEntityType.LOANS.getValue()); + LocalDate calculatedRepaymentsStartingFromDate = this.getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan, + calendarInstance); + CalendarInstance restCalendarInstance = null; + CalendarInstance compoundingCalendarInstance = null; + Long overdurPenaltyWaitPeriod = null; + if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { + restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), + CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); + compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( + loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); + overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); + } + FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); + ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, + calculatedRepaymentsStartingFromDate, holidayDetails, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, + overdurPenaltyWaitPeriod, floatingRateDTO); + + return scheduleGeneratorDTO; + } + + public LocalDate getCalculatedRepaymentsStartingFromDate(final Loan loan) { + final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), + CalendarEntityType.LOANS.getValue()); + return this.getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan, calendarInstance); + } + + private HolidayDetailDTO constructHolidayDTO(final Loan loan) { + final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); + final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan + .getDisbursementDate().toDate(), HolidayStatusType.ACTIVE.getValue()); + final WorkingDays workingDays = this.workingDaysRepository.findOne(); + final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); + final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); + + HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, + allowTransactionsOnNonWorkingDay); + return holidayDetailDTO; + } + + private FloatingRateDTO constructFloatingRateDTO(final Loan loan) { + FloatingRateDTO floatingRateDTO = null; + if (loan.loanProduct().isLinkedToFloatingInterestRate()) { + boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); + BigDecimal interestRateDiff = loan.getInterestRateDifferential(); + List baseLendingRatePeriods = null; + try { + baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods(); + } catch (final FloatingRateNotFoundException ex) { + // Do not do anything + } + + floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, + baseLendingRatePeriods); + } + return floatingRateDTO; + } + + private LocalDate getCalculatedRepaymentsStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, final CalendarInstance calendarInstance) { final Calendar calendar = calendarInstance == null ? null : calendarInstance.getCalendar(); + return calculateRepaymentStartingFromDate(actualDisbursementDate, loan, calendar); + } + + public LocalDate getCalculatedRepaymentsStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, + final Calendar calendar) { + if (calendar == null) { return getCalculatedRepaymentsStartingFromDate(loan); } + return calculateRepaymentStartingFromDate(actualDisbursementDate, loan, calendar); + + } + + private LocalDate calculateRepaymentStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, final Calendar calendar) { LocalDate calculatedRepaymentsStartingFromDate = loan.getExpectedFirstRepaymentOnDate(); if (calendar != null) {// sync repayments @@ -87,54 +170,4 @@ public class LoanUtilService { return calculatedRepaymentsStartingFromDate; } - public ScheduleGeneratorDTO buildScheduleGeneratorDTO(final Loan loan) { - - final MonetaryCurrency currency = loan.getCurrency(); - ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - LocalDate calculatedRepaymentsStartingFromDate = this.getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan, - calendarInstance); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan - .getExpectedDisbursedOnLocalDate().toDate(), HolidayStatusType.ACTIVE.getValue()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); - final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, - allowTransactionsOnNonWorkingDay); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - } - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, floatingRateDTO); - - return scheduleGeneratorDTO; - } - - private FloatingRateDTO constructFloatingRateDTO(final Loan loan) { - FloatingRateDTO floatingRateDTO = null; - if (loan.loanProduct().isLinkedToFloatingInterestRate()) { - boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); - BigDecimal interestRateDiff = loan.getInterestRateDifferential(); - List baseLendingRatePeriods = null; - try { - baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods(); - } catch (final FloatingRateNotFoundException ex) { - // Do not do anything - } - - floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, - baseLendingRatePeriods); - } - return floatingRateDTO; - } - } 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 f74e7989e..da44b4cd7 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 @@ -97,10 +97,6 @@ import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUS import org.mifosplatform.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS; import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.common.service.BusinessEventNotifierService; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRateDTO; -import org.mifosplatform.portfolio.floatingrates.data.FloatingRatePeriodData; -import org.mifosplatform.portfolio.floatingrates.exception.FloatingRateNotFoundException; -import org.mifosplatform.portfolio.floatingrates.service.FloatingRatesReadPlatformService; import org.mifosplatform.portfolio.group.domain.Group; import org.mifosplatform.portfolio.group.exception.GroupNotActiveException; import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants; @@ -140,7 +136,6 @@ import org.mifosplatform.portfolio.loanaccount.exception.MultiDisbursementDataRe import org.mifosplatform.portfolio.loanaccount.guarantor.service.GuarantorDomainService; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator; -import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator; @@ -188,7 +183,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final LoanChargeRepository loanChargeRepository; private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository; private final JournalEntryWritePlatformService journalEntryWritePlatformService; - private final LoanScheduleGeneratorFactory loanScheduleFactory; private final CalendarInstanceRepository calendarInstanceRepository; private final PaymentDetailWritePlatformService paymentDetailWritePlatformService; private final HolidayRepositoryWrapper holidayRepository; @@ -210,7 +204,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final AccountTransferDetailRepository accountTransferDetailRepository; private final BusinessEventNotifierService businessEventNotifierService; private final GuarantorDomainService guarantorDomainService; - private final FloatingRatesReadPlatformService floatingRatesReadPlatformService; + private final LoanUtilService loanUtilService; @Autowired public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -221,7 +215,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final ChargeRepositoryWrapper chargeRepository, final LoanChargeRepository loanChargeRepository, final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository, final JournalEntryWritePlatformService journalEntryWritePlatformService, - final LoanScheduleGeneratorFactory loanScheduleFactory, final CalendarInstanceRepository calendarInstanceRepository, + final CalendarInstanceRepository calendarInstanceRepository, final PaymentDetailWritePlatformService paymentDetailWritePlatformService, final HolidayRepositoryWrapper holidayRepository, final ConfigurationDomainService configurationDomainService, final WorkingDaysRepositoryWrapper workingDaysRepository, final LoanProductReadPlatformService loanProductReadPlatformService, @@ -237,7 +231,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final AccountAssociationsRepository accountAssociationRepository, final AccountTransferDetailRepository accountTransferDetailRepository, final BusinessEventNotifierService businessEventNotifierService, final GuarantorDomainService guarantorDomainService, - final FloatingRatesReadPlatformService floatingRatesReadPlatformService) { + final LoanUtilService loanUtilService) { this.context = context; this.loanEventApiJsonValidator = loanEventApiJsonValidator; this.loanAssembler = loanAssembler; @@ -250,7 +244,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.applicationCurrencyRepository = applicationCurrencyRepository; this.journalEntryWritePlatformService = journalEntryWritePlatformService; this.loanUpdateCommandFromApiJsonDeserializer = loanUpdateCommandFromApiJsonDeserializer; - this.loanScheduleFactory = loanScheduleFactory; this.calendarInstanceRepository = calendarInstanceRepository; this.paymentDetailWritePlatformService = paymentDetailWritePlatformService; this.holidayRepository = holidayRepository; @@ -272,7 +265,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.accountTransferDetailRepository = accountTransferDetailRepository; this.businessEventNotifierService = businessEventNotifierService; this.guarantorDomainService = guarantorDomainService; - this.floatingRatesReadPlatformService = floatingRatesReadPlatformService; + this.loanUtilService = loanUtilService; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -306,9 +299,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_DISBURSAL, constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); - final MonetaryCurrency currency = loan.getCurrency(); - final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); @@ -318,14 +308,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf // Recalculate first repayment date based in actual disbursement date. final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate"); - final LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - actualDisbursementDate, loan, calendarInstance); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), - actualDisbursementDate.toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); - final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); updateLoanCounters(loan, actualDisbursementDate); Money amountBeforeAdjust = loan.getPrincpal(); loan.validateAccountStatus(LoanEvent.LOAN_DISBURSED); @@ -348,24 +330,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loan.getLoanTransactions().add(disbursementTransaction); } - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - } - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, - allowTransactionsOnNonWorkingDay); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, - recalculateFrom, overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); regenerateScheduleOnDisbursement(command, loan, recalculateSchedule, scheduleGeneratorDTO); if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { @@ -483,7 +449,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private void updateRecurringCalendarDatesForInterestRecalculation(final Loan loan) { if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled() - && loan.loanInterestRecalculationDetails().getRestFrequencyType().isSameAsRepayment() && !loan.isDisbursed()) { + && loan.loanInterestRecalculationDetails().getRestFrequencyType().isSameAsRepayment()) { final CalendarInstance calendarInstanceForInterestRecalculation = this.calendarInstanceRepository .findByEntityIdAndEntityTypeIdAndCalendarTypeId(loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue(), CalendarType.COLLECTION.getValue()); @@ -560,8 +526,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf checkClientOrGroupActive(loan); this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_DISBURSAL, constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); - final MonetaryCurrency currency = loan.getCurrency(); - final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); @@ -574,14 +538,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf // disbursement date and next available meeting dates // assuming repayment schedule won't regenerate because expected // disbursement and actual disbursement happens on same date - final LocalDate firstRepaymentOnDate = null; final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate"); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), - actualDisbursementDate.toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); - final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); loan.validateAccountStatus(LoanEvent.LOAN_DISBURSED); updateLoanCounters(loan, actualDisbursementDate); boolean canDisburse = loan.canDisburse(actualDisbursementDate); @@ -604,24 +561,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf disbursementTransaction.updateLoan(loan); loan.getLoanTransactions().add(disbursementTransaction); } - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - } - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, - allowTransactionsOnHoliday, allowTransactionsOnNonWorkingDay); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - final ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - firstRepaymentOnDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); regenerateScheduleOnDisbursement(command, loan, recalculateSchedule, scheduleGeneratorDTO); if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive( @@ -691,37 +632,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); removeLoanCycle(loan); + final List existingTransactionIds = new ArrayList<>(); + final List existingReversedTransactionIds = new ArrayList<>(); // final MonetaryCurrency currency = loan.getCurrency(); final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - final LocalDate actualDisbursementDate = loan.getDisbursementDate(); - final LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - actualDisbursementDate, loan, calendarInstance); - - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), - actualDisbursementDate.toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - - final List existingTransactionIds = new ArrayList<>(); - final List existingReversedTransactionIds = new ArrayList<>(); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - } - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(this.loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, floatingRateDTO); + final LocalDate recalculateFrom = null; + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); final Map changes = loan.undoDisbursal(scheduleGeneratorDTO, existingTransactionIds, existingReversedTransactionIds, currentUser); @@ -806,25 +724,25 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf HolidayDetailDTO holidayDetailDTO = null; Boolean isHolidayValidationDone = false; final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); - for(final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand){ - if(singleLoanRepaymentCommand != null){ - Loan loans = this.loanRepository.findOne(singleLoanRepaymentCommand.getLoanId()); + for (final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) { + if (singleLoanRepaymentCommand != null) { + Loan loans = this.loanRepository.findOne(singleLoanRepaymentCommand.getLoanId()); final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loans.getOfficeId(), - singleLoanRepaymentCommand.getTransactionDate().toDate()); + singleLoanRepaymentCommand.getTransactionDate().toDate()); final WorkingDays workingDays = this.workingDaysRepository.findOne(); final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); boolean isHolidayEnabled = false; isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, allowTransactionsOnNonWorkingDay); - loans.validateRepaymentDateIsOnHoliday(singleLoanRepaymentCommand.getTransactionDate(), holidayDetailDTO.isAllowTransactionsOnHoliday(), - holidayDetailDTO.getHolidays()); - loans.validateRepaymentDateIsOnNonWorkingDay(singleLoanRepaymentCommand.getTransactionDate(), holidayDetailDTO.getWorkingDays(), - holidayDetailDTO.isAllowTransactionsOnNonWorkingDay()); + loans.validateRepaymentDateIsOnHoliday(singleLoanRepaymentCommand.getTransactionDate(), + holidayDetailDTO.isAllowTransactionsOnHoliday(), holidayDetailDTO.getHolidays()); + loans.validateRepaymentDateIsOnNonWorkingDay(singleLoanRepaymentCommand.getTransactionDate(), + holidayDetailDTO.getWorkingDays(), holidayDetailDTO.isAllowTransactionsOnNonWorkingDay()); isHolidayValidationDone = true; break; - } - + } + } for (final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) { if (singleLoanRepaymentCommand != null) { @@ -836,7 +754,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder(); LoanTransaction loanTransaction = this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, bulkRepaymentCommand.getTransactionDate(), singleLoanRepaymentCommand.getTransactionAmount(), paymentDetail, - bulkRepaymentCommand.getNote(), null, isRecoveryRepayment, isAccountTransfer, holidayDetailDTO, isHolidayValidationDone); + bulkRepaymentCommand.getNote(), null, isRecoveryRepayment, isAccountTransfer, holidayDetailDTO, + isHolidayValidationDone); transactionIds.add(loanTransaction.getId()); } } @@ -896,46 +815,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf interestComponent, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(), currentUser); } - final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); - final List holidays = this.holidayRepository - .findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), transactionDate.toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); - - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - ApplicationCurrency applicationCurrency = null; - LocalDate calculatedRepaymentsStartingFromDate = null; - boolean isHolidayEnabled = false; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - - final MonetaryCurrency currency = loan.getCurrency(); - applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); recalculateFrom = transactionToAdjust.getTransactionDate().isAfter(transactionDate) ? transactionDate : transactionToAdjust .getTransactionDate(); } - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday, - allowTransactionsOnNonWorkingDay); - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); final ChangedTransactionDetail changedTransactionDetail = loan.adjustExistingTransaction(newTransactionDetail, defaultLoanLifecycleStateMachine(), transactionToAdjust, existingTransactionIds, existingReversedTransactionIds, @@ -1050,41 +937,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf transactionDate, interestComponent, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(), currentUser); this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_WAIVE_INTEREST, constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION, waiveInterestTransaction)); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - ApplicationCurrency applicationCurrency = null; - LocalDate calculatedRepaymentsStartingFromDate = null; - List holidays = null; - boolean isHolidayEnabled = false; - WorkingDays workingDays = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - - final MonetaryCurrency currency = loan.getCurrency(); - applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate().toDate()); - workingDays = this.workingDaysRepository.findOne(); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); recalculateFrom = transactionDate; } - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); final ChangedTransactionDetail changedTransactionDetail = loan.waiveInterest(waiveInterestTransaction, defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser); @@ -1151,37 +1009,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - final LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan - .getDisbursementDate().toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); updateLoanCounters(loan, loan.getDisbursementDate()); - final MonetaryCurrency currency = loan.getCurrency(); - final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); recalculateFrom = command.localDateValueOfParameterNamed("transactionDate"); } - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); final ChangedTransactionDetail changedTransactionDetail = loan.closeAsWrittenOff(command, defaultLoanLifecycleStateMachine(), changes, existingTransactionIds, existingReversedTransactionIds, currentUser, scheduleGeneratorDTO); @@ -1235,39 +1070,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - final LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan - .getDisbursementDate().toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); updateLoanCounters(loan, loan.getDisbursementDate()); - final MonetaryCurrency currency = loan.getCurrency(); - final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); recalculateFrom = command.localDateValueOfParameterNamed("transactionDate"); } - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(this.loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); ChangedTransactionDetail changedTransactionDetail = loan.close(command, defaultLoanLifecycleStateMachine(), changes, existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser); final LoanTransaction possibleClosingTransaction = changedTransactionDetail.getNewTransactionMappings().remove(0L); @@ -1503,30 +1313,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf public void runScheduleRecalculation(final Loan loan, final LocalDate recalculateFrom) { AppUser currentUser = getAppUserIfPresent(); if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - CalendarInstance restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - CalendarInstance compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - - final MonetaryCurrency currency = loan.getCurrency(); - ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate() - .toDate()); - WorkingDays workingDays = this.workingDaysRepository.findOne(); - final Long overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO generatorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, - recalculateFrom, overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); ChangedTransactionDetail changedTransactionDetail = loan.handleRegenerateRepaymentScheduleWithInterestRecalculation( generatorDTO, currentUser); saveLoanWithDataIntegrityViolationChecks(loan); @@ -1545,33 +1332,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf public void updateOriginalSchedule(Loan loan) { if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - - final MonetaryCurrency currency = loan.getCurrency(); - ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate() - .toDate()); - WorkingDays workingDays = this.workingDaysRepository.findOne(); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - } - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, - floatingRateDTO); + final LocalDate recalculateFrom = null; + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); createLoanScheduleArchive(loan, scheduleGeneratorDTO); } @@ -1697,40 +1459,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - ApplicationCurrency applicationCurrency = null; - LocalDate calculatedRepaymentsStartingFromDate = null; - List holidays = null; - boolean isHolidayEnabled = false; - WorkingDays workingDays = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - - final MonetaryCurrency currency = loan.getCurrency(); - applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate().toDate()); - workingDays = this.workingDaysRepository.findOne(); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - } - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); Money accruedCharge = Money.zero(loan.getCurrency()); if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) { @@ -2641,43 +2371,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (!loan.isClosedWrittenOff()) { throw new PlatformServiceUnavailableException( "error.msg.loan.status.not.written.off.update.not.allowed", "Loan :" + loanId + " update not allowed as loan status is not written off", loanId); } - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - ApplicationCurrency applicationCurrency = null; - LocalDate calculatedRepaymentsStartingFromDate = null; - List holidays = null; - boolean isHolidayEnabled = false; - WorkingDays workingDays = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; LoanTransaction writeOffTransaction = loan.findWriteOffTransaction(); this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_UNDO_WRITTEN_OFF, constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION, writeOffTransaction)); - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - final MonetaryCurrency currency = loan.getCurrency(); - applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate().toDate()); - workingDays = this.workingDaysRepository.findOne(); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - } - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); ChangedTransactionDetail changedTransactionDetail = loan.undoWrittenOff(existingTransactionIds, existingReversedTransactionIds, scheduleGeneratorDTO, currentUser); @@ -2776,38 +2475,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private CommandProcessingResult processLoanDisbursementDetail(final Loan loan, Long loanId, JsonCommand command, LoanDisbursementDetails loanDisbursementDetails) { - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - final LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan - .getDisbursementDate().toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - - final MonetaryCurrency currency = loan.getCurrency(); - final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); final Map changes = new LinkedHashMap<>(); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; LocalDate recalculateFrom = null; - Long overdurPenaltyWaitPeriod = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - } - - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(this.loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); ChangedTransactionDetail changedTransactionDetail = null; AppUser currentUser = getAppUserIfPresent(); @@ -2949,35 +2621,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf AppUser currentUser = getAppUserIfPresent(); this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_INTEREST_RECALCULATION, constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - } - final MonetaryCurrency currency = loan.getCurrency(); - ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - loan.getDisbursementDate(), loan, calendarInstance); - - boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate() - .toDate()); - WorkingDays workingDays = this.workingDaysRepository.findOne(); - Long overdurPenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - - ScheduleGeneratorDTO generatorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, recalculateFrom, - overdurPenaltyWaitPeriod, floatingRateDTO); + ScheduleGeneratorDTO generatorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom); ChangedTransactionDetail changedTransactionDetail = loan.recalculateScheduleFromLastTransaction(generatorDTO, existingTransactionIds, existingReversedTransactionIds, currentUser); @@ -3105,47 +2752,47 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf map.put(entityEvent, entity); return map; } - + @Override - @Transactional - public CommandProcessingResult undoLastLoanDisbursal(Long loanId, JsonCommand command) { - final AppUser currentUser = getAppUserIfPresent(); + @Transactional + public CommandProcessingResult undoLastLoanDisbursal(Long loanId, JsonCommand command) { + final AppUser currentUser = getAppUserIfPresent(); - final Loan loan = this.loanAssembler.assembleFrom(loanId); - final LocalDate recalculateFromDate = loan.getLastRepaymentDate(); - validateIsMultiDisbursalLoanAndDisbursedMoreThanOneTranche(loan); - checkClientOrGroupActive(loan); - this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_UNDO_LASTDISBURSAL, - constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); - - final MonetaryCurrency currency = loan.getCurrency(); - final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); - final List existingTransactionIds = new ArrayList<>(); - final List existingReversedTransactionIds = new ArrayList<>(); + final Loan loan = this.loanAssembler.assembleFrom(loanId); + final LocalDate recalculateFromDate = loan.getLastRepaymentDate(); + validateIsMultiDisbursalLoanAndDisbursedMoreThanOneTranche(loan); + checkClientOrGroupActive(loan); + this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_UNDO_LASTDISBURSAL, + constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); - ScheduleGeneratorDTO scheduleGeneratorDTO = getScheduleGeneratorDTO(loan, recalculateFromDate, applicationCurrency); + final MonetaryCurrency currency = loan.getCurrency(); + final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); + final List existingTransactionIds = new ArrayList<>(); + final List existingReversedTransactionIds = new ArrayList<>(); - final Map changes = loan.undoLastDisbursal(scheduleGeneratorDTO, existingTransactionIds, - existingReversedTransactionIds, currentUser, loan); - if (!changes.isEmpty()) { - saveAndFlushLoanWithDataIntegrityViolationChecks(loan); - String noteText = null; - if (command.hasParameter("note")) { - noteText = command.stringValueOfParameterNamed("note"); - if (StringUtils.isNotBlank(noteText)) { - final Note note = Note.loanNote(loan, noteText); - this.noteRepository.save(note); - } - } - boolean isAccountTransfer = false; - final Map accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(), - existingTransactionIds, existingReversedTransactionIds, isAccountTransfer); - this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData); - this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_UNDO_LASTDISBURSAL, - constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); - } + ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFromDate); - return new CommandProcessingResultBuilder() // + final Map changes = loan.undoLastDisbursal(scheduleGeneratorDTO, existingTransactionIds, + existingReversedTransactionIds, currentUser, loan); + if (!changes.isEmpty()) { + saveAndFlushLoanWithDataIntegrityViolationChecks(loan); + String noteText = null; + if (command.hasParameter("note")) { + noteText = command.stringValueOfParameterNamed("note"); + if (StringUtils.isNotBlank(noteText)) { + final Note note = Note.loanNote(loan, noteText); + this.noteRepository.save(note); + } + } + boolean isAccountTransfer = false; + final Map accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(), + existingTransactionIds, existingReversedTransactionIds, isAccountTransfer); + this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData); + this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_UNDO_LASTDISBURSAL, + constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); + } + + return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(loan.getId()) // .withOfficeId(loan.getOfficeId()) // @@ -3154,74 +2801,23 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf .withLoanId(loanId) // .with(changes) // .build(); - } - - private ScheduleGeneratorDTO getScheduleGeneratorDTO(final Loan loan, final LocalDate recalculateFromDate, - final ApplicationCurrency applicationCurrency) { - - final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(), - CalendarEntityType.LOANS.getValue()); - final LocalDate actualDisbursementDate = loan.getDisbursementDate(); - final LocalDate calculatedRepaymentsStartingFromDate = this.loanAccountDomainService.getCalculatedRepaymentsStartingFromDate( - actualDisbursementDate, loan, calendarInstance); - - final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); - final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), - actualDisbursementDate.toDate()); - final WorkingDays workingDays = this.workingDaysRepository.findOne(); - - HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays); - CalendarInstance restCalendarInstance = null; - CalendarInstance compoundingCalendarInstance = null; - if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { - restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(loan.loanInterestRecalculationDetailId(), - CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue()); - compoundingCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId( - loan.loanInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue()); - } - FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan); - Long overduePenaltyWaitPeriod = this.configurationDomainService.retrievePenaltyWaitPeriod(); - - ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(this.loanScheduleFactory, applicationCurrency, - calculatedRepaymentsStartingFromDate, holidayDetailDTO, restCalendarInstance, compoundingCalendarInstance, - recalculateFromDate, overduePenaltyWaitPeriod, floatingRateDTO); - - return scheduleGeneratorDTO; - } - - private void validateIsMultiDisbursalLoanAndDisbursedMoreThanOneTranche(Loan loan) { - if(!loan.isMultiDisburmentLoan()){ - final String errorMessage = "loan.product.does.not.support.multiple.disbursals.cannot.undo.last.disbursal"; - throw new LoanMultiDisbursementException(errorMessage); - } - Integer trancheDisbursedCount = 0; - for(LoanDisbursementDetails disbursementDetails : loan.getDisbursementDetails()){ - if(disbursementDetails.actualDisbursementDate() != null){ - trancheDisbursedCount++; - } - } - if(trancheDisbursedCount <=1){ - final String errorMessage = "tranches.should.be.disbursed.more.than.one.to.undo.last.disbursal"; - throw new LoanMultiDisbursementException(errorMessage); - } - - } - - private FloatingRateDTO constructFloatingRateDTO(final Loan loan) { - FloatingRateDTO floatingRateDTO = null; - if (loan.loanProduct().isLinkedToFloatingInterestRate()) { - boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); - BigDecimal interestRateDiff = loan.getInterestRateDifferential(); - List baseLendingRatePeriods = null; - try { - baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods(); - } catch (final FloatingRateNotFoundException ex) { - // Do not do anything - } - floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, - baseLendingRatePeriods); - } - return floatingRateDTO; } + private void validateIsMultiDisbursalLoanAndDisbursedMoreThanOneTranche(Loan loan) { + if (!loan.isMultiDisburmentLoan()) { + final String errorMessage = "loan.product.does.not.support.multiple.disbursals.cannot.undo.last.disbursal"; + throw new LoanMultiDisbursementException(errorMessage); + } + Integer trancheDisbursedCount = 0; + for (LoanDisbursementDetails disbursementDetails : loan.getDisbursementDetails()) { + if (disbursementDetails.actualDisbursementDate() != null) { + trancheDisbursedCount++; + } + } + if (trancheDisbursedCount <= 1) { + final String errorMessage = "tranches.should.be.disbursed.more.than.one.to.undo.last.disbursal"; + throw new LoanMultiDisbursementException(errorMessage); + } + + } } \ No newline at end of file