/*
 * 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.util.ArrayList;
import java.util.Date;
import java.util.List;

import jp.mosp.framework.base.MospException;
import jp.mosp.framework.constant.MospConst;
import jp.mosp.framework.utils.DateUtility;
import jp.mosp.platform.base.PlatformBean;
import jp.mosp.platform.bean.workflow.WorkflowRegistBeanInterface;
import jp.mosp.platform.constant.PlatformConst;
import jp.mosp.platform.dto.workflow.WorkflowDtoInterface;
import jp.mosp.time.bean.AttendanceBean;
import jp.mosp.time.bean.AttendanceCalcBeanInterface;
import jp.mosp.time.bean.AttendanceCorrectionReferenceBeanInterface;
import jp.mosp.time.bean.AttendanceCorrectionRegistBeanInterface;
import jp.mosp.time.bean.AttendanceListRegistBeanInterface;
import jp.mosp.time.bean.AttendanceRegistBeanInterface;
import jp.mosp.time.bean.CutoffReferenceBeanInterface;
import jp.mosp.time.bean.DifferenceRequestReferenceBeanInterface;
import jp.mosp.time.bean.GoOutReferenceBeanInterface;
import jp.mosp.time.bean.GoOutRegistBeanInterface;
import jp.mosp.time.bean.HolidayRequestReferenceBeanInterface;
import jp.mosp.time.bean.OvertimeRequestReferenceBeanInterface;
import jp.mosp.time.bean.RequestUtilBeanInterface;
import jp.mosp.time.bean.RestReferenceBeanInterface;
import jp.mosp.time.bean.RestRegistBeanInterface;
import jp.mosp.time.bean.SubHolidayRegistBeanInterface;
import jp.mosp.time.bean.SubHolidayRequestReferenceBeanInterface;
import jp.mosp.time.constant.TimeConst;
import jp.mosp.time.constant.TimeMessageConst;
import jp.mosp.time.dao.settings.RestDaoInterface;
import jp.mosp.time.dto.settings.ApplicationDtoInterface;
import jp.mosp.time.dto.settings.AttendanceCorrectionDtoInterface;
import jp.mosp.time.dto.settings.AttendanceDtoInterface;
import jp.mosp.time.dto.settings.CutoffDtoInterface;
import jp.mosp.time.dto.settings.DifferenceRequestDtoInterface;
import jp.mosp.time.dto.settings.GoOutDtoInterface;
import jp.mosp.time.dto.settings.HolidayRequestDtoInterface;
import jp.mosp.time.dto.settings.OvertimeRequestDtoInterface;
import jp.mosp.time.dto.settings.RestDtoInterface;
import jp.mosp.time.dto.settings.ScheduleDateDtoInterface;
import jp.mosp.time.dto.settings.SubHolidayDtoInterface;
import jp.mosp.time.dto.settings.SubHolidayRequestDtoInterface;
import jp.mosp.time.dto.settings.TimeSettingDtoInterface;
import jp.mosp.time.dto.settings.WorkOnHolidayRequestDtoInterface;
import jp.mosp.time.dto.settings.WorkTypeDtoInterface;
import jp.mosp.time.dto.settings.WorkTypeItemDtoInterface;

/**
 * 勤怠一覧登録クラス。
 */
public class AttendanceListRegistBean extends AttendanceBean implements AttendanceListRegistBeanInterface {
	
	/**
	 * 勤怠データ登録クラス。
	 */
	protected AttendanceRegistBeanInterface					attendanceRegist;
	
	/**
	 * 勤怠修正データ参照クラス。
	 */
	protected AttendanceCorrectionReferenceBeanInterface	attendanceCorrectionReference;
	
	/**
	 * 勤怠修正データ登録クラス。
	 */
	protected AttendanceCorrectionRegistBeanInterface		attendanceCorrectionRegist;
	
	/**
	 * 休憩データ登録クラス。
	 */
	protected RestRegistBeanInterface						restRegist;
	
	/**
	 * 休憩データDAOインターフェース
	 */
	protected RestDaoInterface								restDao;
	
	/**
	 * 外出データ登録クラス。
	 */
	protected GoOutRegistBeanInterface						goOutRegist;
	
	/**
	 * 代休データ登録クラス。
	 */
	protected SubHolidayRegistBeanInterface					subHolidayRegist;
	
	/**
	 * 残業申請データ参照クラス。
	 */
	protected OvertimeRequestReferenceBeanInterface			overtimeRequestReference;
	
	/**
	 * 休暇申請データ参照クラス。
	 */
	protected HolidayRequestReferenceBeanInterface			holidayRequestReference;
	
	/**
	 * 代休申請データ参照クラス。
	 */
	protected SubHolidayRequestReferenceBeanInterface		subHolidayRequestReference;
	
	/**
	 * 時差出勤申請参照クラス。
	 */
	protected DifferenceRequestReferenceBeanInterface		differenceReference;
	
	/**
	 * 時差出勤申請DTOインターフェース
	 */
	protected DifferenceRequestDtoInterface					differenceDto;
	
	/**
	 * 勤怠データ自動計算クラス。
	 */
	protected AttendanceCalcBeanInterface					attendanceCalc;
	
	/**
	 * ワークフロー登録クラス。
	 */
	WorkflowRegistBeanInterface								workflowRegist;
	
	/**
	 * 対象個人ID。<br>
	 * インターフェースに定義されたメソッドの最初で設定される。<br>
	 */
	protected String										personalId;
	
	/**
	 * 対象日。<br>
	 * インターフェースに定義されたメソッドにおける日毎処理の最初で設定される。<br>
	 */
	protected Date											targetDate;
	
	/**
	 * 設定適用マスタ情報。<br>
	 * 勤怠データ新規作成時に取得及び設定をされる。<br>
	 */
	protected ApplicationDtoInterface						applicationDto;
	
	/**
	 * カレンダ日情報。<br>
	 * 勤怠データ新規作成時に取得及び設定をされる。<br>
	 */
	protected ScheduleDateDtoInterface						scheduleDateDto;
	
	/**
	 * 勤務形態マスタ情報。<br>
	 * 勤怠データ新規作成時に取得及び設定をされる。<br>
	 */
	protected WorkTypeDtoInterface							workTypeDto;
	
