/*
 * MosP - Mind Open Source Project    http://www.mosp.jp/
 * Copyright (C) MIND Co., Ltd.       http://www.e-mind.co.jp/
 * 
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package jp.mosp.time.bean.impl;

import java.sql.Connection;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.mosp.framework.base.MospException;
import jp.mosp.framework.base.MospParams;
import jp.mosp.framework.constant.MospConst;
import jp.mosp.framework.utils.DateUtility;
import jp.mosp.platform.base.PlatformBean;
import jp.mosp.platform.bean.human.EntranceReferenceBeanInterface;
import jp.mosp.platform.constant.PlatformMessageConst;
import jp.mosp.time.base.TimeApplicationBean;
import jp.mosp.time.bean.CutoffUtilBeanInterface;
import jp.mosp.time.bean.HolidayRequestReferenceBeanInterface;
import jp.mosp.time.bean.PaidHolidayDataRegistBeanInterface;
import jp.mosp.time.bean.PaidHolidayInfoReferenceBeanInterface;
import jp.mosp.time.constant.TimeConst;
import jp.mosp.time.dao.settings.PaidHolidayDataDaoInterface;
import jp.mosp.time.dao.settings.PaidHolidayEntranceDateDaoInterface;
import jp.mosp.time.dao.settings.PaidHolidayFirstYearDaoInterface;
import jp.mosp.time.dao.settings.PaidHolidayPointDateDaoInterface;
import jp.mosp.time.dao.settings.PaidHolidayTransactionDaoInterface;
import jp.mosp.time.dao.settings.TotalTimeDataDaoInterface;
import jp.mosp.time.dto.settings.PaidHolidayDataDtoInterface;
import jp.mosp.time.dto.settings.PaidHolidayEntranceDateDtoInterface;
import jp.mosp.time.dto.settings.PaidHolidayFirstYearDtoInterface;
import jp.mosp.time.dto.settings.PaidHolidayPointDateDtoInterface;
import jp.mosp.time.dto.settings.PaidHolidayTransactionDtoInterface;
import jp.mosp.time.dto.settings.TotalTimeDataDtoInterface;
import jp.mosp.time.utils.TimeUtility;

/**
 * 有給休暇情報参照クラス。
 */
public class PaidHolidayInfoReferenceBean extends TimeApplicationBean implements PaidHolidayInfoReferenceBeanInterface {
	
	/**
	 * 有給休暇データDAO。
	 */
	private PaidHolidayDataDaoInterface				paidHolidayDataDao;
	
	/**
	 * 有給休暇トランザクションDAO。
	 */
	private PaidHolidayTransactionDaoInterface		paidHolidayTransactionDao;
	
	/**
	 * 休暇申請参照。
	 */
	private HolidayRequestReferenceBeanInterface	holidayRequest;
	
	/**
	 * 有給休暇基準日管理DAO。
	 */
	private PaidHolidayPointDateDaoInterface		paidHolidayPointDao;
	
	/**
	 * 有給休暇入社日管理DAO。
	 */
	private PaidHolidayEntranceDateDaoInterface		paidHolidayEntranceDateDao;
	
	/**
	 * 勤怠集計データDAO。
	 */
	private TotalTimeDataDaoInterface				totalTimeDataDao;
	
	/**
	 * 有給休暇初年度DAO。
	 */
	private PaidHolidayFirstYearDaoInterface		firstYearDao;
	
	/**
	 * 人事入社情報参照クラス。
	 */
	protected EntranceReferenceBeanInterface		entranceRefer;
	
	/**
	 * 有給休暇データ登録クラス。
	 */
	protected PaidHolidayDataRegistBeanInterface	paidHolidayDataRegist;
	
	/**
	 * 締日ユーティリティ。
	 */
	protected CutoffUtilBeanInterface				cutoffUtil;
	

	/**
	 * {@link PlatformBean#PlatformBean()}を実行する。<br>
	 */
	public PaidHolidayInfoReferenceBean() {
		super();
	}
	
	/**
	 * {@link PlatformBean#PlatformBean(MospParams, Connection)}を実行する。<br>
	 * @param mospParams MosPパラメータクラス
	 * @param connection DBコネクション
	 */
	public PaidHolidayInfoReferenceBean(MospParams mospParams, Connection connection) {
		super(mospParams, connection);
	}
	
	@Override
	public void initBean() throws MospException {
		// 継承元のBean初期化処理を実施
		super.initBean();
		// 有給休暇データDAO取得
		paidHolidayDataDao = (PaidHolidayDataDaoInterface)createDao(PaidHolidayDataDaoInterface.class);
		// 有給休暇トランザクションDAO取得
		paidHolidayTransactionDao = (PaidHolidayTransactionDaoInterface)createDao(PaidHolidayTransactionDaoInterface.class);
		// 休暇申請参照クラス取得
		holidayRequest = (HolidayRequestReferenceBeanInterface)createBean(HolidayRequestReferenceBeanInterface.class);
		// 有給休暇基準日管理DAO
		paidHolidayPointDao = (PaidHolidayPointDateDaoInterface)createDao(PaidHolidayPointDateDaoInterface.class);
		// 有給休暇入社日管理DAO
		paidHolidayEntranceDateDao = (PaidHolidayEntranceDateDaoInterface)createDao(PaidHolidayEntranceDateDaoInterface.class);
		// 勤怠集計データDAO
		totalTimeDataDao = (TotalTimeDataDaoInterface)createDao(TotalTimeDataDaoInterface.class);
		// 有給休暇初年度DAO
		firstYearDao = (PaidHolidayFirstYearDaoInterface)createDao(PaidHolidayFirstYearDaoInterface.class);
		// 各種Bean準備
		entranceRefer = (EntranceReferenceBeanInterface)createBean(EntranceReferenceBeanInterface.class);
		paidHolidayDataRegist = (PaidHolidayDataRegistBeanInterface)createBean(PaidHolidayDataRegistBeanInterface.class);
		// 締日ユーティリティ
		cutoffUtil = (CutoffUtilBeanInterface)createBean(CutoffUtilBeanInterface.class);
	}
	
