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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import jp.mosp.framework.base.BaseDtoInterface;
import jp.mosp.framework.base.BaseVo;
import jp.mosp.framework.base.MospException;
import jp.mosp.framework.utils.DateUtility;
import jp.mosp.platform.constant.PlatformConst;
import jp.mosp.platform.constant.PlatformMessageConst;
import jp.mosp.time.base.TimeAction;
import jp.mosp.time.bean.CutoffReferenceBeanInterface;
import jp.mosp.time.bean.PaidHolidayDataRegistBeanInterface;
import jp.mosp.time.bean.PaidHolidayInfoReferenceBeanInterface;
import jp.mosp.time.bean.StockHolidayDataRegistBeanInterface;
import jp.mosp.time.bean.StockHolidayInfoReferenceBeanInterface;
import jp.mosp.time.bean.TotalTimeCalcBeanInterface;
import jp.mosp.time.bean.TotalTimeEmployeeTransactionRegistBeanInterface;
import jp.mosp.time.bean.TotalTimeTransactionRegistBeanInterface;
import jp.mosp.time.bean.TotalTimeTransactionSearchBeanInterface;
import jp.mosp.time.calculation.vo.TotalTimeVo;
import jp.mosp.time.comparator.settings.TotalTimeCutoffListCutoffCodeComparator;
import jp.mosp.time.constant.TimeConst;
import jp.mosp.time.constant.TimeMessageConst;
import jp.mosp.time.dto.settings.CutoffDtoInterface;
import jp.mosp.time.dto.settings.CutoffErrorListDtoInterface;
import jp.mosp.time.dto.settings.HolidayDtoInterface;
import jp.mosp.time.dto.settings.PaidHolidayDataDtoInterface;
import jp.mosp.time.dto.settings.StockHolidayDataDtoInterface;
import jp.mosp.time.dto.settings.TotalAbsenceDtoInterface;
import jp.mosp.time.dto.settings.TotalLeaveDtoInterface;
import jp.mosp.time.dto.settings.TotalOtherVacationDtoInterface;
import jp.mosp.time.dto.settings.TotalTimeCutoffListDtoInterface;
import jp.mosp.time.dto.settings.TotalTimeDataDtoInterface;
import jp.mosp.time.dto.settings.TotalTimeDtoInterface;
import jp.mosp.time.dto.settings.TotalTimeEmployeeDtoInterface;
import jp.mosp.time.settings.base.TimeSettingAction;

/**
 * 勤怠設定情報の確認、管理を行う。<br>
 * <br>
 * 以下のコマンドを扱う。<br>
 * <ul><li>
 * {@link #CMD_SHOW}
 * </li><li>
 * {@link #CMD_SEARCH}
 * </li><li>
 * {@link #CMD_TEMP_TIGHTEN}
 * </li><li>
 * {@link #CMD_DECIDE}
 * </li><li>
 * {@link #CMD_REMOVE}
 * </li><li>
 * {@link #CMD_SORT}
 * </li><li>
 * {@link #CMD_PAGE}
 * </li><li>
 */
public class TotalTimeAction extends TimeSettingAction {
	
	/**
	 * 表示コマンド。<br>
	 * <br>
	 * 初期表示を行う。<br>
	 */
	public static final String	CMD_SHOW			= "TM3110";
	
	/**
	 * 検索コマンド。<br>
	 * <br>
	 * 検索欄に入力された各種情報項目を基に検索を行い、条件に沿った締日情報の一覧表示を行う。<br>
	 * 一覧表示の際には締日コードでソートを行う。<br>
	 */
	public static final String	CMD_SEARCH			= "TM3112";
	
	/**
	 * 再表示コマンド。<br>
	 * <br>
	 * 一度この画面を表示してからパンくずリスト等で再度遷移する場合は保持していた検索条件で検索を行って再表示する。<br>
	 */
	public static final String	CMD_RE_SHOW			= "TM3113";
	
	/**
	 * 仮締コマンド。<br>
	 * <br>
	 * その月の勤怠情報が編集できないようにロックする。対象月に未承認・未申請のレコードの有無をチェックし、<br>
	 * 発見された場合はエラー内容の参照画面へ遷移する。<br>
	 */
	public static final String	CMD_TEMP_TIGHTEN	= "TM3114";
	
