/*
 * 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 General Public License
 * as published by the Free Software Foundation; either version 2
 * 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
/**
 * 
 */
package jp.mosp.kintai.common.part;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import jp.mosp.common.CommonConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.common.part.PartInfo;
import jp.mosp.common.utils.DateUtil;
import jp.mosp.common.utils.NumberUtil;
import jp.mosp.common.utils.StringUtil;
import jp.mosp.common.utils.TimeUtil;
import jp.mosp.common.utils.VariousUtil;
import jp.mosp.kintai.payroll.dao.KdPaidHolidayDao;
import jp.mosp.kintai.payroll.dao.MYukyuDao;
import jp.mosp.kintai.payroll.dto.KdPaidHolidayDto;
import jp.mosp.kintai.payroll.dto.KintaiCompileDto;
import jp.mosp.kintai.payroll.dto.MYukyuDto;
import jp.mosp.kintai.workflow.dto.KtHolidayRequestDto;

/**
 * @author yoshida
 *
 */
public class PaidHolidayPart extends KintaiBasePart {
	
	/**
	 * 有休管理テーブル（旧）
	 */
	public static final String	OLD_TABLE				= MYukyuDao.TABLE;
	/**
	 * 有休管理テーブル（新）
	 */
	public static final String	NEW_TABLE				= KdPaidHolidayDao.TABLE;
	
	/**
	 * 前年度残日数
	 */
	public static final String	KEY_LAST_REMAIN_DAYS	= "keyLastRemainDays";
	/**
	 * 前年度残時間
	 */
	public static final String	KEY_LAST_REMAIN_HOUR	= "keyLastRemainHour";
	/**
	 * 今年度残日数
	 */
	public static final String	KEY_REMAIN_DAYS			= "keyRemainDays";
	/**
	 * 今年度残時間
	 */
	public static final String	KEY_REMAIN_HOUR			= "keyRemainHour";
	/**
	 * 時間単位で取得可能な日数
	 */
	public static final String	KEY_POSSIBLE			= "keyPossible";
	/**
	 * 支給日数
	 */
	public static final String	KEY_SUPPLY_DAYS			= "keySupplyDays";
	/**
	 * 支給時間
	 */
	public static final String	KEY_SUPPLY_HOUR			= "keySupplyHour";
	/**
	 * 廃棄日数
	 */
	public static final String	KEY_WASTE_DAYS			= "keyWasteDays";
	/**
	 * 廃棄時間
	 */
	public static final String	KEY_WASTE_HOUR			= "keyWasteHour";
	/**
	 * 利用日数
	 */
	public static final String	KEY_USE_DAYS			= "keyUseDays";
	/**
	 * 利用時間
	 */
	public static final String	KEY_USE_HOUR			= "keyUseHour";
	/**
	 * 時間単位で取得可能な最大日数（5日）
	 */
	public static final int		MAX_POSSIBLE_DAYS		= 5;
	

	/**
	 * コンストラクタ
	 */
	public PaidHolidayPart() {
		super();
	}
	
	/**
	 * コンストラクタ
	 * @param partInfo Partを利用する際に必要な情報
	 */
	public PaidHolidayPart(PartInfo partInfo) {
		super(partInfo);
	}
	

	private MYukyuDao	yukyuDao;
	

	/**
	 * @return yukyuDao
	 * @throws MospException  	MosP例外処理が発生した場合
	 */
	public MYukyuDao getMYukyuDao() throws MospException {
		if (VariousUtil.isNull(yukyuDao)) {
			yukyuDao = (MYukyuDao)getPreparedDao(MYukyuDao.class.getCanonicalName());
		}
		return yukyuDao;
	}
	
	/**
	 * 有休情報（旧）
	 * @param kCode 社員コード(検索キー)
	 * @param targetDate 対象年月日(yyyyMMdd)
	 * @return	対象年月有休情報
	 * @throws SQLException SQL例外が発生した場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws MospException 	MosP例外処理が発生した場合
	 */
	public MYukyuDto getYukyuInfo(String kCode, String targetDate) throws SQLException, IllegalAccessException,
			NoSuchFieldException, MospException {
		return getMYukyuDao().findForKey(kCode, targetDate);
	}
	
	/**
	 * 有休情報（旧）
	 * @param kCode 社員コード(検索キー)
	 * @param targetDate 対象年月日(yyyyMMdd)
	 * @return	対象年月有休情報
	 * @throws SQLException SQL例外が発生した場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws MospException 	MosP例外処理が発生した場合
	 */
	public MYukyuDto getYukyuInfo(String kCode, int targetDate) throws SQLException, IllegalAccessException,
			NoSuchFieldException, MospException {
		return getMYukyuDao().findForKey(kCode, targetDate);
	}
	
	/**
	 * 有休情報（旧）
	 * @param kCode 社員コード(検索キー)
	 * @param targetDate 対象年月日
	 * @return	対象年月有休情報
	 * @throws SQLException SQL例外が発生した場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws MospException 	MosP例外処理が発生した場合
	 */
	public MYukyuDto getYukyuInfo(String kCode, Date targetDate) throws SQLException, IllegalAccessException,
			NoSuchFieldException, MospException {
		return getYukyuInfo(kCode, DateUtil.convDateToString(targetDate));
	}
	
	/**
	 * 有休情報（旧）
	 * @param kCode 対象社員コード
	 * @param startDate 対象年月開始日
	 * @param endDate 対象年月終了日
	 * @return 対象年月有休情報
	 * @throws Exception 例外処理が発生した場合
	 */
	public MYukyuDto getTargetMonthYukyuInfo(String kCode, Date startDate, Date endDate) throws Exception {
		return getMYukyuDao().findForPeriod(kCode, DateUtil.convDateToInteger(startDate),
				DateUtil.convDateToInteger(endDate));
	}
	
	/**
	 * 有休情報（旧）
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月
	 * @return 対象年月に一番近い有休情報
	 * @throws SQLException SQL例外が発生した場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws MospException 	MosP例外処理が発生した場合
	 */
	public MYukyuDto getNearlyYukyuInfo(String kCode, Date targetDate) throws SQLException, IllegalAccessException,
			NoSuchFieldException, MospException {
		return getMYukyuDao().findForDateNearly(kCode, DateUtil.convDateToInteger(targetDate));
	}
	
