/*
 * 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.base;

import java.sql.Connection;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import jp.mosp.framework.base.MospException;
import jp.mosp.framework.base.MospParams;
import jp.mosp.framework.utils.DateUtility;
import jp.mosp.platform.base.PlatformBean;
import jp.mosp.platform.constant.PlatformMessageConst;
import jp.mosp.platform.dto.human.HumanDtoInterface;
import jp.mosp.time.bean.ApplicationReferenceBeanInterface;
import jp.mosp.time.bean.PaidHolidayReferenceBeanInterface;
import jp.mosp.time.bean.ScheduleReferenceBeanInterface;
import jp.mosp.time.bean.TimeSettingReferenceBeanInterface;
import jp.mosp.time.constant.TimeConst;
import jp.mosp.time.constant.TimeMessageConst;
import jp.mosp.time.dto.settings.ApplicationDtoInterface;
import jp.mosp.time.dto.settings.PaidHolidayDtoInterface;
import jp.mosp.time.dto.settings.ScheduleDtoInterface;
import jp.mosp.time.dto.settings.TimeSettingDtoInterface;

/**
 * 勤怠管理におけるBeanの基本機能を提供する。<br>
 * <br>
 */
public abstract class TimeBean extends PlatformBean {
	
	/**
	 * デフォルト勤務回数。
	 */
	public static final int		TIMES_WORK_DEFAULT	= 1;
	
	/**
	 * 1時間あたりのミリ秒数。<br>
	 */
	public static final int		MILLI_SEC_PER_HOUR	= 3600000;
	
	/**
	 * 時刻正規表現。
	 */
	public static final String	REG_ATTENDANCE_TIME	= "([0-3][0-9]|[4][0-7])[0-5][0-9]";
	

	/**
	 * コンストラクタ。
	 */
	public TimeBean() {
		// 処理無し
	}
	
	/**
	 * {@link PlatformBean#PlatformBean()}を実行する。<br>
	 * @param mospParams 設定するMosP処理情報
	 * @param connection 設定するデータベースコネクション
	 */
	protected TimeBean(MospParams mospParams, Connection connection) {
		super(mospParams, connection);
	}
	
	/**
	 * 勤怠管理用機能コードセットを取得する。<br>
	 * @return 勤怠管理用機能コードセット
	 */
	protected Set<String> getTimeFunctionSet() {
		// 勤怠管理用機能コードセット準備
		Set<String> set = new HashSet<String>();
		set.add(TimeConst.CODE_FUNCTION_WORK_MANGE);
		set.add(TimeConst.CODE_FUNCTION_OVER_WORK);
		set.add(TimeConst.CODE_FUNCTION_VACATION);
		set.add(TimeConst.CODE_FUNCTION_WORK_HOLIDAY);
		set.add(TimeConst.CODE_FUNCTION_COMPENSATORY_HOLIDAY);
		set.add(TimeConst.CODE_FUNCTION_DIFFERENCE);
		return set;
	}
	
	/**
	 * 時刻を取得する。<br>
	 * デフォルト基準日付の時刻を、基準日付における時刻に変換する。<br>
	 * @param time         デフォルト基準日付の時刻
	 * @param standardDate 基準日付
	 * @return 勤怠時刻
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected Date getTime(Date time, Date standardDate) throws MospException {
		// デフォルト基準日付との差を取得
		long deference = time.getTime() - getDefaultStandardDate().getTime();
		// 基準日付における時刻を取得
		return new Date(standardDate.getTime() + deference);
	}
	
	/**
	 * デフォルト基準日付(1970/01/01 00:00:00)オブジェクトを取得する。<br>
	 * @return デフォルト基準日付オブジェクト
	 * @throws MospException 日付の変換に失敗した場合
	 */
	protected Date getDefaultStandardDate() throws MospException {
		return DateUtility.getTime(0, 0);
	}
	