	/**
	 * 確定コマンド。<br>
	 * <br>
	 * その月の勤怠集計を確定し、対象月を翌月へ進める。仮締と同様に未申請・未承認レコードの有無を確認し、<br>
	 * 発見されたらエラー内容表示画面を表示する。<br>
	 */
	public static final String	CMD_DECIDE			= "TM3115";
	
	/**
	 * 解除コマンド。<br>
	 * <br>
	 * 仮締、確定の実行されたレコードを元の未集計状態へと戻す。該当データのレコードは修正が可能となる。<br>
	 */
	public static final String	CMD_REMOVE			= "TM3117";
	
	/**
	 * ソートコマンド。<br>
	 * <br>
	 * それぞれのレコードの値を比較して一覧表示欄の各情報毎に並び替えを行う。
	 * これが実行される度に並び替えが昇順・降順と交互に切り替わる。<br>
	 */
	public static final String	CMD_SORT			= "TM3118";
	
	/**
	 * ページ繰りコマンド。<br>
	 * <br>
	 * 検索処理を行った際に検索結果が100件を超えた場合に分割されるページ間の遷移を行う。<br>
	 */
	public static final String	CMD_PAGE			= "TM3119";
	
	/**
	 * 集計月決定コマンド。<br>
	 * <br>
	 * 集計月欄に入力されている年月を基に締日情報を検索し、締日名称と締日日付の各プルダウンにその年月時点で有効な情報を入れて表示する。<br>
	 */
	public static final String	CMD_SET_TOTAL_MONTH	= "TM3180";
	
	/**
	 * 状態ステータス（未締）。<br>
	 * <br>
	 * 検索結果の締状態が未締の場合に設定する。<br>
	 */
	public static final String	PRM_STATE_UNWELLSET	= "未締";
	
	/**
	 * パラメータ状態（仮締）。<br>
	 * <br>
	 * 検索結果の締状態が仮締の場合に設定する。<br>
	 */
	public static final String	PRM_STATE_DRAFT		= "仮締";
	
	/**
	 * 状態ステータス（確定）。<br>
	 * <br>
	 * 検索結果の締状態が確定の場合に設定する。<br>
	 */
	public static final String	PRM_STATE_REGIST	= "確定";
	
	/**
	 * 未締状態ステータス。<br>
	 * <br>
	 * 検索結果の締状態に未締があればtrueを設定する。<br>
	 */
	public static boolean		unwellsetState;
	
	/**
	 * 仮締状態ステータス。<br>
	 * <br>
	 * 検索結果の締状態に仮締があればtrueを設定する。<br>
	 */
	public static boolean		draftState;
	

	/**
	 * {@link TimeAction#TimeAction()}を実行する。<br>
	 */
	public TotalTimeAction() {
		super();
		topicPathCommand = CMD_RE_SHOW;
	}
	
	@Override
	protected BaseVo getSpecificVo() {
		return new TotalTimeVo();
	}
	
	/**
	 * 各コマンドの処理を実行する。<br>
	 */
	public void action() throws MospException {
		// コマンド毎の処理
		if (mospParams.getCommand().equals(CMD_SHOW)) {
			// 表示
			prepareVo(false, false);
			show();
		} else if (mospParams.getCommand().equals(CMD_SEARCH)) {
			// 検索処理
			prepareVo();
			search();
		} else if (mospParams.getCommand().equals(CMD_RE_SHOW)) {
			// 再表示
			prepareVo(true, false);
			search();
		} else if (mospParams.getCommand().equals(CMD_TEMP_TIGHTEN)) {
			// 仮締
			prepareVo();
			tmpTighten();
		} else if (mospParams.getCommand().equals(CMD_DECIDE)) {
			// 確定
			prepareVo();
			decide();
		} else if (mospParams.getCommand().equals(CMD_REMOVE)) {
			// 解除
			prepareVo();
			remove();
		} else if (mospParams.getCommand().equals(CMD_SORT)) {
			// ソート
			prepareVo();
			sort();
		} else if (mospParams.getCommand().equals(CMD_PAGE)) {
			// ページ繰り
			prepareVo();
			page();
		} else if (mospParams.getCommand().equals(CMD_SET_TOTAL_MONTH)) {
			// 集計月決定コマンド
			prepareVo();
			setActivationMonth();
		}
	}
	