	/**
	 * 有休繰越処理（旧）
	 * @param lastRemainDays	前年度残日数
	 * @param remainDays		今年度残日数
	 * @param useDays			消化日数
	 * @param supply			支給日数
	 * @param isCarryForward	繰越処理判断
	 * @return	繰越処理結果マップ
	 * @throws Exception 例外処理が発生した場合
	 */
	public Map<String, Double> getOldCarryForwardInfo(double lastRemainDays, double remainDays, double useDays,
			int supply, boolean isCarryForward) throws Exception {
		// 当月残日数（前年度分）
		double dLastRemainDays = lastRemainDays;
		// 当月残日数（当年度分）
		double dRemainDays = remainDays;
		// 使用日数
		double use = useDays;
		// 破棄日数
		double waste = 0;
		// 来月有休予定数（前年度分）
		double carryLastRemainDays = 0;
		// 来月有休予定数（当年度分）
		double carryRemainDays = 0;
		if (isCarryForward) {
			// 繰越区分
			String carriedForwardType = part().mospcode().getCarriedForwardType();
			// 繰り越し区分判別
			// 当年のみ
			if (StringUtil.isFlagOff(carriedForwardType)) {
				// 廃棄更新
				// 前々年度分を消化数を引いた分破棄。
				if (dLastRemainDays < use) {
					use = Math.abs(dLastRemainDays - use);
					waste = 0;
				} else {
					waste = dLastRemainDays - use;
					use = 0;
				}
				// 前月前年度分を当月前年度分に移動。
				carryLastRemainDays = dRemainDays;
			} else if (StringUtil.isFlagOn(carriedForwardType)) {
				// 合計で繰り越し
				// 繰越日数
				int carriedForwardDays = part().mospcode().getCarriedForwardDays();
				// 前月分を合計して繰越日数分だけ繰り越す。
				if ((dLastRemainDays + dRemainDays) >= carriedForwardDays) {
					waste = (dLastRemainDays + dRemainDays) - carriedForwardDays;
				} else {
					waste = 0;
				}
				carryLastRemainDays = dLastRemainDays + dRemainDays - waste;
			}
			carryRemainDays += supply;
			// 有給更新
			if (use <= carryLastRemainDays) {
				carryLastRemainDays -= use;
			} else {
				// 当月消化分
				use -= carryLastRemainDays;
				carryLastRemainDays = 0;
				carryRemainDays -= use;
			}
		} else {
			// 有給取得更新
			carryRemainDays = dRemainDays;
			carryLastRemainDays = dLastRemainDays;
			// 有給更新
			if (use <= carryLastRemainDays) {
				carryLastRemainDays -= use;
			} else {
				// 当月消化分
				use -= carryLastRemainDays;
				carryLastRemainDays = 0;
				carryRemainDays -= use;
			}
		}
		return createRemainMap(carryLastRemainDays, 0, carryRemainDays, 0, 0, Double.valueOf(supply), 0, Double
			.valueOf(waste), 0, use, 0);
	}
	
	/**
	 * 旧テーブル情報にMAPの情報をセットする。
	 * <p>
	 * 利用日数、付与日数、廃棄日数、今年度残日数、前年度残日数をセットする。
	 * </p>
	 * @param dto 対象DTO
	 * @param map 対象MAP
	 */
	public static void setMapInfoToOldInfo(MYukyuDto dto, Map<String, Double> map) {
		if (VariousUtil.isNotNull(dto)) {
			dto.setSyoka(getMapUseDays(map));
			dto.setSyutoku(Double.valueOf(getMapSupplyDays(map)).intValue());
			dto.setHaiki(getMapWasteDays(map));
			dto.setTZanT(getMapRemainDays(map));
			dto.setTZanZ(getMapLastRemainDays(map));
		}
	}
	
	/**
	 * 旧テーブルをMAPの情報に変換して取得。
	 * @param dto 対象DTO
	 * @param prescribedHour 所定労働時間
	 * @return  対象MAP
	 */
	public static Map<String, Double> convOldInfoToMap(MYukyuDto dto, int prescribedHour) {
		if (VariousUtil.isNotNull(dto)) {
			return createRemainMap(dto.getTZanZ(), 0, dto.getTZanT(), 0, MAX_POSSIBLE_DAYS * prescribedHour, dto
				.getSyutoku(), 0, dto.getHaiki(), 0, dto.getSyoka(), 0);
		}
		return null;
	}
	
	/**
	 * 有給休暇情報リスト取得
	 * @param kCode			対象社員コード
	 * @param startDate		開始年月日
	 * @param endDate		終了年月日
	 * @return	検索結果(DTOのList)
	 * @throws Exception	例外処理が発生した場合
	 */
	public List<MYukyuDto> getOldYukyuInfoList(String kCode, Date startDate, Date endDate) throws Exception {
		return getMYukyuDao().findForCondition(kCode, DateUtil.convDateToInteger(startDate),
				DateUtil.convDateToInteger(endDate));
	}
	

	/* 改正労働基準法用新テーブル */

	private KdPaidHolidayDao	paidHolidayDao;
	

	/**
	 * @return KdPaidHolidayDaoインスタンス。
	 * @throws MospException  	MosP例外処理が発生した場合
	 */
	public KdPaidHolidayDao getPaidHolidayDao() throws MospException {
		if (VariousUtil.isNull(paidHolidayDao)) {
			paidHolidayDao = (KdPaidHolidayDao)getPreparedDao(KdPaidHolidayDao.class.getCanonicalName());
		}
		return paidHolidayDao;
	}
	
	/**
	 * @param kCode 社員コード
	 * @param targetDate 対象年月日
	 * @param processType 処理コード
	 * @return 対象年月日の有休管理情報（新）
	 * @throws SQLException SQL例外が発生した場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws MospException  	MosP例外処理が発生した場合
	 */
	public KdPaidHolidayDto getPaidHolidayInfo(String kCode, Date targetDate, String processType) throws SQLException,
			IllegalAccessException, NoSuchFieldException, MospException {
		return getPaidHolidayDao().findForProcess(kCode, processType, targetDate);
	}
	
	/**
	 * @param kCode  社員コード
	 * @param targetDate  対象年月日
	 * @param processType 処理コード
	 * @return  対象年月日に最も近い有休管理情報（新）
	 * @throws MospException  	MosP例外処理が発生した場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws SQLException  SQL例外が発生した場合
	 * 
	 */
	public KdPaidHolidayDto getNearlyPaidHolidayInfo(String kCode, Date targetDate, String processType)
			throws SQLException, IllegalAccessException, NoSuchFieldException, MospException {
		return getPaidHolidayDao().findForProcessNearlyDate(kCode, processType, targetDate);
	}
	