	/**
	 * 勤怠設定マスタ情報。<br>
	 * 勤怠データ新規作成時に取得及び設定をされる。<br>
	 */
	protected TimeSettingDtoInterface						timeSettingDto;
	
	/**
	 * 勤怠データ休憩情報参照インターフェース。
	 */
	protected RestReferenceBeanInterface					restReference;
	
	/**
	 * 勤怠データ外出情報参照インターフェース。
	 */
	protected GoOutReferenceBeanInterface					goOutReference;
	
	/**
	 * 締日管理参照インターフェース。
	 */
	protected CutoffReferenceBeanInterface					cutoffReference;
	
	/**
	 * 申請ユーティリティ。
	 */
	protected RequestUtilBeanInterface						requestUtil;
	

	@Override
	public void initBean() throws MospException {
		// 継承元クラスのメソッドを実行
		super.initBean();
		// 各種クラス準備
		attendanceRegist = (AttendanceRegistBeanInterface)createBean(AttendanceRegistBeanInterface.class);
		attendanceCorrectionReference = (AttendanceCorrectionReferenceBeanInterface)createBean(AttendanceCorrectionReferenceBeanInterface.class);
		attendanceCorrectionRegist = (AttendanceCorrectionRegistBeanInterface)createBean(AttendanceCorrectionRegistBeanInterface.class);
		restRegist = (RestRegistBeanInterface)createBean(RestRegistBeanInterface.class);
		restDao = (RestDaoInterface)createDao(RestDaoInterface.class);
		goOutRegist = (GoOutRegistBeanInterface)createBean(GoOutRegistBeanInterface.class);
		subHolidayRegist = (SubHolidayRegistBeanInterface)createBean(SubHolidayRegistBeanInterface.class);
		attendanceCalc = (AttendanceCalcBeanInterface)createBean(AttendanceCalcBeanInterface.class);
		workflowRegist = (WorkflowRegistBeanInterface)createBean(WorkflowRegistBeanInterface.class);
		overtimeRequestReference = (OvertimeRequestReferenceBeanInterface)createBean(OvertimeRequestReferenceBeanInterface.class);
		holidayRequestReference = (HolidayRequestReferenceBeanInterface)createBean(HolidayRequestReferenceBeanInterface.class);
		subHolidayRequestReference = (SubHolidayRequestReferenceBeanInterface)createBean(SubHolidayRequestReferenceBeanInterface.class);
		differenceReference = (DifferenceRequestReferenceBeanInterface)createBean(DifferenceRequestReferenceBeanInterface.class);
		restReference = (RestReferenceBeanInterface)createBean(RestReferenceBeanInterface.class);
		goOutReference = (GoOutReferenceBeanInterface)createBean(GoOutReferenceBeanInterface.class);
		cutoffReference = (CutoffReferenceBeanInterface)createBean(CutoffReferenceBeanInterface.class);
		requestUtil = (RequestUtilBeanInterface)createBean(RequestUtilBeanInterface.class);
	}
	
	@Override
	public void draft(String personalId, String[] targetDates, String[] startTimes, String[] endTimes)
			throws MospException {
		// 対象個人ID設定
		this.personalId = personalId;
		// 日付リスト取得
		List<Date> targetDateList = getDateList(targetDates);
		// 始業時刻リスト取得
		List<Date> startTimeList = getAttendanceTimeList(targetDateList, startTimes);
		// 終業時刻リスト取得
		List<Date> endTimeList = getAttendanceTimeList(targetDateList, endTimes);
		// エラー確認
		if (mospParams.hasErrorMessage()) {
			return;
		}
		// エラーメッセージリスト
		List<String> errorMessageList = new ArrayList<String>();
		// 対象日毎に勤怠情報を作成して登録
		for (int i = 0; i < targetDateList.size(); i++) {
			// 対象日付設定
			targetDate = targetDateList.get(i);
			// 勤怠データ取得
			AttendanceDtoInterface dto = getAttendanceDto(startTimeList.get(i), endTimeList.get(i), false);
			// エラー確認
			if (mospParams.hasErrorMessage()) {
				errorMessageList.addAll(mospParams.getErrorMessageList());
				mospParams.getErrorMessageList().clear();
				continue;
			}
			// 妥当性チェック
			attendanceRegist.validate(dto);
			// 申請の相関チェック
			attendanceRegist.checkDraft(dto);
			// エラー確認
			if (mospParams.hasErrorMessage()) {
				errorMessageList.addAll(mospParams.getErrorMessageList());
				mospParams.getErrorMessageList().clear();
				continue;
			}
			// ワークフロー番号設定
			draft(dto);
			// 勤怠データ登録
			attendanceRegist.regist(dto);
			// エラー確認
			if (mospParams.hasErrorMessage()) {
				errorMessageList.addAll(mospParams.getErrorMessageList());
				mospParams.getErrorMessageList().clear();
				continue;
			}
		}
		if (!errorMessageList.isEmpty()) {
			mospParams.getErrorMessageList().addAll(errorMessageList);
		}
	}
	
	@Override
	public void apply(String personalId, String[] targetDates, String[] startTimes, String[] endTimes)
			throws MospException {
		// 対象個人ID設定
		this.personalId = personalId;
		// 日付リスト取得
		List<Date> targetDateList = getDateList(targetDates);
		// 始業時刻リスト取得
		List<Date> startTimeList = getAttendanceTimeList(targetDateList, startTimes);
		// 終業時刻リスト取得
		List<Date> endTimeList = getAttendanceTimeList(targetDateList, endTimes);
		// エラー確認
		if (mospParams.hasErrorMessage()) {
			return;
		}
		// エラーメッセージリスト
		List<String> errorMessageList = new ArrayList<String>();
		// 対象日毎に勤怠情報を作成して登録
		for (int i = 0; i < targetDateList.size(); i++) {
			// 対象日付設定
			targetDate = targetDateList.get(i);
			// 勤怠データ取得
			AttendanceDtoInterface dto = getAttendanceDto(startTimeList.get(i), endTimeList.get(i), true);
			// エラー確認
			if (mospParams.hasErrorMessage()) {
				errorMessageList.addAll(mospParams.getErrorMessageList());
				mospParams.getErrorMessageList().clear();
				continue;
			}
			// 申請の相関チェック
			attendanceRegist.checkAppli(dto);
			// エラー確認
			if (mospParams.hasErrorMessage()) {
				errorMessageList.addAll(mospParams.getErrorMessageList());
				mospParams.getErrorMessageList().clear();
				continue;
			}
			// ワークフロー番号設定
			apply(dto);
			// 代休データを登録する。
			registSubHoliday(dto);
			// 勤怠データ登録
			attendanceRegist.regist(dto);
			// エラー確認
			if (mospParams.hasErrorMessage()) {
				errorMessageList.addAll(mospParams.getErrorMessageList());
				mospParams.getErrorMessageList().clear();
				continue;
			}
		}
		if (!errorMessageList.isEmpty()) {
			mospParams.getErrorMessageList().addAll(errorMessageList);
		}
	}
	
