package org.mifos.clientportfolio.newloan.domain; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.LocalDate; import org.mifos.accounts.productdefinition.util.helpers.GraceType; import org.mifos.accounts.util.helpers.InstallmentDate; import org.mifos.application.holiday.business.Holiday; import org.mifos.application.holiday.persistence.HolidayDao; import org.mifos.config.FiscalCalendarRules; import org.mifos.schedule.ScheduledDateGeneration; import org.mifos.schedule.ScheduledEvent; import org.mifos.schedule.internal.DailyScheduledEvent; import org.mifos.schedule.internal.HolidayAndWorkingDaysAndMoratoriaScheduledDateGeneration; public class AnyScheduledEventLoanInstallmentGenerator implements LoanInstallmentGenerator { private final ScheduledEvent scheduledEvent; private final HolidayDao holidayDao; public AnyScheduledEventLoanInstallmentGenerator(ScheduledEvent scheduledEvent, HolidayDao holidayDao) { this.scheduledEvent = scheduledEvent; this.holidayDao = holidayDao; } @Override public List<InstallmentDate> generate(LocalDate actualDisbursementDate, int numberOfInstallments, GraceType graceType, int gracePeriodDuration, Short officeId) { List<InstallmentDate> installmentDates = new ArrayList<InstallmentDate>(); if (numberOfInstallments > 0) { List<Days> workingDays = new FiscalCalendarRules().getWorkingDaysAsJodaTimeDays(); List<Holiday> holidays = new ArrayList<Holiday>(); LocalDate startFromMeetingDate = null; if (scheduledEvent instanceof DailyScheduledEvent) { startFromMeetingDate = actualDisbursementDate.plusDays(scheduledEvent.getEvery()); } else { startFromMeetingDate = actualDisbursementDate.plusDays(1); } holidays = holidayDao.findAllHolidaysFromDateAndNext(officeId, startFromMeetingDate.toString()); int occurrences = numberOfInstallments; if (graceType == GraceType.GRACEONALLREPAYMENTS) { occurrences += gracePeriodDuration; } ScheduledDateGeneration dateGeneration = new HolidayAndWorkingDaysAndMoratoriaScheduledDateGeneration(workingDays, holidays); List<Date> dueDates = new ArrayList<Date>(); List<DateTime> installmentDateTimes = dateGeneration.generateScheduledDates(occurrences, startFromMeetingDate.toDateMidnight().toDateTime(), scheduledEvent, false); for (DateTime installmentDate : installmentDateTimes) { dueDates.add(installmentDate.toDate()); } installmentDates = createInstallmentDates(dueDates); if (graceType == GraceType.GRACEONALLREPAYMENTS) { removeInstallmentsNeedNotPay(gracePeriodDuration, installmentDates); } } return installmentDates; } private List<InstallmentDate> createInstallmentDates(final List<Date> dueDates) { List<InstallmentDate> installmentDates = new ArrayList<InstallmentDate>(); int installmentId = 1; for (Date date : dueDates) { installmentDates.add(new InstallmentDate((short) installmentId++, date)); } return installmentDates; } private void removeInstallmentsNeedNotPay(final int installmentSkipToStartRepayment, final List<InstallmentDate> installmentDates) { int removeCounter = 0; for (int i = 0; i < installmentSkipToStartRepayment; i++) { installmentDates.remove(removeCounter); } // re-adjust the installment ids if (installmentSkipToStartRepayment > 0) { int count = installmentDates.size(); for (int i = 0; i < count; i++) { InstallmentDate instDate = installmentDates.get(i); instDate.setInstallmentId(new Short(Integer.toString(i + 1))); } } } }