	/**
	 * 残日数・残時間の計算。
	 * @param inputDays 		利用日数
	 * @param inputHour 		利用時間
	 * @param lastRemainDays 	前年度残日数
	 * @param lastRemainHour 	前年度残時間
	 * @param remainDays 		今年度残日数
	 * @param remainHour 		今年度残時間
	 * @param possible 			時間単位で取得可能な日数
	 * @param prescribedTime 	所定労働時間（分）
	 * @return 有休残日数・残時間情報（新）
	 */
	public static Map<String, Double> calcRemain(double inputDays, int inputHour, double lastRemainDays,
			int lastRemainHour, double remainDays, int remainHour, int possible, int prescribedTime) {
		int iInputHour = inputHour;
		double dLastRemainDays = lastRemainDays;
		int iLastRemainHour = lastRemainHour;
		double dRemainDays = remainDays;
		int iRemainHour = remainHour;
		int iPossible = possible;
		final int iPrescribedHour = Double.valueOf(Math.ceil(TimeUtil.convMinutesToDoubleHour(prescribedTime)))
			.intValue();
		// 一日
		double inputAll = Double.valueOf(inputDays).intValue();
		if (dLastRemainDays > 0) {
			if (inputAll > 0) {
				double tmpRemainDay = dLastRemainDays - inputAll;
				if (tmpRemainDay <= 0) {
					dLastRemainDays = 0;
					dRemainDays -= Math.abs(tmpRemainDay);
				} else {
					dLastRemainDays -= inputAll;
				}
			}
		} else {
			dRemainDays -= inputAll;
		}
		// 半日
		double inputHalf = inputDays % 1;
		if (inputHalf > 0) {
			if (dLastRemainDays > 0) {
				dLastRemainDays -= inputHalf;
			} else {
				dRemainDays -= inputHalf;
			}
		}
		// 時間単位
		if (inputHour > 0) {
			// 前年度残日数の一日の日数
			int iLastRemainDays = Double.valueOf(dLastRemainDays).intValue();
			// 所定労働時間の回数（1以上）
			int numPrescribed = Double.valueOf(Math.ceil(iInputHour / Double.valueOf(iPrescribedHour))).intValue();
			// 前年度残日数を超える日数
			int overLastRemainDays = iLastRemainDays - numPrescribed;
			int absOverLastRemainDays = Math.abs(overLastRemainDays);
			// 前年度残時間を超える時間。
			int overLastRemainHour = iLastRemainHour - iInputHour;
			// 利用可能時間数から利用時間を控除。
			iPossible -= inputHour;
			// 前年度残時間がある場合
			if (iLastRemainHour > 0) {
				// 前年度残時間を使い切る場合
				if (overLastRemainHour < 0) {
					// 前年度残日数を超える場合
					if (overLastRemainDays <= 0) {
						// 前年度残日数がある場合
						if (dLastRemainDays > 0) {
							dLastRemainDays = 0;
							iLastRemainHour += iLastRemainDays * iPrescribedHour;
							int tmpLastRemainHour = iLastRemainHour - iInputHour;
							if (tmpLastRemainHour < 0) {
								iLastRemainHour = 0;
								iInputHour = Math.abs(tmpLastRemainHour);
							} else {
								iLastRemainHour -= iInputHour;
								iInputHour = 0;
							}
							if (iInputHour > 0) {
								dRemainDays -= absOverLastRemainDays;
								iRemainHour += absOverLastRemainDays * iPrescribedHour;
								iRemainHour -= iInputHour;
							}
						} else {
							// 前年度残日数がない場合
							// 前年度残日数からまず控除
							iLastRemainHour = 0;
							iInputHour = Math.abs(overLastRemainHour);
							if (numPrescribed > 1) {
								numPrescribed--;
							}
							if (iInputHour > 0) {
								dRemainDays -= numPrescribed;
								iRemainHour += numPrescribed * iPrescribedHour;
								iRemainHour -= iInputHour;
							}
						}
					} else {
						// 前年度残日数がある場合
						if (dLastRemainDays > 0) {
							dLastRemainDays -= numPrescribed;
							iLastRemainHour += numPrescribed * iPrescribedHour;
							iLastRemainHour -= iInputHour;
						} else {
							iLastRemainHour = 0;
							iInputHour = Math.abs(overLastRemainHour);
							dRemainDays--;
							iRemainHour += iPrescribedHour;
							iRemainHour -= iInputHour;
						}
					}
				} else {
					iLastRemainHour -= iInputHour;
				}
			} else {
				if (dLastRemainDays > 0) {
					// 前年度残日数が残っている場合
					if (overLastRemainDays < 0) {
						// 前年度分を超過する場合
						dLastRemainDays = 0;
						iLastRemainHour += iLastRemainDays * iPrescribedHour;
						int tmpLastRemainHour = iLastRemainHour - iInputHour;
						if (tmpLastRemainHour < 0) {
							iLastRemainHour = 0;
							iInputHour = Math.abs(tmpLastRemainHour);
						} else {
							iLastRemainHour -= iInputHour;
							iInputHour = 0;
						}
						if (iInputHour > 0) {
							dRemainDays -= absOverLastRemainDays;
							iRemainHour += absOverLastRemainDays * iPrescribedHour;
							iRemainHour -= iInputHour;
						}
					} else {
						dLastRemainDays -= numPrescribed;
						
						iLastRemainHour += numPrescribed * iPrescribedHour;
						iLastRemainHour -= iInputHour;
					}
				} else {
					int numInputDays = iInputHour / iPrescribedHour;
					int numInputHour = iInputHour % iPrescribedHour;
					int overRemainHour = iRemainHour - iInputHour;
//					int absOverRemainHour = Math.abs(overRemainHour);
					if (overRemainHour < 0) {
//						if (numInputDays > 0 && numInputHour > 0 || numInputHour >= absOverRemainHour) {
//							numInputDays++;
//						}
//						if (iRemainHour - numInputHour > 0) {
//							numInputDays--;
//						}
						if (iRemainHour - numInputHour < 0) {
							numInputDays++;
						}
						dRemainDays -= numInputDays;
						iRemainHour += numInputDays * iPrescribedHour;
						iRemainHour -= iInputHour;
					} else {
						iRemainHour -= iInputHour;
					}
				}
			}
		}
		return createRemainMap(dLastRemainDays, iLastRemainHour, dRemainDays, iRemainHour, iPossible, 0d, 0, 0d, 0,
				inputDays, inputHour);
	}
	
	/**
	 * 残日数・残時間の計算。
	 * @param inputDays 		利用日数
	 * @param inputHour 		利用時間
	 * @param map 有休残日数・残時間情報（新）
	 * @param prescribedTime 	所定労働時間（分）
	 * @return 有休残日数・残時間情報（新）
	 */
	public static Map<String, Double> calcRemainMap(double inputDays, int inputHour, Map<String, Double> map,
			int prescribedTime) {
		return calcRemain(inputDays, inputHour, getMapLastRemainDays(map), getMapLastRemainHour(map),
				getMapRemainDays(map), getMapRemainHour(map), getMapPossible(map), prescribedTime);
	}
	
