/*
 * MosP - Mind Open Source Project    http://www.mosp.jp/
 * Copyright (C) MIND Co., Ltd.       http://www.e-mind.co.jp/
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package jp.mosp.kintai.common.action;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import jp.mosp.common.CommonConst;
import jp.mosp.common.MosPMenuConst;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.common.dto.HumanBasisDtoInterface;
import jp.mosp.common.dto.KintaiCommonDtoInterface;
import jp.mosp.common.dto.MCodeDto;
import jp.mosp.common.utils.DateUtil;
import jp.mosp.common.utils.StringUtil;
import jp.mosp.common.utils.TimeUtil;
import jp.mosp.common.utils.VariousUtil;
import jp.mosp.kintai.common.part.KintaiApprovalPart;
import jp.mosp.kintai.common.part.KintaiCommonPart;
import jp.mosp.kintai.common.part.KintaiCompilePart;
import jp.mosp.kintai.kintai.action.AttendanceCheckCardAction;
import jp.mosp.kintai.kintai.action.AttendanceHolidayCardAction;
import jp.mosp.kintai.kintai.action.AttendanceListAction;
import jp.mosp.kintai.kintai.action.AttendanceQuitCardAction;
import jp.mosp.kintai.kintai.action.AttendanceStartCardAction;
import jp.mosp.kintai.kintai.action.EmployeeAttendanceListAction;
import jp.mosp.kintai.kintai.dao.MSyukkinboDao;
import jp.mosp.kintai.kintai.dto.MSyukkinboDto;
import jp.mosp.kintai.kintai.vo.AttendanceMenuVo;
import jp.mosp.kintai.kintai.vo.EmployeeAttendanceListVo;
import jp.mosp.kintai.payroll.dao.KdPaidHolidayDao;
import jp.mosp.kintai.payroll.dto.KdPaidHolidayDto;
import jp.mosp.kintai.payroll.dto.KintaiCompileDto;
import jp.mosp.kintai.schedule.dao.MScheduleDao;
import jp.mosp.kintai.schedule.dto.MScheduleDto;
import jp.mosp.kintai.schedule.vo.MosPScheduleVo;
import jp.mosp.kintai.workflow.dto.CtOvertimeRequestDto;

/**
 * @author yoshida
 *
 */
public abstract class AttendanceTotalAction extends KintaiCommonAction {
	
	// フィールド
	/**
	 * 開始年月日(yyyy/MM/dd)
	 */
	protected String				startDate;
	/**
	 * 終了年月日(yyyy/MM/dd)
	 */
	protected String				endDate;
	/**
	 * 深夜時間開始時刻
	 */
	protected int					lateNightStart		= 0;
	/**
	 * 深夜時間終了時刻
	 */
	protected int					lateNightEnd		= 0;
	/**
	 * 全休時間
	 */
	protected int					allHoliday			= 0;
	/**
	 * 半休時間
	 */
	protected int					halfHoliday			= 0;
	/**
	 * 入力単位
	 */
	protected int					inputUnit			= 1;
	/**
	 * 自動計算
	 */
	protected boolean				isAutoCalc;
	/**
	 * 勤怠入力時自動計算
	 */
	protected boolean				isDailyAutoCalc;
	/**
	 * 出勤簿情報リスト
	 */
	protected List<MSyukkinboDto>	attendanceList;
	/**
	 * 予定簿情報リスト
	 */
	protected List<MScheduleDto>	scheduleList;
	/**
	 * 休暇理由
	 */
	protected String[][]			aryHolidayReason;
	/**
	 * 日集計データ
	 */
	protected String[][]			aryAttendance;
	/**
	 * 月集計データ
	 */
	protected String[][]			aryAttendanceCompile;
	/**
	 * 勤怠入力選択社員コード
	 */
	protected static final String	SELECT_K_CODE		= "selectKCode";
	/**
	 * 勤怠入力選択年月日
	 */
	protected static final String	SELECT_DATE			= "selectDate";
	/**
	 * COMPILE_SECTION
	 */
	protected static final String	COMPILE_SECTION		= "COMPILE_SECTION";
	/**
	 * COMPILE_K_CODE
	 */
	protected static final String	COMPILE_K_CODE		= "COMPILE_K_CODE";
	/**
	 * 月60時間時間外時間機能
	 */
	protected boolean				useOver60Hour;
	/**
	 * 月60時間時間外警告時間
	 */
	protected int					caution60Hour		= 0;
	/**
	 * 月60時間時間外時間
	 */
	protected final int				warn60Hour			= CommonConst.NUM_OVER_TIME_60_HOUR;
	/**
	 * 1年の限度基準警告時間
	 */
	protected int					cautionLimitYear	= 0;
	/**
	 * 1年の限度基準時間
	 */
	protected int					warnLimitYear		= 0;
	

	/**
	 * 予定簿用DAO取得
	 * @return	初期化済みMScheduleDaoインスタンス
	 * @throws Exception	例外処理が発生した場合
	 */
	protected MScheduleDao scheduleDao() throws Exception {
		// 予定簿用DAO準備
		return kintai().getMScheduleDao();
	}
	
