/*
 * MosP - Mind Open Source Project         http://www.mosp.jp/
 * Copyright (C) 1987-2008 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.action;

import java.util.Date;

import jp.mosp.common.CommonConst;
import jp.mosp.common.action.MosPWorkflowAction;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;

import jp.mosp.human.dto.MKihonDto;

import jp.mosp.kintai.dto.MSyukkinboDto;
import jp.mosp.kintai.vo.ApprovalCardVo;

import jp.mosp.workflow.dto.AmUnitDto;

public class ApprovalCardAction extends MosPWorkflowAction {

	// コマンド
	private static final String CMD_APPROVAL_CARD_SELECT		= "K2116";
	private static final String CMD_APPROVAL_CARD_REGIST		= "K2117";
	private static final String CMD_APPROVAL_CARD_RETURN		= "K2119";

	/**
	 * コンストラクタ
	 */
	public ApprovalCardAction() {
		super();
	}

	public void action() throws Exception {
		// コネクション取得
		getConnection();
		// MANAGER権限確認
		confirmManagerAuth();
		// VOの取得
		ApprovalCardVo vo;
		vo = (ApprovalCardVo)getStoredVo(CommonConst.VO_APPROVAL_CARD);
		if (vo == null) {
			vo = new ApprovalCardVo();
		}
		vo.initVo(cfg, msg, cmd, aspUser, user);
		vo.clearMessage();
		vo.clearErrField();
		storeVo(CommonConst.VO_APPROVAL_CARD, vo);
		vo.setParams(request);
		// VO及びフォワード先URLの設定
		setVo(vo);
		setUrl(vo.getRetUrl());
		// DTOの取得
		MSyukkinboDto dto;
		Object objDto = session.getAttribute(MospConst.ATT_DTO);
		dto = objDto instanceof MSyukkinboDto ? (MSyukkinboDto)objDto : null;
		// ユーザー情報取得
		getInfo(user.getUserId());
		// プルダウンリスト
		setPulldownList(vo);
		// 勤怠管理コマンド
		vo.setCmdMenuButton(vo.CMD_MENU_MAMAGE);
		vo.setCmdListButton(ApprovalListAction.CMD_APPROVAL_LIST_SEARCH);
		vo.setNamListButton(CommonConst.TTL_APPROVAL_LIST);
		// コマンド毎の処理
		if (cmd.equals(CMD_APPROVAL_CARD_SELECT)) {
			// 出勤検索
			dto = searchApproval(vo);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, dto);	
		} else if (cmd.equals(CMD_APPROVAL_CARD_REGIST)) {
			// 承認
			aprroved(vo, dto);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, dto);
		} else if (cmd.equals(CMD_APPROVAL_CARD_RETURN)) {
			// 差戻
			returned(vo, dto);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, dto);			
		} else {
			throw new MospException(MospConst.EX_CMD_INVALID);
		}
	}

	/**
	 * プルダウンリスト設定
	 * @param vo
	 * @throws Exception
	 */
	private void setPulldownList(ApprovalCardVo vo) throws Exception {
		// 手当一覧
		vo.aryAllowance = getMosPCodeArray(CommonConst.TID_ALLOWANCE_NAME);
		// 勤務形態プルダウン
		vo.aryPltWorkType = getWorkTypeArrayWithWeekHoliday();
		// 休出区分プルダウン
		vo.aryPltWorkOnHoliday = getMosPCodeArray(CommonConst.TID_WORK_ON_HOLIDAY_TYPE);
		// 出勤時半休区分プルダウン
		vo.aryPltStartHalfHoliday = getMosPCodeArray(CommonConst.TID_HALF_HOLIDAY_TYPE);
		// 遅刻理由プルダウン
		vo.aryPltLateReason = getMosPCodeArray(CommonConst.TID_LATE_REASON);
		// 遅刻証明書プルダウン
		vo.aryPltLateCertificate = getMosPCodeArray(CommonConst.TID_LATE_CERTIFICATE);
		// 退勤時半休区分プルダウン
		vo.aryPltQuitHalfHoliday = getMosPCodeArray(CommonConst.TID_HALF_HOLIDAY_TYPE);
		// 早退理由プルダウン
		vo.aryPltLeaveEarlyReason = getMosPCodeArray(CommonConst.TID_LEAVE_EARLY_REASON);
		// 早退証明書プルダウン
		vo.aryPltLeaveEarlyCertificate = getMosPCodeArray(CommonConst.TID_LEAVE_EARLY_CERTIFICATE);
		// 承認理由プルダウン
		vo.aryPltApprovalReason = getMosPCodeArray(CommonConst.TID_APPROVAL_REASON);
	}

	/**
	 * 勤怠承認対象日取得
	 * @param vo
	 * @return	MSyukkinboDto	対象DTO
	 * @throws Exception
	 */
	private MSyukkinboDto searchApproval(ApprovalCardVo vo) throws Exception {
		// DBコネクションの取得
		if (conn == null) {
			getConnection();
		}
		// 人事基本情報取得
		MKihonDto mKihonDto = getBasisInfo(key1);
		vo.setLblKCode(mKihonDto.getKCode());
		vo.setLblKName(mKihonDto.getSimei());
		vo.setLblSectionName(util.getCodeName(mKihonDto.getSCode(), getSectionArrayAll()));
		vo.setHidKCode(mKihonDto.getKCode());
		vo.setHidDate(key2);
		vo.setLblYear(String.valueOf(MospUtility.getYear(util.convStringDateToDate(vo.getHidDate()))));
		vo.setLblMonth(String.valueOf(MospUtility.getMonth(util.convStringDateToDate(vo.getHidDate()))));
		vo.setLblDay(String.valueOf(MospUtility.getDay(util.convStringDateToDate(vo.getHidDate()))));
		// DAOの準備
		prepareMSyukkinboDao();
		// 勤怠検索
		MSyukkinboDto dto = getSyukkinboInfo(mKihonDto.getKCode(), vo.getHidDate());
		if (chkExistDto(dto)) {
			// VOに情報をセット
			vo.setFields(dto);
			// 対象年月取得
			Date targetDate = util.convStringDateToDate(vo.getHidDate());
			// 承認ルート情報設定
			String[] aryRouteInfo = getTargetRouteInfo(mKihonDto.getKCode(), targetDate);
			// 一次承認
			String layer1 = aryRouteInfo[0];
			// 二次承認
			String lastLayer = aryRouteInfo[1];
			// DAOの準備
			prepareAmUnitDao();
			// 情報の取得
			AmUnitDto layer1Dto = unitDao.findForCurrentUnit(
					layer1,
					mKihon.getKCode(),
					util.convDateFormattedByHyphen(targetDate)
			);
			AmUnitDto lastLayerDto = unitDao.findForCurrentUnit(
					lastLayer,
					mKihon.getKCode(),
					util.convDateFormattedByHyphen(targetDate)
			);
			// 一次承認
			if (isRequest(dto) && chkExistDto(layer1Dto)) {
				vo.setLblApprovalLayer(CommonConst.NAM_1ST_APPROVED);
				vo.setHidApprovalLayer(CommonConst.NUM_ATTENDANCE_1ST_APPROVED);
				vo.setApproval(ApprovalCardVo.MODE_APPROVAL);
			} 
			// 二次承認
			else if (is1stApproved(dto) && chkExistDto(lastLayerDto)) {
				vo.setLblApprovalLayer(CommonConst.NAM_2ND_APPROVED);
				vo.setHidApprovalLayer(CommonConst.NUM_ATTENDANCE_2ND_APPROVED);
				vo.setApproval(ApprovalCardVo.MODE_APPROVAL);
			} else {
				vo.setDefaultValues();
				vo.setApproval(ApprovalCardVo.MODE_VIEW);
			}
		} else {
			vo.setDefaultValues();
			vo.setApproval(ApprovalCardVo.MODE_VIEW);
		}
		return dto;
	}

	/**
	 * 勤怠承認処理
	 * @param vo
	 * @param dto
	 * @throws Exception
	 */
	private void aprroved(ApprovalCardVo vo, MSyukkinboDto dto) throws Exception {
		// パラメータの妥当性確認
		vo.validate();
		// 排他確認
		chkExclusive(dto, getSyukkinboInfo(vo.getHidKCode(), vo.getHidDate(), true), vo);
		// 承認処理
		runApprovalProcess(
				vo.getHidKCode(),
				vo.getHidDate(),
				vo.getHidApprovalLayer(),
				vo.getTxtApprovalComment(),
				mKihon.getKCode()
		);
		// DTOの再取得
		MSyukkinboDto retDto = getSyukkinboInfo(dto.getKCode(), dto.getHizuke());
		chkUpdate(retDto);
		// コミット
		commit();
		// メッセージ設定
		if (is1stApproved(retDto)) {
			vo.setMessage(MospUtility.getMessage(msg, CommonConst.MSG_DONE, CommonConst.NAM_1ST_APPROVED));
		}
		if (is2ndApproved(retDto)) {
			vo.setMessage(MospUtility.getMessage(msg, CommonConst.MSG_DONE, CommonConst.NAM_2ND_APPROVED));
		}
		// モード設定
		vo.setApproval(ApprovalCardVo.MODE_VIEW);
	}

	/**
	 * 勤怠差戻処理
	 * @param vo
	 * @param dto
	 * @throws Exception
	 */
	private void returned(ApprovalCardVo vo, MSyukkinboDto dto) throws Exception {
		// パラメータの妥当性確認
		vo.validate();
		// 排他確認
		chkExclusive(dto, getSyukkinboInfo(vo.getHidKCode(), vo.getHidDate(), true), vo);
		// 差戻理由の設定
		String reason = "";
		if (is1stApproved(vo.getHidApprovalLayer())) {
			reason = CommonConst.NUM_ATTENDANCE_1ST_RETURNED;
		}
		if (is2ndApproved(vo.getHidApprovalLayer())) {
			reason = CommonConst.NUM_ATTENDANCE_2ND_RETURNED;
		}
		// 差戻処理
		runApprovalProcess(
				vo.getHidKCode(),
				vo.getHidDate(),
				reason,
				vo.getTxtApprovalComment(),
				mKihon.getKCode()
		);
		// DTOの再取得
		chkUpdate(getSyukkinboInfo(dto.getKCode(), dto.getHizuke()));
		// コミット
		commit();
		// メッセージ設定
		vo.setMessage(MospUtility.getMessage(msg, CommonConst.MSG_APPROVAL_RETURNED, ""));
		// モード設定
		vo.setApproval(ApprovalCardVo.MODE_VIEW);
	}

}