	@Override
	public List<PaidHolidayDataDtoInterface> getPaidHolidayCalcInfo(String personalId, Date targetDate)
			throws MospException {
		List<PaidHolidayDataDtoInterface> list = new ArrayList<PaidHolidayDataDtoInterface>();
//		Date oneYearBeforeActivateDate = DateUtility.addYear(targetDate, -1);
		List<PaidHolidayDataDtoInterface> paidHolidayDataDtoList = paidHolidayDataDao.findForInfoList(personalId,
				targetDate);
		for (PaidHolidayDataDtoInterface paidHolidayDataDto : paidHolidayDataDtoList) {
			Date acquisitionDate = paidHolidayDataDto.getAcquisitionDate();
//			if (acquisitionDate.compareTo(oneYearBeforeActivateDate) >= 0) {
			// 手動付与・破棄
			List<PaidHolidayTransactionDtoInterface> paidHolidayTransactionDtoList = paidHolidayTransactionDao
				.findForList(personalId, acquisitionDate, paidHolidayDataDto.getActivateDate(), targetDate);
			for (PaidHolidayTransactionDtoInterface paidHolidayTransactionDto : paidHolidayTransactionDtoList) {
				paidHolidayDataDto.setGivingDay(paidHolidayDataDto.getGivingDay()
						+ paidHolidayTransactionDto.getGivingDay());
				paidHolidayDataDto.setGivingHour(paidHolidayDataDto.getGivingHour()
						+ paidHolidayTransactionDto.getGivingHour());
				paidHolidayDataDto.setCancelDay(paidHolidayDataDto.getCancelDay()
						+ paidHolidayTransactionDto.getCancelDay());
				paidHolidayDataDto.setCancelHour(paidHolidayDataDto.getCancelHour()
						+ paidHolidayTransactionDto.getCancelHour());
			}
			// 申請
			Map<String, Object> approvedMap = holidayRequest.getApprovedDayHour(personalId, acquisitionDate, Integer
				.parseInt(mospParams.getProperties().getCodeArray(TimeConst.CODE_HOLIDAY_TYPE, false)[0][0]),
					mospParams.getProperties().getCodeArray(TimeConst.CODE_HOLIDAY_TYPE2_WITHPAY, false)[0][0],
					paidHolidayDataDto.getActivateDate(), targetDate);
			paidHolidayDataDto.setUseDay(((Double)approvedMap.get(TimeConst.CODE_APPROVED_DAY)).doubleValue());
			paidHolidayDataDto.setUseHour(((Integer)approvedMap.get(TimeConst.CODE_APPROVED_HOUR)).intValue());
			paidHolidayDataDto.setActivateDate(targetDate);
			list.add(paidHolidayDataDto);
//			}
//			if (acquisitionDate.before(oneYearBeforeActivateDate)
//					&& acquisitionDate.compareTo(DateUtility.addYear(targetDate, -2)) >= 0) {
			// 手動付与・破棄
//				List<PaidHolidayTransactionDtoInterface> paidHolidayTransactionDtoList = paidHolidayTransactionDao
//					.findForList(personalId, acquisitionDate, paidHolidayDataDto.getActivateDate(), targetDate);
//				for (PaidHolidayTransactionDtoInterface paidHolidayTransactionDto : paidHolidayTransactionDtoList) {
//					paidHolidayDataDto.setGivingDay(paidHolidayDataDto.getGivingDay()
//							+ paidHolidayTransactionDto.getGivingDay());
//					paidHolidayDataDto.setGivingHour(paidHolidayDataDto.getGivingHour()
//							+ paidHolidayTransactionDto.getGivingHour());
//					paidHolidayDataDto.setCancelDay(paidHolidayDataDto.getCancelDay()
//							+ paidHolidayTransactionDto.getCancelDay());
//					paidHolidayDataDto.setCancelHour(paidHolidayDataDto.getCancelHour()
//							+ paidHolidayTransactionDto.getCancelHour());
//				}
			// 申請
//				Map<String, Object> approvedMap = holidayRequest
//					.getApprovedDayHour(personalId, acquisitionDate, Integer.parseInt(mospParams.getProperties()
//						.getCodeArray(TimeConst.CODE_HOLIDAY_TYPE, false)[0][0]), mospParams.getProperties()
//						.getCodeArray(TimeConst.CODE_HOLIDAY_TYPE2_WITHPAY, false)[0][0], paidHolidayDataDto
//						.getActivateDate(), targetDate);
//				paidHolidayDataDto.setUseDay(((Double)approvedMap.get(TimeConst.CODE_APPROVED_DAY)).doubleValue());
//				paidHolidayDataDto.setUseHour(((Integer)approvedMap.get(TimeConst.CODE_APPROVED_HOUR)).intValue());
//				list.add(paidHolidayDataDto);
//			}
		}
		return list;
	}
	
	@Override
	public Map<String, Object> getPaidHolidayInfo(String personalId, Date targetDate) throws MospException {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(TimeConst.CODE_ACTIVATE_DATE, targetDate);
		map.put(TimeConst.CODE_CURRENT_YEAR_DATE, 0.0);
		map.put(TimeConst.CODE_CURRENT_TIME, 0);
		map.put(TimeConst.CODE_FORMER_YEAR_DATE, 0.0);
		map.put(TimeConst.CODE_FORMER_YEAR_TIME, 0);
		map.put(TimeConst.CODE_GIVING_DATE, 0.0);
		map.put(TimeConst.CODE_GIVING_TIME, 0);
		map.put(TimeConst.CODE_CANCEL_DATE, 0.0);
		map.put(TimeConst.CODE_CANCEL_TIME, 0);
		map.put(TimeConst.CODE_USE_DATE, 0.0);
		map.put(TimeConst.CODE_USE_TIME, 0);
		// 今年度残日数
		double currentDate = 0;
		// 今年度残時間
		int currentTime = 0;
		// 前年度残日数
		double formerDate = 0;
		// 前年度残時間
		int formerTime = 0;
		// 今年度支給日数
		double currentGivingDate = 0;
		// 今年度支給時間
		int currentGivingTime = 0;
		// 前年度支給日数
		double formerGivingDate = 0;
		// 前年度支給時間
		int formerGivingTime = 0;
		// 今年度廃棄日数
		double currentCancelDate = 0;
		// 今年度廃棄時間
		int currentCancelTime = 0;
		// 前年度廃棄日数
		double formerCancelDate = 0;
		// 前年度廃棄時間
		int formerCancelTime = 0;
		// 今年度利用日数
		double currentUseDate = 0;
		// 今年度利用時間
		int currentUseTime = 0;
		// 前年度利用日数
		double formerUseDate = 0;
		// 前年度利用時間
		int formerUseTime = 0;
		Date oneYearBeforeActivateDate = DateUtility.addYear(targetDate, -1);
		List<PaidHolidayDataDtoInterface> paidHolidayDataDtoList = paidHolidayDataDao.findForInfoList(personalId,
				targetDate);
		for (PaidHolidayDataDtoInterface paidHolidayDataDto : paidHolidayDataDtoList) {
			map.put(TimeConst.CODE_ACTIVATE_DATE, paidHolidayDataDto.getActivateDate());
			Date acquisitionDate = paidHolidayDataDto.getAcquisitionDate();
			double holdDay = paidHolidayDataDto.getHoldDay();
			int holdHour = paidHolidayDataDto.getHoldHour();
			// 対象個人ID及び対象日付で勤怠設定情報群を取得し設定
			setApplicationSettings(personalId, targetDate);
			// 処理結果確認
			if (mospParams.hasErrorMessage()) {
				return map;
			}
			
			int generalWorkHour = timeSettingRefer.getGeneralWorkHour(applicationDto.getWorkSettingCode(),
					paidHolidayDataDto.getActivateDate());
			if (acquisitionDate.after(oneYearBeforeActivateDate)) {
				currentGivingDate = paidHolidayDataDto.getGivingDay();
				currentGivingTime = paidHolidayDataDto.getGivingHour();
				currentCancelDate = paidHolidayDataDto.getCancelDay();
				currentCancelTime = paidHolidayDataDto.getCancelHour();
				// 手動付与・破棄
				List<PaidHolidayTransactionDtoInterface> paidHolidayTransactionDtoList = paidHolidayTransactionDao
					.findForList(personalId, acquisitionDate, paidHolidayDataDto.getActivateDate(), targetDate);
				for (PaidHolidayTransactionDtoInterface paidHolidayTransactionDto : paidHolidayTransactionDtoList) {
					currentGivingDate += paidHolidayTransactionDto.getGivingDay();
					currentGivingTime += paidHolidayTransactionDto.getGivingHour();
					currentCancelDate += paidHolidayTransactionDto.getCancelDay();
					currentCancelTime += paidHolidayTransactionDto.getCancelHour();
				}
				// 申請
				Map<String, Object> requestMap = holidayRequest.getRequestDayHour(personalId, acquisitionDate, 1,
						Integer.toString(1), paidHolidayDataDto.getActivateDate(), paidHolidayDataDto.getLimitDate());
				currentUseDate = ((Double)requestMap.get(TimeConst.CODE_REQUEST_DAY)).doubleValue();
				currentUseTime = ((Integer)requestMap.get(TimeConst.CODE_REQUEST_HOUR)).intValue();
				currentDate = holdDay + currentGivingDate - currentCancelDate - currentUseDate;
				currentTime = holdHour + currentGivingTime - currentCancelTime - currentUseTime;
				while (currentTime < 0) {
					currentDate--;
					currentTime += generalWorkHour;
				}
			} else if (!acquisitionDate.after(oneYearBeforeActivateDate)
					&& acquisitionDate.after(DateUtility.addYear(targetDate, TimeConst.PAID_HOLIDAY_CALCULATE_DAY))) {
				formerGivingDate = paidHolidayDataDto.getGivingDay();
				formerGivingTime = paidHolidayDataDto.getGivingHour();
				formerCancelDate = paidHolidayDataDto.getCancelDay();
				formerCancelTime = paidHolidayDataDto.getCancelHour();
				// 手動付与・破棄
				List<PaidHolidayTransactionDtoInterface> paidHolidayTransactionDtoList = paidHolidayTransactionDao
					.findForList(personalId, acquisitionDate, paidHolidayDataDto.getActivateDate(), targetDate);
				for (PaidHolidayTransactionDtoInterface paidHolidayTransactionDto : paidHolidayTransactionDtoList) {
					formerGivingDate += paidHolidayTransactionDto.getGivingDay();
					formerGivingTime += paidHolidayTransactionDto.getGivingHour();
					formerCancelDate += paidHolidayTransactionDto.getCancelDay();
					formerCancelTime += paidHolidayTransactionDto.getCancelHour();
				}
				// 申請
				Map<String, Object> requestMap = holidayRequest.getRequestDayHour(personalId, acquisitionDate, 1,
						Integer.toString(1), paidHolidayDataDto.getActivateDate(), paidHolidayDataDto.getLimitDate());
				formerUseDate = ((Double)requestMap.get(TimeConst.CODE_REQUEST_DAY)).doubleValue();
				formerUseTime = ((Integer)requestMap.get(TimeConst.CODE_REQUEST_HOUR)).intValue();
				formerDate = holdDay + formerGivingDate - formerCancelDate - formerUseDate;
				formerTime = holdHour + formerGivingTime - formerCancelTime - formerUseTime;
				while (formerTime < 0) {
					formerDate--;
					formerTime += generalWorkHour;
				}
			}
		}
		map.put(TimeConst.CODE_CURRENT_YEAR_DATE, currentDate);
		map.put(TimeConst.CODE_CURRENT_TIME, currentTime);
		map.put(TimeConst.CODE_FORMER_YEAR_DATE, formerDate);
		map.put(TimeConst.CODE_FORMER_YEAR_TIME, formerTime);
		map.put(TimeConst.CODE_GIVING_DATE, currentGivingDate + formerGivingDate);
		map.put(TimeConst.CODE_GIVING_TIME, currentGivingTime + formerGivingTime);
		map.put(TimeConst.CODE_CANCEL_DATE, currentCancelDate + formerCancelDate);
		map.put(TimeConst.CODE_CANCEL_TIME, currentCancelTime + formerCancelTime);
		map.put(TimeConst.CODE_USE_DATE, currentUseDate + formerUseDate);
		map.put(TimeConst.CODE_USE_TIME, currentUseTime + formerUseTime);
		return map;
	}
	