	/**
	 * 繰越処理（新）
	 * @param lastRemainDays 	前年度残日数
	 * @param lastRemainHour 	前年度残時間
	 * @param remainDays 		今年度残日数
	 * @param remainHour 		今年度残時間
	 * @param supplyDays 支給日数
	 * @param prescribedTime 所定労働時間(分)
	 * @return	繰越処理後有休残日数・残時間情報（新）
	 * @throws Exception 例外処理が発生した場合
	 */
	public Map<String, Double> carryForward(double lastRemainDays, int lastRemainHour, double remainDays,
			int remainHour, int supplyDays, int prescribedTime) throws Exception {
		// 今月残日数（前年度）
		double dLastRemainDays = lastRemainDays;
		// 今月残時間（前年度）
		int iLastRemainHour = lastRemainHour;
		// 今月残日数（今年度）
		double dRemainDays = remainDays;
		// 今月残時間（今年度）
		int iRemainHour = remainHour;
		// 廃棄日数
		double wasteDays = 0;
		// 廃棄時間
		int wasteHour = 0;
		// 来月有休予定数（前年度分）
		double carryLastRemainDays = 0;
		// 来月残時間（前年度分）
		int carryLastRemainHour = 0;
		// 繰越区分
		String carriedForwardType = part().mospcode().getCarriedForwardType();
		// 所定労働時間(時間)
		int prescribedHour = getPrescribedHour(prescribedTime);
		// 繰り越し区分判別
		// 当年のみ
		if (StringUtil.isFlagOff(carriedForwardType)) {
			// 廃棄更新
			wasteDays = dLastRemainDays;
			wasteHour = iLastRemainHour;
			dLastRemainDays = 0;
			iLastRemainHour = 0;
			// 今年度分を前年度分に移動。
			carryLastRemainDays = dRemainDays;
			carryLastRemainHour = iRemainHour;
		} else if (StringUtil.isFlagOn(carriedForwardType)) {
			// 合計で繰り越し
			// 繰越日数
			int carriedForwardDays = part().mospcode().getCarriedForwardDays();
			int cfLastRemain = 0;
			int cfRemainHour = 0;
			// 前年度残時間
			if (iLastRemainHour > 0) {
				cfLastRemain++;
			}
			// 前年度残半日
			if (dLastRemainDays % 1 > 0) {
				cfLastRemain++;
			}
			// 今年度残時間
			if (iRemainHour > 0) {
				cfRemainHour++;
			}
			// 半日、残時間を含めた合計日数
			double totalDays = dLastRemainDays + dRemainDays + cfLastRemain + cfRemainHour;
			double totalWaste = totalDays - carriedForwardDays;
			if (totalWaste < 0) {
				totalWaste = 0;
			}
			// 前月分を合計して繰越日数分だけ繰り越す。
			wasteDays = dLastRemainDays + dRemainDays - carriedForwardDays;
			if (wasteDays < 0) {
				wasteDays = 0;
			}
			// 残日数の繰越
			if (totalWaste == 0) {
				carryLastRemainDays = dLastRemainDays + dRemainDays;
				carryLastRemainHour = iLastRemainHour + iRemainHour;
			} else {
				carryLastRemainDays = dLastRemainDays + dRemainDays - wasteDays;
				if (cfLastRemain > 0) {
					if (dRemainDays >= carriedForwardDays || cfLastRemain > 1) {
						wasteHour += iLastRemainHour;
					}
					if (cfRemainHour > 0) {
						wasteDays += CommonConst.NUM_HALF_DAY;
						carryLastRemainDays -= CommonConst.NUM_HALF_DAY;
						carryLastRemainHour = iRemainHour;
					}
				}
			}
		}
		// 時間単位の可能日数の設定
		// 上限日数
		int iPossible = MAX_POSSIBLE_DAYS * prescribedHour;
		return createRemainMap(carryLastRemainDays, carryLastRemainHour, supplyDays, 0, iPossible, supplyDays, 0,
				wasteDays, wasteHour, 0, 0);
	}
	
	/**
	 * 支給用DTOの生成
	 * @param kCode 対象社員コード
	 * @param supplyDate 対象支給年月日
	 * @param supplyLastDay 前年度支給日数
	 * @param supplyLastHour 前年度支給時間
	 * @param supplyDay 今年度支給日数
	 * @param supplyHour 今年度支給時間
	 * @return 支給用DTO
	 */
	public static KdPaidHolidayDto createSupplyDto(String kCode, Date supplyDate, double supplyLastDay,
			int supplyLastHour, double supplyDay, int supplyHour) {
		KdPaidHolidayDto dto = new KdPaidHolidayDto();
		dto.setKCode(kCode);
		dto.setProcessType(CommonConst.CODE_PROCESS_SUPPLY);
		dto.setProcessDate(supplyDate);
		dto.setLastRemainDays(supplyLastDay);
		dto.setLastRemainHour(supplyLastHour);
		dto.setRemainDays(supplyDay);
		dto.setRemainHour(supplyHour);
		return dto;
	}
	
	/**
	 * 廃棄用DTOの生成
	 * @param kCode 対象社員コード
	 * @param wasteDate 対象廃棄年月日
	 * @param wasteLastDay 前年度廃棄日数
	 * @param wasteLastHour 前年度廃棄時間
	 * @param wasteDay 今年度廃棄日数
	 * @param wasteHour 今年度廃棄時間
	 * @return 廃棄用DTO
	 */
	public static KdPaidHolidayDto createWasteDto(String kCode, Date wasteDate, double wasteLastDay, int wasteLastHour,
			double wasteDay, int wasteHour) {
		KdPaidHolidayDto dto = new KdPaidHolidayDto();
		dto.setKCode(kCode);
		dto.setProcessType(CommonConst.CODE_PROCESS_WASTE);
		dto.setProcessDate(wasteDate);
		dto.setLastRemainDays(wasteLastDay);
		dto.setLastRemainHour(wasteLastHour);
		dto.setRemainDays(wasteDay);
		dto.setRemainHour(wasteHour);
		return dto;
	}
	
	/**
	 * 月次処理用DTOの生成
	 * @param kCode 対象社員コード
	 * @param processDate 対象年月日
	 * @param map 残日数・残時間情報
	 * @return 月次処理用DTO
	 */
	public static KdPaidHolidayDto createMonthlyDto(String kCode, Date processDate, Map<String, Double> map) {
		KdPaidHolidayDto dto = new KdPaidHolidayDto();
		dto.setKCode(kCode);
		dto.setProcessDate(processDate);
		dto.setProcessType(CommonConst.CODE_PROCESS_MONTHLY);
		setMapInfoToNewInfo(dto, map);
		return dto;
	}
	
	/**
	 * 対象期間の残日数、残時間情報取得
	 * @param kCode 対象社員コード
	 * @param startDate 対象期間開始日
	 * @param endDate 対象期間終了日
	 * @return 対象期間の残日数、残時間情報
	 * @throws Exception 例外処理が発生した場合
	 */
	public Map<String, Double> getAvairablePaidHolidayMap(String kCode, Date startDate, Date endDate) throws Exception {
		return getAvairablePaidHolidayMap(kCode, startDate, endDate, getPeriodRemainInfoMap(kCode, startDate, endDate));
	}
	