	/**
	 * 出勤簿用DAO取得
	 * @return	初期化済みMSyukkinboDaoインスタンス
	 * @throws Exception	例外処理が発生した場合
	 */
	protected MSyukkinboDao syukkinboDao() throws Exception {
		// 出勤簿用DAO準備
		return kintai().getMSyukkinboDao();
	}
	
	/**
	 * 勤怠一覧データ
	 * @param kCode		対象社員コード
	 * @return 勤怠一覧リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	protected List<MSyukkinboDto> getAttendanceList(String kCode) throws Exception {
		// 月一覧の取得
		attendanceList = kintai().getAttendanceList(kCode, startDate, endDate);
		return attendanceList;
	}
	
	/**
	 * 勤怠月一覧データ取得
	 * @param kCode       対象社員コード
	 * @param targetMonth 対象月
	 * @return  勤怠一覧リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	protected List<MSyukkinboDto> getAttendanceList(String kCode, Date targetMonth) throws Exception {
		// 検索範囲取得
		startDate = DateUtil.convDateFormatted(getStartDate(targetMonth));
		endDate = DateUtil.convDateFormatted(getEndDate(targetMonth));
		// 検索
		getAttendanceList(kCode);
		return attendanceList;
	}
	
	/**
	 * 勤怠月一覧データ取得（表示用）
	 * <p>2009/01/20	m.yoshida	追加</p>
	 * @param kCode			対象社員コード
	 * @param targetDate	対象年月日
	 * @return  勤怠一覧リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	protected List<MSyukkinboDto> getAttendanceListForView(String kCode, Date targetDate) throws Exception {
		// 検索範囲取得
		startDate = DateUtil.convDateFormatted(getStartDateForList(targetDate));
		endDate = DateUtil.convDateFormatted(getEndDateForList(targetDate));
		// 検索
		getAttendanceList(kCode);
		return attendanceList;
	}
	
	/**
	 * 月集計
	 * @param kCode				対象社員コード
	 * @param attendanceList	対象出勤簿リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void totalAttendanceDaily(String kCode, List<MSyukkinboDto> attendanceList) throws Exception {
		KintaiCompileDto dto = compile().getCompiledInfo(kCode, attendanceList, false);
		// 配列の初期化
		aryAttendanceCompile = StringUtil.getBlankArray(19, 2);
		// 配列
		// 勤務時間合計
		aryAttendanceCompile[0][0] = CommonConst.NAM_WORKING;
		aryAttendanceCompile[0][1] = getHourString(TimeUtil.convIntegerTimeToDoubleTime(dto.getTotalWork()));
		// 休憩時間合計
		aryAttendanceCompile[1][0] = CommonConst.NAM_INTERVAL_TIME;
		aryAttendanceCompile[1][1] = getHourString(TimeUtil.convIntegerTimeToDoubleTime(dto.getTotalInterbal()));
		// 遅刻時間合計
		aryAttendanceCompile[2][0] = CommonConst.NAM_ARRIVE_LATE;
		aryAttendanceCompile[2][1] = getHourString(TimeUtil.convIntegerTimeToDoubleTime(dto.getTotalLate()));
		// 早退時間合計
		aryAttendanceCompile[3][0] = CommonConst.NAM_LEAVE_EARLY;
		aryAttendanceCompile[3][1] = getHourString(TimeUtil.convIntegerTimeToDoubleTime(dto.getTotalLeave()));
		// 残業時間合計
		aryAttendanceCompile[4][0] = CommonConst.NAM_OVERTIME;
		aryAttendanceCompile[4][1] = getHourString(TimeUtil.convIntegerTimeToDoubleTime(dto.getTotalOver()));
		// 休出時間合計
		aryAttendanceCompile[5][0] = CommonConst.NAM_WORK_ON_HOLIDAY;
		aryAttendanceCompile[5][1] = getHourString(TimeUtil.convIntegerTimeToDoubleTime(dto.getTotalHolidayWork()));
		// 深夜時間合計
		aryAttendanceCompile[6][0] = CommonConst.NAM_LATE_NIGHT;
		aryAttendanceCompile[6][1] = getHourString(TimeUtil.convIntegerTimeToDoubleTime(dto.getTotalLateNight()));
		// 出勤日数
		aryAttendanceCompile[7][0] = CommonConst.NAM_PRESENCE;
		aryAttendanceCompile[7][1] = String.valueOf(dto.getTotalWorkDays());
		// 有給休暇日数
		aryAttendanceCompile[8][0] = aryHolidayReason[0][1];
		aryAttendanceCompile[8][1] = String.valueOf(dto.getTotalPaidHoliday());
		// 特別休暇日数
		aryAttendanceCompile[9][0] = aryHolidayReason[1][1];
		aryAttendanceCompile[9][1] = String.valueOf(dto.getTotalParticularHoliday());
		// 欠勤休暇日数
		aryAttendanceCompile[10][0] = aryHolidayReason[2][1];
		aryAttendanceCompile[10][1] = String.valueOf(dto.getTotalAbsence());
		// 傷病休暇日数
		aryAttendanceCompile[11][0] = aryHolidayReason[3][1];
		aryAttendanceCompile[11][1] = String.valueOf(dto.getTotalMedicalLeave());
		// 代休日数
		aryAttendanceCompile[12][0] = aryHolidayReason[4][1];
		aryAttendanceCompile[12][1] = String.valueOf(dto.getTotalCompensationDay());
		// 振替休暇日数
		aryAttendanceCompile[13][0] = aryHolidayReason[5][1];
		aryAttendanceCompile[13][1] = String.valueOf(dto.getTotalTransfer());
		// 其他休暇日数
		aryAttendanceCompile[14][0] = CommonConst.NAM_OTHER_SHORT;
		aryAttendanceCompile[14][1] = String.valueOf(dto.getTotalOther());
		// 遅刻早退数
		aryAttendanceCompile[15][0] = CommonConst.NAM_LATE_AND_LEAVE_EARLY;
		aryAttendanceCompile[15][1] = String.valueOf(dto.getLeaveAndLate());
		// 手当
		StringBuffer allowance = new StringBuffer();
		allowance.append(dto.getSyokuji());
		allowance.append(CommonConst.STR_SLASH_SEPARATOR);
		allowance.append(dto.getCyoku1());
		allowance.append(dto.getCyoku2());
		allowance.append(dto.getCyoku3());
		allowance.append(CommonConst.STR_SLASH_SEPARATOR);
		allowance.append(dto.getHoka1());
		allowance.append(dto.getHoka2());
		allowance.append(dto.getHoka3());
		allowance.append(dto.getHoka4());
		allowance.append(dto.getHoka5());
		aryAttendanceCompile[16][0] = CommonConst.NAM_ALLOWANCE;
		aryAttendanceCompile[16][1] = allowance.toString();
		// 皆勤（欠勤、特別休暇、傷病、遅刻早退数の合計）
		aryAttendanceCompile[17][0] = CommonConst.NAM_PERFECT_ATTENDANCE;
		aryAttendanceCompile[17][1] = "";
		if (dto.isApplyAttendanceAllowance()) {
			aryAttendanceCompile[17][1] = CommonConst.NAM_PERFECT_ATTENDANCE;
		}
		// 時間外警告
		if (checkCautionOverTime(dto.getTotalOver(), 0)) {
			aryAttendanceCompile[18][1] = CommonConst.CSS_CLASS_CAUTION_TD;
		} else if (checkWarningOverTime(dto.getTotalOver(), 0)) {
			aryAttendanceCompile[18][1] = CommonConst.CSS_CLASS_WARNING_TD;
		}
	}
	
	/**
	 * 深夜時間取得
	 * @throws Exception 	例外処理
	 */
	private void setLateNightTime() throws Exception {
		// 値の設定
		lateNightStart = kintai().getLateNightStart();
		lateNightEnd = lateNightStart + kintai().getLateNightEnd();
	}
	
