diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 60c9afa1f..2ea7e17de 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -125,10 +125,12 @@ import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementData import org.apache.fineract.portfolio.loanaccount.exception.UndoLastTrancheDisbursementException; import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator; +import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod; +import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService; import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod; import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod; import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod; @@ -4524,12 +4526,61 @@ public class Loan extends AbstractPersistableCustom { // startDate } - public void applyHolidayToRepaymentScheduleDates(final Holiday holiday) { + public void applyHolidayToRepaymentScheduleDates(final Holiday holiday, final LoanUtilService loanUtilService) { + final DefaultScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator(); + ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(this, holiday.getFromDateLocalDate()); + final LoanApplicationTerms loanApplicationTerms = this.constructLoanApplicationTerms(scheduleGeneratorDTO); + + // LocalDate rescheduleFromDate = holiday.getFromDateLocalDate(); + LocalDate adjustedRescheduleToDate = null; + + if (holiday.getReScheduleType().isResheduleToNextRepaymentDate()) { + final LocalDate rescheduleToDate = holiday.getToDateLocalDate(); + for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.getRepaymentScheduleInstallments()) { + if (rescheduleToDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) { + adjustedRescheduleToDate = rescheduleToDate; + break; + } else { + // Account for a Bimonthly Loan Product + // if (loanApplicationTerms.getRepaymentPeriodFrequencyType().isSemiMonthly()) { + // if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate()) + // && rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(15))) { + // adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate(); + // break; + // } + // } else { + // // Once Bimonthly product implemented, Replace the `Standard Monthly Loan Holiday check` below + // HERE + // if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate()) + // && rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) { + // adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate(); + // break; + // } + // } + + // Standard Monthly Loan Holiday check + if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate()) + && rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) { + adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate(); + break; + } + } + } + } else { + adjustedRescheduleToDate = holiday.getRepaymentsRescheduledToLocalDate(); + } + // first repayment's from date is same as disbursement date. LocalDate tmpFromDate = getDisbursementDate(); + // Loop through all loanRepayments List installments = getRepaymentScheduleInstallments(); for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) { + + if (adjustedRescheduleToDate == null) { + break; + } + final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate(); // update from date if it's not same as previous installament's due @@ -4537,17 +4588,15 @@ public class Loan extends AbstractPersistableCustom { if (!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)) { loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate); } - if (oldDueDate.isAfter(holiday.getToDateLocalDate())) { - break; - } - if (oldDueDate.equals(holiday.getFromDateLocalDate()) || oldDueDate.equals(holiday.getToDateLocalDate()) - || (oldDueDate.isAfter(holiday.getFromDateLocalDate()) && oldDueDate.isBefore(holiday.getToDateLocalDate()))) { + if (oldDueDate.equals(holiday.getFromDateLocalDate()) || oldDueDate.isAfter(holiday.getFromDateLocalDate())) { // FIXME: AA do we need to apply non-working days. // Assuming holiday's repayment reschedule to date cannot be // created on a non-working day. - final LocalDate newRepaymentDate = holiday.getRepaymentsRescheduledToLocalDate(); - loanRepaymentScheduleInstallment.updateDueDate(newRepaymentDate); + + adjustedRescheduleToDate = scheduledDateGenerator.generateNextRepaymentDate(adjustedRescheduleToDate, loanApplicationTerms, + false); + loanRepaymentScheduleInstallment.updateDueDate(adjustedRescheduleToDate); } tmpFromDate = loanRepaymentScheduleInstallment.getDueDate(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index d4bb52b90..448cce74d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -2615,7 +2615,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf for (final Loan loan : loans) { // apply holiday - loan.applyHolidayToRepaymentScheduleDates(holiday); + loan.applyHolidayToRepaymentScheduleDates(holiday, this.loanUtilService); } this.loanRepositoryWrapper.save(loans); holiday.processed();