	/**
	 * 対象期間の残日数、残時間情報取得
	 * @param kCode 対象社員コード
	 * @param startDate 休暇申請対象期間開始日
	 * @param endDate 休暇申請対象期間終了日
	 * @param map 対象期間残日数
	 * @return 対象期間の残日数、残時間情報
	 * @throws Exception 例外処理が発生した場合
	 */
	public Map<String, Double> getAvairablePaidHolidayMap(String kCode, Date startDate, Date endDate,
			Map<String, Double> map) throws Exception {
		// 残日数、残時間
		double lastRemainDays = getMapLastRemainDays(map);
		int lastRemainHour = getMapLastRemainHour(map);
		double remainDays = getMapRemainDays(map);
		int remainHour = getMapRemainHour(map);
		int possible = getMapPossible(map);
		// 付与
		double totalSupplyDays = getMapSupplyDays(map);
		int totalSupplyHour = getMapSupplyHour(map);
		// 控除
		double totaolWasteDays = getMapWasteDays(map);
		int totalWasteHour = getMapWasteHour(map);
		double useDays = 0;
		int useHour = 0;
		// 勤怠承認機能を利用する場合
		if (part().mospcode().isAttendanceApprovalFunction()) {
			// 今月の承認済み有休申請情報を取得
			List<KtHolidayRequestDto> requestList = part().holidayRequest().getApprovedPaidHolidayRequestList(kCode,
					startDate, endDate);
			for (KtHolidayRequestDto requestDto : requestList) {
				double inputDays = 0;
				int inputHour = 0;
				if (HolidayRequestPart.isPaidHolidayAll(requestDto)) {
					inputDays++;
				}
				if (HolidayRequestPart.isPaidHolidayHalf(requestDto)) {
					inputDays += CommonConst.NUM_HALF_DAY;
				}
				if (HolidayRequestPart.isPaidHolidayTime(requestDto)) {
					inputHour += HolidayRequestPart.getHolidayTime(requestDto);
				}
				useDays += inputDays;
				useHour += inputHour;
			}
		} else {
			// 承認機能を利用しない場合
			KintaiCompileDto compileDto = part().compile().getCompileInfo(kCode,
					part().calculate().getCalcAttendanceMonth(endDate));
			useDays = compileDto.getTotalPaidHoliday();
		}
		// 所定労働時間
		int prescribedTime = part().laborAgreement().getPrescribedTime(kCode, startDate);
		Map<String, Double> retMap = calcRemain(useDays, useHour, lastRemainDays, lastRemainHour, remainDays,
				remainHour, possible, prescribedTime);
		lastRemainDays = getMapLastRemainDays(retMap);
		lastRemainHour = getMapLastRemainHour(retMap);
		remainDays = getMapRemainDays(retMap);
		remainHour = getMapRemainHour(retMap);
		possible = getMapPossible(retMap);
		return createRemainMap(lastRemainDays, lastRemainHour, remainDays, remainHour, possible, totalSupplyDays,
				totalSupplyHour, totaolWasteDays, totalWasteHour, useDays, useHour);
	}
	
	/**
	 * 対象期間の残日数、残時間情報
	 * @param kCode 対象社員コード
	 * @param startDate 対象期間開始年月日
	 * @param endDate 対象期間終了年月日
	 * @return 対象期間の残日数、残時間情報
	 * @throws Exception 例外処理が発生した場合
	 */
	public Map<String, Double> getPeriodRemainInfoMap(String kCode, Date startDate, Date endDate) throws Exception {
		// 今月分の情報を取得
		KdPaidHolidayDto dto = getPaidHolidayInfo(kCode, startDate, CommonConst.CODE_PROCESS_MONTHLY);
		if (VariousUtil.isNull(dto)) {
			// 今月分が無い場合、一番近い有休情報を取得する。
			dto = getNearlyPaidHolidayInfo(kCode, startDate, CommonConst.CODE_PROCESS_MONTHLY);
		}
		// 旧テーブルの情報を取得
		if (VariousUtil.isNull(dto)) {
			dto = new KdPaidHolidayDto();
			setMapInfoToNewInfo(dto, convOldInfoToMap(getNearlyYukyuInfo(kCode, startDate), getPrescribedHour(part()
				.laborAgreement().getPrescribedTime(kCode, startDate))));
		}
		return getRemainInfoMap(dto, startDate, endDate);
	}
	
	/**
	 * 対象年月の残日数、残時間情報取得
	 * @param kCode 対象社員コード
	 * @param targetYear 対象年
	 * @param targetMonth 対象月
	 * @return 対象年月の残日数、残時間情報
	 * @throws Exception 例外処理が発生した場合
	 */
	public Map<String, Double> getAvairablePaidHolidayMap(String kCode, int targetYear, int targetMonth)
			throws Exception {
		// 有給休暇支給月
		int carryForwardMonth = 0;
		if (part().mospcode().useProvideEmployMonth()) {
			// 対象社員の入社月をセット。
			carryForwardMonth = MospUtility.getMonth(part().human().getEmployDate(kCode));
		} else {
			// 繰越月をセット。
			carryForwardMonth = part().mospcode().getCarriedForwardMonth();
		}
		// 繰越年月
		Date carryForward = DateUtil.getYearMonth(targetYear, carryForwardMonth);
		// 開始年月日
		Date startDate = part().calculate().getStartDate(carryForward);
		// 終了年月日
		Date endDate = DateUtil.addDay(DateUtil.addYear(startDate, 1), -1);
		KdPaidHolidayDto carryDto;
		if (targetMonth == 0) {
			// 支給月の情報を取得
			carryDto = getPaidHolidayInfo(kCode, startDate, CommonConst.CODE_PROCESS_MONTHLY);
			if (VariousUtil.isNull(carryDto)) {
				// 支給月が無い場合、支給月に一番近い新テーブルの情報を取得する。
				carryDto = getNearlyPaidHolidayInfo(kCode, startDate, CommonConst.CODE_PROCESS_MONTHLY);
				if (VariousUtil.isNotNull(carryDto)) {
					// 終了日を繰越の開始日前日までにする。
					endDate = DateUtil.addDay(startDate, -1);
					startDate = carryDto.getProcessDate();
				}
			}
			// それでも無い場合、旧テーブルの情報を取得。
			if (VariousUtil.isNull(carryDto)) {
				MYukyuDto yukyuDto = getTargetMonthYukyuInfo(kCode, startDate, endDate);
				if (VariousUtil.isNotNull(yukyuDto)) {
					startDate = part().calculate().getStartDate(DateUtil.convIntegerDateToDate(yukyuDto.getKyuyoYMD()));
				}
				carryDto = new KdPaidHolidayDto();
				setMapInfoToNewInfo(carryDto, convOldInfoToMap(yukyuDto, getPrescribedHour(part().laborAgreement()
					.getPrescribedTime(kCode, startDate))));
			}
		} else {
			Date yearMonth = DateUtil.getYearMonth(targetYear, targetMonth);
			startDate = part().calculate().getStartDate(yearMonth);
			endDate = part().calculate().getEndDate(yearMonth);
			// 今月の情報を取得
			carryDto = getPaidHolidayInfo(kCode, startDate, CommonConst.CODE_PROCESS_MONTHLY);
			if (VariousUtil.isNull(carryDto)) {
				// 今月の情報が無い場合、今月に一番近い新テーブルの情報を取得する。
				carryDto = getNearlyPaidHolidayInfo(kCode, startDate, CommonConst.CODE_PROCESS_MONTHLY);
				if (VariousUtil.isNotNull(carryDto)) {
					startDate = carryDto.getProcessDate();
				}
			}
			// それでも無い場合、旧テーブルの情報を取得。
			if (VariousUtil.isNull(carryDto)) {
				// 1ヶ月前の給与支給日
				Date oneMonthBeforeCalcPayment = part().calculate().getCalcPayment(DateUtil.addMonth(yearMonth, -1));
				MYukyuDto yukyuDto = getTargetMonthYukyuInfo(kCode, DateUtil
					.getFirstDateOfMonth(oneMonthBeforeCalcPayment), DateUtil
					.getLastDateOfMonth(oneMonthBeforeCalcPayment));
				carryDto = new KdPaidHolidayDto();
				setMapInfoToNewInfo(carryDto, convOldInfoToMap(yukyuDto, getPrescribedHour(part().laborAgreement()
					.getPrescribedTime(kCode, startDate))));
			}
		}
		return getAvairablePaidHolidayMap(kCode, startDate, endDate, getRemainInfoMap(carryDto, startDate, endDate));
	}
	