	@Override
	public Map<String, Object> getPaidHolidayPossibleRequest(String personalId, Date targetDate) throws MospException {
		Map<String, Object> map = new HashMap<String, Object>();
		// 今年度残日数
		double currentDate = 0;
		// 今年度残時間
		int currentTime = 0;
		// 前年度残日数
		double formerDate = 0;
		// 前年度残時間
		int formerTime = 0;
		// 今年度支給日数
		double currentGivingDate = 0;
		// 今年度支給時間
		int currentGivingTime = 0;
		// 前年度支給日数
		double formerGivingDate = 0;
		// 前年度支給時間
		int formerGivingTime = 0;
		// 今年度廃棄日数
		double currentCancelDate = 0;
		// 今年度廃棄時間
		int currentCancelTime = 0;
		// 前年度廃棄日数
		double formerCancelDate = 0;
		// 前年度廃棄時間
		int formerCancelTime = 0;
		// 今年度利用日数
		double currentUseDate = 0;
		// 今年度利用時間
		int currentUseTime = 0;
		// 前年度利用日数
		double formerRequestDate = 0;
		// 前年度利用時間
		int formerRequestTime = 0;
		Date oneYearBeforeActivateDate = DateUtility.addYear(targetDate, -1);
		List<PaidHolidayDataDtoInterface> paidHolidayDataDtoList = paidHolidayDataDao.findForInfoList(personalId,
				targetDate);
		for (PaidHolidayDataDtoInterface paidHolidayDataDto : paidHolidayDataDtoList) {
			Date acquisitionDate = paidHolidayDataDto.getAcquisitionDate();
			double holdDay = paidHolidayDataDto.getHoldDay();
			int holdHour = paidHolidayDataDto.getHoldHour();
			int generalWorkHour = 8;
			// 対象日付における取得対象個人IDの設定適用情報を取得し設定
			if (hasApplicationSettings(personalId, targetDate)) {
				// 所定労働時間取得(設定適用情報が存在する場合)
				generalWorkHour = timeSettingRefer.getGeneralWorkHour(applicationDto.getWorkSettingCode(),
						paidHolidayDataDto.getActivateDate());
			}
			if (acquisitionDate.after(oneYearBeforeActivateDate)) {
				currentGivingDate = paidHolidayDataDto.getGivingDay();
				currentGivingTime = paidHolidayDataDto.getGivingHour();
				currentCancelDate = paidHolidayDataDto.getCancelDay();
				currentCancelTime = paidHolidayDataDto.getCancelHour();
				// 手動付与・破棄
				List<PaidHolidayTransactionDtoInterface> paidHolidayTransactionDtoList = paidHolidayTransactionDao
					.findForList(personalId, acquisitionDate, paidHolidayDataDto.getActivateDate(), targetDate);
				for (PaidHolidayTransactionDtoInterface paidHolidayTransactionDto : paidHolidayTransactionDtoList) {
					currentGivingDate += paidHolidayTransactionDto.getGivingDay();
					currentGivingTime += paidHolidayTransactionDto.getGivingHour();
					currentCancelDate += paidHolidayTransactionDto.getCancelDay();
					currentCancelTime += paidHolidayTransactionDto.getCancelHour();
				}
				// 申請
				Map<String, Object> requestMap = holidayRequest.getRequestDayHour(personalId, acquisitionDate, 1,
						Integer.toString(1), paidHolidayDataDto.getActivateDate(), paidHolidayDataDto.getLimitDate());
				currentUseDate = ((Double)requestMap.get(TimeConst.CODE_REQUEST_DAY)).doubleValue();
				currentUseTime = ((Integer)requestMap.get(TimeConst.CODE_REQUEST_HOUR)).intValue();
				currentDate = holdDay + currentGivingDate - currentCancelDate - currentUseDate;
				currentTime = holdHour + currentGivingTime - currentCancelTime - currentUseTime;
				while (currentTime < 0) {
					currentDate--;
					currentTime += generalWorkHour;
				}
				map.put(TimeConst.CODE_CURRENT_ACQUISITION_DATE_DATE, acquisitionDate);
			} else if (!acquisitionDate.after(oneYearBeforeActivateDate)
					&& acquisitionDate.after(DateUtility.addYear(targetDate, TimeConst.PAID_HOLIDAY_CALCULATE_DAY))) {
				formerGivingDate = paidHolidayDataDto.getGivingDay();
				formerGivingTime = paidHolidayDataDto.getGivingHour();
				formerCancelDate = paidHolidayDataDto.getCancelDay();
				formerCancelTime = paidHolidayDataDto.getCancelHour();
				// 手動付与・破棄
				List<PaidHolidayTransactionDtoInterface> paidHolidayTransactionDtoList = paidHolidayTransactionDao
					.findForList(personalId, acquisitionDate, paidHolidayDataDto.getActivateDate(), targetDate);
				for (PaidHolidayTransactionDtoInterface paidHolidayTransactionDto : paidHolidayTransactionDtoList) {
					formerGivingDate += paidHolidayTransactionDto.getGivingDay();
					formerGivingTime += paidHolidayTransactionDto.getGivingHour();
					formerCancelDate += paidHolidayTransactionDto.getCancelDay();
					formerCancelTime += paidHolidayTransactionDto.getCancelHour();
				}
				// 申請
				Map<String, Object> requestMap = holidayRequest.getRequestDayHour(personalId, acquisitionDate, 1,
						Integer.toString(1), paidHolidayDataDto.getActivateDate(), paidHolidayDataDto.getLimitDate());
				formerRequestDate = ((Double)requestMap.get(TimeConst.CODE_REQUEST_DAY)).doubleValue();
				formerRequestTime = ((Integer)requestMap.get(TimeConst.CODE_REQUEST_HOUR)).intValue();
				formerDate = holdDay + formerGivingDate - formerCancelDate - formerRequestDate;
				formerTime = holdHour + formerGivingTime - formerCancelTime - formerRequestTime;
				while (formerTime < 0) {
					formerDate--;
					formerTime += generalWorkHour;
				}
				map.put(TimeConst.CODE_FORMER_ACQUISITION_DATE_DATE, acquisitionDate);
			}
		}
		map.put(TimeConst.CODE_CURRENT_YEAR_DATE, currentDate);
		map.put(TimeConst.CODE_CURRENT_TIME, currentTime);
		map.put(TimeConst.CODE_FORMER_YEAR_DATE, formerDate);
		map.put(TimeConst.CODE_FORMER_YEAR_TIME, formerTime);
		map.put(TimeConst.CODE_GIVING_DATE, currentGivingDate + formerGivingDate);
		map.put(TimeConst.CODE_GIVING_TIME, currentGivingTime + formerGivingTime);
		map.put(TimeConst.CODE_CANCEL_DATE, currentCancelDate + formerCancelDate);
		map.put(TimeConst.CODE_CANCEL_TIME, currentCancelTime + formerCancelTime);
//		map.put(TimeConst.CODE_USE_DATE, currentUseDate + formerRequestDate);
//		map.put(TimeConst.CODE_USE_TIME, currentUseTime + formerRequestTime);
		return map;
	}
	