	/**
	 * 登録用勤怠データを取得する。<br>
	 * 対象日における勤怠データが存在する場合は、始業時刻及び終業時刻を設定して返す。<br>
	 * <br>
	 * 存在しない場合は、新規に勤怠データを作成し、始業時刻及び終業時刻を設定する。<br>
	 * 勤怠データは、設定適用から各種情報を取得し、作成する。<br>
	 * 勤怠休憩情報、勤怠外出情報が勤務形態に設定されている場合は、これらを登録する。<br>
	 * <br>
	 * 設定適用情報等が存在せず勤怠データを作成できない場合は、nullを返す。<br>
	 * <br>
	 * @param startTime 始業時刻
	 * @param endTime   終業時刻
	 * @param isAppli 申請の場合はtrue、下書の場合はfalse
	 * @return 登録用勤怠データ
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected AttendanceDtoInterface getAttendanceDto(Date startTime, Date endTime, boolean isAppli)
			throws MospException {
		// 勤怠データ新規作成に必要な情報を取得及び設定
		setTimeDtos();
		// 処理結果確認
		if (mospParams.hasErrorMessage()) {
			return null;
		}
		// 勤怠データ取得(個人ID及び日付で取得)
		AttendanceDtoInterface dto = attendanceReference.findForKey(personalId, targetDate, TIMES_WORK_DEFAULT);
		if (dto == null) {
			// 勤怠データを新規に取得
			dto = attendanceRegist.getInitDto();
			// 個人ID設定
			dto.setPersonalId(personalId);
			// 勤務日設定
			dto.setWorkDate(targetDate);
			// 勤務回数設定
			dto.setTimesWork(TIMES_WORK_DEFAULT);
			int checkboxOff = Integer.parseInt(MospConst.CHECKBOX_OFF);
			// その他項目の初期化
			dto.setDirectStart(checkboxOff);
			dto.setDirectEnd(checkboxOff);
			dto.setTimeComment("");
			dto.setLateReason("");
			dto.setLateCertificate("");
			dto.setLateComment("");
			dto.setLeaveEarlyReason("");
			dto.setLeaveEarlyCertificate("");
			dto.setLeaveEarlyComment("");
		}
		// 勤務形態設定
		dto.setWorkTypeCode(workTypeDto.getWorkTypeCode());
		if (differenceDto != null) {
			dto.setWorkTypeCode(differenceDto.getDifferenceType());
		}
		// 始業時刻設定
		dto.setStartTime(startTime);
		// 終業時刻設定
		dto.setEndTime(endTime);
		// 始業終業時刻自動計算
		attendanceCalc.calcStartEndTime(dto, true);
		// 休憩時間
		List<RestDtoInterface> oldRestList = restReference.getRestList(personalId, targetDate, dto.getTimesWork());
		// 公用外出時間
		List<GoOutDtoInterface> oldPublicGoOutList = goOutReference.getPublicGoOutList(personalId, targetDate);
		// 私用外出時間
		List<GoOutDtoInterface> oldPrivateGoOutList = goOutReference.getPrivateGoOutList(personalId, targetDate);
		// 休憩時間登録
		registRest(startTime, endTime, oldRestList);
		// 公用外出時間登録
		registPublicGoOut(startTime, endTime);
		// 私用外出時間登録
		registPrivateGoOut(startTime, endTime);
		// 勤怠データ自動計算
		attendanceCalc.attendanceCalc(dto);
		if (isAppli) {
			// 私用外出チェック
			attendanceRegist.checkPrivateGoOut(dto, restReference.getRestList(personalId, targetDate, dto
				.getTimesWork()), goOutReference.getPrivateGoOutList(personalId, targetDate));
			// 修正履歴を登録
			registCorrection(dto, oldRestList, oldPublicGoOutList, oldPrivateGoOutList);
		}
		return dto;
	}
	
	/**
	 * 対象個人IDの対象日における勤怠データを新規作成するのに必要な
	 * 各種情報を、取得及び設定する。<br>
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void setTimeDtos() throws MospException {
		// 設定適用情報取得及び確認
		applicationDto = applicationReference.findForPerson(personalId, targetDate);
		// 確認
		applicationReference.chkExistApplication(applicationDto, targetDate);
		if (mospParams.hasErrorMessage()) {
			return;
		}
		// カレンダコード取得
		String scheduleCode = applicationDto.getScheduleCode();
		// カレンダ日情報取得
		scheduleDateDto = scheduleDateReference.getScheduleDateInfo(scheduleCode, targetDate, targetDate);
		// 確認
		scheduleDateReference.chkExistScheduleDate(scheduleDateDto, targetDate);
		if (mospParams.hasErrorMessage()) {
			return;
		}
		// 勤務形態コード取得
		String workTypeCode = scheduleDateDto.getWorkTypeCode();
		// 勤怠データ取得
		AttendanceDtoInterface attendanceDto = attendanceReference.findForKey(personalId, targetDate,
				TIMES_WORK_DEFAULT);
		// 勤怠データ確認
		if (attendanceDto != null && !attendanceDto.getWorkTypeCode().isEmpty()
				&& !TimeConst.CODE_DIFFERENCE_TYPE_A.equals(attendanceDto.getWorkTypeCode())
				&& !TimeConst.CODE_DIFFERENCE_TYPE_B.equals(attendanceDto.getWorkTypeCode())
				&& !TimeConst.CODE_DIFFERENCE_TYPE_C.equals(attendanceDto.getWorkTypeCode())
				&& !TimeConst.CODE_DIFFERENCE_TYPE_D.equals(attendanceDto.getWorkTypeCode())
				&& !TimeConst.CODE_DIFFERENCE_TYPE_S.equals(attendanceDto.getWorkTypeCode())) {
			// 勤怠データの勤務形態を取得
			workTypeCode = attendanceDto.getWorkTypeCode();
		}
		// 休日出勤情報取得
		WorkOnHolidayRequestDtoInterface workOnHolidayRequestDto = workOnHoliday.findForKeyOnWorkflow(personalId,
				targetDate);
		// 休日出勤申請確認
		if (workOnHolidayRequestDto != null) {
			// 最新のワークフロー取得
			WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(workOnHolidayRequestDto.getWorkflow());
			// 申請があり、承認済の場合
			if (workflowDto != null && PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
				// 休日出勤申請情報から休日出勤時の予定勤務形態を取得
				workTypeCode = getWorkOnHolidayWorkType(workOnHolidayRequestDto);
			}
		}
		// 勤務形態情報取得
		workTypeDto = workTypeReference.getWorkTypeInfo(workTypeCode, targetDate);
		// 確認
		if (workTypeDto == null) {
			// エラーメッセージ設定
			addWorkTypeNotExistErrorMessage(targetDate);
			return;
		}
		// 勤怠設定情報取得
		timeSettingDto = timeSettingReference.getTimeSettingInfo(applicationDto.getWorkSettingCode(), targetDate);
		// 確認
		timeSettingReference.chkExistTimeSetting(timeSettingDto, targetDate);
		if (mospParams.hasErrorMessage()) {
			return;
		}
		// 時差出勤初期化
		differenceDto = null;
		// 時差出勤
		DifferenceRequestDtoInterface differenceRequestDto = differenceReference.findForKeyOnWorkflow(personalId,
				targetDate);
		if (differenceRequestDto == null) {
			return;
		}
		WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(differenceRequestDto.getWorkflow());
		if (workflowDto == null) {
			return;
		}
		if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
			differenceDto = differenceRequestDto;
		}
	}
	
	@Override
	public List<RestDtoInterface> getRestList(AttendanceDtoInterface dto) throws MospException {
		// 勤怠関連情報を取得
		personalId = dto.getPersonalId();
		targetDate = dto.getWorkDate();
		setTimeDtos();
		if (differenceDto == null) {
			// 勤務形態情報取得
			workTypeDto = workTypeReference.getWorkTypeInfo(dto.getWorkTypeCode(), targetDate);
		}
		return registRest(dto.getStartTime(), dto.getEndTime());
	}
	
	/**
	 * 設定されている勤務形態情報から休憩情報を取得し、登録する。<br>
	 * @param startTime 始業時刻
	 * @param endTime 終業時刻
	 * @param list 休憩リスト
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void registRest(Date startTime, Date endTime, List<RestDtoInterface> list) throws MospException {
		Date initTime = DateUtility.getDateTime(DateUtility.getYear(targetDate), DateUtility.getMonth(targetDate),
				DateUtility.getDay(targetDate), 0, 0);
		List<RestDtoInterface> newList = restReference.getRestList(personalId, targetDate, TIMES_WORK_DEFAULT);
		for (RestDtoInterface dto : newList) {
			if (initTime.equals(dto.getRestStart()) && initTime.equals(dto.getRestEnd())) {
				continue;
			} else if (startTime == null || endTime == null || startTime.after(dto.getRestStart())
					|| endTime.before(dto.getRestEnd())) {
				dto.setRestStart(initTime);
				dto.setRestEnd(initTime);
				dto.setRestTime(0);
				// 登録
				restRegist.regist(dto);
			}
		}
		if (startTime == null || endTime == null) {
			return;
		}
		for (RestDtoInterface dto : list) {
			if (!initTime.equals(dto.getRestStart()) || !initTime.equals(dto.getRestEnd())) {
				return;
			}
		}
		List<RestDtoInterface> restList = registRest(startTime, endTime);
		for (RestDtoInterface dto : restList) {
			//	休憩時間登録
			restRegist.regist(dto);
		}
	}
	
	/**
	 * 設定されている勤務形態情報から休憩情報を取得する。<br>
	 * @param startTime 始業時刻
	 * @param endTime 終業時刻
	 * @return 休憩リスト
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected List<RestDtoInterface> registRest(Date startTime, Date endTime) throws MospException {
		Date initTime = DateUtility.getDateTime(DateUtility.getYear(targetDate), DateUtility.getMonth(targetDate),
				DateUtility.getDay(targetDate), 0, 0);
		List<RestDtoInterface> list = new ArrayList<RestDtoInterface>();
		// 勤務形態マスタ項目情報リスト準備
		List<WorkTypeItemDtoInterface> startList = new ArrayList<WorkTypeItemDtoInterface>();
		List<WorkTypeItemDtoInterface> endList = new ArrayList<WorkTypeItemDtoInterface>();
		createRestTimeList(startTime, endTime, startList, endList);
		// 勤務形態マスタ項目毎に処理
		for (int i = 0; i < startList.size(); i++) {
			Date restStartTime = initTime;
			Date restEndTime = initTime;
			// 休憩情報存在確認
			if (startList.get(i) != null) {
				// 勤務形態マスタ項目情報から休憩開始時刻を取得
				restStartTime = getTime(startList.get(i).getWorkTypeItemValue(), targetDate);
			}
			if (endList.get(i) != null) {
				// 勤務形態マスタ項目情報から休憩終了時刻を取得
				restEndTime = getTime(endList.get(i).getWorkTypeItemValue(), targetDate);
			}
			if (endTime != null && restStartTime.before(endTime) && startTime != null && restEndTime.after(startTime)) {
				// 休憩開始時刻が終業時刻より前且つ
				// 休憩終了時刻が始業時刻より後の場合
				if (restStartTime.before(startTime)) {
					// 休憩開始時刻が始業時刻より前の場合は
					// 始業時刻を休憩開始時刻とする
					restStartTime = startTime;
				}
				if (restEndTime.after(endTime)) {
					// 休憩終了時刻が終業時刻より後の場合は
					// 終業時刻を休憩終了時刻とする
					restEndTime = endTime;
				}
			} else {
				restStartTime = initTime;
				restEndTime = initTime;
			}
			// 休憩情報準備(休憩回数はi + 1)
			RestDtoInterface dto = restRegist.getInitDto();
			RestDtoInterface restDto = restDao.findForKey(personalId, targetDate, TIMES_WORK_DEFAULT, i + 1);
			if (restDto != null) {
				dto.setTmdRestId(restDto.getTmdRestId());
			}
			dto.setPersonalId(personalId);
			dto.setWorkDate(targetDate);
			dto.setTimesWork(TIMES_WORK_DEFAULT);
			dto.setRest(i + 1);
			dto.setRestStart(restStartTime);
			dto.setRestEnd(restEndTime);
			Date roundRestStartTime = attendanceCalc.getRoundMinute(restStartTime, timeSettingDto
				.getRoundDailyRestStart(), timeSettingDto.getRoundDailyRestStartUnit());
			Date roundRestEndTime = attendanceCalc.getRoundMinute(restEndTime, timeSettingDto.getRoundDailyRestEnd(),
					timeSettingDto.getRoundDailyRestEndUnit());
			dto.setRestTime(attendanceCalc.getRoundMinute(getDefferenceMinutes(roundRestStartTime, roundRestEndTime),
					timeSettingDto.getRoundDailyRestTime(), timeSettingDto.getRoundDailyRestTimeUnit()));
			list.add(dto);
		}
		return list;
	}
	
	/**
	 * 休憩時刻リスト作成。<br>
	 * @param startTime 始業時刻
	 * @param endTime 終業時刻
	 * @param startList 休憩開始時刻リスト
	 * @param endList 休憩終了時刻リスト
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void createRestTimeList(Date startTime, Date endTime, List<WorkTypeItemDtoInterface> startList,
			List<WorkTypeItemDtoInterface> endList) throws MospException {
		// 勤務形態コード及び勤務形態有効日取得
		String workTypeCode = workTypeDto.getWorkTypeCode();
		Date activateDate = workTypeDto.getActivateDate();
		if (TimeConst.CODE_WORK_ON_LEGAL_HOLIDAY.equals(workTypeCode)
				|| TimeConst.CODE_WORK_ON_PRESCRIBED_HOLIDAY.equals(workTypeCode)) {
			// 法定休日労働又は所定休日労働の場合
			startList.add(null); // 休憩1
			startList.add(null); // 休憩2
			startList.add(null); // 休憩3
			startList.add(null); // 休憩4
			startList.add(null); // 休憩5
			startList.add(null); // 休憩6
			endList.add(null); // 休憩1
			endList.add(null); // 休憩2
			endList.add(null); // 休憩3
			endList.add(null); // 休憩4
			endList.add(null); // 休憩5
			endList.add(null); // 休憩6
		} else {
			boolean holidayAm = false;
			boolean holidayPm = false;
			// 休暇申請リスト取得
			List<HolidayRequestDtoInterface> holidayList = holidayRequestReference.getHolidayRequestList(personalId,
					targetDate);
			// 休暇申請リスト毎に処理
			for (HolidayRequestDtoInterface dto : holidayList) {
				// ワークフロー取得
				WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(dto.getWorkflow());
				if (workflowDto == null) {
					continue;
				}
				// 承認済でない場合
				if (!PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
					continue;
				}
				int range = dto.getHolidayRange();
				if (range == TimeConst.CODE_HOLIDAY_RANGE_AM) {
					holidayAm = true;
				} else if (range == TimeConst.CODE_HOLIDAY_RANGE_PM) {
					holidayPm = true;
				}
			}
			// 代休申請一覧取得
			List<SubHolidayRequestDtoInterface> subHolidayList = subHolidayRequestReference.getSubHolidayRequestList(
					personalId, targetDate);
			// 代休申請一覧毎に処理
			for (SubHolidayRequestDtoInterface dto : subHolidayList) {
				// ワークフロー取得
				WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(dto.getWorkflow());
				if (workflowDto == null) {
					continue;
				}
				if (!PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
					continue;
				}
				int range = dto.getHolidayRange();
				if (range == TimeConst.CODE_HOLIDAY_RANGE_AM) {
					holidayAm = true;
				} else if (range == TimeConst.CODE_HOLIDAY_RANGE_PM) {
					holidayPm = true;
				}
			}
			if (holidayAm) {
				// 午前休の場合
				WorkTypeItemDtoInterface halfRestDto = workTypeItemReference.findForKey(workTypeCode, activateDate,
						TimeConst.CODE_HALFREST);
				if (endTime != null
						&& halfRestDto != null
						&& DateUtility.getHour(endTime, targetDate) * TimeConst.CODE_DEFINITION_HOUR
								+ DateUtility.getMinute(endTime) >= DateUtility.getHour(halfRestDto
							.getWorkTypeItemValue(), getDefaultStandardDate())
								* TimeConst.CODE_DEFINITION_HOUR
								+ DateUtility.getMinute(halfRestDto.getWorkTypeItemValue())) {
					startList.add(workTypeItemReference.findForKey(workTypeCode, activateDate,
							TimeConst.CODE_HALFRESTSTART));
					endList.add(workTypeItemReference
						.findForKey(workTypeCode, activateDate, TimeConst.CODE_HALFRESTEND));
				} else {
					startList.add(null); // 休憩1
					endList.add(null); // 休憩1
				}
				startList.add(null); // 休憩2
				startList.add(null); // 休憩3
				startList.add(null); // 休憩4
				startList.add(null); // 休憩5
				startList.add(null); // 休憩6
				endList.add(null); // 休憩2
				endList.add(null); // 休憩3
				endList.add(null); // 休憩4
				endList.add(null); // 休憩5
				endList.add(null); // 休憩6
			} else if (holidayPm) {
				// 午後休の場合
				startList.add(null); // 休憩1
				startList.add(null); // 休憩2
				startList.add(null); // 休憩3
				startList.add(null); // 休憩4
				startList.add(null); // 休憩5
				startList.add(null); // 休憩6
				endList.add(null); // 休憩1
				endList.add(null); // 休憩2
				endList.add(null); // 休憩3
				endList.add(null); // 休憩4
				endList.add(null); // 休憩5
				endList.add(null); // 休憩6
			} else {
				startList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTSTART1));
				startList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTSTART2));
				startList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTSTART3));
				startList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTSTART4));
				startList.add(null); // 休憩5
				startList.add(null); // 休憩6
				endList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTEND1));
				endList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTEND2));
				endList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTEND3));
				endList.add(workTypeItemReference.findForKey(workTypeCode, activateDate, TimeConst.CODE_RESTEND4));
				endList.add(null); // 休憩5
				endList.add(null); // 休憩6
			}
		}
	}
	
	/**
	 * 公用外出時間を登録する。<br>
	 * @param startTime 始業時刻
	 * @param endTime 終業時刻
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void registPublicGoOut(Date startTime, Date endTime) throws MospException {
		Date initTime = DateUtility.getDateTime(DateUtility.getYear(targetDate), DateUtility.getMonth(targetDate),
				DateUtility.getDay(targetDate), 0, 0);
		List<GoOutDtoInterface> list = goOutReference.getPublicGoOutList(personalId, targetDate);
		for (GoOutDtoInterface dto : list) {
			if (initTime.equals(dto.getGoOutStart()) && initTime.equals(dto.getGoOutEnd())) {
				continue;
			} else if (startTime == null || endTime == null || dto.getGoOutStart().before(startTime)
					|| dto.getGoOutEnd().after(endTime)) {
				dto.setGoOutStart(initTime);
				dto.setGoOutEnd(initTime);
				dto.setGoOutTime(0);
				// 登録
				goOutRegist.regist(dto);
			}
		}
	}
	
	/**
	 * 私用外出時間を登録する。<br>
	 * @param startTime 始業時刻
	 * @param endTime 終業時刻
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void registPrivateGoOut(Date startTime, Date endTime) throws MospException {
		Date initTime = DateUtility.getDateTime(DateUtility.getYear(targetDate), DateUtility.getMonth(targetDate),
				DateUtility.getDay(targetDate), 0, 0);
		List<GoOutDtoInterface> list = goOutReference.getPrivateGoOutList(personalId, targetDate);
		for (GoOutDtoInterface dto : list) {
			if (initTime.equals(dto.getGoOutStart()) && initTime.equals(dto.getGoOutEnd())) {
				continue;
			} else if (startTime == null || endTime == null || dto.getGoOutStart().before(startTime)
					|| dto.getGoOutEnd().after(endTime)) {
				dto.setGoOutStart(initTime);
				dto.setGoOutEnd(initTime);
				dto.setGoOutTime(0);
				// 登録
				goOutRegist.regist(dto);
			}
		}
	}
	
	@Override
	public void registSubHoliday(AttendanceDtoInterface dto) throws MospException {
		// 勤怠関連情報を取得
		personalId = dto.getPersonalId();
		targetDate = dto.getWorkDate();
		setTimeDtos();
		subHolidayRegist.delete(personalId, targetDate);
		WorkOnHolidayRequestDtoInterface workOnHolidayRequestDto = workOnHoliday.findForKeyOnWorkflow(personalId,
				targetDate);
		if (workOnHolidayRequestDto == null) {
			return;
		}
		if (workOnHolidayRequestDto.getSubstitute() == TimeConst.CODE_WORK_ON_HOLIDAY_SUBSTITUTE_ON) {
			// 振替休日を申請している場合
			return;
		}
		// 最新のワークフロー取得
		WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(workOnHolidayRequestDto.getWorkflow());
		if (workflowDto == null) {
			return;
		}
		if (!PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
			// 申請が承認済でない場合
			return;
		}
		// 代休データ取得
		SubHolidayDtoInterface subHolidayDto = subHolidayRegist.getInitDto();
		subHolidayDto.setPersonalId(dto.getPersonalId());
		subHolidayDto.setWorkDate(dto.getWorkDate());
		subHolidayDto.setTimesWork(dto.getTimesWork());
		if (TimeConst.CODE_HOLIDAY_LEGAL_HOLIDAY.equals(workOnHolidayRequestDto.getWorkOnHolidayType())) {
			// 法定休日代休
			subHolidayDto.setSubHolidayType(TimeConst.CODE_LEGAL_SUBHOLIDAY_CODE);
		} else if (TimeConst.CODE_HOLIDAY_PRESCRIBED_HOLIDAY.equals(workOnHolidayRequestDto.getWorkOnHolidayType())) {
			// 所定休日代休
			subHolidayDto.setSubHolidayType(TimeConst.CODE_PRESCRIBED_SUBHOLIDAY_CODE);
		} else {
			return;
		}
		if (dto.getWorkTime() >= DateUtility.getHour(timeSettingDto.getSubHolidayHalfNorm())
				* TimeConst.CODE_DEFINITION_HOUR + DateUtility.getMinute(timeSettingDto.getSubHolidayHalfNorm())) {
			// 労働時間が代休基準時間(半休)以上の場合は半休とする
			subHolidayDto.setSubHolidayDays(TimeConst.HOLIDAY_TIMES_HALF);
			if (dto.getWorkTime() >= DateUtility.getHour(timeSettingDto.getSubHolidayAllNorm())
					* TimeConst.CODE_DEFINITION_HOUR + DateUtility.getMinute(timeSettingDto.getSubHolidayAllNorm())) {
				// 労働時間が第旧基準時間(全休)以上の場合は全休とする
				subHolidayDto.setSubHolidayDays(TimeConst.HOLIDAY_TIMES_ALL);
			}
			subHolidayRegist.insert(subHolidayDto);
		}
	}
	
	@Override
	public void registCorrection(AttendanceDtoInterface dto, List<RestDtoInterface> restList,
			List<GoOutDtoInterface> publicList, List<GoOutDtoInterface> privateList) throws MospException {
		// 勤怠関連情報を取得
		personalId = dto.getPersonalId();
		targetDate = dto.getWorkDate();
		List<RestDtoInterface> oldRestList = restList;
		List<GoOutDtoInterface> oldPublicList = publicList;
		List<GoOutDtoInterface> oldPrivateList = privateList;
		// ワークフロー番号確認
		if (dto.getWorkflow() != 0) {
			// 既にワークフロー番号が設定されている場合
			// 最新のワークフロー取得
			WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(dto.getWorkflow());
			if (PlatformConst.CODE_STATUS_DRAFT.equals(workflowDto.getWorkflowStatus())) {
				// 下書の場合
				oldRestList = new ArrayList<RestDtoInterface>();
				oldPublicList = new ArrayList<GoOutDtoInterface>();
				oldPrivateList = new ArrayList<GoOutDtoInterface>();
			}
		}
		// DTOの準備
		AttendanceCorrectionDtoInterface attendanceCorrectionDto = attendanceCorrectionRegist.getInitDto();
		// 個人ID
		attendanceCorrectionDto.setPersonalId(personalId);
		// 勤務日。
		attendanceCorrectionDto.setWorkDate(targetDate);
		// 勤務回数
		attendanceCorrectionDto.setWorks(dto.getTimesWork());
		// 修正番号
		AttendanceCorrectionDtoInterface latestDto = attendanceCorrectionReference.getLatestAttendanceCorrectionInfo(
				personalId, targetDate, dto.getTimesWork());
		int correctionTimes = 1;
		if (latestDto != null) {
			correctionTimes += latestDto.getCorrectionTimes();
		}
		attendanceCorrectionDto.setCorrectionTimes(correctionTimes);
		// 修正日時
		attendanceCorrectionDto.setCorrectionDate(getSystemTimeAndSecond());
		// 修正個人ID
		attendanceCorrectionDto.setCorrectionPersonalId(mospParams.getUser().getPersonalId());
		// 修正理由
		attendanceCorrectionDto.setCorrectionReason("");
		// 勤怠修正データ登録
		registAttendanceCorrection(attendanceCorrectionDto, dto);
		// 休憩修正データ登録
		registRestCorrection(attendanceCorrectionDto, oldRestList, restReference.getRestList(personalId, targetDate,
				dto.getTimesWork()));
		// 公用外出修正データ登録
		registGoOutCorrection(attendanceCorrectionDto, oldPublicList, goOutReference.getPublicGoOutList(personalId,
				targetDate));
		// 私用外出修正データ登録
		registGoOutCorrection(attendanceCorrectionDto, oldPrivateList, goOutReference.getPrivateGoOutList(personalId,
				targetDate));
	}
	
	private void registAttendanceCorrection(AttendanceCorrectionDtoInterface dto, AttendanceDtoInterface newDto)
			throws MospException {
		// 勤怠関連情報を取得
		AttendanceDtoInterface oldDto = attendanceReference.findForKey(personalId, targetDate, dto.getWorks());
		if (oldDto == null) {
			oldDto = attendanceRegist.getInitDto();
		}
		// ワークフロー番号確認
		if (newDto.getWorkflow() != 0) {
			// 既にワークフロー番号が設定されている場合
			// 最新のワークフロー取得
			WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(newDto.getWorkflow());
			if (PlatformConst.CODE_STATUS_DRAFT.equals(workflowDto.getWorkflowStatus())) {
				// 下書の場合
				oldDto = attendanceRegist.getInitDto();
			}
		}
		attendanceCorrectionRegist.insertAttendance(dto, oldDto, newDto);
	}
	
	private void registRestCorrection(AttendanceCorrectionDtoInterface dto, List<RestDtoInterface> oldList,
			List<RestDtoInterface> newList) throws MospException {
		for (int i = 0; i < newList.size(); i++) {
			if (i < oldList.size()) {
				if (attendanceCorrectionReference.chkRest(newList.get(i), oldList.get(i))) {
					attendanceCorrectionRegist.insertRest(dto, oldList.get(i), newList.get(i));
				}
			} else {
				if (attendanceCorrectionReference.chkRest(newList.get(i), restRegist.getInitDto())) {
					attendanceCorrectionRegist.insertRest(dto, restRegist.getInitDto(), newList.get(i));
				}
			}
		}
	}
	
	private void registGoOutCorrection(AttendanceCorrectionDtoInterface dto, List<GoOutDtoInterface> oldList,
			List<GoOutDtoInterface> newList) throws MospException {
		for (int i = 0; i < newList.size(); i++) {
			if (i < oldList.size()) {
				if (attendanceCorrectionReference.chkGoOut(newList.get(i), oldList.get(i))) {
					attendanceCorrectionRegist.insertGoOut(dto, oldList.get(i), newList.get(i));
				}
			} else {
				if (attendanceCorrectionReference.chkGoOut(newList.get(i), goOutRegist.getInitDto())) {
					attendanceCorrectionRegist.insertGoOut(dto, goOutRegist.getInitDto(), newList.get(i));
				}
			}
		}
	}
	
	@Override
	public void draft(AttendanceDtoInterface dto) throws MospException {
		// ワークフロー番号確認
		if (dto.getWorkflow() != 0) {
			// 既にワークフロー番号が設定されている場合
			// 最新のワークフロー取得
			WorkflowDtoInterface workflowDto = workflow.getLatestWorkflowInfo(dto.getWorkflow());
			if (PlatformConst.CODE_STATUS_DRAFT.equals(workflowDto.getWorkflowStatus())) {
				// 下書の場合
				return;
			}
			// 下書でない場合
			mospParams.addErrorMessage(TimeMessageConst.MSG_NOT_DRAFT, new String[]{ DateUtility.getStringDate(dto
				.getWorkDate()) });
			return;
		}
		// 勤怠関連情報を取得
		personalId = dto.getPersonalId();
		targetDate = dto.getWorkDate();
		// ワークフロー情報準備
		WorkflowDtoInterface workflowDto = workflowRegist.getInitDto();
		workflowDto.setFunctionCode(TimeConst.CODE_FUNCTION_WORK_MANGE);
		// ワークフロー登録(下書)
		workflowDto = workflowRegist.draft(workflowDto, personalId, targetDate, PlatformConst.WORKFLOW_TYPE_TIME);
		// ワークフロー番号を勤怠データに設定
		dto.setWorkflow(workflowDto.getWorkflow());
	}
	
	/**
	 * 対象勤怠データ情報に対し、
	 * ワークフロー(申請)を作成して、ワークフロー番号を設定する。<br>
	 * @param dto 対象勤怠データ情報
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void apply(AttendanceDtoInterface dto) throws MospException {
		// ワークフロー情報準備
		WorkflowDtoInterface workflowDto = workflowRegist.getInitDto();
		// ワークフロー情報確認
		if (dto.getWorkflow() != 0) {
			// ワークフロー情報取得(新規でない場合)
			workflowDto = workflow.getLatestWorkflowInfo(dto.getWorkflow());
		}
		// ルートコード或いは承認者を設定
		setRouteApprover(workflowDto);
		// ワークフロー情報機能コード設定
		workflowDto.setFunctionCode(TimeConst.CODE_FUNCTION_WORK_MANGE);
		// ワークフロー申請
		workflowDto = workflowRegist.appli(workflowDto, personalId, targetDate, PlatformConst.WORKFLOW_TYPE_TIME, null);
		// ワークフロー申請確認
		if (workflowDto == null) {
			return;
		}
		// ワークフロー番号を勤怠データに設定
		dto.setWorkflow(workflowDto.getWorkflow());
	}
	
	/**
	 * ワークフロー情報に、承認者を設定する。<br>
	 * 一つの階層に複数の承認者が設定されている場合、
	 * 先頭の(職位ランクの最も優れた)承認者を設定する。<br>
	 * @param workflowDto ワークフロー情報
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void setRouteApprover(WorkflowDtoInterface workflowDto) throws MospException {
		// 承認者リスト取得
		List<List<String[]>> routeApproverList = workflow.getRouteApproverList(personalId, targetDate,
				PlatformConst.WORKFLOW_TYPE_TIME);
		// デフォルト承認者リスト作成
		List<String> defaultApproverList = new ArrayList<String>();
		// 承認者リスト毎に処理
		for (List<String[]> stageApproverList : routeApproverList) {
			// デフォルト承認者設定
			defaultApproverList.add(stageApproverList.get(0)[0]);
		}
		// ワークフロー情報に設定
		workflowDto.setApproverId(toSeparatedString(defaultApproverList, PlatformBean.SEPARATOR_DATA));
		// 承認者を指定するためルートコードは不要
		workflowDto.setRouteCode("");
	}
	
	/**
	 * 日付文字列配列を日付オブジェクトリストに変換して取得する。<br>
	 * @param dates 日付文字列配列
	 * @return 日付オブジェクトリスト
	 */
	protected List<Date> getDateList(String[] dates) {
		// リスト準備
		List<Date> list = new ArrayList<Date>();
		// 変換して追加
		for (String date : dates) {
			list.add(DateUtility.getDate(date));
		}
		return list;
	}
	