	/**
	 * 初期表示処理を行う。<br>
	 * @throws MospException 例外発生時
	 */
	protected void show() throws MospException {
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// 初期値設定
		setDefaultValues();
		// ページ繰り設定
		setPageInfo(CMD_PAGE, getListLength());
		// ソートキー設定
		vo.setComparatorName(TotalTimeCutoffListCutoffCodeComparator.class.getName());
		// 有効日モード設定
		vo.setModeActivateDate(PlatformConst.MODE_ACTIVATE_DATE_FIXED);
	}
	
	/**
	 * @throws MospException 例外処理が発生した場合 
	 */
	protected void search() throws MospException {
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// 検索クラス取得
		TotalTimeTransactionSearchBeanInterface search = timeReference().totalTimeTransactionSearch();
		// VOの値を検索クラスへ設定
		search.setRequestYear(Integer.valueOf(vo.getPltEditRequestYear()));
		search.setRequestMonth(Integer.valueOf(vo.getPltEditRequestMonth()));
		search.setCutoffDate(vo.getPltEditCutoffDate());
		search.setCutoffCode(vo.getTxtEditCutoffCode());
		search.setCutoffName(vo.getTxtEditCutoffName());
		search.setCutoffState(vo.getPltEditCutoffState());
		List<TotalTimeCutoffListDtoInterface> list = search.getSearchList();
		// 検索結果リスト設定
		vo.setList(list);
		// デフォルトソートキー及びソート順設定
		vo.setComparatorName(TotalTimeCutoffListCutoffCodeComparator.class.getName());
		vo.setAscending(false);
		// ソート
		sort();
		// 検索結果確認
		if (list.isEmpty()) {
			// 検索結果無しメッセージ設定
			addNoSearchResultMessage();
		}
		// 検索した時点の年月を保存する。
		vo.setTotalTimeRequestYear(vo.getPltEditRequestYear());
		vo.setTotalTimeRequestMonth(vo.getPltEditRequestMonth());
	}
	