	@Override
	public Date getNextGivingDate(String personalId) throws MospException {
		// システム日付準備
		Date systemDate = getSystemDate();
		// 対象個人ID及び対象日付で有給休暇設定情報を取得し設定
		if (hasPaidHolidaySettings(personalId, systemDate) == false) {
			// 有給休暇情報が取得できない場合
			return null;
		}
		// 入社日取得及び確認
		Date entranceDate = entranceRefer.getEntranceDate(personalId);
		if (entranceDate == null) {
			// 該当する入社日が存在しない
			String errorMes = mospParams.getName("Joined");
			mospParams.addErrorMessage(PlatformMessageConst.MSG_EMPLOYEE_IS_NOT, errorMes, null);
			return null;
		}
		// 入社年月取得
		int entranceYear = DateUtility.getYear(entranceDate);
		int entranceMonth = DateUtility.getMonth(entranceDate);
		// 初年度付与情報取得
		PaidHolidayFirstYearDtoInterface paidHolidayFirstYearDto = firstYearDao.findForKey(paidHolidayDto
			.getPaidHolidayCode(), paidHolidayDto.getActivateDate(), entranceMonth);
		// 付与区分取得
		int paidHolidayType = paidHolidayDto.getPaidHolidayType();
		// 付与区分確認
		if (paidHolidayType == TimeConst.CODE_PAID_HOLIDAY_TYPE_STANDARDSDAY) {
			// 基準日
			int pointMonth = paidHolidayDto.getPointDateMonth();
			int pointDay = paidHolidayDto.getPointDateDay();
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null && paidHolidayFirstYearDto.getGivingAmount() > 0) {
				// 初年度付与マスタが存在し且つ付与日数が0より大きい場合
				// 初年度付与日取得(入社月の基準日から付与月を加算)
				firstYearGivingDate = DateUtility.addDay(DateUtility.addMonth(DateUtility
					.getFirstDateOfMonth(entranceDate), paidHolidayFirstYearDto.getGivingMonth()), pointDay - 1);
				// 初年度付与日確認
				if (systemDate.before(firstYearGivingDate)) {
					return firstYearGivingDate;
				}
			}
			// 基準日準備
			Date pointDate = DateUtility.getDate(entranceYear, pointMonth, pointDay);
			if (!entranceDate.before(pointDate)) {
				// 入社日が基準日より前でない場合は基準日に1年を加算する
				pointDate = DateUtility.addYear(pointDate, 1);
			}
			// 初年度付与日確認
			if (firstYearGivingDate != null && !firstYearGivingDate.before(pointDate)) {
				// 初年度付与日が基準日より前でない場合は1年加算
				pointDate = DateUtility.addYear(pointDate, 1);
			}
			// 基準日経過回数設定
			while (!pointDate.after(systemDate)) {
				// 基準日が締日より後でない場合は1年加算
				pointDate = DateUtility.addYear(pointDate, 1);
			}
			return pointDate;
		} else if (paidHolidayType == 1) {
			// 入社月
			// 対象個人ID及び対象日付で締日情報を取得し設定
			if (!hasCutoffSettings(personalId, systemDate)) {
				// 締日情報が取得できない場合
				return null;
			}
			Date pointDate = DateUtility.addDay(DateUtility.getLastDateOfMonth(entranceDate), 1);
			int cutoffDate = cutoffDto.getCutoffDate();
			if (cutoffDate != 0) {
				// 締日が末日でない場合
				pointDate = DateUtility.addDay(DateUtility.getDate(entranceYear, entranceMonth, cutoffDate), 1);
			}
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null && paidHolidayFirstYearDto.getGivingAmount() > 0) {
				// 初年度付与マスタが存在し且つ付与日数が0より大きい場合
				// 初年度付与日取得(入社月の締日の翌日から付与月を加算)
				firstYearGivingDate = DateUtility.addMonth(pointDate, paidHolidayFirstYearDto.getGivingMonth());
				// 初年度付与日確認
				if (systemDate.before(firstYearGivingDate)) {
					return firstYearGivingDate;
				}
			}
			Date givingDate = null;
			Date maxDate = pointDate;
			List<PaidHolidayEntranceDateDtoInterface> list = paidHolidayEntranceDateDao.findForList(paidHolidayDto
				.getPaidHolidayCode(), paidHolidayDto.getActivateDate());
			for (PaidHolidayEntranceDateDtoInterface paidHolidayEntranceDateDto : list) {
				Date workDate = DateUtility.addMonth(pointDate, paidHolidayEntranceDateDto.getWorkMonth());
				if (firstYearGivingDate != null && !firstYearGivingDate.before(workDate)) {
					continue;
				}
				if (maxDate.before(workDate)) {
					maxDate = workDate;
				}
				if (workDate.after(systemDate) && (givingDate == null || givingDate.after(workDate))) {
					givingDate = workDate;
				}
			}
			if (givingDate == null) {
				// 登録情報最大まで経過後
				int generalJoiningMonth = paidHolidayDto.getGeneralJoiningMonth();
				if (generalJoiningMonth == 0) {
					return null;
				}
				while (!maxDate.after(systemDate)) {
					maxDate = DateUtility.addMonth(maxDate, generalJoiningMonth);
				}
				return maxDate;
			}
			return givingDate;
		} else if (paidHolidayType == 2) {
			// 入社日
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null && paidHolidayFirstYearDto.getGivingAmount() > 0) {
				// 初年度付与マスタが存在し且つ付与日数が0より大きい場合
				// 初年度付与日取得(入社日から付与月を加算)
				firstYearGivingDate = DateUtility.addMonth(entranceDate, paidHolidayFirstYearDto.getGivingMonth());
				// 初年度付与日確認
				if (systemDate.before(firstYearGivingDate)) {
					return firstYearGivingDate;
				}
			}
			Date givingDate = null;
			Date maxDate = entranceDate;
			List<PaidHolidayEntranceDateDtoInterface> list = paidHolidayEntranceDateDao.findForList(paidHolidayDto
				.getPaidHolidayCode(), paidHolidayDto.getActivateDate());
			for (PaidHolidayEntranceDateDtoInterface paidHolidayEntranceDateDto : list) {
				Date workDate = DateUtility.addMonth(entranceDate, paidHolidayEntranceDateDto.getWorkMonth());
				if (firstYearGivingDate != null && !firstYearGivingDate.before(workDate)) {
					continue;
				}
				if (maxDate.before(workDate)) {
					maxDate = workDate;
				}
				if (workDate.after(systemDate) && (givingDate == null || givingDate.after(workDate))) {
					givingDate = workDate;
				}
			}
			if (givingDate == null) {
				// 登録情報最大まで経過後
				int generalJoiningMonth = paidHolidayDto.getGeneralJoiningMonth();
				if (generalJoiningMonth == 0) {
					return null;
				}
				while (!maxDate.after(systemDate)) {
					maxDate = DateUtility.addMonth(maxDate, generalJoiningMonth);
				}
				return maxDate;
			}
			return givingDate;
		}
		return null;
	}
	
	@Override
	public int getNextGivingDay(String personalId) throws MospException {
		// システム日付準備
		Date systemDate = getSystemDate();
		// 対象個人ID及び対象日付で有給休暇設定情報を取得し設定
		if (hasPaidHolidaySettings(personalId, systemDate) == false) {
			// 有給休暇情報が取得できない場合
			return 0;
		}
		// 入社日取得及び確認
		Date entranceDate = entranceRefer.getEntranceDate(personalId);
		if (entranceDate == null) {
			// 該当する入社日が存在しない
			String errorMes = mospParams.getName("Joined");
			mospParams.addErrorMessage(PlatformMessageConst.MSG_EMPLOYEE_IS_NOT, errorMes, null);
			return 0;
		}
		// 入社年月取得
		int entranceYear = DateUtility.getYear(entranceDate);
		int entranceMonth = DateUtility.getMonth(entranceDate);
		// 初年度付与情報取得
		PaidHolidayFirstYearDtoInterface paidHolidayFirstYearDto = firstYearDao.findForKey(paidHolidayDto
			.getPaidHolidayCode(), paidHolidayDto.getActivateDate(), entranceMonth);
		// 付与区分取得
		int paidHolidayType = paidHolidayDto.getPaidHolidayType();
		// 付与区分確認
		if (paidHolidayType == TimeConst.CODE_PAID_HOLIDAY_TYPE_STANDARDSDAY) {
			// 基準日
			int pointMonth = paidHolidayDto.getPointDateMonth();
			int pointDay = paidHolidayDto.getPointDateDay();
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null) {
				// 初年度付与マスタが存在する場合
				int amount = paidHolidayFirstYearDto.getGivingAmount();
				if (amount > 0) {
					// 付与日数が0より大きい場合
					// 初年度付与日取得(入社月の基準日から付与月を加算)
					firstYearGivingDate = DateUtility.addDay(DateUtility.addMonth(DateUtility
						.getFirstDateOfMonth(entranceDate), paidHolidayFirstYearDto.getGivingMonth()), pointDay - 1);
					// 初年度付与日確認
					if (systemDate.before(firstYearGivingDate)) {
						return amount;
					}
				}
			}
			// 基準日準備
			Date pointDate = DateUtility.getDate(entranceYear, pointMonth, pointDay);
			if (!entranceDate.before(pointDate)) {
				// 入社日が基準日より前でない場合は基準日に1年を加算する
				pointDate = DateUtility.addYear(pointDate, 1);
			}
			// 初年度付与日確認
			if (firstYearGivingDate != null && !firstYearGivingDate.before(pointDate)) {
				// 初年度付与日が基準日より前でない場合は1年加算
				pointDate = DateUtility.addYear(pointDate, 1);
			}
			// 基準日経過回数準備
			int count = 2;
			// 基準日経過回数設定
			while (!pointDate.after(systemDate)) {
				// 基準日が締日より後でない場合は1年加算
				pointDate = DateUtility.addYear(pointDate, 1);
				count++;
			}
			// 基準日経過回数から有給休暇基準日管理情報を取得
			PaidHolidayPointDateDtoInterface paidHolidayPointDateDto = paidHolidayPointDao.findForKey(paidHolidayDto
				.getPaidHolidayCode(), paidHolidayDto.getActivateDate(), count);
			if (paidHolidayPointDateDto == null) {
				// 登録情報超過後
				return paidHolidayDto.getGeneralPointAmount();
			}
			return paidHolidayPointDateDto.getPointDateAmount();
		} else if (paidHolidayType == 1) {
			// 入社月
			// 対象個人ID及び対象日付で締日情報を取得し設定
			if (!hasCutoffSettings(personalId, systemDate)) {
				// 締日情報が取得できない場合
				return 0;
			}
			Date pointDate = DateUtility.addDay(DateUtility.getLastDateOfMonth(entranceDate), 1);
			int cutoffDate = cutoffDto.getCutoffDate();
			if (cutoffDate != 0) {
				// 締日が末日でない場合
				pointDate = DateUtility.addDay(DateUtility.getDate(entranceYear, entranceMonth, cutoffDate), 1);
			}
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null) {
				// 初年度付与マスタが存在する場合
				int amount = paidHolidayFirstYearDto.getGivingAmount();
				if (amount > 0) {
					// 付与日数が0より大きい場合
					// 初年度付与日取得(入社月の締日の翌日から付与月を加算)
					firstYearGivingDate = DateUtility.addMonth(pointDate, paidHolidayFirstYearDto.getGivingMonth());
					// 初年度付与日確認
					if (systemDate.before(firstYearGivingDate)) {
						return amount;
					}
				}
			}
			Date givingDate = null;
			int amount = 0;
			List<PaidHolidayEntranceDateDtoInterface> list = paidHolidayEntranceDateDao.findForList(paidHolidayDto
				.getPaidHolidayCode(), paidHolidayDto.getActivateDate());
			for (PaidHolidayEntranceDateDtoInterface paidHolidayEntranceDateDto : list) {
				Date workDate = DateUtility.addMonth(pointDate, paidHolidayEntranceDateDto.getWorkMonth());
				if (firstYearGivingDate != null && !firstYearGivingDate.before(workDate)) {
					continue;
				}
				if (workDate.after(systemDate) && (givingDate == null || givingDate.after(workDate))) {
					givingDate = workDate;
					amount = paidHolidayEntranceDateDto.getJoiningDateAmount();
				}
			}
			if (givingDate == null) {
				// 登録情報最大まで経過後
				if (paidHolidayDto.getGeneralJoiningMonth() == 0) {
					return 0;
				}
				return paidHolidayDto.getGeneralJoiningAmount();
			}
			return amount;
		} else if (paidHolidayType == 2) {
			// 入社日
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null) {
				// 初年度付与マスタが存在する場合
				int amount = paidHolidayFirstYearDto.getGivingAmount();
				if (amount > 0) {
					// 付与日数が0より大きい場合
					// 初年度付与日取得(入社日から付与月を加算)
					firstYearGivingDate = DateUtility.addMonth(entranceDate, paidHolidayFirstYearDto.getGivingMonth());
					// 初年度付与日確認
					if (systemDate.before(firstYearGivingDate)) {
						return amount;
					}
				}
			}
			Date givingDate = null;
			int amount = 0;
			List<PaidHolidayEntranceDateDtoInterface> list = paidHolidayEntranceDateDao.findForList(paidHolidayDto
				.getPaidHolidayCode(), paidHolidayDto.getActivateDate());
			for (PaidHolidayEntranceDateDtoInterface paidHolidayEntranceDateDto : list) {
				Date workDate = DateUtility.addMonth(entranceDate, paidHolidayEntranceDateDto.getWorkMonth());
				if (firstYearGivingDate != null && !firstYearGivingDate.before(workDate)) {
					continue;
				}
				if (workDate.after(systemDate) && (givingDate == null || givingDate.after(workDate))) {
					givingDate = workDate;
					amount = paidHolidayEntranceDateDto.getJoiningDateAmount();
				}
			}
			if (givingDate == null) {
				// 登録情報最大まで経過後
				if (paidHolidayDto.getGeneralJoiningMonth() == 0) {
					return 0;
				}
				return paidHolidayDto.getGeneralJoiningAmount();
			}
			return amount;
		}
		return 0;
	}
	
	@Override
	public Date getNextManualGivingDate(String personalId) throws MospException {
		// 個人ID及びシステム日付で有給休暇トランザクション情報リストを取得
		List<PaidHolidayTransactionDtoInterface> list = paidHolidayTransactionDao.findForNextGiving(personalId,
				getSystemDate());
		// リスト確認
		if (list.isEmpty()) {
			return null;
		}
		// 直近の有給休暇トランザクション情報から付与日を取得
		return list.get(0).getActivateDate();
	}
	
	@Override
	public String getNextManualGivingDaysAndHours(String personalId) throws MospException {
		// 次回付与予定日を取得
		Date activateDate = getNextManualGivingDate(personalId);
		if (activateDate == null) {
			return null;
		}
		// 直近の有給休暇トランザクション情報を取得
		List<PaidHolidayTransactionDtoInterface> list = paidHolidayTransactionDao.findForList(personalId, activateDate);
		// 日数及び時間を準備
		double givingDays = 0D;
		int givingHours = 0;
		// 日数及び時間を加算
		for (PaidHolidayTransactionDtoInterface dto : list) {
			givingDays += dto.getGivingDay();
			givingDays -= dto.getCancelDay();
			givingHours += dto.getGivingHour();
			givingHours -= dto.getCancelHour();
		}
		// 日数及び時間を文字列に変換
		StringBuffer sb = new StringBuffer();
		sb.append(getStringDays(givingDays));
		sb.append(getDayNaming());
		if (givingHours != 0) {
			sb.append(givingHours);
			sb.append(getTimeNaming());
		}
		return sb.toString();
	}
	
	@Override
	public List<PaidHolidayDataDtoInterface> getPaidHolidayNextMonthInfo(String personalId, Date cutoffDate,
			int calculationYear, int calculationMonth, List<PaidHolidayDataDtoInterface> list) throws MospException {
		List<PaidHolidayDataDtoInterface> paidHolidayDataList = new ArrayList<PaidHolidayDataDtoInterface>();
		for (PaidHolidayDataDtoInterface dto : list) {
			if (dto.getLimitDate().after(cutoffDate)) {
				Date acquisitionDate = dto.getAcquisitionDate();
				if (dto.getTemporaryFlag() == 0 && cutoffDate.before(acquisitionDate)
						&& !DateUtility.addMonth(cutoffDate, 1).before(acquisitionDate)) {
					// 仮付与フラグが有効の場合
					if (!isOverRatio(personalId, cutoffDate, calculationYear, calculationMonth)) {
						// 出勤率が下回っていたら保有日数を0とする
						dto.setHoldDay(0);
					}
					// 仮付与フラグを無効とする
					dto.setTemporaryFlag(1);
				}
				if (!dto.getActivateDate().after(cutoffDate)) {
					// 有効日が締日より後でない場合は有効日に締日の翌日をセットする
					dto.setActivateDate(DateUtility.addDay(cutoffDate, 1));
				}
				dto.setHoldDay(dto.getHoldDay() + dto.getGivingDay() - dto.getCancelDay() - dto.getUseDay());
				dto.setHoldHour(dto.getHoldHour() + dto.getGivingHour() - dto.getCancelHour() - dto.getUseHour());
				dto.setGivingDay(0);
				dto.setGivingHour(0);
				dto.setCancelDay(0);
				dto.setCancelHour(0);
				dto.setUseDay(0);
				dto.setUseHour(0);
				paidHolidayDataList.add(dto);
			}
		}
		return paidHolidayDataList;
	}
	
	@Override
	public double getExpirationDay(List<PaidHolidayDataDtoInterface> list, Date cutoffDate) {
		for (PaidHolidayDataDtoInterface dto : list) {
			if (dto.getLimitDate().compareTo(cutoffDate) <= 0) {
				return dto.getHoldDay() + dto.getGivingDay() - dto.getCancelDay() - dto.getUseDay();
			}
		}
		return 0;
	}
	
	@Override
	public PaidHolidayDataDtoInterface getNewPaidHolidayInfo(String personalId, Date cutoffLastDate,
			int calculationYear, int calculationMonth) throws MospException {
		// 対象個人ID及び対象日付で有給休暇設定情報を取得し設定
		if (hasPaidHolidaySettings(personalId, cutoffLastDate) == false) {
			// 有給休暇情報が取得できない場合
			return null;
		}
		// 入社日取得及び確認
		Date entranceDate = entranceRefer.getEntranceDate(personalId);
		if (entranceDate == null) {
			// 該当する入社日が存在しない
			return null;
		}
		// 入社年月取得
		int entranceYear = DateUtility.getYear(entranceDate);
		int entranceMonth = DateUtility.getMonth(entranceDate);
		// 初年度付与情報取得
		PaidHolidayFirstYearDtoInterface paidHolidayFirstYearDto = firstYearDao.findForKey(paidHolidayDto
			.getPaidHolidayCode(), paidHolidayDto.getActivateDate(), entranceMonth);
		// 有給休暇データ準備
		PaidHolidayDataDtoInterface dto = paidHolidayDataRegist.getInitDto();
		// 有給休暇データ初期設定
		dto.setPersonalId(personalId);
		dto.setHoldDay(0);
		dto.setHoldHour(0);
		dto.setGivingDay(0);
		dto.setGivingHour(0);
		dto.setCancelDay(0);
		dto.setCancelHour(0);
		dto.setUseDay(0);
		dto.setUseHour(0);
		dto.setTemporaryFlag(1);
		// 仮付与日確認
		if (paidHolidayDto.getScheduleGiving() != 0) {
			// 仮付与日が0でない場合は仮付与フラグを有効にする
			dto.setTemporaryFlag(0);
		}
		int limit = 1;
		int maxCarryOverYear = paidHolidayDto.getMaxCarryOverYear();
		if (maxCarryOverYear == MospConst.DELETE_FLAG_ON) {
			// 有休繰越が無効の場合は期限は1年
			limit = 1;
		} else if (maxCarryOverYear == MospConst.DELETE_FLAG_OFF) {
			// 有休繰越が有効の場合は期限は2年
			limit = 2;
		}
		// 付与区分取得
		int paidHolidayType = paidHolidayDto.getPaidHolidayType();
		// 付与区分確認
		if (paidHolidayType == TimeConst.CODE_PAID_HOLIDAY_TYPE_STANDARDSDAY) {
			// 基準日
			int pointMonth = paidHolidayDto.getPointDateMonth();
			int pointDay = paidHolidayDto.getPointDateDay();
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null) {
				// 初年度付与マスタが存在する場合
				int amount = paidHolidayFirstYearDto.getGivingAmount();
				if (amount > 0) {
					// 付与日数が0より大きい場合
					// 初年度付与日取得(入社月の基準日から付与月を加算)
					firstYearGivingDate = DateUtility.addDay(DateUtility.addMonth(DateUtility
						.getFirstDateOfMonth(entranceDate), paidHolidayFirstYearDto.getGivingMonth()), pointDay - 1);
					// 仮付与日準備
					Date temporaryDate = DateUtility.addMonth(firstYearGivingDate, -paidHolidayDto.getScheduleGiving());
					// 締期間最終日及び仮付与日確認
					if (DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
						return null;
					} else if (cutoffLastDate.before(temporaryDate)) {
						dto.setActivateDate(firstYearGivingDate);
						dto.setAcquisitionDate(firstYearGivingDate);
						dto.setLimitDate(DateUtility.addDay(DateUtility.addMonth(firstYearGivingDate,
								paidHolidayFirstYearDto.getGivingLimit()), -1));
						dto.setHoldDay(amount);
						dto.setHoldHour(0);
						if (dto.getTemporaryFlag() == 1
								&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
							// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
							dto.setHoldDay(0);
							dto.setHoldHour(0);
						}
						return dto;
					}
				}
			}
			// 基準日準備
			Date pointDate = DateUtility.getDate(entranceYear, pointMonth, pointDay);
			if (!entranceDate.before(pointDate)) {
				// 入社日が基準日より前でない場合は基準日に1年を加算する
				pointDate = DateUtility.addYear(pointDate, 1);
			}
			// 初年度付与日確認
			if (firstYearGivingDate != null && !firstYearGivingDate.before(pointDate)) {
				// 初年度付与日が基準日より前でない場合は1年加算
				pointDate = DateUtility.addYear(pointDate, 1);
			}
			// 基準日経過回数準備
			int count = 2;
			// 基準日経過回数設定
			while (!pointDate.after(cutoffLastDate)) {
				// 基準日が締日より後でない場合は1年加算
				pointDate = DateUtility.addYear(pointDate, 1);
				count++;
			}
			// 仮付与日準備
			Date temporaryDate = DateUtility.addMonth(pointDate, -paidHolidayDto.getScheduleGiving());
			// 締期間最終日及び仮付与日確認
			if (cutoffLastDate.before(temporaryDate) && !DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
				dto.setActivateDate(pointDate);
				dto.setAcquisitionDate(pointDate);
				dto.setLimitDate(DateUtility.addDay(DateUtility.addYear(pointDate, limit), -1));
				dto.setHoldDay(paidHolidayDto.getGeneralPointAmount());
				// 基準日経過回数から有給休暇基準日管理情報を取得
				PaidHolidayPointDateDtoInterface paidHolidayPointDateDto = paidHolidayPointDao.findForKey(
						paidHolidayDto.getPaidHolidayCode(), paidHolidayDto.getActivateDate(), count);
				if (paidHolidayPointDateDto != null) {
					dto.setHoldDay(paidHolidayPointDateDto.getPointDateAmount());
				}
				dto.setHoldHour(0);
				if (dto.getTemporaryFlag() == 1
						&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
					// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
					dto.setHoldDay(0);
					dto.setHoldHour(0);
				}
				return dto;
			}
			return null;
		} else if (paidHolidayType == 1) {
			// 入社月
			// 対象個人ID及び対象日付で締日情報を取得し設定
			if (!hasCutoffSettings(personalId, cutoffLastDate)) {
				// 締日情報が取得できない場合
				return null;
			}
			Date pointDate = DateUtility.addDay(DateUtility.getLastDateOfMonth(entranceDate), 1);
			int cutoffDate = cutoffDto.getCutoffDate();
			if (cutoffDate != 0) {
				// 締日が末日でない場合
				pointDate = DateUtility.addDay(DateUtility.getDate(entranceYear, entranceMonth, cutoffDate), 1);
			}
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null) {
				// 初年度付与マスタが存在する場合
				int amount = paidHolidayFirstYearDto.getGivingAmount();
				if (amount > 0) {
					// 付与日数が0より大きい場合
					// 初年度付与日取得(入社月の締日の翌日から付与月を加算)
					firstYearGivingDate = DateUtility.addMonth(pointDate, paidHolidayFirstYearDto.getGivingMonth());
					// 仮付与日準備
					Date temporaryDate = DateUtility.addMonth(firstYearGivingDate, -paidHolidayDto.getScheduleGiving());
					// 締期間最終日及び仮付与日確認
					if (DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
						return null;
					} else if (cutoffLastDate.before(temporaryDate)) {
						dto.setActivateDate(firstYearGivingDate);
						dto.setAcquisitionDate(firstYearGivingDate);
						dto.setLimitDate(DateUtility.addDay(DateUtility.addMonth(firstYearGivingDate,
								paidHolidayFirstYearDto.getGivingLimit()), -1));
						dto.setHoldDay(amount);
						dto.setHoldHour(0);
						if (dto.getTemporaryFlag() == 1
								&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
							// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
							dto.setHoldDay(0);
							dto.setHoldHour(0);
						}
						return dto;
					}
				}
			}
			Date givingDate = null;
			Date maxDate = pointDate;
			Date maxTemporaryDate = null;
			int amount = 0;
			List<PaidHolidayEntranceDateDtoInterface> list = paidHolidayEntranceDateDao.findForList(paidHolidayDto
				.getPaidHolidayCode(), paidHolidayDto.getActivateDate());
			for (PaidHolidayEntranceDateDtoInterface paidHolidayEntranceDateDto : list) {
				Date workDate = DateUtility.addMonth(pointDate, paidHolidayEntranceDateDto.getWorkMonth());
				if (firstYearGivingDate != null && !firstYearGivingDate.before(workDate)) {
					continue;
				}
				if (maxDate.before(workDate)) {
					maxDate = workDate;
				}
				// 仮付与日準備
				Date temporaryDate = DateUtility.addMonth(workDate, -paidHolidayDto.getScheduleGiving());
				if (maxTemporaryDate == null || maxTemporaryDate.before(temporaryDate)) {
					maxTemporaryDate = temporaryDate;
				}
				// 締期間最終日及び仮付与日確認
				if (cutoffLastDate.before(temporaryDate)
						&& !DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
					if (givingDate == null || givingDate.after(workDate)) {
						givingDate = workDate;
						amount = paidHolidayEntranceDateDto.getJoiningDateAmount();
					}
				}
			}
			if (givingDate == null) {
				if (maxTemporaryDate != null && !DateUtility.addMonth(cutoffLastDate, 1).before(maxTemporaryDate)) {
					return null;
				}
				// 登録情報最大まで経過後
				int generalJoiningMonth = paidHolidayDto.getGeneralJoiningMonth();
				if (generalJoiningMonth == 0) {
					return null;
				}
				// 仮付与日準備
				Date temporaryDate = DateUtility.addMonth(maxDate, -paidHolidayDto.getScheduleGiving());
				// 締期間最終日及び仮付与日確認
				if (!temporaryDate.before(DateUtility.addMonth(cutoffLastDate, 1))) {
					return null;
				}
				while (!cutoffLastDate.before(temporaryDate)
						|| DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
					maxDate = DateUtility.addMonth(maxDate, generalJoiningMonth);
					temporaryDate = DateUtility.addMonth(maxDate, -paidHolidayDto.getScheduleGiving());
					if (!temporaryDate.before(DateUtility.addMonth(cutoffLastDate, 1))) {
						return null;
					}
				}
				dto.setActivateDate(maxDate);
				dto.setAcquisitionDate(maxDate);
				dto.setLimitDate(DateUtility.addDay(DateUtility.addYear(maxDate, limit), -1));
				dto.setHoldDay(paidHolidayDto.getGeneralJoiningAmount());
				dto.setHoldHour(0);
				if (dto.getTemporaryFlag() == 1
						&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
					// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
					dto.setHoldDay(0);
					dto.setHoldHour(0);
				}
				return dto;
			}
			dto.setActivateDate(givingDate);
			dto.setAcquisitionDate(givingDate);
			dto.setLimitDate(DateUtility.addDay(DateUtility.addYear(givingDate, limit), -1));
			dto.setHoldDay(amount);
			dto.setHoldHour(0);
			if (dto.getTemporaryFlag() == 1
					&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
				// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
				dto.setHoldDay(0);
				dto.setHoldHour(0);
			}
			return dto;
		} else if (paidHolidayType == 2) {
			// 入社日
			// 初年度付与日準備
			Date firstYearGivingDate = null;
			if (paidHolidayFirstYearDto != null) {
				// 初年度付与マスタが存在する場合
				int amount = paidHolidayFirstYearDto.getGivingAmount();
				if (amount > 0) {
					// 付与日数が0より大きい場合
					// 初年度付与日取得(入社日から付与月を加算)
					firstYearGivingDate = DateUtility.addMonth(entranceDate, paidHolidayFirstYearDto.getGivingMonth());
					// 仮付与日準備
					Date temporaryDate = DateUtility.addMonth(firstYearGivingDate, -paidHolidayDto.getScheduleGiving());
					// 締期間最終日及び仮付与日確認
					if (DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
						return null;
					} else if (cutoffLastDate.before(temporaryDate)) {
						dto.setActivateDate(firstYearGivingDate);
						dto.setAcquisitionDate(firstYearGivingDate);
						dto.setLimitDate(DateUtility.addDay(DateUtility.addMonth(firstYearGivingDate,
								paidHolidayFirstYearDto.getGivingLimit()), -1));
						dto.setHoldDay(amount);
						dto.setHoldHour(0);
						if (dto.getTemporaryFlag() == 1
								&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
							// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
							dto.setHoldDay(0);
							dto.setHoldHour(0);
						}
						return dto;
					}
				}
			}
			Date givingDate = null;
			Date maxDate = entranceDate;
			Date maxTemporaryDate = null;
			int amount = 0;
			List<PaidHolidayEntranceDateDtoInterface> list = paidHolidayEntranceDateDao.findForList(paidHolidayDto
				.getPaidHolidayCode(), paidHolidayDto.getActivateDate());
			for (PaidHolidayEntranceDateDtoInterface paidHolidayEntranceDateDto : list) {
				Date workDate = DateUtility.addMonth(entranceDate, paidHolidayEntranceDateDto.getWorkMonth());
				if (firstYearGivingDate != null && !firstYearGivingDate.before(workDate)) {
					continue;
				}
				if (maxDate.before(workDate)) {
					maxDate = workDate;
				}
				// 仮付与日準備
				Date temporaryDate = DateUtility.addMonth(workDate, -paidHolidayDto.getScheduleGiving());
				if (maxTemporaryDate == null || maxTemporaryDate.before(temporaryDate)) {
					maxTemporaryDate = temporaryDate;
				}
				// 締期間最終日及び仮付与日確認
				if (cutoffLastDate.before(temporaryDate)
						&& !DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
					if (givingDate == null || givingDate.after(workDate)) {
						givingDate = workDate;
						amount = paidHolidayEntranceDateDto.getJoiningDateAmount();
					}
				}
			}
			if (givingDate == null) {
				if (maxTemporaryDate != null && !DateUtility.addMonth(cutoffLastDate, 1).before(maxTemporaryDate)) {
					return null;
				}
				// 登録情報最大まで経過後
				int generalJoiningMonth = paidHolidayDto.getGeneralJoiningMonth();
				if (generalJoiningMonth == 0) {
					return null;
				}
				// 仮付与日準備
				Date temporaryDate = DateUtility.addMonth(maxDate, -paidHolidayDto.getScheduleGiving());
				// 締期間最終日及び仮付与日確認
				if (!temporaryDate.before(DateUtility.addMonth(cutoffLastDate, 1))) {
					return null;
				}
				while (!cutoffLastDate.before(temporaryDate)
						|| DateUtility.addMonth(cutoffLastDate, 1).before(temporaryDate)) {
					maxDate = DateUtility.addMonth(maxDate, generalJoiningMonth);
					temporaryDate = DateUtility.addMonth(maxDate, -paidHolidayDto.getScheduleGiving());
					if (!temporaryDate.before(DateUtility.addMonth(cutoffLastDate, 1))) {
						return null;
					}
				}
				dto.setActivateDate(maxDate);
				dto.setAcquisitionDate(maxDate);
				dto.setLimitDate(DateUtility.addDay(DateUtility.addYear(maxDate, limit), -1));
				dto.setHoldDay(paidHolidayDto.getGeneralJoiningAmount());
				dto.setHoldHour(0);
				if (dto.getTemporaryFlag() == 1
						&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
					// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
					dto.setHoldDay(0);
					dto.setHoldHour(0);
				}
				return dto;
			}
			dto.setActivateDate(givingDate);
			dto.setAcquisitionDate(givingDate);
			dto.setLimitDate(DateUtility.addDay(DateUtility.addYear(givingDate, limit), -1));
			dto.setHoldDay(amount);
			dto.setHoldHour(0);
			if (dto.getTemporaryFlag() == 1
					&& !isOverRatio(personalId, cutoffLastDate, calculationYear, calculationMonth)) {
				// 仮付与フラグが無効で且つ出勤率が下回っている場合は保有数に0をセットする
				dto.setHoldDay(0);
				dto.setHoldHour(0);
			}
			return dto;
		}
		return null;
	}
	
	@Override
	public PaidHolidayDataDtoInterface getNewPaidHolidayInfo(String personalId, int calculationYear,
			int calculationMonth) throws MospException {
		if (hasCutoffSettings(personalId, TimeUtility.getYearMonthTargetDate(calculationYear, calculationMonth,
				mospParams))) {
			return getNewPaidHolidayInfo(personalId, cutoffUtil.getCutoffLastDate(cutoffUtil.getCutoff(
					cutoffDto.getCutoffCode(), calculationYear, calculationMonth).getCutoffCode(), calculationYear,
					calculationMonth), calculationYear, calculationMonth);
		}
		return null;
	}
	
	/**
	 * 設定した出勤率以上かどうか判断。
	 * @param personalId 個人ID
	 * @param activateDate 有効日
	 * @param calculationYear 集計年
	 * @param calculationMonth 集計月
	 * @return 出勤率以上の場合はtrue、そうでない場合はfalse
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected boolean isOverRatio(String personalId, Date activateDate, int calculationYear, int calculationMonth)
			throws MospException {
		// 対象個人ID及び対象日付で有給休暇設定情報を取得し設定
		if (hasPaidHolidaySettings(personalId, activateDate) == false) {
			// 有給休暇情報が取得できない場合
			return false;
		}
		if (paidHolidayDto.getWorkRatio() == 0) {
			// 出勤率が0%の場合
			return true;
		}
		int achievement = 0;
		int totalWorkDate = 0;
		// 1年前の年月を取得
		int year = calculationYear - 1;
		int month = calculationMonth + 1;
		if (month == 13) {
			month = 1;
		}
		while (year * TimeConst.CODE_DEFINITION_YEAR + month <= calculationYear * TimeConst.CODE_DEFINITION_YEAR
				+ calculationMonth) {
			TotalTimeDataDtoInterface dto = totalTimeDataDao.findForKey(personalId, year, month);
			if (dto != null) {
				// 出勤実績日数を加算
				achievement += dto.getTimesAchievement();
				// 出勤対象日数を加算
				totalWorkDate += dto.getTimesTotalWorkDate();
			}
			month++;
			if (month == 13) {
				year++;
				month = 1;
			}
		}
		if (totalWorkDate == 0) {
			// 出勤対象日数が0の場合
			return false;
		}
		// 出勤率が0%でなく且つ出勤対象日数が0日でない場合
		double rate = (achievement * 100) / totalWorkDate;
		return rate >= paidHolidayDto.getWorkRatio();
	}
	
	/**
	 * 日数文字列を取得する。<br>
	 * 日数を文字列(小数点以下1桁)で表す。<br>
	 * @param days 対象日数
	 * @return 日数文字列
	 */
	protected String getStringDays(double days) {
		DecimalFormat df = new DecimalFormat("0.#");
		// 日付文字列取得
		return df.format(days);
	}
	
	/**
	 * 日名称を取得する。<br>
	 * @return 日名称
	 */
	protected String getDayNaming() {
		return mospParams.getName("Day");
	}
	
	/**
	 * 時間名称を取得する。<br>
	 * @return 時間名称
	 */
	protected String getTimeNaming() {
		return mospParams.getName("Time");
	}
	
}