	/**
	 * 日付オブジェクトの差を時間(分)で取得する。<br>
	 * @param startTime 開始時刻
	 * @param endTime   終了時刻
	 * @return 日付オブジェクトの差(分)
	 */
	protected int getDefferenceMinutes(Date startTime, Date endTime) {
		// ミリ秒で差を取得
		long defference = endTime.getTime() - startTime.getTime();
		// 時間に変換
		return (int)(defference / (MILLI_SEC_PER_HOUR / TimeConst.CODE_DEFINITION_HOUR));
	}
	
	/**
	 * 日付文字列を取得する(Date→String)。<br>
	 * 基準日付からの時間(HH)部は、基準日付からの時間数で表される。<br>
	 * @param date	対象日付オブジェクト
	 * @param standardDate 基準日付
	 * @return 日付文字列(HH:mm)
	 */
	protected String getStringTime(Date date, Date standardDate) {
		// 日付確認
		if (date == null) {
			// 日付がnullならハイフン
			return getHyphenNaming();
		}
		// 基準時刻との差を取得
		long deference = date.getTime() - standardDate.getTime();
		// 差の時間を取得(小数点以下は切り捨て)
		long hours = deference / MILLI_SEC_PER_HOUR;
		// フォーマット指定
		DecimalFormat df = new DecimalFormat("#00");
		// 日付文字列取得
		return df.format(hours) + DateUtility.getStringDate(date, ":mm");
	}
	
	/**
	 * 勤怠時刻文字列を日付オブジェクトに変換し取得する。<br>
	 * 勤怠時刻文字列は4文字の数字(HHmm)とする。<br>
	 * 基準日は、変換の際に基準として用いる。<br>
	 * @param date 基準日
	 * @param time 勤怠時刻文字列
	 * @return 日付オブジェクト
	 */
	protected Date getAttendanceTime(Date date, String time) {
		// フォーマット確認
		if (time.matches(REG_ATTENDANCE_TIME) == false) {
			// エラーメッセージ設定
			mospParams.addErrorMessage(TimeMessageConst.MSG_TIME_FORMAT_CHECK, getStringDate(date), null);
			return null;
		}
		// 時間取得
		Integer hour = getInteger(time.substring(0, 2));
		Integer minute = getInteger(time.substring(2, 4));
		// 対象日時間取得
		long attendanceTime = date.getTime();
		// 時間を加算
		attendanceTime += hour.longValue() * MILLI_SEC_PER_HOUR;
		// 分を加算
		attendanceTime += minute * MILLI_SEC_PER_HOUR / TimeConst.CODE_DEFINITION_HOUR;
		// 日付オブジェクトに変換
		return new Date(attendanceTime);
	}
	
	/**
	 * 対象時間を分単位で返す<br>
	 * @param date 対象時間
	 * @return 分
	 */
	protected int setHourMinute(Date date) {
		if (date == null) {
			return 0;
		}
		return (DateUtility.getHour(date) * TimeConst.CODE_DEFINITION_HOUR) + DateUtility.getMinute(date);
	}
	
	/**
	 * 対象時間を分単位で返す<br>
	 * @param date 対象時間
	 * @param deltaDate 差分
	 * @return 分
	 */
	protected int setHourMinute(Date date, Date deltaDate) {
		if (date == null || deltaDate == null) {
			return 0;
		}
		if (DateUtility.getDay(date) != DateUtility.getDay(deltaDate)) {
			return (((DateUtility.getHour(date) + 24) * TimeConst.CODE_DEFINITION_HOUR)) + DateUtility.getMinute(date);
		}
		return (DateUtility.getHour(date) * TimeConst.CODE_DEFINITION_HOUR) + DateUtility.getMinute(date);
	}
	
	/**
	 * ハイフン名称を取得する。<br>
	 * @return ハイフン名称
	 */
	protected String getHyphenNaming() {
		return mospParams.getName("Hyphen");
	}
	