	/**
	 * 自動計算フラグ取得
	 * @throws Exception	例外処理が発生した場合
	 */
	private void setAutoCalc() throws Exception {
		// 自動計算フラグ取得
		isAutoCalc = kintai().isAutoCalc();
		// 日次自動計算フラグ
		isDailyAutoCalc = kintai().isDailyAutoCalc();
	}
	
	/**
	 * 休暇時間取得
	 * @throws Exception	例外処理が発生した場合
	 */
	private void setHolidayTimes() throws Exception {
		allHoliday = kintai().getAllHolidayTimes();
		halfHoliday = kintai().getHalfHolidayTimes();
	}
	
	/**
	 * 入力単位時間設定
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setInputUnit() throws Exception {
		// 入力単位時間
		inputUnit = kintai().getInputUnitTimes();
	}
	
	/**
	 * 休暇理由設定
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setHolidayReason() throws Exception {
		// 休暇理由
		aryHolidayReason = part().mospcode().getHolidayReasonArray();
	}
	
	/**
	 * 月60時間時間外時間機能設定
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setUseOver60Hour() throws Exception {
		// 月60時間時間外時間機能
		useOver60Hour = part().mospcode().useOverTime60HourFunction();
	}
	
	/**
	 * 集計基本設定
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setCalcParam() throws Exception {
		// 自動計算設定
		setAutoCalc();
		// 入力単位時間
		setInputUnit();
		// 深夜時間設定
		setLateNightTime();
		// 休暇時間設定
		setHolidayTimes();
		// 休暇理由設定
		setHolidayReason();
		// 月60時間時間外時間機能
		setUseOver60Hour();
	}
	
	/**
	 * 半休休暇理由配列取得
	 * @return 半休休暇理由配列(時間外代休有効の場合追加)
	 * @throws Exception	例外処理が発生した場合
	 */
	public String[][] getHalfHolidayArray() throws Exception {
		return part().mospcode().getHalfHolidayArray();
	}
	
	/**
	 * 承認理由表示
	 * @param riyuu 承認理由
	 * @return	result
	 * @throws Exception	例外処理が発生した場合
	 */
	protected String[] getApproval(String riyuu) throws Exception {
		return part().kintaiApproval().getApproval(riyuu);
	}
	
