package jp.mosp.payroll.common.action;

import java.sql.SQLException;

import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.common.part.DatePart;
import jp.mosp.human.action.HumanCalcAction;
import jp.mosp.payroll.base.AdjustmentAction;
import jp.mosp.payroll.base.PayrollConst;
import jp.mosp.payroll.common.vo.AdjustmentCardVo;
import jp.mosp.payroll.dto.CdAdjustmentDto;

public class AdjustmentCardAction extends AdjustmentAction {
	
	// コマンド
	private static final String CMD_ADJUSTMENT_CARD_SHOW    = "P3021"; // 参照
	private static final String CMD_ADJUSTMENT_CARD_SELECT  = "P3022"; // 選択
	private static final String CMD_ADJUSTMENT_CARD_REGIST  = "P3023"; // 登録
	private static final String CMD_ADJUSTMENT_CARD_REG_CAL = "P3024"; // 登録＆計算
	private static final String CMD_ADJUSTMENT_CARD_MOVE    = "P3025"; // 移動
	public  static final String CMD_ADJUSTMENT_CARD_BACK    = "P3026"; // 戻し
	
	/**
	 * アクション
	 */
	public void action() throws Exception {
		// DBコネクション取得
		getConnection();
		// PAYROLL権限確認
		confirmPayrollAuth();
		// VOの取得
		// VOの取得
		
		// VOの取得及び設定
		AdjustmentCardVo vo =  new AdjustmentCardVo();
		vo = (AdjustmentCardVo)getStoredVo(vo.getClassName());
		if (vo == null || cmd.equals(CMD_ADJUSTMENT_CARD_SHOW)) {
			vo = new AdjustmentCardVo();
			storeVo(vo.getClassName(), vo);
		}
		vo.initVo(cfg, msg, cmd, aspUser, user);
		vo.clearMessage();
		vo.clearErrField();
		// VO及びフォワード先URLの設定
		setVo(vo);
		setUrl(vo.getRetUrl());
		// 名称取得用配列取得
		setNameArray(vo);
		// コマンド毎の処理
		if (cmd.equals(CMD_ADJUSTMENT_CARD_SHOW)) {
			// 表示
			show(vo);
		} else if (cmd.equals(CMD_ADJUSTMENT_CARD_SELECT)) {
			// 選択表示
			// パラメータ取得
			vo.setParams(request);
			// 選択社員コード取得
			kCode = "";
			if (vo.getTxtChangeKCode() != null && !vo.getTxtChangeKCode().equals("") ) {
				kCode = vo.getTxtChangeKCode();
			} else if (key1 != null && !key1.equals("")) {
				kCode = key1;
			} else {
				kCode = vo.getHidKCode();
			}
			// 調整年確認
			confirmAdjustYear(vo.getHidAdjustYear());
			// 年末調整データ設定
			select(vo);
			// 対象年月、対象データ設定
			setTargetData();
			// 給与データ設定
			setTargetPaymentData();

			// 年調区分確認
			confirmAdjustType();
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, cdAdjustmentDto);
		} else if (cmd.equals(CMD_ADJUSTMENT_CARD_REGIST)) {
			// 登録
			// パラメータ取得
			vo.setParamsAll(request);
			// 対象社員コード取得
			kCode = vo.getHidKCode();
			// 調整年確認
			confirmAdjustYear(vo.getHidAdjustYear());
			// 登録
			regist(vo, (CdAdjustmentDto)session.getAttribute(MospConst.ATT_DTO));
			// 年末調整データ再取得
			vo.setTxtChangeKCode(vo.getHidKCode());
			select(vo);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, cdAdjustmentDto);
		} else if (cmd.equals(CMD_ADJUSTMENT_CARD_REG_CAL)) {
			// 登録及び計算
			// パラメータ取得
			vo.setParamsAll(request);
			// 対象社員コード取得
			kCode = vo.getHidKCode();
			// 調整年確認
			confirmAdjustYear(vo.getHidAdjustYear());
			// 登録
			regist(vo, (CdAdjustmentDto)session.getAttribute(MospConst.ATT_DTO));
			// 年末調整計算
			calculate(vo);
			// 年末調整データ再取得
			vo.setTxtChangeKCode(vo.getHidKCode());
			select(vo);
			// セッションにDTOをセット
			session.setAttribute(MospConst.ATT_DTO, cdAdjustmentDto);
		} else if (cmd.equals(CMD_ADJUSTMENT_CARD_MOVE)) {
			// パラメータ取得
			vo.setParamsAll(request);
			// 対象社員コード取得
			kCode = vo.getHidKCode();
			// 調整年確認
			confirmAdjustYear(vo.getHidAdjustYear());
			// DAO準備
			prepareDao();
			// 人事情報設定
			setHumanInfo(vo);
			// 次コマンド設定
			setNextCmd(HumanCalcAction.CMD_HUMAN_CALC_TAB);
			setUrl(MospConst.URL_SRV);
		} else if (cmd.equals(CMD_ADJUSTMENT_CARD_BACK)) {
			// 人事給与情報からの戻り
			// DAO準備
			prepareDao();
			// 選択社員コード取得
			kCode = vo.getHidKCode();
			// 調整年確認
			confirmAdjustYear(vo.getHidAdjustYear());
			// 人事情報設定
			setHumanInfo(vo);
			// 対象年月、対象データ設定
			setTargetData();
			// 給与データ設定
			setTargetPaymentData();
			// 年調区分確認
			confirmAdjustType();
		} else {
			throw new MospException(MospConst.EX_CMD_INVALID);
		}
	}
	
	/**
	 * 年末調整画面表示
	 * @param vo 設定対象VO
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws SQLException 
	 * @throws ClassNotFoundException 
	 */
	private void show(
			AdjustmentCardVo vo
	) throws SQLException, IllegalAccessException, NoSuchFieldException, ClassNotFoundException {
		// DBコネクション取得
		getConnection();
		// VO初期化
		vo.initAllFields();
		// 調整年取得
		vo.setHidAdjustYear(getAdjustYear());
	}
	
	/**
	 * 年末調整データ設定
	 * @param vo 設定対象VO
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @throws SQLException
	 * @throws ClassNotFoundException 
	 * @throws MospException
	 */
	private void select(
			AdjustmentCardVo vo
	) throws SQLException, IllegalAccessException, NoSuchFieldException, ClassNotFoundException, MospException {
		// VO初期化
		vo.initFields();
		// DAO準備
		prepareDao();
		// 人事情報設定
		setHumanInfo(vo);
		// 年末調整データ取得
		cdAdjustmentDto = cdAdjustmentDao.findForKey(kCode, adjustYear);
		// VOに設定
		vo.setFields(cdAdjustmentDto);
	}
	
	/**
	 * 年末調整データ登録
	 * @param vo       登録対象VO
	 * @param storedVo セッション保存DTO
	 * @throws Exception 
	 */
	private void regist(AdjustmentCardVo vo, CdAdjustmentDto storedDto) throws Exception  {
		// DAO準備
		prepareDao();
		// 人事情報設定
		setHumanInfo(vo);
		// 年末調整データ取得
		CdAdjustmentDto currentDto = cdAdjustmentDao.findForUpdate(kCode, adjustYear);
		// 対象年月、対象データ設定
		setTargetData();
		// 給与データ設定
		setTargetPaymentData();
		// 登録DTOの準備
		cdAdjustmentDto = new CdAdjustmentDto();
		vo.setDtoFields(cdAdjustmentDto, kCode, adjustYear);
		// 年末調整データ作成対象者確認
		if(!checkCreateAdjustData(true)) {
			return;
		}
		if (storedDto == null) {
			// 新規登録
			// 存在チェック
			chkDuplicate(currentDto, vo);
			// データの挿入
			cdAdjustmentDao.insert(cdAdjustmentDto);
			// データ挿入確認
			chkInsert(cdAdjustmentDao.findForKey(kCode, adjustYear));
			// コミット
			commit();
			// メッセージ設定
			vo.setMessage(MospUtility.getMessage(msg, MospConst.MSG_INSERT, ""));
		} else {
			// 更新登録
			// 排他確認
			chkExclusive(storedDto, currentDto, vo);
			// データの更新
			cdAdjustmentDao.update(cdAdjustmentDto);
			// データ更新確認
			chkUpdate(cdAdjustmentDao.findForKey(kCode, adjustYear));
			// コミット
			commit();
			// メッセージ設定
			vo.setMessage(MospUtility.getMessage(msg, MospConst.MSG_UPDATE, ""));
		}
	}
	
	/**
	 * 人事情報設定
	 * @param vo 設定対象VO
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws SQLException 
	 * @throws ClassNotFoundException 
	 * @throws MospException 
	 */
	private void setHumanInfo(
			AdjustmentCardVo vo
	) throws SQLException, IllegalAccessException, NoSuchFieldException, ClassNotFoundException, MospException {
		// 人事基本情報取得
		mKihonDto = mKihonPayrollDao.findForDate(kCode, DatePart.convDateToInteger(lastDate));
		if (mKihonDto == null) {
			// 人事基本情報が無い場合
			show(vo);
			vo.setTxtChangeKCode(kCode);
			String errMessage = MospUtility.getMessage(msg, PayrollConst.MSG_NO_HUMAN_DATA, "");
			addErrMessage(errMessage);
			throw new MospException(PayrollConst.EX_BEFORE_ENTRANCE, errMessage);
		}
		// 人事給与情報取得
		cmIncomeTaxDto   = cmIncomeTaxDao  .findForEmployeeDate(kCode, lastDate);
		cmMidwayEnterDto = cmMidwayEnterDao.findForKey         (kCode          );
		// 家族情報取得
//		listFamily = cmFamilyDao.findForAdjustment(kCode);
		// VO設定
//		vo.setFields(mKihonDto, cmIncomeTaxDto, cmMidwayEnterDto, listFamily);
		vo.setFields(mKihonDto, cmIncomeTaxDto, cmMidwayEnterDto);
	}
	

	
	/**
	 * 名称取得用配列取得
	 * @param vo 設定対象VO
	 * @throws IllegalAccessException 
	 * @throws NoSuchFieldException 
	 * @throws SQLException 
	 * @throws ClassNotFoundException 
	 */
	private void setNameArray(
			AdjustmentCardVo vo
	) throws SQLException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
		// DBコネクション取得
		getConnection();
		// 取得済確認
		if (vo.aryStation != null) {
			return;
		}
		// 配列取得
		vo.aryStation  = getStationArrayAll() ;
		vo.aryPosition = getPositionArrayAll();
		vo.aryEra      = getCodeArray(PayrollConst.TID_JAPANESE);
		vo.aryRelation = getCodeArray(PayrollConst.TID_RELATION);
		// 和暦設定取得
		vo.listConf = getConfList(PayrollConst.CONF_ID_JP_IMP_CAL);
	}
	
	/**
	 * 年末調整計算
	 * @param vo
	 * @throws Exception 
	 */
	private void calculate(AdjustmentCardVo vo) throws Exception {
		// 計算確認準備
		boolean isCreateData = true;
		// DAO準備
		prepareDao();
		// 対象年月、対象データ設定
		setTargetData();
		// 給与データ設定
		setTargetPaymentData();
		// 既存対象外データ削除
		cdAdjustmentDao.deleteAdjustYear(adjustYear, startAdjDate, lastDate);
		// 人事情報設定
		setHumanInfo(vo);
		// 年末調整データ作成対象者確認
		if(!checkCreateAdjustData(false)) {
			return;
		}
		// 年末調整計算対象者確認
		if (!confirmAdjustType()) {
			isCreateData = false;
		}
		// 上記の確認でエラーがない社員は年調計算
		if (isCreateData) {
			// 対象データ所得税計算
			calcTargetIncomeTax(true);
			// 年末調整に必要な項目の計算
			calcNeedAdjust();
			// 年末調整計算
			adjustIncomeTax();
		} else {
			// 年末調整に必要な項目の計算(＊退職者の支払金額取得用)
			calcNeedAdjust();
			// 年調データは作成するが計算対象外の社員
			setAdjustOotStatus();
		}
		// 年末調整データ取得
		CdAdjustmentDto currentDto = cdAdjustmentDao.findForKey(kCode, adjustYear);
		// 登録処理
		if (currentDto == null) {
			// 新規登録
			cdAdjustmentDao.insert(cdAdjustmentDto);
		} else {
			// 更新
			cdAdjustmentDao.update(cdAdjustmentDto);
		}
		// コミット
		commit();
	}
	
	
}