	/**
	 * 時刻文字列配列を日付オブジジェクトリスト(時刻)に変換して取得する。<br>
	 * 変換の際に、日付リストの日付が基準となる。<br>
	 * @param dateList 日付リスト
	 * @param times 時刻文字列配列
	 * @return 日付オブジェクトリスト(時刻)
	 */
	protected List<Date> getAttendanceTimeList(List<Date> dateList, String[] times) {
		// リスト準備
		List<Date> list = new ArrayList<Date>();
		// 変換して追加
		for (int i = 0; i < times.length; i++) {
			list.add(!times[i].isEmpty() ? getAttendanceTime(dateList.get(i), times[i]) : null);
		}
		return list;
	}
	
	/**
	 * 勤怠申請時に当該申請より残業時間が発生する場合、
	 * 残業申請要否及び残業申請の有無を確認し、必要であれば残業申請を促すメッセージを表示する。
	 * 残業申請督促はするが、勤怠申請自体は行われる。
	 * @param attendanceDto 勤怠データDTOインターフェース
	 * @throws MospException 例外
	 */
	public void checkOvertime(AttendanceDtoInterface attendanceDto) throws MospException {
		// 勤怠申請
		// 勤怠データの後残業時間(tmd_attendance.overtime_after)が0である
		if (attendanceDto.getOvertimeAfter() == 0) {
			// メッセージ不要
			return;
		}
		// 勤怠関連情報を取得
		personalId = attendanceDto.getPersonalId();
		targetDate = attendanceDto.getWorkDate();
		setTimeDtos();
		// エラーチェック
		if (mospParams.hasErrorMessage()) {
			return;
		}
		// 各種申請情報取得
		requestUtil.setRequests(personalId, targetDate);
		// 締め日情報の取得
		CutoffDtoInterface cutoffDto = cutoffReference.getCutoffInfo(timeSettingDto.getCutoffCode(), targetDate);
		if (cutoffDto == null) {
			return;
		}
		int noApproval = cutoffDto.getNoApproval();
		if (noApproval == 0 || noApproval == 2) {
			// 未承認仮締が有効又は無効(残業事前申請のみ)の場合はメッセージ不要
			return;
		}
		// 振出・休出申請を取得
		WorkOnHolidayRequestDtoInterface workOnHolidayRequestDto = requestUtil.getWorkOnHolidayDto(true);
		if (workOnHolidayRequestDto != null
				&& workOnHolidayRequestDto.getSubstitute() == TimeConst.CODE_WORK_ON_HOLIDAY_SUBSTITUTE_OFF) {
			// 振出・休出申請が承認されていて振り替えない場合
			return;
		}
		// 残業申請
		List<OvertimeRequestDtoInterface> overtimeRequestList = requestUtil.getOverTimeList(false);
		for (OvertimeRequestDtoInterface overtimeRequestDto : overtimeRequestList) {
			if (overtimeRequestDto.getOvertimeType() == TimeConst.CODE_OVERTIME_WORK_AFTER) {
				// 勤務後残業申請がある場合
				return;
			}
		}
		// メッセージ追加
		mospParams.addMessage(TimeMessageConst.MSG_REQUEST_CHECK_11, new String[]{ getStringDate(targetDate),
			mospParams.getName("OvertimeWork"), mospParams.getName("OvertimeWork") });
	}
	
	@Override
	public void checkOvertime(String personalId, String[] targetDates) throws MospException {
		// 日付リスト取得
		List<Date> targetDateList = getDateList(targetDates);
		// 勤怠一覧情報参照クラス取得
		AttendanceReferenceBean referenceBean = (AttendanceReferenceBean)createBean(AttendanceReferenceBean.class);
		// 対象日毎に勤怠情報を作成して登録
		for (Date targetDate : targetDateList) {
			// 残業申請督促確認
			checkOvertime(referenceBean.findForKey(personalId, targetDate, TIMES_WORK_DEFAULT));
		}
	}
	
}
