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 9b466c798..f2699c4b5 100644 --- 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 @@ -1317,7 +1317,7 @@ public class Loan extends AbstractPersistable { public Map disburse(final LoanScheduleGeneratorFactory loanScheduleFactory, final AppUser currentUser, final JsonCommand command, final ApplicationCurrency currency, final List existingTransactionIds, final List existingReversedTransactionIds, final Map actualChanges, final PaymentDetail paymentDetail, - final LocalDate firstRepaymentMeetingDate, final boolean isHolidayEnabled, final List holidays, final WorkingDays workingDays) { + final LocalDate calculatedRepaymentsStartingFromDate, final boolean isHolidayEnabled, final List holidays, final WorkingDays workingDays) { updateLoanToPreDisbursalState(); @@ -1347,7 +1347,7 @@ public class Loan extends AbstractPersistable { handleDisbursementTransaction(paymentDetail, actualDisbursementDate); if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate)) { - regenerateRepaymentSchedule(loanScheduleFactory, currency, firstRepaymentMeetingDate, isHolidayEnabled, holidays, workingDays); + regenerateRepaymentSchedule(loanScheduleFactory, currency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, workingDays); updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate); } else { updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate); @@ -1374,7 +1374,7 @@ public class Loan extends AbstractPersistable { * details/state. */ private void regenerateRepaymentSchedule(final LoanScheduleGeneratorFactory loanScheduleFactory, - final ApplicationCurrency applicationCurrency, final LocalDate firstRepaymentMeetingDate, final boolean isHolidayEnabled, + final ApplicationCurrency applicationCurrency, final LocalDate calculatedRepaymentsStartingFromDate, final boolean isHolidayEnabled, final List holidays, final WorkingDays workingDays) { final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod(); @@ -1385,13 +1385,8 @@ public class Loan extends AbstractPersistable { final Integer loanTermFrequency = this.termFrequency; final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType); - // If ExpectedFirstRepaymentOnDate is null and repayment is synced with - // meeting then use firstRepaymentMeetingDate - // to generate repayment schedule dates - final LocalDate firstRepaymentOnDate = (getExpectedFirstRepaymentOnDate() == null) ? firstRepaymentMeetingDate - : getExpectedFirstRepaymentOnDate(); LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency, - loanTermPeriodFrequencyType, getDisbursementDate(), firstRepaymentOnDate, getInArrearsTolerance(), + loanTermPeriodFrequencyType, getDisbursementDate(), getExpectedFirstRepaymentOnDate(), calculatedRepaymentsStartingFromDate, getInArrearsTolerance(), this.loanRepaymentScheduleDetail); LoanScheduleModel loanSchedule = loanScheduleGenerator.generate(mc, applicationCurrency, loanApplicationTerms, this.charges, isHolidayEnabled, holidays, workingDays); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java index 4bde5c0cc..3af0e561d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java @@ -26,7 +26,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator { final List dueRepaymentPeriodDates = new ArrayList(numberOfRepayments); LocalDate startDate = loanApplicationTerms.getExpectedDisbursementDate(); - final LocalDate firstRepaymentPeriodDate = loanApplicationTerms.getRepaymentsStartingFromLocalDate(); + final LocalDate firstRepaymentPeriodDate = loanApplicationTerms.getCalculatedRepaymentsStartingFromLocalDate(); for (int repaymentPeriod = 1; repaymentPeriod <= numberOfRepayments; repaymentPeriod++) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java index f1711f334..552f19e3b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java @@ -38,7 +38,7 @@ public final class LoanApplicationTerms { private final Money principal; private final LocalDate expectedDisbursementDate; private final LocalDate repaymentsStartingFromDate; - + private final LocalDate calculatedRepaymentsStartingFromDate; /** * Integer representing the number of 'repayment frequencies' or * installments where 'grace' should apply to the principal component of a @@ -88,21 +88,22 @@ public final class LoanApplicationTerms { final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod, final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualNominalInterestRate, final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Money principalMoney, - final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate, final Integer graceOnPrincipalPayment, + final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate, + final LocalDate calculatedRepaymentsStartingFromDate, final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate, final Money inArrearsTolerance) { return new LoanApplicationTerms(currency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentPeriodFrequencyType, amortizationMethod, interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney, expectedDisbursementDate, - repaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, - interestChargedFromDate, inArrearsTolerance); + repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, + graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance); } public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency, final PeriodFrequencyType loanTermPeriodFrequencyType, final LocalDate expectedDisbursementDate, - final LocalDate repaymentsStartingFromDate, final Money inArrearsTolerance, - final LoanProductRelatedDetail loanProductRelatedDetail) { + final LocalDate repaymentsStartingFromDate, final LocalDate calculatedRepaymentsStartingFromDate, + final Money inArrearsTolerance, final LoanProductRelatedDetail loanProductRelatedDetail) { final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments(); final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery(); @@ -125,8 +126,8 @@ public final class LoanApplicationTerms { return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentPeriodFrequencyType, amortizationMethod, interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney, - expectedDisbursementDate, repaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, - graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance); + expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, + graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance); } private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency, @@ -135,9 +136,9 @@ public final class LoanApplicationTerms { final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod, final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualNominalInterestRate, final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Money principal, - final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate, final Integer principalGrace, - final Integer interestPaymentGrace, final Integer interestChargingGrace, final LocalDate interestChargedFromDate, - final Money inArrearsTolerance) { + final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate, + final LocalDate calculatedRepaymentsStartingFromDate, final Integer principalGrace, final Integer interestPaymentGrace, + final Integer interestChargingGrace, final LocalDate interestChargedFromDate, final Money inArrearsTolerance) { this.currency = currency; this.loanTermFrequency = loanTermFrequency; this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType; @@ -155,7 +156,8 @@ public final class LoanApplicationTerms { this.principal = principal; this.expectedDisbursementDate = expectedDisbursementDate; this.repaymentsStartingFromDate = repaymentsStartingFromDate; - + this.calculatedRepaymentsStartingFromDate = calculatedRepaymentsStartingFromDate; + this.principalGrace = principalGrace; this.interestPaymentGrace = interestPaymentGrace; this.interestChargingGrace = interestChargingGrace; @@ -685,6 +687,10 @@ public final class LoanApplicationTerms { return this.repaymentsStartingFromDate; } + public LocalDate getCalculatedRepaymentsStartingFromLocalDate() { + return this.calculatedRepaymentsStartingFromDate; + } + public Money getPrincipal() { return this.principal; } 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 1ea4588ac..367694e52 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 @@ -139,8 +139,8 @@ public class LoanScheduleAssembler { final Money principalMoney = Money.of(currency, principal); final LocalDate expectedDisbursementDate = this.fromApiJsonHelper.extractLocalDateNamed("expectedDisbursementDate", element); - LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper.extractLocalDateNamed("repaymentsStartingFromDate", element); - + final LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper.extractLocalDateNamed("repaymentsStartingFromDate", element); + LocalDate calculatedRepaymentsStartingFromDate = repaymentsStartingFromDate; final Boolean synchDisbursement = fromApiJsonHelper.extractBooleanNamed("syncDisbursementWithMeeting", element); final Long calendarId = this.fromApiJsonHelper.extractLongNamed("calendarId", element); Calendar calendar = null; @@ -163,11 +163,11 @@ public class LoanScheduleAssembler { // TODO : AA - Is it require to reset repaymentsStartingFromDate or // set only if it is not provided (or null) // Currently provided repaymentsStartingFromDate takes precedence over system generated next meeting date - if (repaymentsStartingFromDate == null) { + 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 String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType); - repaymentsStartingFromDate = CalendarHelper.getFirstRepaymentMeetingDate(calendar, expectedDisbursementDate, + calculatedRepaymentsStartingFromDate = CalendarHelper.getFirstRepaymentMeetingDate(calendar, expectedDisbursementDate, repaymentEvery, frequency); } else {// validate user provided repaymentsStartFromDate validateRepaymentsStartDateWithMeetingDates(repaymentsStartingFromDate, calendar); @@ -186,7 +186,7 @@ public class LoanScheduleAssembler { return LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentPeriodFrequencyType, amortizationMethod, interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney, - expectedDisbursementDate, repaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, + expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsToleranceMoney); } 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 a139f20e7..a06543cee 100644 --- 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 @@ -176,14 +176,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf // Recalculate first repayment date based in actual disbursement date. final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate"); - final LocalDate firstRepaymentMeetingDate = getFirstRepaymentMeetingDate(actualDisbursementDate, loan, calendarInstance); + final LocalDate calculatedRepaymentsStartingFromDate = 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(); updateLoanCounters(loan, actualDisbursementDate); loan.disburse(this.loanScheduleFactory, currentUser, command, applicationCurrency, existingTransactionIds, - existingReversedTransactionIds, changes, paymentDetail, firstRepaymentMeetingDate, isHolidayEnabled, holidays, workingDays); + existingReversedTransactionIds, changes, paymentDetail, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, workingDays); if (!changes.isEmpty()) { this.loanRepository.save(loan); @@ -208,15 +208,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf .build(); } - private LocalDate getFirstRepaymentMeetingDate(final LocalDate actualDisbursementDate, final Loan loan, + private LocalDate getCalculatedRepaymentsStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, final CalendarInstance calendarInstance) { final Calendar calendar = (calendarInstance == null) ? null : calendarInstance.getCalendar(); - LocalDate firstRepaymentMeetingDate = null; + LocalDate calculatedRepaymentsStartingFromDate = loan.getExpectedFirstRepaymentOnDate(); if (calendar != null) {// sync repayments // TODO: AA - user provided first repayment date takes precedence // over recalculated meeting date - if (loan.getExpectedFirstRepaymentOnDate() == null) { + 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 @@ -227,12 +227,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final Integer repayEvery = repaymentScheduleDetails.getRepayEvery(); final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentScheduleDetails .getRepaymentPeriodFrequencyType()); - firstRepaymentMeetingDate = CalendarHelper.getFirstRepaymentMeetingDate(calendar, actualDisbursementDate, repayEvery, + calculatedRepaymentsStartingFromDate = CalendarHelper.getFirstRepaymentMeetingDate(calendar, actualDisbursementDate, repayEvery, frequency); } } } - return firstRepaymentMeetingDate; + return calculatedRepaymentsStartingFromDate; } /****