	/**
	 * 設定適用が存在しない場合のエラーメッセージを設定する。<br>
	 * @param targetDate 基準日
	 */
	protected void addApplicationNotExistErrorMessage(Date targetDate) {
		String[] rep = { getStringDate(targetDate),
			mospParams.getName("Set") + mospParams.getName("Apply") + mospParams.getName("Information") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_SETTING_APPLICATION_DEFECT, rep);
	}
	
	/**
	 * 勤怠設定が存在しない場合のエラーメッセージを設定する。<br>
	 * @param targetDate 基準日
	 */
	protected void addTimeSettingNotExistErrorMessage(Date targetDate) {
		String[] rep = { getStringDate(targetDate),
			mospParams.getName("WorkManage") + mospParams.getName("Set") + mospParams.getName("Information") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_SETTING_APPLICATION_DEFECT, rep);
	}
	
	/**
	 * カレンダが存在しない場合のエラーメッセージを設定する。<br>
	 * @param targetDate 基準日
	 */
	protected void addScheduleNotExistErrorMessage(Date targetDate) {
		String[] rep = { getStringDate(targetDate), mospParams.getName("Calendar") + mospParams.getName("Information") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_SETTING_APPLICATION_DEFECT, rep);
	}
	
	/**
	 * 有給休暇管理が存在しない場合のエラーメッセージを設定する。<br>
	 * @param targetDate 基準日
	 */
	protected void addPaidHolidayNotExistErrorMessage(Date targetDate) {
		String[] rep = { getStringDate(targetDate),
			mospParams.getName("Salaried") + mospParams.getName("Vacation") + mospParams.getName("Information") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_SETTING_APPLICATION_DEFECT, rep);
	}
	
	/**
	 * 勤怠設定が存在しない場合のエラーメッセージを設定する。<br>
	 * @param targetDate 基準日
	 */
	protected void addWorkTypeNotExistErrorMessage(Date targetDate) {
		String[] rep = { getStringDate(targetDate),
			mospParams.getName("Work") + mospParams.getName("Form") + mospParams.getName("Information") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_SETTING_APPLICATION_DEFECT, rep);
	}
	
	/**
	 * 限度基準に対象のコードが存在しない場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addSettingApplicationDefectLimitStandardErrorMessage(Date date) {
		String errorMes = mospParams.getName("Limit") + mospParams.getName("Norm");
		mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, errorMes, null);
	}
	
	// 残業申請関連
	/**
	 * 残業申請する際に対象日が所定休日または法定休日で申請できない場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addOvertimeTargetWorkDateHolidayErrorMessage(Date date) {
		String[] aryRep = {
			DateUtility.getStringDate(date),
			mospParams.getName("GoingWork") + mospParams.getName("Day"),
			mospParams.getName("OvertimeWork") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_3, aryRep);
	}
	
	/**
	 * 残業申請する際に対象日に既に残業申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addOvertimeTargetDateOvertimeErrorMessage(Date date) {
		String[] aryRep = {
			DateUtility.getStringDate(date),
			mospParams.getName("OvertimeWork"),
			mospParams.getName("OvertimeWork") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") + mospParams.getName("Or") + mospParams.getName("OvertimeWork")
					+ mospParams.getName("Type") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
		
	}
	
	/**
	 * 残業申請する際に対象日に既に他の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addOvertimeTargetDateRequestErrorMessage(Date date) {
		String[] aryRep = {
			getStringDate(date),
			mospParams.getName("Other") + mospParams.getName("Of"),
			mospParams.getName("OvertimeWork") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 残業申請する際に対象日に休日出勤の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addOvertimeTargetWorkDateWorkOnHolidayRequestErrorMessage(Date date) {
		String[] aryRep = {
			DateUtility.getStringDate(date),
			mospParams.getName("Holiday") + mospParams.getName("GoingWork"),
			mospParams.getName("OvertimeWork") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_SETTING_APPLICATION_DEFECT, aryRep);
	}
	
	/**
	 * 申請する際に対象日に既に勤怠の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addOvertimeTargetWorkDateAttendanceRequestErrorMessage(Date date) {
		String[] aryRep = {
			getStringDate(date),
			mospParams.getName("WorkManage"),
			mospParams.getName("OvertimeWork") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 残業申請可能な期間を過ぎた年月日で申請が行われている場合、エラーメッセージを追加する。<br>
	 */
	protected void addOvertimePeriodErrorMessage() {
		String[] aryRep = { mospParams.getName("OvertimeWork") + mospParams.getName("Application"),
			mospParams.getName("No1"), mospParams.getName("OvertimeWork") + mospParams.getName("Year") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_2, aryRep);
	}
	