	/**
	 * 勤怠登録パラメータ設定
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setAttendanceInfo() throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		// 社員コード
		String kCode;
		if (StringUtil.isNotNull(key1)) {
			kCode = key1;
		} else {
			Object obj = request.getAttribute(SELECT_K_CODE);
			if (VariousUtil.isNotNull(obj)) {
				kCode = obj.toString();
			} else {
				kCode = vo.getHidKCode();
			}
		}
		// 対象年月日
		Date selectDate;
		if (StringUtil.isNotNull(key2)) {
			selectDate = MospUtility.getDate(key2);
		} else {
			Object obj = request.getAttribute(SELECT_DATE);
			if (VariousUtil.isNotNull(obj)) {
				selectDate = MospUtility.getDate(obj.toString());
			} else {
				selectDate = MospUtility.getDate(vo.getHidDate());
			}
		}
		vo.setHidKCode(kCode);
		vo.setHidYear(String.valueOf(MospUtility.getYear(selectDate)));
		vo.setHidMonth(String.valueOf(MospUtility.getMonth(selectDate)));
		vo.setHidDay(String.valueOf(MospUtility.getDay(selectDate)));
		vo.setHidDate(DateUtil.convDateFormatted(selectDate));
		// 基本情報表示設定
		setLabelBasisInfo(kCode);
		// 残業申請情報設定
		setOverTimeRequestInfo();
		// 休暇申請情報設定
		setHolidayRequestInfo();
		// 表示設定
		setLabelAttendanceInfo(selectDate);
		// 労使協定情報設定
		setLaborAgreementInfo(kCode, selectDate);
	}
	
	/**
	 * 表示箇所情報設定
	 * @param selectDate	対象年月日
	 * @throws Exception 	例外処理
	 */
	protected void setLabelAttendanceInfo(Date selectDate) throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		if (VariousUtil.isNotNull(selectDate)) {
			vo.setLblDate(DateUtil.convDateToFormatDateJP(selectDate));
			vo.setLblDayOfWeek(VariousUtil.getDayOfWeek(DateUtil.getDayOfWeek(selectDate)));
			vo.setDayOfWeekColorClass(getDayOfWeekColorClass(selectDate));
			Date formerDate = DateUtil.addDay(selectDate, -1);
			Date nextDate = DateUtil.addDay(selectDate, 1);
			vo.setHidFormerDate(DateUtil.convDateFormatted(formerDate));
			vo.setLblFormerDate(DateUtil.convDateToFormatDateJP(formerDate));
			vo.setHidNextDate(DateUtil.convDateFormatted(nextDate));
			vo.setLblNextDate(DateUtil.convDateToFormatDateJP(nextDate));
		}
	}
	
	/**
	 * 表示モードセット
	 * <p>[新規]、[更新]、[承認済み]</p>
	 * @param dto	対象DTO
	 * @throws Exception 	例外処理
	 */
	protected void setMode(MSyukkinboDto dto) throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		vo.setMode(AttendanceMenuVo.MODE_INSERT);
		if (chkExistDto(dto)) {
			vo.setMode(AttendanceMenuVo.MODE_EDIT);
			if (KintaiApprovalPart.isApproved(dto)) {
				vo.setMode(AttendanceMenuVo.MODE_APPROVED);
			}
		}
	}
	
	/**
	 * 勤怠検索
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void searchAttendance() throws Exception {
		// 勤怠検索
		String kCode = key1;
		String strDate = key2;
		if (StringUtil.isNull(key1)) {
			kCode = user.getKCode();
			request.setAttribute(SELECT_K_CODE, kCode);
		}
		if (StringUtil.isNull(key2)) {
			strDate = DateUtil.convDateFormatted(DateUtil.getSystemDate());
			request.setAttribute(SELECT_DATE, strDate);
		}
		MSyukkinboDto dto = kintai().getSyukkinboInfo(kCode, strDate, false);
		if (VariousUtil.chkExistDto(dto)) {
			if (!KintaiCommonPart.isHoliday(dto)) {
				// 出勤有り、退勤無し
				if (StringUtil.isNull(dto.getTaJikoku()) && !KintaiCommonPart.isWeekHoliday(dto)
						&& !KintaiCommonPart.isOfficialHoliday(dto)) {
					// 退勤表示へ
					setNextCmd(AttendanceQuitCardAction.CMD_QUIT_CARD_SHOW);
				} else {
					// 出勤有り、退勤有り（週休の場合も）
					// 確認表示へ
					setNextCmd(AttendanceCheckCardAction.CMD_CHECK_CARD_SELECT);
				}
			} else {
				// 休暇表示へ
				setNextCmd(AttendanceHolidayCardAction.CMD_HOLIDAY_CARD_SHOW);
			}
		} else {
			// 出勤表示へ
			setNextCmd(AttendanceStartCardAction.CMD_START_CARD_SHOW);
		}
		// サーブレットへ転送
		setUrl(MospConst.URL_SRV);
	}
	
	/**
	 * 祝日名称取得
	 * <p>	2009/02/25	m.yoshida	祝日メソッド修正 </p>
	 * @param targetDate		対象年月日
	 * @return	対象年月日祝日名称
	 * @throws Exception	例外処理が発生した場合
	 */
	protected String getPublicHolidayName(Date targetDate) throws Exception {
		return part().jpholiday().getPublicHolidayName(targetDate);
	}
	
	/**
	 * 勤怠一覧用サブタイトルコマンドの設定
	 */
	protected void setSubTitleMenu() {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		// 勤怠管理コマンド
		if (VariousUtil.isNotNull(getStoredVo(EmployeeAttendanceListVo.class.getName()))) {
			// 状態遷移確認
			vo.setCmdMenuButton(CommonConst.CMD_MENU_MAMAGE);
			vo.setCmdListButton(AttendanceListAction.CMD_ATTENDANCE_LIST_RE_SEARCH);
			vo.setNamListButton(CommonConst.TTL_ATTENDANCE_LIST);
			// メニューボタン生成
			vo.setAryMenu(true);
		} else {
			vo.setCmdMenuButton(CommonConst.CMD_MENU_INPUT);
			vo.setCmdListButton(CommonConst.CMD_MENU_INPUT);
			vo.setNamListButton(CommonConst.NAM_MENU);
			// メニューボタン生成
			vo.setAryMenu(false);
		}
	}
	
	/**
	 * 出勤簿の登録
	 * @param dto			対象DTO
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void registSyukkinbo(MSyukkinboDto dto) throws Exception {
		if (VariousUtil.isNotNull(dto)) {
			MSyukkinboDto currentDto = kintai().getSyukkinboInfo(dto.getKCode(), dto.getHizuke());
			if (VariousUtil.isNotNull(currentDto)) {
				if (!KintaiApprovalPart.isApproved(dto)) {
					// 排他確認
					chkExclusive(currentDto, kintai().lockSyukkinboInfo(dto.getKCode(), dto.getHizuke()));
					// 更新
					syukkinboDao().update(dto);
				} else {
					// 承認済みの場合
					StringBuffer sb = new StringBuffer();
					sb.append(getKName(dto.getKCode()));
					sb.append(CommonConst.MSG_OF);
					sb.append(getMessage(CommonConst.MSG_ALREADY_APPROVED, getMessageDate(dto)));
					// エラーメッセージ
					addErrMessage(sb.toString());
				}
			} else {
				// 登録
				syukkinboDao().insert(dto);
			}
			// DTOの再取得
			chkUpdate(kintai().getSyukkinboInfo(dto.getKCode(), dto.getHizuke()));
		}
	}
	
	/**
	 * 勤怠項目削除
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void delete() throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		vo.setParams(request);
		MSyukkinboDto dto = kintai().getSyukkinboInfo(vo.getHidKCode(), vo.getHidDate(), true);
		// データ存在確認
		chkExist(dto);
		// 承認済みの場合はメッセージ表示、削除不可
		if (KintaiApprovalPart.isApproved(dto)) {
			// メッセージ設定
			setMessage(getMessage(CommonConst.MSG_ALREADY_APPROVED, getMessageDate(dto)));
		} else {
			// 削除
			syukkinboDao().delete(dto);
			// コミット
			commit();
			// メッセージ設定
			setMessage(getMessage(MospConst.MSG_DELETE, ""));
		}
		// 勤怠一覧へ遷移
		setNextCmd(AttendanceListAction.CMD_ATTENDANCE_LIST_RE_SEARCH);
	}
	
	/*スケジュール関連*/

	/**
	 * 予定月一覧データ
	 * @param kCode		対象社員コード
	 * @return scheduleList
	 * @throws Exception	例外処理が発生した場合
	 */
	protected List<MScheduleDto> getScheduleList(String kCode) throws Exception {
		// 月一覧の取得
		scheduleList = kintai().getScheduleList(kCode, startDate, endDate);
		return scheduleList;
	}
	
	/**
	 * 予定月一覧データ取得
	 * @param kCode       対象社員コード
	 * @param targetMonth 対象月
	 * @return 予定簿リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	protected List<MScheduleDto> getScheduleList(String kCode, Date targetMonth) throws Exception {
		// 検索範囲取得
		startDate = DateUtil.convDateFormatted(getStartDate(targetMonth));
		endDate = DateUtil.convDateFormatted(getEndDate(targetMonth));
		// 検索
		getScheduleList(kCode);
		return scheduleList;
	}
	
	/**
	 * 予定月一覧データ取得（表示用）
	 * <p>2009/01/20	m.yoshida	追加</p>
	 * @param kCode 		対象社員コード
	 * @param targetDate	対象年月日
	 * @return 予定簿リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	protected List<MScheduleDto> getScheduleListForView(String kCode, Date targetDate) throws Exception {
		// 検索範囲取得
		startDate = DateUtil.convDateFormatted(getStartDateForList(targetDate));
		endDate = DateUtil.convDateFormatted(getEndDateForList(targetDate));
		// 検索
		getScheduleList(kCode);
		return scheduleList;
	}
	
	/**
	 * 日集計データ時間設定
	 * @param scheduleList		対象予定簿リスト
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setScheduleHours(List<MScheduleDto> scheduleList) throws Exception {
		// 勤怠情報設定
		setCalcParam();
		// 日集計データ取得
		for (MScheduleDto dto : scheduleList) {
			if (KintaiCommonPart.isHoliday(dto)) {
				// 休暇の場合
				dto.setKKJikan(allHoliday);
			} else {
				// 出勤の場合
				if (KintaiCommonPart.isAvailableWorkType(dto)) {
					// 勤怠項目の計算
					kintai().runCalculatedInfo(dto);
				}
			}
		}
	}
	
	/**
	 * スケジュール登録
	 * @param kCode			対象社員コード
	 * @param map	対象登録スケジュール情報
	 * @return	更新・登録件数
	 * @throws Exception	例外処理が発生した場合
	 */
	protected int registSchedule(String kCode, Map<Date, String> map) throws Exception {
		// 更新・登録件数
		int number = 0;
		Set<Entry<Date, String>> entrySet = map.entrySet();
		HumanBasisDtoInterface targetBasis = getBasisInfo(kCode);
		// スケジュール登録
		for (Entry<Date, String> entry : entrySet) {
			Date targetDate = entry.getKey();
			// 勤務形態コード
			String workTypeCode = entry.getValue();
			boolean deleteFlag = false;
			if (StringUtil.isNull(workTypeCode)) {
				// 勤務形態が空欄なら対象日の予定を削除する
				deleteFlag = true;
			}
			// 対象年月日が承認されている場合、予定簿を更新しない。
			if (!KintaiApprovalPart.isApproved(kintai().getSyukkinboInfo(kCode, targetDate))) {
				MScheduleDto dto;
				if (deleteFlag) {
					// 削除
					dto = kintai().getScheduleInfo(kCode, targetDate);
					if (VariousUtil.isNotNull(dto)) {
						// データの削除
						scheduleDao().delete(dto);
						number++;
					}
				} else {
					// 勤務形態からデフォルトの値を取得し、予定簿DTOにセットする
					dto = kintai().createScheduleInfo(targetBasis, targetDate, workTypeCode);
					if (KintaiCommonPart.isWeekHoliday(dto) || KintaiCommonPart.isOfficialHoliday(dto)) {
						// 所定休日または法定休日の場合、出勤簿と予定表に同じ値を登録
						registSyukkinbo(KintaiCommonPart.copyToSyukkinbo(dto));
					}
					// 承認済み休暇申請対応
					margeHolidayRequest(dto);
					// 予定簿に登録
					registSchedule(dto);
					number++;
				}
			}
		}
		return number;
	}
	
	/**
	 * 予定簿の登録
	 * @param dto	対象DTO
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void registSchedule(MScheduleDto dto) throws Exception {
		if (VariousUtil.isNotNull(dto)) {
			MScheduleDto currentDto = kintai().getScheduleInfo(dto.getKCode(), dto.getHizuke());
			if (chkExistDto(currentDto)) {
				// 排他確認
				chkExclusive(currentDto, kintai().lockScheduleInfo(dto.getKCode(), dto.getHizuke()));
				// 更新
				scheduleDao().update(dto);
			} else {
				// 登録
				scheduleDao().insert(dto);
			}
			// DTOの再取得	
			chkUpdate(kintai().getScheduleInfo(dto.getKCode(), dto.getHizuke()));
		}
	}
	
	/**
	 * カンマ区切りの日付を取得
	 * @param dto 対象DTO
	 * @return	カンマ区切りの日付
	 */
	protected String getMessageDate(KintaiCommonDtoInterface dto) {
		return DateUtil.convDateFormattedByComma(DateUtil.convStringDateToDate(dto.getHizuke()));
	}
	
	/**
	 * 残業申請情報設定
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setOverTimeRequestInfo() throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		// 残業申請情報取得
		CtOvertimeRequestDto dto = part().overtime().getOverTimeRequest(vo.getHidKCode(),
				DateUtil.convStringDateToDate(vo.getHidDate()));
		// 初期化
		vo.setLblOverTimeRequest("");
		vo.setLblOverTimeRequestStatus("");
		if (VariousUtil.chkExistDto(dto)) {
			// 申請時間
			vo.setLblOverTimeRequest(TimeUtil.convIntegerTimeToJPHours(dto.getOverTime()));
			// 承認状況
			vo.setLblOverTimeRequestStatus(part().kintaiApproval().getApprovalName(
					part().workflow().toKintaiApprovalStatus(dto.getWorkflow())));
		}
	}
	
	/**
	 * 休暇申請情報設定
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void setHolidayRequestInfo() throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		// 休暇申請情報取得
		vo.setAryHolidayRequestStatus(getLabelHolidayRequestStatusArray(vo.getHidKCode(), DateUtil
			.convStringDateToDate(vo.getHidDate())));
	}
	
	/**
	 * KintaiCommonPartインスタンス取得
	 * @return	KintaiCommonPartインスタンス
	 * @throws MospException	MosP例外処理が発生した場合
	 * @throws ClassNotFoundException	 クラスが見つからなかった場合
	 * @throws SQLException	SQL例外が発生した場合
	 */
	protected KintaiCommonPart kintai() throws MospException, ClassNotFoundException, SQLException {
		return part().kintai();
	}
	
	/**
	 * KintaiCompilePartインスタンス取得
	 * @return	KintaiCompilePartインスタンス
	 * @throws MospException	MosP例外処理が発生した場合
	 * @throws ClassNotFoundException	 クラスが見つからなかった場合
	 * @throws SQLException	SQL例外が発生した場合
	 */
	protected KintaiCompilePart compile() throws MospException, ClassNotFoundException, SQLException {
		return part().compile();
	}
	
	/**
	 * 曜日フォント色設定
	 * @param targetDate	対象年月日
	 * @return	フォント色のクラス名
	 * @throws Exception	例外処理が発生した場合
	 */
	public String getDayOfWeekColorClass(Date targetDate) throws Exception {
		return kintai().getDayOfWeekColorClass(targetDate);
	}
	
	/**
	 * 休暇時間申請と出勤簿のマージ
	 * @param dto		対象DTO
	 * @throws Exception	例外処理が発生した場合
	 */
	protected void margeHolidayRequest(KintaiCommonDtoInterface dto) throws Exception {
		part().holidayRequest().margeHolidayRequest(dto);
	}
	
	/**
	 * スケジュール用勤怠管理コマンド設定
	 */
	protected void setScheduleMenuButton() {
		MosPScheduleVo vo = (MosPScheduleVo)getVo();
		// 勤怠管理コマンド
		if (VariousUtil.isNotNull(getStoredVo(EmployeeAttendanceListVo.class.getName()))) {
			// 状態遷移確認
			vo.setCmdMenuButton(CommonConst.CMD_MENU_MAMAGE);
			vo.setCmdListButton(EmployeeAttendanceListAction.CMD_EMPLOYEE_LIST_RE_SEARCH);
			vo.setNamListButton(CommonConst.TTL_EMPLOYEE_SELECT);
			// メニューコマンドの設定
			vo.setAryMenu(true);
		} else {
			vo.setCmdMenuButton(CommonConst.CMD_MENU_INPUT);
			vo.setCmdListButton(MosPMenuConst.getMenuSchedule()[0]);
			vo.setNamListButton(MosPMenuConst.getMenuSchedule()[1]);
			// メニューコマンドの設定
			vo.setAryMenu(true);
		}
	}
	
	/**
	 * 時間外警告時間設定
	 */
	protected void setUserOverTimeCautionInfo() {
		if (VariousUtil.isNotNull(agreement)) {
			// 月60時間時間外警告時間
			caution60Hour = agreement.getCautionMonth();
			// 1年の限度基準警告時間
			cautionLimitYear = agreement.getCautionYear();
			warnLimitYear = agreement.getLimitYear();
		}
	}
	
	/**
	 * 有休情報（新テーブル）の登録・更新
	 * @param dto 対象DTO
	 * @param isUpdate 更新判断
	 * @return 有休情報の登録できた場合true、そうでない場合false。
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected boolean registPaidHoliday(KdPaidHolidayDto dto, boolean isUpdate) throws Exception {
		KdPaidHolidayDao dao = part().paidHoliday().getPaidHolidayDao();
		if (isUpdate) {
			// 排他確認
			chkExclusive(dto, dao.findForUpdate(dto.getPaidId(), dto.getKCode()));
			// 更新
			dao.update(dto);
			chkUpdate(dao.findForKey(dto.getPaidId(), dto.getKCode()));
			return true;
		} else {
			String maxPaidId = dao.findForMax(dto.getKCode());
			if (StringUtil.isNotNull(maxPaidId)) {
				long paidId = Long.parseLong(maxPaidId) + 1;
				// 重複確認
				chkDuplicate(dao.findForUpdate(paidId, dto.getKCode()));
				dto.setPaidId(paidId);
				// 登録
				dao.insert(dto);
				chkInsert(dao.findForKey(dto.getPaidId(), dto.getKCode()));
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 時間外警告判断
	 * @param overTime 対象時間外時間
	 * @param input 入力時間外時間
	 * @return 残業時間の合計が警告時間以上の場合true、そうでない場合false。
	 */
	protected boolean checkCautionOverTime(int overTime, int input) {
		setUserOverTimeCautionInfo();
		if (overTime + input >= caution60Hour && caution60Hour > 0) {
			return true;
		}
		return false;
	}
	
	/**
	 * 時間外超過判断
	 * @param overTime 対象時間外時間
	 * @param input 入力時間外時間
	 * @return 残業時間の合計が60時間以上の場合true、そうでない場合false。
	 */
	protected boolean checkWarningOverTime(int overTime, int input) {
		setUserOverTimeCautionInfo();
		if (overTime + input > warn60Hour && caution60Hour > 0) {
			return true;
		}
		return false;
	}
	
	/**
	 * 対象年月日の月60時間時間外警告判断
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @param inputOverTime 対象年月日の残業時間
	 * @return
	 * <p>
	 * 対象年月日を除いた集計期間の残業時間と対象年月日の残業時間の合計が警告時間以上の場合true、そうでない場合false。
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected boolean checkCautionOverTimeMonthly(String kCode, Date targetDate, int inputOverTime) throws Exception {
		// 集計開始日から前日までの残業時間
		int overTime = part().kintai().getOverTimeForPeriod(kCode, getStartDateForList(targetDate),
				DateUtil.addDay(targetDate, -1));
		// 翌日から集計終了日までの残業時間
		overTime += part().kintai().getOverTimeForPeriod(kCode, DateUtil.addDay(targetDate, 1),
				getEndDateForList(targetDate));
		return checkCautionOverTime(overTime, inputOverTime);
	}
	
	/**
	 * 対象年月日の月60時間時間外超過判断
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @param inputOverTime 対象年月日の残業時間
	 * @return
	 * <p>
	 * 対象年月日を除いた集計期間の残業時間と対象年月日の残業時間の合計が60時間以上の場合true、そうでない場合false。
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected boolean checkWarningOverTimeMonthly(String kCode, Date targetDate, int inputOverTime) throws Exception {
		// 集計開始日から前日までの残業時間
		int overTime = part().kintai().getOverTimeForPeriod(kCode, getStartDateForList(targetDate), targetDate);
		// 翌日から集計終了日までの残業時間
		overTime += part().kintai().getOverTimeForPeriod(kCode, DateUtil.addDay(targetDate, 1),
				getEndDateForList(targetDate));
		return checkWarningOverTime(overTime, inputOverTime);
	}
	
	/**
	 * 対象年月日の月60時間時間外警告判断
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @return 
	 * <p>
	 * 対象年月日までの残業時間が警告時間以上の場合true、そうでない場合false。
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected boolean checkCautionOverTimeMonthly(String kCode, Date targetDate) throws Exception {
		MSyukkinboDto dto = part().kintai().getSyukkinboInfo(kCode, targetDate);
		int overTime = 0;
		if (VariousUtil.isNotNull(dto)) {
			overTime = dto.getZaJikan();
		}
		return checkCautionOverTimeMonthly(kCode, targetDate, overTime);
	}
	
	/**
	 * 対象年月日の月60時間時間外超過判断
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @return
	 * <p>
	 * 対象年月の残業時間が60時間以上の場合true、そうでない場合false。
	 * </p>
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected boolean checkWarningOverTimeMonthly(String kCode, Date targetDate) throws Exception {
		MSyukkinboDto dto = part().kintai().getSyukkinboInfo(kCode, targetDate);
		int overTime = 0;
		if (VariousUtil.isNotNull(dto)) {
			overTime = dto.getZaJikan();
		}
		return checkWarningOverTimeMonthly(kCode, targetDate, overTime);
	}
	
	/**
	 * 対象年月日の月60時間時間外判断設定
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected void setOverTimeCaution(String kCode, Date targetDate) throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		setLaborAgreementInfo(kCode, targetDate);
		vo.setCaution(checkCautionOverTimeMonthly(kCode, targetDate));
		vo.setWarning(checkWarningOverTimeMonthly(kCode, targetDate));
	}
	
	/**
	 * 対象年月日の月60時間時間外判断設定
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @param inputOverTime 対象年月日の残業時間
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected void setOverTimeCaution(String kCode, Date targetDate, int inputOverTime) throws Exception {
		AttendanceMenuVo vo = (AttendanceMenuVo)getVo();
		setLaborAgreementInfo(kCode, targetDate);
		vo.setCaution(checkCautionOverTimeMonthly(kCode, targetDate, inputOverTime));
		vo.setWarning(checkWarningOverTimeMonthly(kCode, targetDate, inputOverTime));
	}
	
	/**
	 * 表示用対象休暇一覧（承認状況追加）取得。
	 * @param kCode 対象社員コード
	 * @param targetDate 対象年月日
	 * @return 表示用対象休暇一覧（承認状況追加）
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected String[] getLabelHolidayRequestStatusArray(String kCode, Date targetDate) throws Exception {
		return part().holidayRequest().getLabelHolidayRequestStatusArray(
				part().holidayRequest().getDateRequestList(kCode, targetDate));
	}
	
	/**
	 * M_CODEから指定されたTCODEのコード変換（なければコード名称）をlength分取得する
	 * @param tid M_CODEから検索するTID
	 * @param tcode M_CODEから検索するTCODE
	 * @param length 取得する文字列長
	 * @return 取得した文字列(lengthが0の場合、全文字列を返す)
	 * @throws Exception    例外処理が発生した場合
	 */
	protected String getTChangeOrTName(String tid, String tcode, int length) throws Exception {
		MCodeDto dto = part().mospcode().findForKey(tid, tcode);
		if (VariousUtil.isNotNull(dto)) {
			String tName = dto.getTName();
			String tChange = dto.getTChange();
			if (StringUtil.isNotNull(tChange)) {
				if (length != 0) {
					return tChange.substring(0, length);
				} else {
					return tChange;
				}
			}
			if (StringUtil.isNotNull(tName)) {
				if (length != 0) {
					return tName.substring(0, length);
				} else {
					return tName;
				}
			}
		}
		return "";
	}
	
}
