/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.application.holiday.persistence;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.mifos.accounts.loan.util.helpers.LoanExceptionConstants;
import org.mifos.application.admin.servicefacade.HolidayServiceFacade;
import org.mifos.application.holiday.business.Holiday;
import org.mifos.application.holiday.business.HolidayBO;
import org.mifos.application.holiday.business.service.HolidayService;
import org.mifos.application.holiday.util.helpers.RepaymentRuleTypes;
import org.mifos.application.master.MessageLookup;
import org.mifos.application.servicefacade.ApplicationContextProvider;
import org.mifos.calendar.WorkingDay;
import org.mifos.config.FiscalCalendarRules;
import org.mifos.dto.domain.HolidayDetails;
import org.mifos.dto.domain.OfficeHoliday;
import org.mifos.service.BusinessRuleException;
import org.springframework.beans.factory.annotation.Autowired;
public class HolidayServiceFacadeWebTier implements HolidayServiceFacade {
private final HolidayService holidayService;
private final HolidayDao holidayDao;
@Autowired
public HolidayServiceFacadeWebTier(HolidayService holidayService, HolidayDao holidayDao) {
this.holidayService = holidayService;
this.holidayDao = holidayDao;
}
@Override
public void createHoliday(HolidayDetails holidayDetails, List<Short> officeIds) {
this.holidayService.create(holidayDetails, officeIds);
}
@Override
public Map<String, List<OfficeHoliday>> holidaysByYear() {
List<HolidayBO> holidays = this.holidayDao.findAllHolidays();
Map<String, List<OfficeHoliday>> holidaysByYear = new TreeMap<String, List<OfficeHoliday>>();
for (HolidayBO holiday : holidays) {
HolidayDetails holidayDetail = new HolidayDetails(holiday.getHolidayName(), holiday.getHolidayFromDate(), holiday
.getHolidayThruDate(), holiday.getRepaymentRuleType().getValue());
String holidayRepaymentRuleName = ApplicationContextProvider.getBean(MessageLookup.class).lookup(holiday.getRepaymentRuleType().getPropertiesKey());
holidayDetail.setRepaymentRuleName(holidayRepaymentRuleName);
int year = holiday.getThruDate().getYear();
List<OfficeHoliday> holidaysInYear = holidaysByYear.get(Integer.toString(year));
if (holidaysInYear == null) {
holidaysInYear = new LinkedList<OfficeHoliday>();
}
holidaysInYear.add(new OfficeHoliday(holidayDetail, this.holidayDao.applicableOffices(holiday.getId())));
holidaysByYear.put(Integer.toString(year), holidaysInYear);
}
sortValuesByFromDate(holidaysByYear);
return holidaysByYear;
}
private void sortValuesByFromDate(Map<String, List<OfficeHoliday>> holidays) {
for (String year : holidays.keySet()) {
List<OfficeHoliday> holidayList = holidays.get(year);
Collections.sort(holidayList, new Comparator<OfficeHoliday>() {
@Override
public int compare(OfficeHoliday o1, OfficeHoliday o2) {
return o1.getHolidayDetails().getFromDate().compareTo(o2.getHolidayDetails().getFromDate());
}
});
}
}
@Override
public OfficeHoliday retrieveHolidayDetailsForPreview(HolidayDetails holidayDetail, List<Short> officeIds) {
String holidayRepaymentRuleName = ApplicationContextProvider.getBean(MessageLookup.class).lookup(RepaymentRuleTypes.fromInt(holidayDetail.getRepaymentRuleType().intValue()).getPropertiesKey());
holidayDetail.setRepaymentRuleName(holidayRepaymentRuleName);
List<String> officeNames = this.holidayDao.retrieveApplicableOfficeNames(officeIds);
return new OfficeHoliday(holidayDetail, officeNames);
}
@Override
public List<String> retrieveOtherHolidayNamesWithTheSameDate(HolidayDetails holidayDetail, List<Short> branchIds) {
List<String> holidayNames = new ArrayList<String>();
// TODO I assume we should look at dates only (without branches). Is this the correct assumption? (MIFOS-3428)
//List<String> offices = this.holidayDao.retrieveApplicableOfficeNames(branchIds);
for (HolidayBO holiday : this.holidayDao.findAllHolidays()) {
//List<String> holidayOffices = this.holidayDao.applicableOffices(holiday.getId());
//if (!Collections.disjoint(offices, holidayOffices)) {
for (LocalDate date = holidayDetail.getFromDate(); date.compareTo(holidayDetail.getThruDate()) <= 0; date = date.plusDays(1)) {
if (holiday.encloses(date.toDateTimeAtStartOfDay())) {
holidayNames.add(holiday.getName());
break;
}
}
//}
}
return holidayNames;
}
@Override
public boolean isWorkingDay(Calendar day, Short officeId) {
return holidayService.isWorkingDay(day, officeId);
}
@Override
public Calendar getNextWorkingDay(Calendar day, Short officeId) {
return holidayService.getNextWorkingDay(day, officeId);
}
@Override
public Date getNextWorkingDay(Date day, Short officeId) {
return holidayService.getNextWorkingDay(day, officeId);
}
@Override
public void validateDisbursementDateForNewLoan(Short officeId, DateTime disbursementDate) {
List<Days> workingDays = new FiscalCalendarRules().getWorkingDaysAsJodaTimeDays();
validateDisbursementDateIsWorkingDay(disbursementDate, workingDays);
List<Holiday> holidays = holidayDao.findAllHolidaysFromDateAndNext(officeId, new LocalDate(disbursementDate).toString());
validateDisbursementDateIsNotInHoliday(disbursementDate, holidays);
}
private void validateDisbursementDateIsWorkingDay(DateTime disbursementDate, List<Days> workingDays) {
if (WorkingDay.isNotWorkingDay(disbursementDate, workingDays)) {
throw new BusinessRuleException(LoanExceptionConstants.DISBURSEMENTDATE_MUST_BE_A_WORKING_DAY);
}
}
private void validateDisbursementDateIsNotInHoliday (DateTime disbursementDate, List<Holiday> holidays) {
for (Holiday holiday : holidays) {
if (holiday.encloses(disbursementDate)) {
throw new BusinessRuleException(LoanExceptionConstants.DISBURSEMENTDATE_MUST_NOT_BE_IN_A_HOLIDAY);
}
}
}
@Override
public boolean isFutureRepaymentHoliday(Short officeId, Calendar date) {
return holidayService.isFutureRepaymentHoliday(date, officeId);
}
}