	/**
	 * 残業申請時間が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addOvertimeRequestTimeErrorMessage() {
		mospParams.addErrorMessage(PlatformMessageConst.MSG_CHR_TYPE, mospParams.getName("OvertimeWork")
				+ mospParams.getName("Application") + mospParams.getName("Time"), mospParams.getName("Time"));
	}
	
	/**
	 * 残業理由が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addOvertimeRequestReasonErrorMessage() {
		mospParams.addErrorMessage(PlatformMessageConst.MSG_REQUIRED, mospParams.getName("OvertimeWork")
				+ mospParams.getName("Reason"), null);
	}
	
	// 休暇申請関連
	/**
	 * 休暇申請する際に対象日が所定休日または法定休日で申請できない場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addHolidayTargetWorkDateHolidayErrorMessage(Date date) {
		String[] aryRep = {
			DateUtility.getStringDate(date),
			mospParams.getName("GoingWork") + mospParams.getName("Day"),
			mospParams.getName("Vacation") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_3, aryRep);
	}
	
	/**
	 * 休暇申請する際に対象日に既に他の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addHolidayTargetDateRequestErrorMessage(Date date) {
		String[] aryRep = {
			getStringDate(date),
			mospParams.getName("Other") + mospParams.getName("Of"),
			mospParams.getName("Vacation") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 休暇申請する際に対象日に既に勤怠の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addHolidayTargetWorkDateAttendanceRequestErrorMessage(Date date) {
		String[] aryRep = {
			getStringDate(date),
			mospParams.getName("WorkManage"),
			mospParams.getName("Vacation") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 休暇年月日が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addHolidayRequestDateErrorMessage() {
		mospParams.addErrorMessage(TimeMessageConst.MSG_HOLIDAY_ACTIVATIONDATE, null);
	}
	
	/**
	 * 休暇年月日が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addHolidayOverlapRange1ErrorMessage() {
		String errorMes1 = mospParams.getName("Vacation") + mospParams.getName("Content");
		String errorMes2 = mospParams.getName("Vacation") + mospParams.getName("Year") + mospParams.getName("Month")
				+ mospParams.getName("Day");
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_4, errorMes1, errorMes2);
	}
	
	/**
	 * 休暇年月日が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addHolidayOverlapRange2ErrorMessage() {
		String errorMes1 = mospParams.getName("Vacation") + mospParams.getName("Content");
		String errorMes2 = mospParams.getName("Vacation") + mospParams.getName("Year") + mospParams.getName("Month")
				+ mospParams.getName("Day") + mospParams.getName("Or") + mospParams.getName("Vacation")
				+ mospParams.getName("Range");
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_4, errorMes1, errorMes2);
	}
	
	/**
	 * 休暇理由が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addHolidayRequestReasonErrorMessage() {
		mospParams.addErrorMessage(PlatformMessageConst.MSG_REQUIRED, mospParams.getName("Vacation")
				+ mospParams.getName("Reason"), null);
	}
	
	/**
	 * 休暇申請可能な期間を過ぎた年月日で申請が行われている場合、エラーメッセージを追加する。<br>
	 */
	protected void addHolidayPeriodErrorMessage() {
		String[] aryRep = {
			mospParams.getName("Vacation") + mospParams.getName("Application"),
			mospParams.getName("No6"),
			mospParams.getName("Vacation") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_2, aryRep);
	}
	
