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

import jp.mosp.framework.base.MospException;
import jp.mosp.framework.utils.DateUtility;
import jp.mosp.platform.bean.workflow.WorkflowReferenceBeanInterface;
import jp.mosp.platform.constant.PlatformConst;
import jp.mosp.platform.dto.workflow.WorkflowDtoInterface;
import jp.mosp.time.base.TimeBean;
import jp.mosp.time.bean.ApplicationReferenceBeanInterface;
import jp.mosp.time.bean.AttendanceCalcBeanInterface;
import jp.mosp.time.bean.DifferenceRequestReferenceBeanInterface;
import jp.mosp.time.bean.GoOutReferenceBeanInterface;
import jp.mosp.time.bean.HolidayRequestReferenceBeanInterface;
import jp.mosp.time.bean.OvertimeRequestReferenceBeanInterface;
import jp.mosp.time.bean.RestReferenceBeanInterface;
import jp.mosp.time.bean.ScheduleDateReferenceBeanInterface;
import jp.mosp.time.bean.ScheduleReferenceBeanInterface;
import jp.mosp.time.bean.SubHolidayRequestReferenceBeanInterface;
import jp.mosp.time.bean.SubstituteReferenceBeanInterface;
import jp.mosp.time.bean.TimeSettingReferenceBeanInterface;
import jp.mosp.time.bean.WorkOnHolidayRequestReferenceBeanInterface;
import jp.mosp.time.bean.WorkTypeItemReferenceBeanInterface;
import jp.mosp.time.bean.WorkTypeReferenceBeanInterface;
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.AttendanceDtoInterface;
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.ScheduleDtoInterface;
import jp.mosp.time.dto.settings.SubHolidayRequestDtoInterface;
import jp.mosp.time.dto.settings.SubstituteDtoInterface;
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 AttendanceCalcBean extends TimeBean implements AttendanceCalcBeanInterface {
	
	/**
	 * 勤務日
	 */
	protected Date										workDate;
	
	/**
	 * 出勤時刻
	 */
	protected Date										startTime;
	
	/**
	 * 退勤時刻
	 */
	protected Date										endTime;
	
	/**
	 * 勤務時間
	 */
	protected int										workTime;
	
	/**
	 * 所定労働時間
	 */
	protected int										prescribedWorkTime;
	
	/**
	 * 休暇時間
	 */
	protected int										totalRest;
	
	/**
	 * 公用外出
	 */
	protected int										totalPublic;
	
	/**
	 * 遅刻
	 */
	protected int										lateTime;
	
	/**
	 * 早退
	 */
	protected int										leaveEarlyTime;
	
	/**
	 * 私用外出
	 */
	protected int										totalPrivate;
	
	/**
	 * 休憩リスト
	 */
	protected List<RestDtoInterface>					restDtoList;
	
	/**
	 * 公用外出リスト
	 */
	protected List<GoOutDtoInterface>					publicGoOutDtoList;
	
	/**
	 * 私用外出リスト
	 */
	protected List<GoOutDtoInterface>					privateGoOutDtoList;
	
	/**
	 * 減額対象時間
	 */
	protected int										decreaseTime;
	
	/**
	 * 勤怠設定管理DTOインターフェース
	 */
	protected TimeSettingDtoInterface					timeSettingDto;
	
	/**
	 * 勤務形態項目管理DTOインターフェース
	 */
	protected WorkTypeItemDtoInterface					workTypeItemDto;
	
	/**
	 * 休日出勤申請DTOインターフェース
	 */
	protected WorkOnHolidayRequestDtoInterface			workOnHolidayDto;
	
	/**
	 * 休暇申請DTOインターフェースリスト
	 */
	protected List<HolidayRequestDtoInterface>			holidayRequestDtoList;
	
	/**
	 * 代休申請DTOインターフェースリスト
	 */
	protected List<SubHolidayRequestDtoInterface>		subHolidayRequestDtoList;
	
	/**
	 * カレンダマスタDTOインターフェース
	 */
	protected ScheduleDtoInterface						scheduleDto;
	
	/**
	 * 時差出勤申請DTOインターフェース
	 */
	protected DifferenceRequestDtoInterface				differenceDto;
	
	/**
	 * カレンダ日マスタDTOインターフェース
	 */
	protected ScheduleDateDtoInterface					scheduleDateDto;
	
	/**
	 * 残業申請DTOインターフェース
	 */
	protected OvertimeRequestDtoInterface				beforeOvertimeDto;
	/**
	 * 公用外出時間
	 */
	protected int										totalPublicTime;
	
	/**
	 * 残業時間
	 */
	protected int										overtimeTime;
	
	/**
	 * 規定始業時刻
	 */
	protected int										regWorkStart;
	
	/**
	 * 規定終業時刻
	 */
	protected int										regWorkEnd;
	
	/**
	 * 規定労働時間
	 */
	protected int										regWorkTime;
	
	/**
	 * 残前休憩
	 */
	protected int										overbefore;
	
	/**
	 * 残業休憩時間(毎)
	 */
	protected int										overper;
	
	/**
	 * 残業休憩時間
	 */
	protected int										overrest;
	
	/**
	 * 前半休(開始)
	 */
	protected int										frontStart;
	
	/**
	 * 前半休(終了)
	 */
	protected int										frontEnd;
	
	/**
	 * 後半休(開始)
	 */
	protected int										backStart;
	
	/**
	 * 後半休(終了)
	 */
	protected int										backEnd;
	
	/**
	 * 法定外残業時間
	 */
	protected int										overTimeOut;
	
	/**
	 * 法定外休憩時間
	 */
	protected int										overRestTime;
	
	/**
	 * 深夜勤務時間
	 */
	protected int										lateNightTime;
	
	/**
	 * 深夜休憩時間
	 */
	protected int										lateBreakTime;
	
	/**
	 * 所定休日勤務時間
	 */
	protected int										predeterminedHolidayWorkTime;
	
	/**
	 * 法定休日勤務時間
	 */
	protected int										legalHolidayWorkTime;
	
	/**
	 * 法内残業
	 */
	protected int										withinStatutoryOvertime;
	
	/**
	 * 対象日
	 */
	protected Date										targetDate;
	
	/**
	 * 暦日の所定余り時間
	 */
	protected int										prescribedCalendarDayTime;
	
	/**
	 * 暦日の法定余り時間
	 */
	protected int										legalCalendarDayTime;
	
	/**
	 * 規定始業時刻前時間
	 */
	protected int										workBeforeTime;
	
	/**
	 * 規定終業時刻後時間
	 */
	protected int										workAfterTime;
	
	/**
	 * 勤怠計算上の始業時刻
	 */
	protected int										calculatedStart;
	
	/**
	 * 勤怠計算上の終業時刻
	 */
	protected int										calculatedEnd;
	
	/**
	 * 時間外労働開始時刻
	 */
	protected int										overtimeWorkStart;
	
	/**
	 * 時間外休憩
	 */
	protected Map<Date, Date>							overtimeRestMap;
	
	/**
	 * 
	 */
	protected String									workTypeCode;
	
	/**
	 * 設定適用管理参照インターフェース。<br>
	 */
	private ApplicationReferenceBeanInterface			applicationReference;
	/**
	 * 勤怠設定参照インターフェース。<br>
	 */
	private TimeSettingReferenceBeanInterface			timeSettingReference;
	/**
	 * カレンダ管理参照インターフェース。<br>
	 */
	private ScheduleReferenceBeanInterface				scheduleReference;
	/**
	 * カレンダ日参照インターフェース。<br>
	 */
	private ScheduleDateReferenceBeanInterface			scheduleDateReference;
	/**
	 * 残業申請参照インターフェース。<br>
	 */
	private OvertimeRequestReferenceBeanInterface		overtimeReference;
	/**
	 * 休暇申請参照インターフェース。<br>
	 */
	private HolidayRequestReferenceBeanInterface		holidayReference;
	/**
	 * 代休申請参照インターフェース。<br>
	 */
	private SubHolidayRequestReferenceBeanInterface		subHolidayReference;
	/**
	 * 時差出勤申請参照インターフェース。<br>
	 */
	private DifferenceRequestReferenceBeanInterface		differenceReference;
	/**
	 * 休日出勤申請参照インターフェース。<br>
	 */
	private WorkOnHolidayRequestReferenceBeanInterface	workOnHolidayReference;
	/**
	 * 振替休日データ参照インターフェース。<br>
	 */
	private SubstituteReferenceBeanInterface			substituteReference;
	/**
	 * ワークフロー参照インターフェース。<br>
	 */
	private WorkflowReferenceBeanInterface				workflowReference;
	/**
	 * 勤務形態項目参照インターフェース。<br>
	 */
	private WorkTypeItemReferenceBeanInterface			workTypeItemReference;
	/**
	 * 勤務形態マスタ参照インターフェース。<br>
	 */
	private WorkTypeReferenceBeanInterface				workTypeReference;
	/**
	 * 勤怠データ休憩情報参照インターフェース。<br>
	 */
	private RestReferenceBeanInterface					restReference;
	/**
	 * 勤怠データ外出情報参照インターフェース。<br>
	 */
	private GoOutReferenceBeanInterface					goOutReference;
	

	@Override
	public void initBean() throws MospException {
		applicationReference = (ApplicationReferenceBeanInterface)createBean(ApplicationReferenceBeanInterface.class);
		timeSettingReference = (TimeSettingReferenceBeanInterface)createBean(TimeSettingReferenceBeanInterface.class);
		scheduleReference = (ScheduleReferenceBeanInterface)createBean(ScheduleReferenceBeanInterface.class);
		scheduleDateReference = (ScheduleDateReferenceBeanInterface)createBean(ScheduleDateReferenceBeanInterface.class);
		overtimeReference = (OvertimeRequestReferenceBeanInterface)createBean(OvertimeRequestReferenceBeanInterface.class);
		holidayReference = (HolidayRequestReferenceBeanInterface)createBean(HolidayRequestReferenceBeanInterface.class);
		subHolidayReference = (SubHolidayRequestReferenceBeanInterface)createBean(SubHolidayRequestReferenceBeanInterface.class);
		differenceReference = (DifferenceRequestReferenceBeanInterface)createBean(DifferenceRequestReferenceBeanInterface.class);
		workOnHolidayReference = (WorkOnHolidayRequestReferenceBeanInterface)createBean(WorkOnHolidayRequestReferenceBeanInterface.class);
		substituteReference = (SubstituteReferenceBeanInterface)createBean(SubstituteReferenceBeanInterface.class);
		workflowReference = (WorkflowReferenceBeanInterface)createBean(WorkflowReferenceBeanInterface.class);
		workTypeItemReference = (WorkTypeItemReferenceBeanInterface)createBean(WorkTypeItemReferenceBeanInterface.class);
		workTypeReference = (WorkTypeReferenceBeanInterface)createBean(WorkTypeReferenceBeanInterface.class);
		restReference = (RestReferenceBeanInterface)createBean(RestReferenceBeanInterface.class);
		goOutReference = (GoOutReferenceBeanInterface)createBean(GoOutReferenceBeanInterface.class);
	}
	
	/**
	 * @param personalId 個人ID
	 * @param targetDate 対象年月日
	 * @param workTypeCode 勤務形態コード
	 * @throws MospException  SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	public void initAttendanceTotal(String personalId, Date targetDate, final String workTypeCode) throws MospException {
		// 設定適用マスタDTOインターフェース
		ApplicationDtoInterface applicationDto = applicationReference.findForPerson(personalId, targetDate);
		applicationReference.chkExistApplication(applicationDto, targetDate);
		if (mospParams.hasErrorMessage()) {
			// 該当する設定適用が存在しない
			return;
		}
		// カレンダマスタDTOインターフェース
		ScheduleDtoInterface scheduleDto = scheduleReference.getScheduleInfo(applicationDto.getScheduleCode(),
				targetDate);
		scheduleReference.chkExistSchedule(scheduleDto, targetDate);
		if (mospParams.hasErrorMessage()) {
			// 該当するカレンダマスタが存在しない
			return;
		}
		// 勤怠設定
		timeSettingDto = timeSettingReference.getTimeSettingInfo(applicationDto.getWorkSettingCode(), targetDate);
		timeSettingReference.chkExistTimeSetting(timeSettingDto, targetDate);
		if (mospParams.hasErrorMessage()) {
			// 該当する勤怠設定が存在しない
			return;
		}
		// カレンダ日マスタDTOインターフェース
		scheduleDateDto = scheduleDateReference.getScheduleDateInfo(scheduleDto.getScheduleCode(), targetDate,
				targetDate);
		scheduleDateReference.chkExistScheduleDate(scheduleDateDto, targetDate);
		if (mospParams.hasErrorMessage()) {
			// 該当するカレンダマスタが存在しない
			return;
		}
		// 残業申請
		if (timeSettingDto.getBeforeOvertimeFlag() == TimeConst.CODE_BEFORE_OVERTIME_VALID) {
			OvertimeRequestDtoInterface beforeOvertimeRequestDto = overtimeReference.findForKeyOnWorkflow(personalId,
					targetDate, 1);
			if (beforeOvertimeRequestDto != null) {
				WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(beforeOvertimeRequestDto
					.getWorkflow());
				if (workflowDto != null) {
					if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
						// 承認完了の場合
						beforeOvertimeDto = beforeOvertimeRequestDto;
					}
				}
			}
		}
		// 休暇申請
		holidayRequestDtoList = holidayReference.getHolidayRequestList(personalId, targetDate);
		// 代休申請
		subHolidayRequestDtoList = subHolidayReference.getSubHolidayRequestList(personalId, targetDate);
		// 時差出勤
		differenceDto = differenceReference.findForKeyOnWorkflow(personalId, targetDate);
		// 休日出勤
		WorkOnHolidayRequestDtoInterface workOnHolidayRequestDto = workOnHolidayReference.findForKeyOnWorkflow(
				personalId, targetDate);
		if (workOnHolidayRequestDto != null) {
			WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(workOnHolidayRequestDto
				.getWorkflow());
			if (workflowDto != null) {
				if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
					// 承認完了の場合
					workOnHolidayDto = workOnHolidayRequestDto;
					if (workOnHolidayDto.getSubstitute() == 1) {
						// 振替休日を申請する場合
						List<SubstituteDtoInterface> list = substituteReference.getSubstituteList(workOnHolidayDto
							.getWorkflow());
						for (SubstituteDtoInterface dto : list) {
							ScheduleDateDtoInterface substituteScheduleDateDto = scheduleDateReference
								.getScheduleDateInfo(scheduleDto.getScheduleCode(), targetDate, dto.getSubstituteDate());
							if (substituteScheduleDateDto == null) {
								continue;
							}
							scheduleDateDto = substituteScheduleDateDto;
							break;
						}
					}
				}
			}
		}
		// 対象日の設定
		this.targetDate = targetDate;
		if (workTypeCode == null || workTypeCode.isEmpty() || TimeConst.CODE_DIFFERENCE_TYPE_A.equals(workTypeCode)
				|| TimeConst.CODE_DIFFERENCE_TYPE_B.equals(workTypeCode)
				|| TimeConst.CODE_DIFFERENCE_TYPE_C.equals(workTypeCode)
				|| TimeConst.CODE_DIFFERENCE_TYPE_D.equals(workTypeCode)
				|| TimeConst.CODE_DIFFERENCE_TYPE_S.equals(workTypeCode)) {
			setFields(scheduleDateDto.getWorkTypeCode());
		} else {
			setFields(workTypeCode);
		}
	}
	
	private void setFields(String workTypeCode) throws MospException {
		// カレンダ日マスタの所定休日、法定休日、空欄の場合
		regWorkStart = 0;
		regWorkEnd = 0;
		regWorkTime = 0;
		overbefore = 0;
		overper = 0;
		overrest = 0;
		frontStart = 0;
		frontEnd = 0;
		backStart = 0;
		backEnd = 0;
		this.workTypeCode = workTypeCode;
		if (workTypeCode != null && !workTypeCode.isEmpty()
				&& !TimeConst.CODE_HOLIDAY_PRESCRIBED_HOLIDAY.equals(workTypeCode)
				&& !TimeConst.CODE_HOLIDAY_LEGAL_HOLIDAY.equals(workTypeCode)) {
			// カレンダ日マスタに勤怠コードが設定されている場合
			WorkTypeDtoInterface workTypeDto = workTypeReference.getWorkTypeInfo(workTypeCode, targetDate);
			if (workTypeDto == null) {
				String errorMes = mospParams.getName("Calendar") + mospParams.getName("Day");
				mospParams.addErrorMessage(TimeMessageConst.MSG_APPLICATION_UNSETTING, DateUtility
					.getStringDate(targetDate), errorMes);
				return;
			}
			String localWorkTypeCode = workTypeDto.getWorkTypeCode();
			// 出勤時刻,退勤時刻の取得
			if (differenceDto != null
					&& workflowReference.getLatestWorkflowInfo(differenceDto.getWorkflow()).getWorkflowStatus().equals(
							PlatformConst.CODE_STATUS_COMPLETE)) {
				// 時差出勤から取得する場合
				// 区分がA
				if (TimeConst.CODE_DIFFERENCE_TYPE_A.equals(differenceDto.getDifferenceType())) {
					// A：始業時刻8:00～終業時刻16:00
					regWorkStart = (8 * 60);
					regWorkEnd = (16 * 60);
					if (chkHolidayRequestListRangeAmElement()) {
						// 午前休
						regWorkStart = (12 * 60);
					} else if (chkHolidayRequestListRangePmElement()) {
						// 午後休
						regWorkEnd = (11 * 60) + 30;
					}
				}
				// 区分がB
				if (TimeConst.CODE_DIFFERENCE_TYPE_B.equals(differenceDto.getDifferenceType())) {
					// B：始業時刻8:30～終業時刻16:30
					regWorkStart = (8 * 60) + 30;
					regWorkEnd = (16 * 60) + 30;
					if (chkHolidayRequestListRangeAmElement()) {
						// 午前休
						regWorkStart = (13 * 60);
					} else if (chkHolidayRequestListRangePmElement()) {
						// 午後休
						regWorkEnd = (12 * 60);
					}
				}
				// 区分がC
				if (TimeConst.CODE_DIFFERENCE_TYPE_C.equals(differenceDto.getDifferenceType())) {
					// C：始業時刻9:30～終業時刻17:30
					regWorkStart = (9 * 60) + 30;
					regWorkEnd = (17 * 60) + 30;
					if (chkHolidayRequestListRangeAmElement()) {
						// 午前休
						regWorkStart = (14 * 60);
					} else if (chkHolidayRequestListRangePmElement()) {
						// 午後休
						regWorkEnd = (13 * 60);
					}
				}
				// 区分がD
				if (TimeConst.CODE_DIFFERENCE_TYPE_D.equals(differenceDto.getDifferenceType())) {
					// D：始業時刻10:00～終業時刻18:00
					regWorkStart = (10 * 60);
					regWorkEnd = (18 * 60);
					if (chkHolidayRequestListRangeAmElement()) {
						// 午前休
						regWorkStart = (14 * 60) + 30;
					} else if (chkHolidayRequestListRangePmElement()) {
						// 午後休
						regWorkEnd = (13 * 60) + 30;
					}
				}
				// 区分がS
				if (TimeConst.CODE_DIFFERENCE_TYPE_S.equals(differenceDto.getDifferenceType())) {
					regWorkStart = setHourMinute(differenceDto.getRequestStart());
					regWorkEnd = setHourMinute(differenceDto.getRequestEnd());
					if (chkHolidayRequestListRangeAmElement()) {
						// 午前休
						regWorkStart = setHourMinute(differenceDto.getRequestStart()) + ((4 * 60) + 30);
					} else if (chkHolidayRequestListRangePmElement()) {
						// 午後休
						regWorkEnd = setHourMinute(differenceDto.getRequestEnd()) - ((4 * 60) + 30);
					}
				}
			} else {
				// 勤務形態から取得
				// 出勤時刻
				WorkTypeItemDtoInterface workStartDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
						targetDate, TimeConst.CODE_WORKSTART);
				if (workStartDto != null) {
					regWorkStart = setHourMinute(workStartDto.getWorkTypeItemValue());
				}
				// 退勤時刻
				WorkTypeItemDtoInterface workEndDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
						targetDate, TimeConst.CODE_WORKEND);
				if (workEndDto != null) {
					regWorkEnd = setHourMinute(workEndDto.getWorkTypeItemValue());
				}
			}
			// 規定労働時間
			WorkTypeItemDtoInterface workTimeDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_WORKTIME);
			if (workTimeDto != null) {
				regWorkTime = setHourMinute(workTimeDto.getWorkTypeItemValue());
			}
			// 残前休憩
			WorkTypeItemDtoInterface overBeforeDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_OVERBEFORE);
			if (overBeforeDto != null) {
				overbefore = setHourMinute(overBeforeDto.getWorkTypeItemValue());
			}
			// 残業休憩時間(毎)
			WorkTypeItemDtoInterface overPerDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_OVERPER);
			if (overPerDto != null) {
				overper = setHourMinute(overPerDto.getWorkTypeItemValue());
			}
			// 残業休憩時間
			WorkTypeItemDtoInterface overRestDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_OVERREST);
			if (overRestDto != null) {
				overrest = setHourMinute(overRestDto.getWorkTypeItemValue());
			}
			// 前半休(開始)
			WorkTypeItemDtoInterface frontStartDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_FRONTSTART);
			if (frontStartDto != null) {
				frontStart = setHourMinute(frontStartDto.getWorkTypeItemValue());
			}
			// 前半休(終了)
			WorkTypeItemDtoInterface frontEndDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_FRONTEND);
			if (frontEndDto != null) {
				frontEnd = setHourMinute(frontEndDto.getWorkTypeItemValue());
			}
			// 後半休(開始)
			WorkTypeItemDtoInterface backStartDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_BACKSTART);
			if (backStartDto != null) {
				backStart = setHourMinute(backStartDto.getWorkTypeItemValue());
			}
			// 後半休(終了)
			WorkTypeItemDtoInterface backEndDto = workTypeItemReference.getWorkTypeItemInfo(localWorkTypeCode,
					targetDate, TimeConst.CODE_BACKEND);
			if (backEndDto != null) {
				backEnd = setHourMinute(backEndDto.getWorkTypeItemValue());
			}
		}
	}
	
	/**
	 * 出勤時刻の出力
	 * @return 出勤時刻
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	protected Date getStartTime() throws MospException {
		// 勤怠設定管理DTOが存在しない
		if (timeSettingDto == null) {
			return null;
		}
		// 丸め単位
		return getItmeDateTime(startTime, timeSettingDto.getRoundDailyStartUnit(), timeSettingDto.getRoundDailyStart());
	}
	
	/**
	 * 退勤時刻の出力
	 * @return 退勤時刻
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	public Date getEndTime() throws MospException {
		// 勤怠設定管理DTOが存在しない
		if (timeSettingDto == null) {
			return null;
		}
		// 丸め単位
		return getItmeDateTime(endTime, timeSettingDto.getRoundDailyEndUnit(), timeSettingDto.getRoundDailyEnd());
	}
	
	/**
	 * 勤務時間の出力
	 * @return 勤務時間
	 */
	public int getWorkTime() {
		// 勤怠設定管理DTOが存在しない
		if (timeSettingDto == null) {
			return 0;
		}
		// 丸め単位 
		return getCheckCalcResults(roundingTreatmentCalc(workTime, timeSettingDto.getRoundDailyWorkUnit(),
				timeSettingDto.getRoundDailyWork()));
	}
	
	/**
	 * 遅刻の出力
	 * @return 遅刻
	 */
	public int getLateTime() {
		// 勤怠設定管理DTOが存在しない
		if (timeSettingDto == null) {
			return 0;
		}
		// 丸め処理
		return getCheckCalcResults(roundingTreatmentCalc(lateTime, timeSettingDto.getRoundDailyLateUnit(),
				timeSettingDto.getRoundDailyLate()));
	}
	
	/**
	 * 早退の出力
	 * @return 早退
	 */
	public int getLeaveEarlyTime() {
		// 勤怠設定管理DTOが存在しない
		if (timeSettingDto == null) {
			return 0;
		}
		// 丸め処理
		return getCheckCalcResults(roundingTreatmentCalc(leaveEarlyTime, timeSettingDto.getRoundDailyLeaveEarlyUnit(),
				timeSettingDto.getRoundDailyLeaveEarly()));
	}
	
	/**
	 * 減額対象時間の出力
	 * @return 減額対象時間
	 */
	public int getDecreaseTime() {
		// 勤怠設定管理DTOが存在しない
		if (timeSettingDto == null) {
			return 0;
		}
		// 丸め処理
		return getCheckCalcResults(roundingTreatmentCalc(decreaseTime, timeSettingDto.getRoundDailyDecreaseTimeUnit(),
				timeSettingDto.getRoundDailyDecreaseTime()));
	}
	
	/**
	 * @return overtimeTime
	 */
	public int getOvertimeTime() {
		return getRoundMinute(overtimeTime, timeSettingDto.getRoundDailyWork(), timeSettingDto.getRoundDailyWorkUnit());
	}
	
	/**
	 * @return overTimeOut
	 */
	public int getOverTimeOut() {
		return getRoundMinute(overTimeOut, timeSettingDto.getRoundDailyWork(), timeSettingDto.getRoundDailyWorkUnit());
	}
	
	/**
	 * @return predeterminedHolidayWorkTime
	 */
	public int getPredeterminedHolidayWorkTime() {
		return predeterminedHolidayWorkTime;
	}
	
	/**
	 * @return withinStatutoryOvertime
	 */
	public int getWithinStatutoryOvertime() {
		return getRoundMinute(withinStatutoryOvertime, timeSettingDto.getRoundDailyWork(), timeSettingDto
			.getRoundDailyWorkUnit());
	}
	
	/**
	 * @return legalHolidayWorkTime
	 */
	public int getLegalHolidayWorkTime() {
		return legalHolidayWorkTime;
	}
	
	/**
	 * @return lateNightTime
	 */
	public int getLateNightTime() {
		return getRoundMinute(lateNightTime, timeSettingDto.getRoundDailyWork(), timeSettingDto.getRoundDailyWorkUnit());
	}
	
	/**
	 * @return lateBreakTime
	 */
	public int getLateBreakTime() {
		return lateBreakTime;
	}
	
	/**
	 * @return overRestTime
	 */
	public int getOverRestTime() {
		return getCheckCalcResults(overRestTime);
	}
	
	/**
	 * @param totalRest セットする totalRest
	 */
	public void setTotaltRest(int totalRest) {
		this.totalRest = totalRest;
	}
	
	/**
	 * @param lateTime セットする lateTime
	 */
	public void setLateTime(int lateTime) {
		this.lateTime = lateTime;
	}
	
	/**
	 * @param leaveEarlyTime セットする leaveEarlyTime
	 */
	public void setLeaveEarlyTime(int leaveEarlyTime) {
		this.leaveEarlyTime = leaveEarlyTime;
	}
	
	/**
	 * @param decreaseTime セットする decreaseTime
	 */
	public void setDecreaseTime(int decreaseTime) {
		this.decreaseTime = decreaseTime;
	}
	
	/**
	 * @param overTimeOut セットする overTimeOut
	 */
	public void setOverTimeOut(int overTimeOut) {
		this.overTimeOut = overTimeOut;
	}
	
	/**
	 * @param overRestTime セットする overRestTime
	 */
	public void setOverRestTime(int overRestTime) {
		this.overRestTime = overRestTime;
	}
	
	/**
	 * @param predeterminedHolidayWorkTime セットする predeterminedHolidayWorkTime
	 */
	public void setPredeterminedHolidayWorkTime(int predeterminedHolidayWorkTime) {
		this.predeterminedHolidayWorkTime = predeterminedHolidayWorkTime;
	}
	
	/**
	 * @param legalHolidayWorkTime セットする legalHolidayWorkTime
	 */
	public void setLegalHolidayWorkTime(int legalHolidayWorkTime) {
		this.legalHolidayWorkTime = legalHolidayWorkTime;
	}
	
	/**
	 * @param withinStatutoryOvertime セットする withinStatutoryOvertime
	 */
	public void setWithinStatutoryOvertime(int withinStatutoryOvertime) {
		this.withinStatutoryOvertime = withinStatutoryOvertime;
	}
	
	/* 自動計算 */
	/**
	 * 労働時間を計算する。<br>
	 * 合わせて休憩時間を計算する。<br>
	 */
	private void calcWorkTime() {
		// 初期化
		overtimeRestMap = new TreeMap<Date, Date>();
		int totalManualRest = 0;
		for (RestDtoInterface dto : restDtoList) {
			totalManualRest += dto.getRestTime();
		}
		// 休日出勤申請
		if (workOnHolidayDto != null && workOnHolidayDto.getSubstitute() == 2) {
			// 休日出勤申請があり且つ振り替えない場合
			// 休憩の合計値
			totalRest = totalManualRest;
			workTime = calculatedEnd - calculatedStart - totalRest - totalPublic - totalPrivate;
			return;
		}
		Map<Date, Date> map = new TreeMap<Date, Date>();
		for (RestDtoInterface dto : restDtoList) {
			Date startTime = getRoundMinute(dto.getRestStart(), timeSettingDto.getRoundDailyRestStart(), timeSettingDto
				.getRoundDailyRestStartUnit());
			Date endTime = getRoundMinute(dto.getRestEnd(), timeSettingDto.getRoundDailyRestEnd(), timeSettingDto
				.getRoundDailyRestEndUnit());
			if (map.containsKey(startTime)) {
				if (map.get(startTime).before(endTime)) {
					map.put(startTime, endTime);
				}
			} else {
				map.put(startTime, endTime);
			}
		}
		for (GoOutDtoInterface dto : publicGoOutDtoList) {
			Date startTime = getRoundMinute(dto.getGoOutStart(), timeSettingDto.getRoundDailyPublicStart(),
					timeSettingDto.getRoundDailyPublicStartUnit());
			Date endTime = getRoundMinute(dto.getGoOutEnd(), timeSettingDto.getRoundDailyPublicEnd(), timeSettingDto
				.getRoundDailyPublicEndUnit());
			if (map.containsKey(startTime)) {
				if (map.get(startTime).before(endTime)) {
					map.put(startTime, endTime);
				}
			} else {
				map.put(startTime, endTime);
			}
		}
		for (GoOutDtoInterface dto : privateGoOutDtoList) {
			Date startTime = getRoundMinute(dto.getGoOutStart(), timeSettingDto.getRoundDailyPrivateStart(),
					timeSettingDto.getRoundDailyPrivateStartUnit());
			Date endTime = getRoundMinute(dto.getGoOutEnd(), timeSettingDto.getRoundDailyPrivateEnd(), timeSettingDto
				.getRoundDailyPrivateEndUnit());
			if (map.containsKey(startTime)) {
				if (map.get(startTime).before(endTime)) {
					map.put(startTime, endTime);
				}
			} else {
				map.put(startTime, endTime);
			}
		}
		int time = calculatedStart;
		int tmpWorkTime = 0;
		int scheduledWorkEndTime = 0;
		for (Entry<Date, Date> entry : map.entrySet()) {
			Date mapStartTime = entry.getKey();
			Date mapEndTime = entry.getValue();
			int mapStartTimeInt = DateUtility.getHour(mapStartTime) * TimeConst.CODE_DEFINITION_HOUR
					+ DateUtility.getMinute(mapStartTime);
			if (time <= mapStartTimeInt) {
				int addWorkTime = mapStartTimeInt - time;
				if (tmpWorkTime + addWorkTime >= prescribedWorkTime) {
					// 勤務時間に追加勤務時間を加えたものが所定労働時間以上の場合は
					// 時間に所定労働時間から勤務時間を引いたものが
					// 所定労働時間終了時刻となる
					scheduledWorkEndTime = time + (prescribedWorkTime - tmpWorkTime);
					break;
				}
				tmpWorkTime += addWorkTime;
				time = DateUtility.getHour(mapEndTime) * 60 + DateUtility.getMinute(mapEndTime);
			}
		}
		if (scheduledWorkEndTime == 0) {
			int remainWorkTime = calculatedEnd - time;
			if (tmpWorkTime + remainWorkTime <= prescribedWorkTime) {
				totalRest = totalManualRest;
				workTime = calculatedEnd - calculatedStart - totalRest - totalPublic - totalPrivate;
				return;
			} else {
				scheduledWorkEndTime = time + (prescribedWorkTime - tmpWorkTime);
			}
		}
		if (scheduledWorkEndTime + overbefore >= calculatedEnd) {
			// 終業時刻が残前休憩終了時刻以前の場合
			int overtimeBeforeTime = calculatedEnd - scheduledWorkEndTime;
			totalRest = totalManualRest + overtimeBeforeTime;
			workTime = calculatedEnd - calculatedStart - totalRest - totalPublic - totalPrivate;
			return;
		}
		// 時間外労働開始時刻
		overtimeWorkStart = scheduledWorkEndTime + overbefore;
		// 残業時間
		int totalOvertimeTime = calculatedEnd - overtimeWorkStart;
		// 残業休憩繰越回数の設定
		int overtimeRestTimes = 0;
		if (overper > 1) {
			overtimeRestTimes = totalOvertimeTime / overper;
		}
		// 残業休憩時間
		int totalOvertimeRest = overrest * overtimeRestTimes;
		int previousOvertimeRestEndTime = overtimeWorkStart;
		for (int i = 0; i < overtimeRestTimes; i++) {
			int overtimeRestStartTime = previousOvertimeRestEndTime + overper - overrest;
			int overtimeRestEndTime = previousOvertimeRestEndTime + overper;
			overtimeRestMap.put(getAttendanceTime(workDate, overtimeRestStartTime), getAttendanceTime(workDate,
					overtimeRestEndTime));
			previousOvertimeRestEndTime = overtimeRestEndTime;
		}
		totalRest = totalManualRest + overbefore + totalOvertimeRest;
		workTime = calculatedEnd - calculatedStart - totalRest - totalPublic - totalPrivate;
	}
	
	/**
	 * 法定外時間の計算
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	private void setLegalOutTimeCalc() throws MospException {
		if (workOnHolidayDto != null && workOnHolidayDto.getSubstitute() == 2) {
			// 休日出勤申請があり且つ振り替えない場合
			if (TimeConst.CODE_HOLIDAY_LEGAL_HOLIDAY.equals(workOnHolidayDto.getWorkOnHolidayType())) {
				// 法定休日出勤の場合
				overTimeOut = 0;
			}
		}
		// 法定外勤務時間設定
		int overTimeOut = 0;
		// 法定外休憩時間設定
		int overRestTime = 0;
		// スケジュール内の勤務形態コードが所定、法定で無い場合
		if (!TimeConst.CODE_HOLIDAY_PRESCRIBED_HOLIDAY.equals(workTypeCode)
				&& !TimeConst.CODE_HOLIDAY_LEGAL_HOLIDAY.equals(workTypeCode)
				&& !TimeConst.CODE_WORK_ON_PRESCRIBED_HOLIDAY.equals(workTypeCode)
				&& !TimeConst.CODE_WORK_ON_LEGAL_HOLIDAY.equals(workTypeCode)) {
			// 法定外勤務時間設定の設定
//			int localWorkTime = getHourMinuteInt(endTime) - getHourMinuteInt(startTime);
//			if (8 * 60 < localWorkTime) {
			// TODO 今後対応
//				overTimeOut = (getWorkTime() - (8 * 60));
//			} else {
//				overTimeOut = (getWorkTime() - (8 * 60));
//			}
			overTimeOut = getOvertimeTime() - getWithinStatutoryOvertime();
		}
		// 法定外勤務時間設定		
		setOverTimeOut(overTimeOut);
		// 法定外休憩時間設定
		setOverRestTime(overRestTime);
	}
	
	/**
	 * 公用外出時間の計算
	 */
	private void calcPublicGoOutTime() {
		int total = 0;
		for (GoOutDtoInterface dto : publicGoOutDtoList) {
			total += dto.getGoOutTime();
		}
		totalPublic = total;
	}
	
	/**
	 * 私用外出時間の計算
	 */
	private void calcPrivateGoOutTime() {
		int total = 0;
		for (GoOutDtoInterface dto : privateGoOutDtoList) {
			total += dto.getGoOutTime();
		}
		totalPrivate = total;
	}
	
	/**
	 * 遅刻時間の計算
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	private void setTardinessTimeCalc() throws MospException {
		// 限度時間を越えている場合は申請時の確認処理でチェックする
		
		// 初期化
		int lateTimeCale = 0;
		// 休日出勤申請が存在している場合、休日出勤を行う。
		if (workOnHolidayDto != null) {
			// ワークフローDTO
			WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(workOnHolidayDto.getWorkflow());
			// 申請状態が完了チェック
			if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
				if (workOnHolidayDto.getSubstitute() == 1) {
					// 振替休日を申請している場合
					List<SubstituteDtoInterface> list = substituteReference.getSubstituteList(workOnHolidayDto
						.getWorkflow());
					boolean isSubstituteAll = false;
					boolean isSubstituteAm = false;
					boolean isSubstitutePm = false;
					for (SubstituteDtoInterface substituteDto : list) {
						int substituteRange = substituteDto.getSubstituteRange();
						if (substituteRange == 1) {
							// 全休の場合
							isSubstituteAll = true;
						} else if (substituteRange == 2) {
							// 午前休の場合
							isSubstituteAm = true;
						} else if (substituteRange == 3) {
							// 午後休の場合
							isSubstitutePm = true;
						}
					}
					if (isSubstituteAll) {
						boolean isHolidayAm = false;
						// 休暇申請
						for (HolidayRequestDtoInterface holidayRequestDto : holidayRequestDtoList) {
							WorkflowDtoInterface holidayRequestWorkflowDto = workflowReference
								.getLatestWorkflowInfo(holidayRequestDto.getWorkflow());
							if (PlatformConst.CODE_STATUS_COMPLETE
								.equals(holidayRequestWorkflowDto.getWorkflowStatus())) {
								if (holidayRequestDto.getHolidayRange() == 2) {
									// 午前半休の場合
									isHolidayAm = true;
									break;
								}
							}
						}
						// 代休申請
						for (SubHolidayRequestDtoInterface requestDto : subHolidayRequestDtoList) {
							WorkflowDtoInterface requestWorkflowDto = workflowReference
								.getLatestWorkflowInfo(requestDto.getWorkflow());
							if (requestWorkflowDto == null) {
								continue;
							}
							if (PlatformConst.CODE_STATUS_COMPLETE.equals(requestWorkflowDto.getWorkflowStatus())) {
								if (requestDto.getHolidayRange() == 2) {
									// 午前半休の場合
									isHolidayAm = true;
									break;
								}
							}
						}
						// 出勤時刻 - 勤務形態の開始時間
						lateTimeCale = getHourMinuteInt(getStartTime()) - regWorkStart;
						if (isHolidayAm) {
							// 出勤時間 - 後半休
							lateTimeCale = getHourMinuteInt(getStartTime()) - backStart;
						}
					} else if (isSubstituteAm) {
						// 出勤時間 - 前半休
						lateTimeCale = getHourMinuteInt(getStartTime()) - frontStart;
					} else if (isSubstitutePm) {
						// 出勤時間 - 後半休
						lateTimeCale = getHourMinuteInt(getStartTime()) - backStart;
					}
				}
			}
		} else if ((holidayRequestDtoList != null && !holidayRequestDtoList.isEmpty())
				|| (subHolidayRequestDtoList != null && !subHolidayRequestDtoList.isEmpty())) {
			boolean holidayFlag = false;
			if (differenceDto == null) {
				// 休暇申請
				if (chkHolidayRequestListRangeAmElement()) {
					holidayFlag = true;
				}
				// 代休申請
				for (SubHolidayRequestDtoInterface requestDto : subHolidayRequestDtoList) {
					WorkflowDtoInterface workflowDto = workflowReference
						.getLatestWorkflowInfo(requestDto.getWorkflow());
					if (workflowDto == null) {
						continue;
					}
					if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
						if (requestDto.getHolidayRange() == 2) {
							holidayFlag = true;
							break;
						}
					}
				}
			}
			if (holidayFlag) {
				if (workTypeItemReference.getWorkTypeItemInfo(workTypeCode, targetDate, TimeConst.CODE_BACKSTART) != null) {
					regWorkStart = setHourMinute(workTypeItemReference.getWorkTypeItemInfo(workTypeCode, targetDate,
							TimeConst.CODE_BACKSTART).getWorkTypeItemValue());
					lateTimeCale = getHourMinuteInt(getStartTime()) - regWorkStart;
				}
			}
		} else {
			// 出勤時刻 - 勤務形態の開始時間
			if (getStartTime() != null) {
				lateTimeCale = getHourMinuteInt(getStartTime()) - regWorkStart;
			}
		}
		setLateTime(lateTimeCale);
	}
	
	/**
	 * 早退時間の計算
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	private void setLeaveEarlyTimeCalc() throws MospException {
		// 限度時間を越えている場合は申請時の確認処理でチェックする
		
		// 初期化
		int leaveEarlyTimeCale = 0;
		// 休日出勤の場合
		if (workOnHolidayDto != null) {
			// ワークフローDTO
			WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(workOnHolidayDto.getWorkflow());
			// 申請状態が完了チェック
			if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
				if (workOnHolidayDto.getSubstitute() == 1) {
					// 振替休日を申請している場合
					List<SubstituteDtoInterface> list = substituteReference.getSubstituteList(workOnHolidayDto
						.getWorkflow());
					boolean isSubstituteAll = false;
					boolean isSubstituteAm = false;
					boolean isSubstitutePm = false;
					for (SubstituteDtoInterface substituteDto : list) {
						int substituteRange = substituteDto.getSubstituteRange();
						if (substituteRange == 1) {
							// 全休の場合
							isSubstituteAll = true;
						} else if (substituteRange == 2) {
							// 午前休の場合
							isSubstituteAm = true;
						} else if (substituteRange == 3) {
							// 午後休の場合
							isSubstitutePm = true;
						}
					}
					if (isSubstituteAll) {
						boolean isHolidayPm = false;
						// 休暇申請
						for (HolidayRequestDtoInterface holidayRequestDto : holidayRequestDtoList) {
							WorkflowDtoInterface holidayRequestWorkflowDto = workflowReference
								.getLatestWorkflowInfo(holidayRequestDto.getWorkflow());
							if (PlatformConst.CODE_STATUS_COMPLETE
								.equals(holidayRequestWorkflowDto.getWorkflowStatus())) {
								if (holidayRequestDto.getHolidayRange() == 3) {
									// 午後半休の場合
									isHolidayPm = true;
									break;
								}
							}
						}
						// 代休申請
						for (SubHolidayRequestDtoInterface requestDto : subHolidayRequestDtoList) {
							WorkflowDtoInterface requestWorkflowDto = workflowReference
								.getLatestWorkflowInfo(requestDto.getWorkflow());
							if (requestWorkflowDto == null) {
								continue;
							}
							if (PlatformConst.CODE_STATUS_COMPLETE.equals(requestWorkflowDto.getWorkflowStatus())) {
								if (requestDto.getHolidayRange() == 3) {
									// 午後半休の場合
									isHolidayPm = true;
									break;
								}
							}
						}
						// 勤務形態の終了時間 - 退勤時刻
						leaveEarlyTimeCale = regWorkEnd - getCheckEndTime();
						if (isHolidayPm) {
							// 前半休 - 退勤時刻
							leaveEarlyTimeCale = frontEnd - getHourMinuteInt(getStartTime());
						}
					} else if (isSubstituteAm) {
						// 前半休 - 退勤時刻
						leaveEarlyTimeCale = frontEnd - getHourMinuteInt(getStartTime());
					} else if (isSubstitutePm) {
						// 後半休 - 退勤時刻
						leaveEarlyTimeCale = backEnd - getHourMinuteInt(getStartTime());
					}
				}
			}
		} else if (holidayRequestDtoList != null && holidayRequestDtoList.size() != 0) {
			boolean holidayFlag = false;
			if (differenceDto == null) {
				if (chkHolidayRequestListRangePmElement()) {
					holidayFlag = true;
				}
				// 代休申請
				for (SubHolidayRequestDtoInterface requestDto : subHolidayRequestDtoList) {
					WorkflowDtoInterface workflowDto = workflowReference
						.getLatestWorkflowInfo(requestDto.getWorkflow());
					if (workflowDto == null) {
						continue;
					}
					if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
						if (requestDto.getHolidayRange() == 3) {
							holidayFlag = true;
							break;
						}
					}
				}
			}
			if (holidayFlag) {
				regWorkEnd = setHourMinute(workTypeItemReference.getWorkTypeItemInfo(workTypeCode, targetDate,
						TimeConst.CODE_FRONTEND).getWorkTypeItemValue());
				leaveEarlyTimeCale = regWorkEnd - getCheckEndTime();
			}
		} else {
			// 勤務形態の終了時間 - 退勤時刻
			leaveEarlyTimeCale = regWorkEnd - getCheckEndTime();
		}
		setLeaveEarlyTime(leaveEarlyTimeCale);
	}
	
	/**
	 * 残業時間の計算
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	private void setOvertimeTimeCalc() throws MospException {
		// 初期化
		overtimeTime = 0;
		int previousOvertime = 0;
		// 合計残業時間
		int totalOvertime = 0;
		// 残業休憩繰越回数
		int overtimeRestNum = 0;
		// 余り時間の初期化
		prescribedCalendarDayTime = 0;
		legalCalendarDayTime = 0;
		// 休日出勤申請
		if (workOnHolidayDto != null && workOnHolidayDto.getSubstitute() == 2) {
			// 休日出勤申請があり且つ振り替えない場合
			if (scheduleDateDto.getWorkTypeCode().equals(TimeConst.CODE_HOLIDAY_PRESCRIBED_HOLIDAY)) {
				// 所定休日の場合、労働時間を残業時間に設定
				overtimeTime = getWorkTime();
			}
			return;
		}
		if (getWorkTime() <= prescribedWorkTime) {
			// 労働時間が所定労働時間以下の場合
			return;
		}
		// 深夜労働開始時刻以後の合計手動休憩時間
		int totalManualRest = 0;
		for (RestDtoInterface dto : restDtoList) {
			Date startTime = getRoundMinute(dto.getRestStart(), timeSettingDto.getRoundDailyRestStart(), timeSettingDto
				.getRoundDailyRestStartUnit());
			Date endTime = getRoundMinute(dto.getRestEnd(), timeSettingDto.getRoundDailyRestEnd(), timeSettingDto
				.getRoundDailyRestEndUnit());
			int start = getDefferenceMinutes(workDate, startTime);
			int end = getDefferenceMinutes(workDate, endTime);
			if (start < 24 * TimeConst.CODE_DEFINITION_HOUR && end > overtimeWorkStart) {
				if (start < overtimeWorkStart) {
					start = overtimeWorkStart;
				}
				if (end > 24 * TimeConst.CODE_DEFINITION_HOUR) {
					end = 24 * TimeConst.CODE_DEFINITION_HOUR;
				}
				totalManualRest += getRoundMinute(end - start, timeSettingDto.getRoundDailyRestTime(), timeSettingDto
					.getRoundDailyRestTimeUnit());
			}
		}
		// 深夜労働開始時刻以後の合計公用外出時間
		int totalPublicGoOut = 0;
		for (GoOutDtoInterface dto : publicGoOutDtoList) {
			Date startTime = getRoundMinute(dto.getGoOutStart(), timeSettingDto.getRoundDailyPublicStart(),
					timeSettingDto.getRoundDailyPublicStartUnit());
			Date endTime = getRoundMinute(dto.getGoOutEnd(), timeSettingDto.getRoundDailyPublicEnd(), timeSettingDto
				.getRoundDailyPublicEndUnit());
			int start = getDefferenceMinutes(workDate, startTime);
			int end = getDefferenceMinutes(workDate, endTime);
			if (start < 24 * TimeConst.CODE_DEFINITION_HOUR && end > overtimeWorkStart) {
				if (start < overtimeWorkStart) {
					start = overtimeWorkStart;
				}
				if (end > 24 * TimeConst.CODE_DEFINITION_HOUR) {
					end = 24 * TimeConst.CODE_DEFINITION_HOUR;
				}
				totalPublicGoOut += end - start;
			}
		}
		// 深夜労働開始時刻以後の合計私用外出時間
		int totalPrivateGoOut = 0;
		for (GoOutDtoInterface dto : privateGoOutDtoList) {
			Date startTime = getRoundMinute(dto.getGoOutStart(), timeSettingDto.getRoundDailyPrivateStart(),
					timeSettingDto.getRoundDailyPrivateStartUnit());
			Date endTime = getRoundMinute(dto.getGoOutEnd(), timeSettingDto.getRoundDailyPrivateEnd(), timeSettingDto
				.getRoundDailyPrivateEndUnit());
			int start = getDefferenceMinutes(workDate, startTime);
			int end = getDefferenceMinutes(workDate, endTime);
			if (start < 24 * TimeConst.CODE_DEFINITION_HOUR && end > overtimeWorkStart) {
				if (start < overtimeWorkStart) {
					start = overtimeWorkStart;
				}
				if (end > 24 * TimeConst.CODE_DEFINITION_HOUR) {
					end = 24 * TimeConst.CODE_DEFINITION_HOUR;
				}
				totalPrivateGoOut += end - start;
			}
		}
		// 合計残業時間の設定
		totalOvertime = calculatedEnd - overtimeWorkStart;
		// 暦日の対応
		// (残業開始時間＋残業時間)が24時を超えている場合、勤怠設定画面のフラグを確認する
		if (overtimeWorkStart + totalOvertime > (24 * 60)) {
			// 所定休日取扱が暦日の場合（1：通常、2：暦日）
			if (timeSettingDto.getSpecificHolidayHandling() == 2) {
				// 暦日の場合、対象日の次の日のカレンダを取得
				ScheduleDateDtoInterface nextScheduleDateDto = scheduleDateReference.getScheduleDateInfo(scheduleDto
					.getScheduleCode(), DateUtility.addDay(targetDate, 1), DateUtility.addDay(targetDate, 1));
				if (nextScheduleDateDto != null) {
					// 次の日のカレンダを確認し、カレンダが休日（所定、法定）の場合
					if (TimeConst.CODE_HOLIDAY_PRESCRIBED_HOLIDAY.equals(nextScheduleDateDto.getWorkTypeCode())) {
						// 余り時間の取得
						prescribedCalendarDayTime = totalOvertime + previousOvertime - (24 * 60);
					} else if (TimeConst.CODE_HOLIDAY_LEGAL_HOLIDAY.equals(nextScheduleDateDto.getWorkTypeCode())) {
						// 余り時間の取得
						legalCalendarDayTime = totalOvertime + previousOvertime - (24 * 60);
					}
					// 24時間から残業開始時間を引いた値を残業時間とする
					totalOvertime = (24 * 60) - overtimeWorkStart;
				}
			}
		}
		// 残業休憩繰越回数の設定
		if (overper > 1) {
			overtimeRestNum = totalOvertime / overper;
		}
		// 残業時間設定
		int overtimeCalc = (totalOvertime + previousOvertime) - (overtimeRestNum * overrest);
		overtimeCalc -= totalManualRest;
		if (overtimeCalc < 0) {
			// 0未満の場合は0とする
			overtimeCalc = 0;
		}
		// 残業時間の設定
		overtimeTime = overtimeCalc;
	}
	
	/**
	 * 規定終業時刻後時間の計算。
	 */
	private void calcWorkAfterTime() {
		workAfterTime = getOvertimeTime() - workBeforeTime;
	}
	
	/**
	 * 深夜労働時間の計算
	 */
	private void calcNightWorkTime() {
		// 初期化
		lateNightTime = 0;
		lateBreakTime = 0;
		// 規定深夜労働開始時刻
		int regNightWorkStart = 22 * 60;
		if (calculatedEnd <= regNightWorkStart) {
			// 終業時刻が規定深夜労働開始時刻以前の場合
			return;
		}
		// 深夜労働開始時刻
		int nightWorkStart = regNightWorkStart;
		if (calculatedStart >= regNightWorkStart) {
			// 始業時刻が規定深夜労働開始時刻以後の場合は
			// 始業時刻を深夜労働開始時刻とする
			nightWorkStart = calculatedStart;
		}
		// 規定深夜労働終了時刻
		int regNightWorkEnd = 29 * 60;
		// 深夜労働終了時刻
		int nightWorkEnd = regNightWorkEnd;
		if (calculatedEnd <= regNightWorkEnd) {
			// 終業時刻が規定深夜労働終了時刻以前の場合は
			// 終業時刻を深夜労働終了時刻とする
			nightWorkEnd = calculatedEnd;
		}
		// 深夜労働開始時刻以後の合計残業休憩時間
		int totalAutoRest = 0;
		if (overtimeRestMap != null) {
			for (Entry<Date, Date> entry : overtimeRestMap.entrySet()) {
				int startTime = getDefferenceMinutes(workDate, entry.getKey());
				int endTime = getDefferenceMinutes(workDate, entry.getValue());
				if (startTime < nightWorkEnd && endTime > nightWorkStart) {
					if (startTime < nightWorkStart) {
						startTime = nightWorkStart;
					}
					if (endTime > nightWorkEnd) {
						endTime = nightWorkEnd;
					}
					totalAutoRest += endTime - startTime;
				}
			}
		}
		// 深夜労働開始時刻以後の合計手動休憩時間
		int totalManualRest = 0;
		for (RestDtoInterface dto : restDtoList) {
			Date startTime = getRoundMinute(dto.getRestStart(), timeSettingDto.getRoundDailyRestStart(), timeSettingDto
				.getRoundDailyRestStartUnit());
			Date endTime = getRoundMinute(dto.getRestEnd(), timeSettingDto.getRoundDailyRestEnd(), timeSettingDto
				.getRoundDailyRestEndUnit());
			int start = getDefferenceMinutes(workDate, startTime);
			int end = getDefferenceMinutes(workDate, endTime);
			if (start < nightWorkEnd && end > nightWorkStart) {
				if (start < nightWorkStart) {
					start = nightWorkStart;
				}
				if (end > nightWorkEnd) {
					end = nightWorkEnd;
				}
				totalManualRest += getRoundMinute(end - start, timeSettingDto.getRoundDailyRestTime(), timeSettingDto
					.getRoundDailyRestTimeUnit());
			}
		}
		// 深夜労働開始時刻以後の合計公用外出時間
		int totalPublicGoOut = 0;
		for (GoOutDtoInterface dto : publicGoOutDtoList) {
			Date startTime = getRoundMinute(dto.getGoOutStart(), timeSettingDto.getRoundDailyPublicStart(),
					timeSettingDto.getRoundDailyPublicStartUnit());
			Date endTime = getRoundMinute(dto.getGoOutEnd(), timeSettingDto.getRoundDailyPublicEnd(), timeSettingDto
				.getRoundDailyPublicEndUnit());
			int start = getDefferenceMinutes(workDate, startTime);
			int end = getDefferenceMinutes(workDate, endTime);
			if (start < nightWorkEnd && end > nightWorkStart) {
				if (start < nightWorkStart) {
					start = nightWorkStart;
				}
				if (end > nightWorkEnd) {
					end = nightWorkEnd;
				}
				totalPublicGoOut += end - start;
			}
		}
		// 深夜労働開始時刻以後の合計私用外出時間
		int totalPrivateGoOut = 0;
		for (GoOutDtoInterface dto : privateGoOutDtoList) {
			Date startTime = getRoundMinute(dto.getGoOutStart(), timeSettingDto.getRoundDailyPrivateStart(),
					timeSettingDto.getRoundDailyPrivateStartUnit());
			Date endTime = getRoundMinute(dto.getGoOutEnd(), timeSettingDto.getRoundDailyPrivateEnd(), timeSettingDto
				.getRoundDailyPrivateEndUnit());
			int start = getDefferenceMinutes(workDate, startTime);
			int end = getDefferenceMinutes(workDate, endTime);
			if (start < nightWorkEnd && end > nightWorkStart) {
				if (start < nightWorkStart) {
					start = nightWorkStart;
				}
				if (end > nightWorkEnd) {
					end = nightWorkEnd;
				}
				totalPrivateGoOut += end - start;
			}
		}
		// 深夜労働時間
		int nightWorkTime = nightWorkEnd - nightWorkStart - totalAutoRest - totalManualRest - totalPublicGoOut
				- totalPrivateGoOut;
		if (nightWorkTime < 0) {
			// 深夜労働時間が0未満の場合は0とする
			nightWorkTime = 0;
		}
		lateNightTime = nightWorkTime;
		lateBreakTime = totalAutoRest + totalManualRest;
	}
	
	/**
	 * 所定休日勤務時間の計算
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	private void setPredeterminedHolidayWorkTimeCalc() throws MospException {
		// 初期化
		int predeterminedHolidayWorkTimeCalc = 0;
		// 所定代休チェック
		if (TimeConst.CODE_WORK_ON_PRESCRIBED_HOLIDAY.equals(workTypeCode)) {
			predeterminedHolidayWorkTimeCalc = getWorkTime();
		}
		// 所定休日チェック
		if (TimeConst.CODE_HOLIDAY_PRESCRIBED_HOLIDAY.equals(workTypeCode)) {
			// 休日出勤申請
			if (workOnHolidayDto != null) {
				// ワークフローDTO
				WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(workOnHolidayDto
					.getWorkflow());
				// 申請状態が完了チェック
				if (workflowDto.getWorkflowStatus().equals(PlatformConst.CODE_STATUS_COMPLETE)) {
					// 申請しない
					if (workOnHolidayDto.getSubstitute() == 1) {
						// 勤務時間と所定労働時間を比べる
						if (getWorkTime() < getHourMinuteInt(timeSettingDto.getGeneralWorkTime())) {
							// 勤務時間が小さい場合
							predeterminedHolidayWorkTimeCalc = getHourMinuteInt(timeSettingDto.getGeneralWorkTime());
						} else {
							// 勤務時間が大きい場合
							predeterminedHolidayWorkTimeCalc = getWorkTime();
						}
					}
				}
			}
		}
		setPredeterminedHolidayWorkTime(predeterminedHolidayWorkTimeCalc + prescribedCalendarDayTime);
	}
	
	/**
	 * 法定休日勤務時間の計算
	 * @throws MospException MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	private void setLegalHolidayWorkTimeCalc() throws MospException {
		// 初期化
		int legalHolidayWorkTime = 0;
		// 法定休出チェック
		if (TimeConst.CODE_WORK_ON_LEGAL_HOLIDAY.equals(workTypeCode)) {
			legalHolidayWorkTime = getWorkTime();
		}
		// 法定休日チェック
		if (TimeConst.CODE_HOLIDAY_LEGAL_HOLIDAY.equals(workTypeCode)) {
			if (workOnHolidayDto != null) {
				// ワークフローDTO
				WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(workOnHolidayDto
					.getWorkflow());
				// 申請状態が完了チェック
				if (workflowDto.getWorkflowStatus().equals(PlatformConst.CODE_STATUS_COMPLETE)) {
					// 申請しない
					if (workOnHolidayDto.getSubstitute() == 1) {
						// 勤務時間と所定労働時間を比べる
						if (getWorkTime() < getHourMinuteInt(timeSettingDto.getGeneralWorkTime())) {
							// 勤務時間が小さい場合
							legalHolidayWorkTime = getHourMinuteInt(timeSettingDto.getGeneralWorkTime());
						} else {
							// 勤務時間が大きい場合
							legalHolidayWorkTime = getWorkTime();
						}
					}
				}
			}
		}
		
		setLegalHolidayWorkTime(legalHolidayWorkTime + legalCalendarDayTime);
	}
	
	/**
	 * 減額対象時間の計算
	 */
	private void setReducedTargetTimeCalc() {
		// 遅刻時間 + 早退時間  + 私用外出時間
		setDecreaseTime(getLateTime() + getLeaveEarlyTime() + totalPrivate);
	}
	
	/**
	 * 所定労働時間の計算
	 */
	private void calcPrescribedWorkTime() {
		if (workOnHolidayDto != null && workOnHolidayDto.getSubstitute() == 2) {
			// 休日出勤の場合
			prescribedWorkTime = 0;
			return;
		}
		if (regWorkTime > 8 * TimeConst.CODE_DEFINITION_HOUR) {
			// 8時間を超える場合は8時間とする
			prescribedWorkTime = 8 * TimeConst.CODE_DEFINITION_HOUR;
			return;
		}
		prescribedWorkTime = regWorkTime;
	}
	
	/**
	 * 法内残業の計算
	 */
	private void setWithinStatutoryOvertimeCalc() {
		// 残業時間  - (法定外残業時間 + 所定休日勤務時間 + 法定休日勤務時間)
//		setWithinStatutoryOvertime(getOvertimeTime()
//				- (getOverTimeOut() + getPredeterminedHolidayWorkTime() + getLegalHolidayWorkTime()));
		withinStatutoryOvertime = 0;
		if (workOnHolidayDto != null && workOnHolidayDto.getSubstitute() == 2) {
			// 休日出勤申請があり且つ振り替えない場合
			if (TimeConst.CODE_HOLIDAY_PRESCRIBED_HOLIDAY.equals(workOnHolidayDto.getWorkOnHolidayType())) {
				// 所定休日出勤の場合
				if (getWorkTime() >= (8 * 60)) {
					// 8時間以上の場合
					withinStatutoryOvertime = 8 * 60;
				} else {
					// 8時間未満の場合
					withinStatutoryOvertime = getWorkTime();
				}
			}
			return;
		}
		int differenceTime = 8 * 60 - prescribedWorkTime;
		if (differenceTime < 0) {
			withinStatutoryOvertime = 0;
			return;
		}
		if (differenceTime <= getOvertimeTime()) {
			withinStatutoryOvertime = differenceTime;
			return;
		}
		withinStatutoryOvertime = getOvertimeTime();
	}
	
	/**
	 * 丸め処理
	 * @param time 対象時間
	 * @param unit 対象丸め単位
	 * @return 丸め計算
	 */
	public long roundingTreatmentCalc(long time, int unit) {
		if (unit == 0) {
			return time;
		} else {
			return time -= time % unit;
		}
	}
	
	/**
	 * 丸め処理
	 * @param time 対象時間
	 * @param unit 対象丸め単位
	 * @param roundType 対象丸め単位
	 * @return 丸め計算
	 */
	public int roundingTreatmentCalc(int time, int unit, int roundType) {
		if (time == 0) {
			return 0;
		}
		// 丸め値
		int rounding = 0;
		if (unit != 0) {
			rounding = time % unit;
		}
		// 切り上げ、切り捨て処理
		if (roundType == 0) {
			// 丸め無し
			return time;
		} else if (roundType == 1) {
			// 切り捨て
			return time - rounding;
		} else if (roundType == 2) {
			if (0 < rounding) {
				// 切り上げ
				return time - rounding + unit;
			} else {
				return time;
			}
		}
		return 0;
	}
	
	/**
	 * 
	 * @param date 変換対象の日付データ
	 * @return 時分をInt型に変換した結果を返す
	 */
	public int getHourMinuteInt(Date date) {
		if (date == null) {
			return 0;
		}
		return (DateUtility.getHour(new Date(date.getTime())) * 60 + DateUtility.getMinute(new Date(date.getTime())));
	}
	
	/**
	 * @param time int型の分
	 * @return 引数で取得した分を時間と分に変換したDate型
	 * @throws MospException 例外処理発生時
	 */
	public Date getHourMinuteDate(int time) throws MospException {
		if (time != 0) {
			int hour = time / 60;
			int minute = time % 60;
			// 丸め単位 
			return DateUtility.getTime(hour, minute);
		} else {
			return DateUtility.getTime(0, 0);
		}
	}
	
	/**
	 * 
	 * @return 退勤時間
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	public int getCheckEndTime() throws MospException {
		if (getEndTime() == null) {
			return 0;
		}
		int endTimeInt = getHourMinuteInt(getEndTime());
		// 日がまたがるかチェック
		// 等しくない
		if (getStartTime() == null) {
			return endTimeInt;
		}
		
		if (DateUtility.getDay(getStartTime()) != DateUtility.getDay(getEndTime())) {
			endTimeInt = endTimeInt + (24 * 60);
		}
		return endTimeInt;
	}
	
	/**
	 * 
	 * @param i 計算結果
	 * @return 計算結果が0未満なら0を返す。それ以外はそのまま受け取った引数を返す。
	 */
	public int getCheckCalcResults(int i) {
		if (i > 0) {
			return i;
		}
		return 0;
	}
	
	/**
	 * @param time 対象時間
	 * @param unit 対象丸め単位
	 * @param roundType 対象丸め単位
	 * @return 日付オブジェクト
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合 
	 */
	public Date getItmeDateTime(Date time, int unit, int roundType) throws MospException {
		if (time == null) {
			return null;
		}
		Date dateHourMinute = getHourMinuteDate(roundingTreatmentCalc(getHourMinuteInt(time), unit, roundType));
		String year = DateUtility.getStringYear(time);
		String month = DateUtility.getStringMonth(time);
		String day = DateUtility.getStringDay(time);
		String hour = DateUtility.getStringHour(dateHourMinute);
		String minute = DateUtility.getStringMinute(dateHourMinute);
		return DateUtility.getDateTime(year, month, day, hour, minute);
	}
	
	/**
	 * 自動計算
	 * @throws MospException SQLの作成に失敗した場合、或いはSQL例外が発生した場合
	 */
	protected void setAutoCalc() throws MospException {
		if (startTime == null || endTime == null) {
			return;
		}
		// 勤怠計算上の始業時刻・規定始業時刻前時間の計算
		calcCalculatedStart();
		// 勤怠計算上の終業時刻の計算
		calcCalculatedEnd();
		// 遅刻時間の計算
		setTardinessTimeCalc();
		// 早退時間の計算
		setLeaveEarlyTimeCalc();
		// 公用外出時間の計算
		calcPublicGoOutTime();
		// 私用外出時間の計算
		calcPrivateGoOutTime();
		// 所定労働時間の計算
		calcPrescribedWorkTime();
		// 労働時間・休憩時間の計算
		calcWorkTime();
		// 残業時間の計算
		setOvertimeTimeCalc();
		// 規定終業時刻後時間の計算
		calcWorkAfterTime();
		// 深夜労働時間の計算
		calcNightWorkTime();
		// 所定休日勤務時間の計算
		setPredeterminedHolidayWorkTimeCalc();
		// 法定休日勤務時間の計算
		setLegalHolidayWorkTimeCalc();
		// 減額対象時間の計算
		setReducedTargetTimeCalc();
		// 法内残業の計算
		setWithinStatutoryOvertimeCalc();
		// 法定外残業時間、法定外休憩時間の計算
		setLegalOutTimeCalc();
	}
	
	/**
	 * 計算基準値設定
	 * @param attendanceDto 勤怠データ
	 * @param restDtoList 休憩データ
	 * @param publicGoOutDtoList 公用データ
	 * @param privateGoOutDtoList 私用データ
	 */
	public void setCalcInfo(AttendanceDtoInterface attendanceDto, List<RestDtoInterface> restDtoList,
			List<GoOutDtoInterface> publicGoOutDtoList, List<GoOutDtoInterface> privateGoOutDtoList) {
		// TODO
		// 勤務日
		workDate = attendanceDto.getWorkDate();
		// 出勤時刻
		startTime = attendanceDto.getStartTime();
		// 退勤時刻 
		endTime = attendanceDto.getEndTime();
		// 休憩リスト
		this.restDtoList = restDtoList;
		// 公用外出リスト
		this.publicGoOutDtoList = publicGoOutDtoList;
		// 私用外出リスト
		this.privateGoOutDtoList = privateGoOutDtoList;
	}
	
	/**
	 * 計算結果設定
	 * @param attendanceDto 勤怠データ
	 */
	public void getCalcInfo(AttendanceDtoInterface attendanceDto) {
		// 出勤時刻
		attendanceDto.setStartTime(startTime);
		// 退勤時刻 
		attendanceDto.setEndTime(endTime);
		attendanceDto.setDecreaseTime(getDecreaseTime());
		attendanceDto.setGeneralWorkTime(prescribedWorkTime);
		attendanceDto.setLateNightTime(getLateNightTime());
		attendanceDto.setLateTime(getLateTime());
		attendanceDto.setLeaveEarlyTime(getLeaveEarlyTime());
		attendanceDto.setLegalWorkTime(getLegalHolidayWorkTime());
		attendanceDto.setNightRestTime(getLateBreakTime());
		attendanceDto.setOverRestTime(getOverRestTime());
		attendanceDto.setOvertime(getOvertimeTime());
		attendanceDto.setOvertimeIn(getWithinStatutoryOvertime());
		attendanceDto.setOvertimeOut(getOverTimeOut());
		attendanceDto.setOvertimeAfter(workAfterTime);
		attendanceDto.setOvertimeBefore(workBeforeTime);
		attendanceDto.setPrivateTime(totalPrivate);
		attendanceDto.setPublicTime(totalPublic);
		attendanceDto.setRestTime(totalRest);
		attendanceDto.setSpecificWorkTime(getPredeterminedHolidayWorkTime());
		attendanceDto.setWorkTime(getWorkTime());
	}
	
	/**
	 * 休暇申請で午前半の申請状況チェック
	 * @return 申請されていて承認完了状態であればtrue、それ以外false
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	public boolean chkHolidayRequestListRangeAmElement() throws MospException {
		if (holidayRequestDtoList != null && !holidayRequestDtoList.isEmpty()) {
			// 休暇申請
			for (HolidayRequestDtoInterface requestDto : holidayRequestDtoList) {
				WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(requestDto.getWorkflow());
				if (workflowDto == null) {
					continue;
				}
				if (!PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
					if (requestDto.getHolidayRange() == 2) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	/**
	 * 休暇申請で午後半の申請状況チェック
	 * @return 申請されていて承認完了状態であればtrue、それ以外false
	 * @throws MospException インスタンスの取得、或いはSQL実行に失敗した場合
	 */
	public boolean chkHolidayRequestListRangePmElement() throws MospException {
		if (holidayRequestDtoList != null && !holidayRequestDtoList.isEmpty()) {
			// 休暇申請
			for (HolidayRequestDtoInterface requestDto : holidayRequestDtoList) {
				WorkflowDtoInterface workflowDto = workflowReference.getLatestWorkflowInfo(requestDto.getWorkflow());
				if (workflowDto == null) {
					continue;
				}
				if (PlatformConst.CODE_STATUS_COMPLETE.equals(workflowDto.getWorkflowStatus())) {
					if (requestDto.getHolidayRange() == 3) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	@Override
	public void attendanceCalc(AttendanceDtoInterface attendanceDto) throws MospException {
		// 休憩リストの取得
		List<RestDtoInterface> restList = restReference.getRestList(attendanceDto.getPersonalId(), attendanceDto
			.getWorkDate(), attendanceDto.getTimesWork());
		// 公用外出リストの取得
		List<GoOutDtoInterface> publicGoOutList = goOutReference.getGoOutList(attendanceDto.getPersonalId(),
				attendanceDto.getWorkDate(), attendanceDto.getTimesWork(), 1);
		// 私用外出リストの取得
		List<GoOutDtoInterface> privateGoOutList = goOutReference.getGoOutList(attendanceDto.getPersonalId(),
				attendanceDto.getWorkDate(), attendanceDto.getTimesWork(), 2);
		// 計算基準値設定
		setCalcInfo(attendanceDto, restList, publicGoOutList, privateGoOutList);
		// 基本情報取得
		initAttendanceTotal(attendanceDto.getPersonalId(), attendanceDto.getWorkDate(), attendanceDto.getWorkTypeCode());
		if (mospParams.hasErrorMessage()) {
			// 該当する設定適用が存在しない
			return;
		}
		// 自動計算
		setAutoCalc();
		// 計算結果設定
		getCalcInfo(attendanceDto);
	}
	
	@Override
	public void attendanceCalc(AttendanceDtoInterface attendanceDto, List<RestDtoInterface> restList,
			List<GoOutDtoInterface> publicGoOutList, List<GoOutDtoInterface> privateGoOutList) throws MospException {
		// 計算基準値設定
		setCalcInfo(attendanceDto, restList, publicGoOutList, privateGoOutList);
		// 基本情報取得
		initAttendanceTotal(attendanceDto.getPersonalId(), attendanceDto.getWorkDate(), attendanceDto.getWorkTypeCode());
		if (mospParams.hasErrorMessage()) {
			return;
		}
		// 自動計算
		setAutoCalc();
		// 計算結果設定
		getCalcInfo(attendanceDto);
	}
	
	/**
	 * 勤怠計算上の始業時刻を計算する。<br>
	 * 合わせて規定始業時刻前時間を計算する。<br>
	 */
	protected void calcCalculatedStart() {
		// 初期化
		workBeforeTime = 0;
		// 実際の始業時刻
		int actualStart = getRoundMinute(getDefferenceMinutes(workDate, startTime),
				timeSettingDto.getRoundDailyStart(), timeSettingDto.getRoundDailyStartUnit());
		if (regWorkStart <= actualStart) {
			// 勤務形態の始業時刻以後に始業した場合
			calculatedStart = actualStart;
			return;
		}
		// 勤務前残業予定時間
		int planBeforeOvertime = 0;
		if (beforeOvertimeDto != null) {
			planBeforeOvertime = beforeOvertimeDto.getRequestTime();
		}
		if (planBeforeOvertime <= 0) {
			// 勤務前残業がない場合
			calculatedStart = regWorkStart;
			return;
		}
		// 勤務前残業時間
		int beforeOvertimeTime = regWorkStart - actualStart;
		if (beforeOvertimeTime <= planBeforeOvertime) {
			// 勤務前残業時間が勤務前残業予定時間以下の場合
			calculatedStart = actualStart;
			workBeforeTime = beforeOvertimeTime;
			return;
		}
		calculatedStart = regWorkStart - planBeforeOvertime;
		workBeforeTime = planBeforeOvertime;
	}
	
	/**
	 * 勤怠計算上の終業時刻を計算する。<br>
	 */
	protected void calcCalculatedEnd() {
		calculatedEnd = getRoundMinute(getDefferenceMinutes(workDate, endTime), timeSettingDto.getRoundDailyEnd(),
				timeSettingDto.getRoundDailyEndUnit());
	}
	
	@Override
	public int getDefferenceMinutes(Date startTime, Date endTime) {
		return super.getDefferenceMinutes(startTime, endTime);
	}
	
	/**
	 * 時刻を日付オブジェクトに変換し取得する。<br>
	 * 時刻は分単位とする。<br>
	 * 基準日は、変換の際に基準として用いる。<br>
	 * @param date 基準日
	 * @param minute 時刻
	 * @return 日付オブジェクト
	 */
	private Date getAttendanceTime(Date date, int minute) {
		StringBuffer sb = new StringBuffer();
		sb.append(minute / TimeConst.CODE_DEFINITION_HOUR);
		sb.append(minute % TimeConst.CODE_DEFINITION_HOUR);
		return getAttendanceTime(date, sb.toString());
	}
	
	@Override
	public Date getAttendanceTime(Date date, String hour, String minute) {
		StringBuffer sb = new StringBuffer();
		if (hour.length() == 1) {
			sb.append(0);
		}
		sb.append(hour);
		if (minute.length() == 1) {
			sb.append(0);
		}
		sb.append(minute);
		return getAttendanceTime(date, sb.toString());
	}
	
	@Override
	public Date getRoundMinute(Date time, int type, int unit) {
		if (time == null) {
			return null;
		}
		long milliseconds = time.getTime();
		if (milliseconds == 0 || type == 0 || unit <= 0) {
			return time;
		}
		if (type == 1 || type == 2) {
			// 丸め単位を分単位からミリ秒単位に変換
			long millisecondsUnit = unit * TimeConst.CODE_DEFINITION_HOUR * 1000;
			// 余り
			long remainder = milliseconds % millisecondsUnit;
			if (remainder == 0) {
				// 余りが0の場合はそのまま返す
				return time;
			}
			long rounded = milliseconds - remainder;
			if (type == 1) {
				// 切捨て
				return new Date(rounded);
			} else if (type == 2) {
				// 切上げ
				return new Date(rounded + millisecondsUnit);
			}
		}
		return time;
	}
	
	@Override
	public int getRoundMinute(int time, int type, int unit) {
		return super.getRoundMinute(time, type, unit);
	}
	
}