	/**
	 * 対象期間の残日数、残時間情報
	 * @param dto 対象DTO
	 * @param startDate 対象期間開始年月日
	 * @param endDate 対象期間終了年月日
	 * @return 対象期間の残日数、残時間情報
	 * @throws SQLException SQL例外が発生した場合
	 * @throws IllegalAccessException	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException	フィールドが見つからなかった場合
	 * @throws MospException	MosP例外処理が発生した場合
	 */
	public Map<String, Double> getRemainInfoMap(KdPaidHolidayDto dto, Date startDate, Date endDate)
			throws SQLException, IllegalAccessException, NoSuchFieldException, MospException {
		// 残日数、残時間
		double lastRemainDays = 0;
		int lastRemainHour = 0;
		double remainDays = 0;
		int remainHour = 0;
		int possible = 0;
		// 付与情報
		double supplyLastDay = 0;
		int supplyLastHour = 0;
		double supplyDay = 0;
		int supplyHour = 0;
		int supplyPossible = 0;
		// 控除情報
		double wasteLastDay = 0;
		int wasteLastHour = 0;
		double wasteDay = 0;
		int wasteHour = 0;
		int wastePossible = 0;
		// 合計
		double totalSupplyDays = 0;
		int totalSupplyHour = 0;
		double totaolWasteDays = 0;
		int totalWasteHour = 0;
		int totalPossible = 0;
		if (VariousUtil.isNotNull(dto)) {
			String kCode = dto.getKCode();
			lastRemainDays = dto.getLastRemainDays();
			lastRemainHour = dto.getLastRemainHour();
			remainDays = dto.getRemainDays();
			remainHour = dto.getRemainHour();
			possible = dto.getPossible();
			// 今月の付与情報を取得
			List<KdPaidHolidayDto> supplyList = getSupplyList(kCode, startDate, endDate);
			for (KdPaidHolidayDto supplyDto : supplyList) {
				supplyLastDay += supplyDto.getLastRemainDays();
				supplyLastHour += supplyDto.getLastRemainHour();
				supplyDay += supplyDto.getRemainDays();
				supplyHour += supplyDto.getRemainHour();
				supplyPossible += supplyDto.getPossible();
			}
			// 今月の控除情報を取得
			List<KdPaidHolidayDto> wasteList = getWasteList(kCode, startDate, endDate);
			for (KdPaidHolidayDto wasteDto : wasteList) {
				wasteLastDay += wasteDto.getLastRemainDays();
				wasteLastHour += wasteDto.getLastRemainHour();
				wasteDay += wasteDto.getRemainDays();
				wasteHour += wasteDto.getRemainHour();
				wastePossible += wasteDto.getPossible();
			}
			// 合計残日数、残時間
			lastRemainDays = lastRemainDays + supplyLastDay - wasteLastDay;
			lastRemainHour = lastRemainHour + supplyLastHour - wasteLastHour;
			remainDays = remainDays + supplyDay - wasteDay;
			remainHour = remainHour + supplyHour - wasteHour;
			totalSupplyDays = supplyLastDay + supplyDay;
			totalSupplyHour = supplyLastHour + supplyHour;
			totaolWasteDays = wasteLastDay + wasteDay;
			totalWasteHour = wasteLastHour + wasteHour;
			totalPossible = possible + supplyPossible - wastePossible;
		}
		return createRemainMap(lastRemainDays, lastRemainHour, remainDays, remainHour, totalPossible, totalSupplyDays,
				totalSupplyHour, totaolWasteDays, totalWasteHour, 0, 0);
	}
	
	/**
	 * 新テーブル情報にMAPの情報をセットする。
	 * <p>
	 * 前年度残日数、前年度残時間、今年度残日数、今年度残時間、時間単位年休利用可能日数をセットする。
	 * </p>
	 * @param dto 対象DTO
	 * @param map 対象MAP
	 */
	public static void setMapInfoToNewInfo(KdPaidHolidayDto dto, Map<String, Double> map) {
		if (VariousUtil.isNotNull(dto)) {
			dto.setLastRemainDays(getMapLastRemainDays(map));
			dto.setLastRemainHour(getMapLastRemainHour(map));
			dto.setRemainDays(getMapRemainDays(map));
			dto.setRemainHour(getMapRemainHour(map));
			dto.setPossible(getMapPossible(map));
		}
	}
	
	/**
	 * 有休残日数、残時間情報MAP生成
	 * @param lastRemainDays 前年度残日数
	 * @param lastRemainHour 前年度残時間
	 * @param remainDays 今年度残日数
	 * @param remainHour 今年度残時間
	 * @param possible 時間単位年休利用可能日数
	 * @param supplyDays 支給日数
	 * @param supplyHour 支給時間
	 * @param wasteDays 廃棄日数
	 * @param wasteHour 廃棄時間
	 * @param useDays 利用日数
	 * @param useHour 利用時間
	 * @return 有休残日数、残時間情報MAP
	 */
	public static Map<String, Double> createRemainMap(double lastRemainDays, int lastRemainHour, double remainDays,
			int remainHour, int possible, double supplyDays, int supplyHour, double wasteDays, int wasteHour,
			double useDays, int useHour) {
		Map<String, Double> map = new HashMap<String, Double>();
		map.put(KEY_LAST_REMAIN_DAYS, lastRemainDays);
		map.put(KEY_LAST_REMAIN_HOUR, Double.valueOf(lastRemainHour));
		map.put(KEY_REMAIN_DAYS, remainDays);
		map.put(KEY_REMAIN_HOUR, Double.valueOf(remainHour));
		map.put(KEY_POSSIBLE, Double.valueOf(possible));
		map.put(KEY_SUPPLY_DAYS, supplyDays);
		map.put(KEY_SUPPLY_HOUR, Double.valueOf(supplyHour));
		map.put(KEY_WASTE_DAYS, wasteDays);
		map.put(KEY_WASTE_HOUR, Double.valueOf(wasteHour));
		map.put(KEY_USE_DAYS, useDays);
		map.put(KEY_USE_HOUR, Double.valueOf(useHour));
		return map;
	}
	