	// 休日出勤関連
	/**
	 * 休日出勤申請する際に対象日が所定休日または法定休日で申請できない場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addWorkOnHolidayTargetWorkDateHolidayErrorMessage(Date date) {
		String[] aryRep = { DateUtility.getStringDate(date), mospParams.getName("Holiday"),
			mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_3, aryRep);
	}
	
	/**
	 * 休日出勤申請する際に対象日に既に他の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addWorkOnHolidayTargetDateRequestErrorMessage(Date date) {
		String[] aryRep = { getStringDate(date), mospParams.getName("Other") + mospParams.getName("Of"),
			mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 休日出勤申請する際に対象日に既に休日出勤申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addWorkOnHolidayTargetDateWorkOnHolidayRequestErrorMessage(Date date) {
		String[] aryRep = { DateUtility.getStringDate(date),
			mospParams.getName("Holiday") + mospParams.getName("GoingWork"),
			mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 申請理由が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addWorkOnHolidayRequestReasonErrorMessage() {
		mospParams.addErrorMessage(PlatformMessageConst.MSG_REQUIRED, mospParams.getName("Application")
				+ mospParams.getName("Reason"), null);
	}
	
	/**
	 * 休日出勤申請可能な期間を過ぎた年月日で申請が行われている場合、エラーメッセージを追加する。<br>
	 */
	protected void addWorkOnHolidayPeriodErrorMessage() {
		String[] aryRep = {
			mospParams.getName("Holiday") + mospParams.getName("GoingWork") + mospParams.getName("Application"),
			mospParams.getName("No1"),
			mospParams.getName("Holiday") + mospParams.getName("GoingWork") + mospParams.getName("Year") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_2, aryRep);
	}
	