	/**
	 * 仮締処理を行う。<br>
	 * @throws MospException 比較クラスのインスタンス生成に失敗した場合
	 */
	protected void tmpTighten() throws MospException {
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		String cutoffCode = getTransferredCode();
		// 登録クラス取得
		TotalTimeTransactionRegistBeanInterface regist = time().totalTimeTransactionRegist();
		TotalTimeEmployeeTransactionRegistBeanInterface employeeRegist = time().totalTimeEmployeeTransactionRegist();
		// 集計クラス取得
		TotalTimeCalcBeanInterface calc = time().totalTimeCalc();
		// DTOの準備
		TotalTimeDtoInterface dto = regist.getInitDto();
		// DTOに値を設定
		setDtoFields(dto);
		// 仮締をセット
		dto.setCutoffState(1);
		// 仮締結果確認
		// 締日→勤怠設定→設定適用から個人IDを取得する
		Date date = DateUtility.getDate(vo.getPltEditRequestYear(), vo.getPltEditRequestMonth(), "1");
		int calculationYear = Integer.parseInt(vo.getPltEditRequestYear());
		int calculationMonth = Integer.parseInt(vo.getPltEditRequestMonth());
		List<String> workSettingCodeList = timeReference().timeSetting().getWorkSettingCode(cutoffCode, date);
		if (workSettingCodeList.isEmpty()) {
			// 勤怠設定コードが存在しないなら処理終了
			addInsertFailedMessage();
			mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, mospParams.getName("menuTimeSettings"), null);
			return;
		}
		List<String> personalIdList = timeReference().application().getPersonalIdList(workSettingCodeList, date);
		if (personalIdList.isEmpty()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, mospParams.getName("Employee"), null);
			return;
		}
		List<CutoffErrorListDtoInterface> errorList = new ArrayList<CutoffErrorListDtoInterface>();
		int employeeCount = 0;
		List<String> registerdPersonalId = new ArrayList<String>();
		for (String personalId : personalIdList) {
			TotalTimeEmployeeDtoInterface totalTimeEmployeeDto = timeReference().totalTimeEmployeeTransaction()
				.findForKey(personalId, Integer.parseInt(vo.getPltEditRequestYear()),
						Integer.parseInt(vo.getPltEditRequestMonth()));
			if (totalTimeEmployeeDto == null || totalTimeEmployeeDto.getCutoffState() == 0) {
				// 未締の場合
				time().totalLeaveRegist().delete(personalId, calculationYear, calculationMonth);
				List<HolidayDtoInterface> specialHolidayList = timeReference().holiday().getHolidayList(date, 2);
				for (HolidayDtoInterface holidayDto : specialHolidayList) {
					TotalLeaveDtoInterface totalLeaveDto = calc.calcTotalLeave(personalId, calculationYear,
							calculationMonth, cutoffCode, holidayDto.getHolidayCode());
					if (mospParams.hasErrorMessage()) {
						// 登録失敗メッセージ設定
						addInsertFailedMessage();
						return;
					}
					time().totalLeaveRegist().insert(totalLeaveDto);
					if (mospParams.hasErrorMessage()) {
						// 登録失敗メッセージ設定
						addInsertFailedMessage();
						return;
					}
				}
				time().totalOtherVacationRegist().delete(personalId, calculationYear, calculationMonth);
				List<HolidayDtoInterface> otherHolidayList = timeReference().holiday().getHolidayList(date, 3);
				for (HolidayDtoInterface holidayDto : otherHolidayList) {
					TotalOtherVacationDtoInterface totalOtherVacationDto = calc.calcTotalOtherVacation(personalId,
							calculationYear, calculationMonth, cutoffCode, holidayDto.getHolidayCode());
					if (mospParams.hasErrorMessage()) {
						// 登録失敗メッセージ設定
						addInsertFailedMessage();
						return;
					}
					time().totalOtherVacationRegist().insert(totalOtherVacationDto);
					if (mospParams.hasErrorMessage()) {
						// 登録失敗メッセージ設定
						addInsertFailedMessage();
						return;
					}
				}
				time().totalAbsenceRegist().delete(personalId, calculationYear, calculationMonth);
				List<HolidayDtoInterface> absenceList = timeReference().holiday().getHolidayList(date, 4);
				for (HolidayDtoInterface holidayDto : absenceList) {
					TotalAbsenceDtoInterface totalAbsenceDto = calc.calcTotalAbsence(personalId, calculationYear,
							calculationMonth, cutoffCode, holidayDto.getHolidayCode());
					if (mospParams.hasErrorMessage()) {
						// 登録失敗メッセージ設定
						addInsertFailedMessage();
						return;
					}
					time().totalAbsenceRegist().insert(totalAbsenceDto);
					if (mospParams.hasErrorMessage()) {
						// 登録失敗メッセージ設定
						addInsertFailedMessage();
						return;
					}
				}
				// 手当は使わない
				TotalTimeDataDtoInterface totalTimeDataDto = timeReference().totalTime().findForKey(personalId,
						calculationYear, calculationMonth);
				if (totalTimeDataDto == null) {
					totalTimeDataDto = time().totalTimeRegist().getInitDto();
				}
				List<CutoffErrorListDtoInterface> list = calc.calc(totalTimeDataDto, personalId, calculationYear,
						calculationMonth, cutoffCode);
				if (mospParams.hasErrorMessage()) {
					// 登録失敗メッセージ設定
					addInsertFailedMessage();
					return;
				}
				if (!list.isEmpty()) {
					errorList.addAll(list);
					continue;
				}
				time().totalTimeRegist().regist(totalTimeDataDto);
				if (mospParams.hasErrorMessage()) {
					// 登録失敗メッセージ設定
					addInsertFailedMessage();
					return;
				}
				registerdPersonalId.add(personalId);
			}
			employeeCount++;
		}
		employeeRegist.draft(registerdPersonalId, Integer.parseInt(vo.getTotalTimeRequestYear()), Integer.parseInt(vo
			.getTotalTimeRequestMonth()), cutoffCode);
		if (personalIdList.size() == employeeCount) {
			// 仮締処理
			regist.draft(dto);
		}
		if (mospParams.hasErrorMessage()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			return;
		}
		// エラーリストがあるか取得する
		if (!errorList.isEmpty()) {
			// 仮締処理からlistが帰ってきたら集計時エラー内容参照画面へ遷移する
			mospParams.addGeneralParam(TimeConst.CODE_TOTALTIME_ERROR, errorList);
			mospParams.setNextCommand(CutoffErrorListAction.CMD_SHOW);
			return;
		}
		// コミット
		commit();
		// 仮締成功メッセージ設定
		addTighteningMessage();
		// 検索
		search();
	}
	
	/**
	 * 確定処理を行う。<br>
	 * @throws MospException 比較クラスのインスタンス生成に失敗した場合
	 */
	protected void decide() throws MospException {
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// 登録クラス取得
		TotalTimeTransactionRegistBeanInterface regist = time().totalTimeTransactionRegist();
		String cutoffCode = getTransferredCode();
		int calculationYear = Integer.parseInt(vo.getPltEditRequestYear());
		int calculationMonth = Integer.parseInt(vo.getPltEditRequestMonth());
		Date date = DateUtility.getFirstDateOfMonth(calculationYear, calculationMonth);
		List<String> workSettingCodeList = timeReference().timeSetting().getWorkSettingCode(cutoffCode, date);
		if (workSettingCodeList.isEmpty()) {
			// 勤怠設定コードが存在しないなら処理終了
			addInsertFailedMessage();
			mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, mospParams.getName("menuTimeSettings"), null);
			return;
		}
		List<String> personalIdList = timeReference().application().getPersonalIdList(workSettingCodeList, date);
		if (personalIdList.isEmpty()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, mospParams.getName("Employee"), null);
			return;
		}
		for (String personalId : personalIdList) {
			TotalTimeEmployeeDtoInterface totalTimeEmployeeDto = timeReference().totalTimeEmployeeTransaction()
				.findForKey(personalId, calculationYear, calculationMonth);
			if (totalTimeEmployeeDto == null || totalTimeEmployeeDto.getCutoffState() != 1) {
				// 仮締でない場合
				String employeeCode = reference().human().getEmployeeCode(personalId, date);
				// 登録失敗メッセージ設定
				mospParams.addErrorMessage(TimeMessageConst.MSG_NOT_TIGHTENING, employeeCode, null);
				continue;
			}
		}
		if (mospParams.hasErrorMessage()) {
			addInsertFailedMessage();
			return;
		}
		// DTOの準備
		TotalTimeDtoInterface dto = timeReference().totalTimeTransaction().findForKey(calculationYear,
				calculationMonth, cutoffCode);
		// DTOに値を設定
		setDtoFields(dto);
		// 確定をセット
		dto.setCutoffState(2);
		// 確定処理
		regist.regist(dto);
		// 確定結果確認
		if (mospParams.hasErrorMessage()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			return;
		}
		// 有給休暇更新
		updatePaidHoliday(personalIdList);
		if (mospParams.hasErrorMessage()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			return;
		}
		// コミット
		commit();
		// 確定成功メッセージ設定
		addDecideMessage();
		// 検索
		search();
	}
	
	/**
	 * 解除処理を行う。<br>
	 * @throws MospException 比較クラスのインスタンス生成に失敗した場合
	 */
	protected void remove() throws MospException {
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// 登録クラス取得
		TotalTimeTransactionRegistBeanInterface regist = time().totalTimeTransactionRegist();
		TotalTimeEmployeeTransactionRegistBeanInterface employeeRegist = time().totalTimeEmployeeTransactionRegist();
		String cutoffCode = getTransferredCode();
		int calculationYear = Integer.parseInt(vo.getPltEditRequestYear());
		int calculationMonth = Integer.parseInt(vo.getPltEditRequestMonth());
		Date date = DateUtility.getFirstDateOfMonth(calculationYear, calculationMonth);
		List<String> workSettingCodeList = timeReference().timeSetting().getWorkSettingCode(cutoffCode, date);
		if (workSettingCodeList.isEmpty()) {
			// 勤怠設定コードが存在しないなら処理終了
			addInsertFailedMessage();
			mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, mospParams.getName("menuTimeSettings"), null);
			return;
		}
		List<String> personalIdList = timeReference().application().getPersonalIdList(workSettingCodeList, date);
		if (personalIdList.isEmpty()) {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			mospParams.addErrorMessage(PlatformMessageConst.MSG_NO_ITEM, mospParams.getName("Employee"), null);
			return;
		}
		List<String> removePersonalIdList = new ArrayList<String>();
		TotalTimeDtoInterface totalTimeDto = timeReference().totalTimeTransaction().findForKey(calculationYear,
				calculationMonth, cutoffCode);
		if (totalTimeDto.getCutoffState() == 1) {
			// 仮締解除(仮締→未締)
			for (String personalId : personalIdList) {
				TotalTimeEmployeeDtoInterface totalTimeEmployeeDto = timeReference().totalTimeEmployeeTransaction()
					.findForKey(personalId, calculationYear, calculationMonth);
				if (totalTimeEmployeeDto == null) {
					continue;
				}
				if (totalTimeEmployeeDto.getCutoffState() == 0) {
					// 未締の場合
					continue;
				}
				removePersonalIdList.add(personalId);
			}
			// DTOに値を設定
			setDtoFields(totalTimeDto);
			// 未締をセット
			totalTimeDto.setCutoffState(0);
			// 仮締解除
			regist.draftRelease(totalTimeDto);
			employeeRegist.draftRelease(removePersonalIdList, calculationYear, calculationMonth, cutoffCode);
			time().totalTimeRegist().delete(removePersonalIdList, calculationYear, calculationMonth);
			time().totalLeaveRegist().delete(removePersonalIdList, calculationYear, calculationMonth);
			time().totalOtherVacationRegist().delete(removePersonalIdList, calculationYear, calculationMonth);
			time().totalAbsenceRegist().delete(removePersonalIdList, calculationYear, calculationMonth);
		} else if (totalTimeDto.getCutoffState() == 2) {
			// 確定解除(確定→仮締)
			for (String personalId : personalIdList) {
				TotalTimeEmployeeDtoInterface totalTimeEmployeeDto = timeReference().totalTimeEmployeeTransaction()
					.findForKey(personalId, calculationYear, calculationMonth);
				if (totalTimeEmployeeDto == null || totalTimeEmployeeDto.getCutoffState() == 0) {
					// 未締の場合
					String employeeCode = reference().human().getEmployeeCode(personalId, date);
					// 登録失敗メッセージ設定
					mospParams.addErrorMessage(TimeMessageConst.MSG_NOT_TIGHTENING, employeeCode, null);
					continue;
				}
			}
			if (mospParams.hasErrorMessage()) {
				addInsertFailedMessage();
				return;
			}
			// DTOに値を設定
			setDtoFields(totalTimeDto);
			// 仮締をセット
			totalTimeDto.setCutoffState(1);
			// 確定解除
			regist.registRelease(totalTimeDto);
//			employeeRegist.registRelease(personalIdList, calculationYear, calculationMonth, cutoffCode);
		} else {
			// 登録失敗メッセージ設定
			addInsertFailedMessage();
			return;
		}
		// 解除結果確認
		if (mospParams.hasErrorMessage()) {
			// 仮締解除失敗メッセージ設定
			addInsertFailedMessage();
			return;
		}
		// コミット
		commit();
		// 仮締解除成功メッセージ設定
		addReleaseMessage();
		// 検索
		search();
	}
	
	/**
	 * 一覧のソート処理を行う。<br>
	 * @throws MospException 比較クラスのインスタンス生成に失敗した場合
	 */
	protected void sort() throws MospException {
		setVoList(sortList(getTransferredSortKey()));
	}
	
	/**
	 * 一覧のページ処理を行う。
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected void page() throws MospException {
		setVoList(pageList());
	}
	
	/**
	 * 集計月設定処理を行う。<br>
	 * 保持有効日モードを確認し、モード及びプルダウンの再設定を行う。<br>
	 * @throws MospException プルダウンの取得に失敗した場合
	 */
	protected void setActivationMonth() throws MospException {
		// VO取得
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// 現在の有効日モードを確認
		if (vo.getModeActivateDate().equals(PlatformConst.MODE_ACTIVATE_DATE_CHANGING)) {
			// 有効日モード設定
			vo.setModeActivateDate(PlatformConst.MODE_ACTIVATE_DATE_FIXED);
		} else {
			// 有効日モード設定
			vo.setModeActivateDate(PlatformConst.MODE_ACTIVATE_DATE_CHANGING);
		}
	}
	
	/**
	 * 初期値を設定する。<br>
	 */
	public void setDefaultValues() {
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// システム日付取得
		String editRequestYear;
		Date date = DateUtility.getSystemDate();
		// 検索項目設定
		editRequestYear = DateUtility.getStringYear(date);
		vo.setAryPltEditRequestYear(getYearArray(editRequestYear));
		vo.setPltEditRequestYear(editRequestYear);
		vo.setAryPltEditRequestMonth(getMonthArray());
		vo.setPltEditRequestMonth(String.valueOf(DateUtility.getMonth(date)));
		vo.setTxtEditCutoffCode("");
		vo.setTxtEditCutoffName("");
		vo.setPltEditCutoffDate(Integer.toString(0));
		vo.setTxtEditCutoffCode("");
		vo.setPltEditCutoffState("");
		// 集計対象年月ラベルの初期化
		vo.setTxtLblRequestYear("");
		vo.setTxtLblRequestMonth("");
		unwellsetState = false;
		draftState = false;
	}
	
	/**
	 * 検索結果リストの内容をVOに設定する。<br>
	 * @param list 対象リスト
	 * @throws MospException インスタンスの取得及びSQL実行に失敗した場合
	 */
	protected void setVoList(List<? extends BaseDtoInterface> list) throws MospException {
		// VO取得
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// データ配列初期化
		String[] aryCkbRecordId = new String[list.size()];
		String[] aryLblCutoffCode = new String[list.size()];
		String[] aryLblCutoffName = new String[list.size()];
		String[] aryLblCutoffDate = new String[list.size()];
		String[] aryLblCutoffState = new String[list.size()];
		unwellsetState = false;
		draftState = false;
		// データ作成
		for (int i = 0; i < list.size(); i++) {
			// リストから情報を取得
			TotalTimeCutoffListDtoInterface dto = (TotalTimeCutoffListDtoInterface)list.get(i);
			// 配列に情報を設定
			aryCkbRecordId[i] = String.valueOf(dto.getTmmCutoffId());
			aryLblCutoffCode[i] = dto.getCutoffCode();
			aryLblCutoffName[i] = dto.getCutoffName();
			if (dto.getCutoffDate() == 0) {
				aryLblCutoffDate[i] = mospParams.getName("TheEnd");
			} else {
				aryLblCutoffDate[i] = String.valueOf(dto.getCutoffDate());
			}
			aryLblCutoffState[i] = getStringState(Integer.valueOf(dto.getCutoffState()));
		}
		// データをVOに設定
		vo.setAryCkbTotalTimeListId(aryCkbRecordId);
		vo.setAryLblCutoffCode(aryLblCutoffCode);
		vo.setAryLblCutoffName(aryLblCutoffName);
		vo.setAryLblCutoffDate(aryLblCutoffDate);
		vo.setAryLblCutoffState(aryLblCutoffState);
	}
	
	/**
	 * 締め状態をInt型からString型の文字列に変換する。<br>
	 * @param state Int型の締め状態
	 * @return 文字列に変換された締め状態
	 * @throws MospException インスタンスの取得及びSQL実行に失敗した場合
	 */
	protected String getStringState(int state) throws MospException {
		if (state == 0) {
			// 未締
			unwellsetState = true;
			return PRM_STATE_UNWELLSET;
		} else if (state == 1) {
			// 仮締
			draftState = true;
			return PRM_STATE_DRAFT;
		} else {
			// 確定
			return PRM_STATE_REGIST;
		}
	}
	
	/**
	 * VO(編集項目)の値をDTOに設定する。<br>
	 * @param dto 対象DTO
	 * @throws MospException 例外発生時
	 */
	protected void setDtoFields(TotalTimeDtoInterface dto) throws MospException {
		// VO取得
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		// 参照クラス取得
		CutoffReferenceBeanInterface cutoff = timeReference().cutoff();
		int year = Integer.parseInt(vo.getTotalTimeRequestYear());
		int month = Integer.parseInt(vo.getTotalTimeRequestMonth());
		String cutoffCode = getTransferredCode();
		Date date = DateUtility.getFirstDateOfMonth(year, month);
		CutoffDtoInterface cutoffDto = cutoff.getCutoffInfo(cutoffCode, date);
		cutoff.chkExistCutoff(cutoffDto, date);
		if (mospParams.hasErrorMessage()) {
			return;
		}
		Date calculationDate = DateUtility.getLastDateOfMonth(year, month);
		int cutoffDate = cutoffDto.getCutoffDate();
		if (cutoffDate != 0) {
			// 締日が末日でない場合
			calculationDate = DateUtility.getDate(year, month, cutoffDate);
			if (cutoffDate <= 15) {
				// 締日が翌月の場合
				Date nextMonth = DateUtility.addMonth(DateUtility.getFirstDateOfMonth(year, month), 1);
				calculationDate = DateUtility.getDate(DateUtility.getYear(nextMonth), DateUtility.getMonth(nextMonth),
						cutoffDate);
			}
		}
		// VOの値をDTOに設定
		dto.setCalculationYear(year);
		dto.setCalculationMonth(month);
		dto.setCutoffCode(cutoffCode);
		dto.setCalculationDate(calculationDate);
		// 未締に設定
		dto.setCutoffState(0);
	}
	
	/**
	 * 有給休暇データを更新する。<br>
	 * @param list 個人IDリスト
	 * @throws MospException 例外発生時
	 */
	protected void updatePaidHoliday(List<String> list) throws MospException {
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		int year = Integer.parseInt(vo.getPltEditRequestYear());
		int month = Integer.parseInt(vo.getPltEditRequestMonth());
		PaidHolidayDataRegistBeanInterface regist = time().paidHolidayDataRegist();
		PaidHolidayInfoReferenceBeanInterface infoReference = timeReference().paidHolidayInfo();
		StockHolidayDataRegistBeanInterface stockRegist = time().stockHolidayDataRegist();
		StockHolidayInfoReferenceBeanInterface stockInfoReference = timeReference().stockHolidayInfo();
		Date cutoffDate = getCutoffDate();
		if (cutoffDate == null) {
			return;
		}
		Date nextDate = DateUtility.addDay(cutoffDate, 1);
		for (String personalId : list) {
			// ストック休暇
			stockRegist.delete(personalId, cutoffDate);
			List<StockHolidayDataDtoInterface> stockHolidayDataList = stockInfoReference.getStockHolidayCalcInfo(
					personalId, cutoffDate);
			for (StockHolidayDataDtoInterface dto : stockHolidayDataList) {
				stockRegist.insert(dto);
			}
			stockRegist.delete(personalId, nextDate);
			List<StockHolidayDataDtoInterface> nextStockHolidayDataList = stockInfoReference
				.getStockHolidayNextMonthInfo(personalId, nextDate, stockHolidayDataList);
			for (StockHolidayDataDtoInterface dto : nextStockHolidayDataList) {
				stockRegist.insert(dto);
			}
			// 有給休暇
			regist.delete(personalId, cutoffDate);
			List<PaidHolidayDataDtoInterface> paidHolidayDataList = infoReference.getPaidHolidayCalcInfo(personalId,
					cutoffDate);
			for (PaidHolidayDataDtoInterface dto : paidHolidayDataList) {
				regist.insert(dto);
			}
			regist.delete(personalId, nextDate);
			List<PaidHolidayDataDtoInterface> nextPaidHolidayDataList = infoReference.getPaidHolidayNextMonthInfo(
					personalId, nextDate, year, month, paidHolidayDataList);
			for (PaidHolidayDataDtoInterface dto : nextPaidHolidayDataList) {
				regist.insert(dto);
			}
			// ストック休暇新規データ
			StockHolidayDataDtoInterface stockHolidayDataDto = stockInfoReference.getNewStockHolidayInfo(personalId,
					nextDate, infoReference.getExpirationDay(paidHolidayDataList, cutoffDate));
			if (stockHolidayDataDto != null) {
				stockRegist.insert(stockHolidayDataDto);
			}
			// 有給休暇新規データ
			PaidHolidayDataDtoInterface paidHolidayDataDto = infoReference.getNewPaidHolidayInfo(personalId,
					cutoffDate, year, month);
			if (paidHolidayDataDto != null) {
				regist.insert(paidHolidayDataDto);
			}
		}
	}
	
	/**
	 * 締日を取得する。<br>
	 * @return 締日
	 * @throws MospException 例外発生時
	 */
	protected Date getCutoffDate() throws MospException {
		String cutoffCode = getTransferredCode();
		if (cutoffCode == null || cutoffCode.isEmpty()) {
			return null;
		}
		// VO準備
		TotalTimeVo vo = (TotalTimeVo)mospParams.getVo();
		int year = Integer.parseInt(vo.getPltEditRequestYear());
		int month = Integer.parseInt(vo.getPltEditRequestMonth());
		CutoffDtoInterface cutoffDto = timeReference().cutoff().getCutoffInfo(cutoffCode,
				DateUtility.getFirstDateOfMonth(year, month));
		if (cutoffDto == null) {
			return null;
		}
		if (cutoffDto.getCutoffDate() == 0) {
			// 末日締の場合
			return DateUtility.getLastDateOfMonth(year, month);
		}
		// 末日締以外の場合
		// TODO
		return null;
	}
	
}