	/**
	 * 前年度残日数取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 前年度残日数
	 */
	public static double getMapLastRemainDays(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return map.get(KEY_LAST_REMAIN_DAYS);
		}
		return 0d;
	}
	
	/**
	 * 前年度残時間取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 前年度残時間
	 */
	public static int getMapLastRemainHour(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return Double.valueOf(map.get(KEY_LAST_REMAIN_HOUR)).intValue();
		}
		return 0;
	}
	
	/**
	 * 今年度残日数取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 今年度残日数
	 */
	public static double getMapRemainDays(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return map.get(KEY_REMAIN_DAYS);
		}
		return 0d;
	}
	
	/**
	 * 今年度残時間取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 今年度残時間
	 */
	public static int getMapRemainHour(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return Double.valueOf(map.get(KEY_REMAIN_HOUR)).intValue();
		}
		return 0;
	}
	
	/**
	 * 時間単位年休利用可能日数取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 時間単位年休利用可能日数
	 */
	public static int getMapPossible(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return Double.valueOf(map.get(KEY_POSSIBLE)).intValue();
		}
		return 0;
	}
	
	/**
	 * 支給日数取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 支給日数
	 */
	public static double getMapSupplyDays(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return map.get(KEY_SUPPLY_DAYS);
		}
		return 0d;
	}
	
	/**
	 * 支給時間取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 支給時間
	 */
	public static int getMapSupplyHour(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return Double.valueOf(map.get(KEY_SUPPLY_HOUR)).intValue();
		}
		return 0;
	}
	
	/**
	 * 廃棄日数取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 廃棄日数
	 */
	public static double getMapWasteDays(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return map.get(KEY_WASTE_DAYS);
		}
		return 0d;
	}
	
	/**
	 * 廃棄時間取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 廃棄時間
	 */
	public static int getMapWasteHour(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return Double.valueOf(map.get(KEY_WASTE_HOUR)).intValue();
		}
		return 0;
	}
	
	/**
	 * 利用日数取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 利用日数
	 */
	public static double getMapUseDays(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return map.get(KEY_USE_DAYS);
		}
		return 0d;
	}
	
	/**
	 * 利用時間取得
	 * @param map 有休残日数、残時間情報MAP
	 * @return 利用時間
	 */
	public static int getMapUseHour(Map<String, Double> map) {
		if (VariousUtil.isNotNull(map)) {
			return Double.valueOf(map.get(KEY_USE_HOUR)).intValue();
		}
		return 0;
	}
	
	/**
	 * 残日数・残時間のチェック
	 * @param map 有休残日数、残時間情報MAP
	 * @return
	 * <p>
	 * 残日数・残時間が残っている場合true、項目にマイナスがある場合false。
	 * </p>
	 */
	public static boolean checkRemainInfoMap(Map<String, Double> map) {
		return getMapLastRemainDays(map) >= 0 && getMapLastRemainHour(map) >= 0 && getMapRemainDays(map) >= 0
				&& getMapRemainHour(map) >= 0 && getMapPossible(map) >= 0;
	}
	
	/**
	 * 対象期間が改正労働基準法施行日より前であるかの判断。
	 * @param startDate 開始年月日
	 * @param endDate 終了年月日
	 * @return 改正労働基準法施行日より前の場合true、そうでない場合false。
	 */
	public static boolean checkBeforeReformDate(Date startDate, Date endDate) {
		return endDate.compareTo(startDate) > 0 && DateUtil.getLegalReformDate().compareTo(endDate) > 0;
	}
	
	/**
	 * 対象期間が改正労働基準法施行日以後であるかの判断。
	 * @param startDate 開始年月日
	 * @param endDate 終了年月日
	 * @return 改正労働基準法施行日以後の場合true、そうでない場合false。
	 */
	public static boolean checkAfterReformDate(Date startDate, Date endDate) {
		return endDate.compareTo(startDate) > 0 && DateUtil.getLegalReformDate().compareTo(endDate) <= 0;
	}
	
	/**
	 * @param kCode 対象社員コード
	 * @param startDate 対象期間開始年月日
	 * @param endDate 対象期間終了年月日
	 * @return 有給休暇情報MAP
	 * @throws Exception 	例外処理が発生した場合
	 */
	public Map<String, Double> getPeriodPaidHolidayInfoMap(String kCode, Date startDate, Date endDate) throws Exception {
		if (checkBeforeReformDate(startDate, endDate)) {
			Date calcAttendanceMonth = part().calculate().getCalcAttendanceMonth(endDate);
			// 二ヶ月前の給与支給日
			Date twoMonthBeforeCalcPayment = part().calculate().getCalcPayment(
					DateUtil.addMonth(calcAttendanceMonth, -2));
			// 1ヶ月前の給与支給日
			Date oneMonthBeforeCalcPayment = part().calculate().getCalcPayment(
					DateUtil.addMonth(calcAttendanceMonth, -1));
			return convOldInfoToMap(getTargetMonthYukyuInfo(kCode, DateUtil.addDay(twoMonthBeforeCalcPayment, 1),
					oneMonthBeforeCalcPayment), getPrescribedHour(part().laborAgreement().getPrescribedTime(kCode,
					startDate)));
		} else if (checkAfterReformDate(startDate, endDate)) {
			return getAvairablePaidHolidayMap(kCode, startDate, endDate);
		}
		return null;
	}
	
	/**
	 * @param kCode 対象社員コード
	 * @param targetMonth 対象年月
	 * @return 有給休暇情報MAP
	 * @throws Exception 	例外処理が発生した場合
	 */
	public Map<String, Double> getPaidHolidayInfoMap(String kCode, Date targetMonth) throws Exception {
		Date startDate = part().calculate().getStartDate(targetMonth);
		Date endDate = part().calculate().getEndDate(targetMonth);
		return getPeriodPaidHolidayInfoMap(kCode, startDate, endDate);
	}
	
	/**
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @return 有給休暇情報MAP
	 * @throws Exception 	例外処理が発生した場合
	 */
	public Map<String, Double> getTargetPaidHolidayInfoMap(String kCode, Date targetDate) throws Exception {
		// 対象年月日の有休情報を取得する。
		Date startDate = part().calculate().getStartDateForList(targetDate);
		Date endDate = part().calculate().getEndDateForList(targetDate);
		return getPeriodPaidHolidayInfoMap(kCode, startDate, endDate);
	}
	
	/**
	 * 有給休暇情報リスト取得
	 * @param kCode			対象社員コード
	 * @param startDate		開始年月日
	 * @param endDate		終了年月日
	 * @return	検索結果(DTOのList)
	 * @throws Exception	例外処理が発生した場合
	 */
	public List<KdPaidHolidayDto> getPaidHolidayInfoList(String kCode, Date startDate, Date endDate) throws Exception {
		return getPaidHolidayDao().findForCondition(kCode, startDate, endDate);
	}
	
	/**
	 * 勤続月数による有給支給月数取得
	 * @param kCode 対象社員コード
	 * @return 勤続月数による有給支給月数
	 * @throws Exception 	例外処理が発生した場合
	 */
	public int getCarryForwardSupplyDays(String kCode) throws Exception {
		int supplyDays = 0;
		// 勤続月数取得
		double yearOfService = part().human().getYearsOfService(kCode);
		// 勤続月数から有給支給日数を取得
		String[][] aryPaidHoliday = part().mospcode().getPaidHolidayArray();
		for (String[] aryPaidHolidayInfo : aryPaidHoliday) {
			if (yearOfService >= NumberUtil.getIntParam(aryPaidHolidayInfo[0])) {
				supplyDays = NumberUtil.getIntParam(aryPaidHolidayInfo[1]);
			}
		}
		return supplyDays;
	}
	
	/**
	 * 有休判断
	 * @param code 対象コード
	 * @return
	 * <p>
	 * 対象コードが有休である場合true、そうでない場合false。
	 * </p>
	 */
	public static boolean isPaidHoliday(String code) {
		return CommonConst.CODE_HOLIDAY_REASON_PAID.equals(code);
	}
	
	/**
	 * CSVファイル用ヘッダー配列(旧テーブル)取得
	 * @return	CSVファイル用ヘッダー配列
	 * @throws Exception 	例外処理が発生した場合
	 */
	public String[] getOldPaidHolidayCsvHeader() throws Exception {
		List<String> headerList = new LinkedList<String>();
		String[] aryColumnInfo = part().export().getTableColumnInfo(OLD_TABLE);
		for (String columnInfo : aryColumnInfo) {
			headerList.add(VariousUtil.getCsvSplitInfo(columnInfo, 3));
		}
		return StringUtil.listToArray(headerList);
	}
	
	/**
	 * CSVファイル用ヘッダー配列(新テーブル)取得
	 * @return	CSVファイル用ヘッダー配列
	 * @throws Exception 	例外処理が発生した場合
	 */
	public String[] getNewPaidHolidayCsvHeader() throws Exception {
		List<String> headerList = new LinkedList<String>();
		String[] aryColumnInfo = part().export().getTableColumnInfo(NEW_TABLE);
		for (String columnInfo : aryColumnInfo) {
			headerList.add(VariousUtil.getCsvSplitInfo(columnInfo, 3));
		}
		return StringUtil.listToArray(headerList);
	}
	
	/**
	 * @param kCode		string	社員コード
	 * @param kyuyoYMD	int		給与計算年月日
	 * @param zZanT		double	前月残数(当年)
	 * @param zZanZ		double	前月残数(前年)
	 * @param syoka		double	当月使用
	 * @param syutoku	int		当月取得
	 * @param haiki		double	当月廃棄
	 * @param tZanT		double	当月残数(当年)
	 * @param tZanZ		double	当月残数(前年)
	 * @return	dto		dto		旧有給休暇Dto
	 */
	public static MYukyuDto createMYukyuDto(String kCode, int kyuyoYMD, double zZanT, double zZanZ, double syoka,
			int syutoku, double haiki, double tZanT, double tZanZ) {
		MYukyuDto dto = new MYukyuDto();
		dto.setKCode(kCode);
		dto.setKyuyoYMD(kyuyoYMD);
		dto.setZZanT(zZanT);
		dto.setZZanZ(zZanZ);
		dto.setSyoka(syoka);
		dto.setSyutoku(syutoku);
		dto.setHaiki(haiki);
		dto.setTZanT(tZanT);
		dto.setTZanZ(tZanZ);
		return dto;
	}
	
	/**
	 * @param paidHolidayId		有休ID
	 * @param kCode				社員コード
	 * @param processType		処理コード
	 * @param processDate		処理日
	 * @param lastRemainDays	前年度残日数
	 * @param lastRemainHour	前年度残時間
	 * @param remainDays		今年度残日数
	 * @param remainHour		今年度算時間
	 * @param possible			時間単位取得可能日数
	 * @param deleteFlag		削除フラグ
	 * @return					新有給休暇Dto
	 */
	public static KdPaidHolidayDto createKdPaidHolidayDto(long paidHolidayId, String kCode, String processType,
			Date processDate, double lastRemainDays, int lastRemainHour, double remainDays, int remainHour,
			int possible, int deleteFlag) {
		KdPaidHolidayDto dto = new KdPaidHolidayDto();
		dto.setPaidId(paidHolidayId);
		dto.setKCode(kCode);
		dto.setProcessType(processType);
		dto.setProcessDate(processDate);
		dto.setLastRemainDays(lastRemainDays);
		dto.setLastRemainHour(lastRemainHour);
		dto.setRemainDays(remainDays);
		dto.setRemainHour(remainHour);
		dto.setPossible(possible);
		dto.setDeleteFlag(deleteFlag);
		return dto;
	}
	
	/**
	 * 時間単位年休用所定労働時間取得
	 * @param prescribedTime 所定労働時間（分）
	 * @return 時間単位年休用所定労働時間（時）
	 */
	public static int getPrescribedHour(int prescribedTime) {
		return Double.valueOf(Math.ceil(TimeUtil.convMinutesToDoubleHour(prescribedTime))).intValue();
	}
	
	/**
	 * 選択期間年休付与情報一覧取得
	 * @param kCode 対象社員コード
	 * @param startDate 期間開始年月日
	 * @param endDate 期間終了年月日
	 * @return 選択期間年休付与情報一覧
	 * @throws SQLException 	SQL例外が発生した場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws MospException MosP例外処理が発生した場合
	 */
	public List<KdPaidHolidayDto> getSupplyList(String kCode, Date startDate, Date endDate) throws SQLException,
			IllegalAccessException, NoSuchFieldException, MospException {
		return getPaidHolidayDao().findForCondition(kCode, CommonConst.CODE_PROCESS_SUPPLY, startDate, endDate);
	}
	
	/**
	 * 選択期間年休控除情報一覧取得
	 * @param kCode 対象社員コード
	 * @param startDate 期間開始年月日
	 * @param endDate 期間終了年月日
	 * @return 選択期間年休控除情報一覧
	 * @throws SQLException 	SQL例外が発生した場合
	 * @throws IllegalAccessException 	メソッドにアクセスできない場合
	 * @throws NoSuchFieldException 	フィールドが見つからなかった場合
	 * @throws MospException MosP例外処理が発生した場合
	 */
	public List<KdPaidHolidayDto> getWasteList(String kCode, Date startDate, Date endDate) throws SQLException,
			IllegalAccessException, NoSuchFieldException, MospException {
		return getPaidHolidayDao().findForCondition(kCode, CommonConst.CODE_PROCESS_WASTE, startDate, endDate);
	}
}