	// 代休申請関連
	/**
	 * 代休申請する際に対象日に既に代休申請が行われている場合、エラーメッセージを追加する。<br>
	 */
	protected void addSubHolidayTargetDateSubHolidayRequestErrorMessage() {
		String errorMes1 = mospParams.getName("Vacation") + mospParams.getName("Content");
		String errorMes2 = mospParams.getName("CompensatoryHoliday") + mospParams.getName("Day")
				+ mospParams.getName("Or") + mospParams.getName("Vacation") + mospParams.getName("Range");
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_4, errorMes1, errorMes2);
	}
	
	/**
	 * 代休申請する際に対象日に既に他の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addSubHolidayTargetDateRequestErrorMessage(Date date) {
		String[] aryRep = { DateUtility.getStringDate(date), mospParams.getName("Other") + mospParams.getName("Of"),
			mospParams.getName("CompensatoryHoliday") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 代休申請する際に対象日に既に勤怠の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addSubHolidayTargetWorkDateAttendanceRequestErrorMessage(Date date) {
		String[] aryRep = { getStringDate(date), mospParams.getName("WorkManage"),
			mospParams.getName("CompensatoryHoliday") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 代休申請する際に対象日が出勤日ではない場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addSubHolidayTargetNoWorkDateErrorMessage(Date date) {
		String[] aryRep = { DateUtility.getStringDate(date),
			mospParams.getName("GoingWork") + mospParams.getName("Day"),
			mospParams.getName("CompensatoryHoliday") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_3, aryRep);
	}
	
	/**
	 * 代休申請する際に対象日が所定休日または法定休日で申請できない場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addSubHolidayTargetWorkDateHolidayErrorMessage(Date date) {
		String[] aryRep = { DateUtility.getStringDate(date),
			mospParams.getName("GoingWork") + mospParams.getName("Day"),
			mospParams.getName("CompensatoryHoliday") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_3, aryRep);
	}
	
	/**
	 * 代休申請可能な期間を過ぎた年月日で申請が行われている場合、エラーメッセージを追加する。<br>
	 */
	protected void addSubHolidayPeriodErrorMessage() {
		String[] aryRep = { mospParams.getName("CompensatoryHoliday") + mospParams.getName("Application"),
			mospParams.getName("No1"), mospParams.getName("CompensatoryHoliday") + mospParams.getName("Year") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_2, aryRep);
	}
	
	// 時差出勤関連
	/**
	 * 時差出勤申請する際に対象日が所定休日または法定休日で申請できない場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addDifferenceTargetWorkDateHolidayErrorMessage(Date date) {
		String[] aryRep = { DateUtility.getStringDate(date),
			mospParams.getName("GoingWork") + mospParams.getName("Day"),
			mospParams.getName("TimeDifference") + mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_3, aryRep);
	}
	
	/**
	 * 時差出勤申請する際に対象日に既に勤怠の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addDifferenceTargetWorkDateAttendanceRequestErrorMessage(Date date) {
		String[] aryRep = { getStringDate(date), mospParams.getName("WorkManage"),
			mospParams.getName("TimeDifference") + mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 時差出勤申請する際に対象日に既に他の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addDifferenceTargetDateRequestErrorMessage(Date date) {
		String[] aryRep = { getStringDate(date), mospParams.getName("Other") + mospParams.getName("Of"),
			mospParams.getName("TimeDifference") + mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 時差出勤申請可能な期間を過ぎた年月日で申請が行われている場合、エラーメッセージを追加する。<br>
	 */
	protected void addDifferencePeriodErrorMessage() {
		String[] aryRep = {
			mospParams.getName("TimeDifference") + mospParams.getName("GoingWork") + mospParams.getName("Application"),
			mospParams.getName("No1"),
			mospParams.getName("TimeDifference") + mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_2, aryRep);
	}
	
	/**
	 * 時差出勤申請する際に対象日に既に時差出勤申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addDifferenceTargetDateDifferenceRequestErrorMessage(Date date) {
		String[] aryRep = { DateUtility.getStringDate(date),
			mospParams.getName("TimeDifference") + mospParams.getName("GoingWork"),
			mospParams.getName("TimeDifference") + mospParams.getName("GoingWork") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 理由が正しく入力でない場合、エラーメッセージを追加する。<br>
	 */
	protected void addDifferenceRequestReasonErrorMessage() {
		mospParams.addErrorMessage(PlatformMessageConst.MSG_REQUIRED, mospParams.getName("Reason"), null);
	}
	
	/**
	 * 申請する際に対象日に既に勤怠の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 */
	protected void addAttendanceTargetWorkDateAttendanceRequestErrorMessage(Date date) {
		String[] aryRep = {
			getStringDate(date),
			mospParams.getName("WorkManage"),
			mospParams.getName("Work") + mospParams.getName("Year") + mospParams.getName("Month")
					+ mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_6, aryRep);
	}
	
	/**
	 * 申請対象日に既に別の申請が行われている場合、エラーメッセージを追加する。<br>
	 * @param date 対象日付
	 * @param requestTitle 対象申請名称
	 */
	protected void addOthersRequestErrorMessage(Date date, String requestTitle) {
		String[] aryRep = { getStringDate(date), requestTitle, requestTitle + mospParams.getName("Application") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_12, aryRep);
	}
	
	/**
	 * 勤怠申請可能な期間を過ぎた年月日で申請が行われている場合、エラーメッセージを追加する。<br>
	 */
	protected void addAttendancePeriodErrorMessage() {
		String[] aryRep = { mospParams.getName("WorkManage") + mospParams.getName("Application"),
			mospParams.getName("No1"), mospParams.getName("Work") + mospParams.getName("Day") };
		mospParams.addErrorMessage(TimeMessageConst.MSG_REQUEST_CHECK_2, aryRep);
	}
	
	/**
	 * 月次処理が行われている場合、エラーメッセージを追加する。<br>
	 * @param targetDate 年月日
	 * @param name 項目名
	 */
	protected void addMonthlyTreatmentErrorMessage(Date targetDate, String name) {
		String mes1 = DateUtility.getYear(targetDate) + mospParams.getName("Year") + DateUtility.getMonth(targetDate)
				+ mospParams.getName("Month");
		mospParams.addErrorMessage(TimeMessageConst.MSG_MONTHLY_TREATMENT, mes1, name);
	}
	
	/**
	 * 勤怠管理対象では無いユーザ対するエラーメッセージを追加する。<br>
	 * @param targetDate 対象年月日
	 * @param code 社員コード
	 */
	protected void addNotUserAttendanceManagementTargetErrorMessage(Date targetDate, String code) {
		mospParams.addErrorMessage(TimeMessageConst.MSG_NOT_USER_ATTENDANCE_MANAGEMENT_TARGET, DateUtility
			.getStringDate(targetDate), code);
	}
	
	/**
	 * 
	 * @param personalId 個人ID
	 * @param targetDate 対象日
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void initial(String personalId, Date targetDate) throws MospException {
		ApplicationReferenceBeanInterface applicationReference = (ApplicationReferenceBeanInterface)createBean(ApplicationReferenceBeanInterface.class);
		TimeSettingReferenceBeanInterface timeSettingReference = (TimeSettingReferenceBeanInterface)createBean(TimeSettingReferenceBeanInterface.class);
		ScheduleReferenceBeanInterface scheduleReference = (ScheduleReferenceBeanInterface)createBean(ScheduleReferenceBeanInterface.class);
		PaidHolidayReferenceBeanInterface paidHolidayReference = (PaidHolidayReferenceBeanInterface)createBean(PaidHolidayReferenceBeanInterface.class);
		
		// 設定適用
		ApplicationDtoInterface applicationDto = applicationReference.findForPerson(personalId, targetDate);
		if (null == applicationDto) {
			addApplicationNotExistErrorMessage(targetDate);
			return;
		}
		// 勤怠設定
		TimeSettingDtoInterface timeSettingDto = timeSettingReference.getTimeSettingInfo(applicationDto
			.getWorkSettingCode(), targetDate);
		if (null == timeSettingDto) {
			addTimeSettingNotExistErrorMessage(targetDate);
			return;
		}
		// 勤怠管理対象フラグのチェック
		if (1 == timeSettingDto.getTimeManagementFlag()) {
			HumanDtoInterface dto = getHumanInfo(personalId, targetDate);
			addNotUserAttendanceManagementTargetErrorMessage(targetDate, dto.getEmployeeCode());
			return;
		}
		// カレンダー
		ScheduleDtoInterface scheduleDto = scheduleReference.getScheduleInfo(applicationDto.getScheduleCode(),
				targetDate);
		if (null == scheduleDto) {
			addScheduleNotExistErrorMessage(targetDate);
			return;
		}
		// 有給休暇管理
		PaidHolidayDtoInterface paidHolidayDto = paidHolidayReference.getPaidHolidayInfo(applicationDto
			.getPaidHolidayCode(), targetDate);
		if (null == paidHolidayDto) {
			addPaidHolidayNotExistErrorMessage(targetDate);
			return;
		}
	}
	
	/**
	 * 丸めた時間を取得する。<br>
	 * @param time 対象時間
	 * @param type 丸め種別
	 * @param unit 丸め単位
	 * @return 丸めた時間
	 */
	protected int getRoundMinute(int time, int type, int unit) {
		if (time <= 0 || type == 0 || unit <= 0) {
			return time;
		}
		if (type == 1 || type == 2) {
			// 余り
			int remainder = time % unit;
			if (remainder == 0) {
				// 余りが0の場合はそのまま返す
				return time;
			}
			int rounded = time - remainder;
			if (type == 1) {
				// 切捨て
				return rounded;
			} else if (type == 2) {
				// 切上げ
				return rounded + unit;
			}
		}
		return time;
	}
	
}
