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

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import jp.mosp.common.common.BaseVo;
import jp.mosp.payroll.base.Bonus;
import jp.mosp.payroll.base.Employee;
import jp.mosp.payroll.base.PayrollAction;
import jp.mosp.payroll.base.PayrollConst;
import jp.mosp.payroll.bonus.BonusConst;
import jp.mosp.payroll.bonus.dao.PdBonAllowanceDao;
import jp.mosp.payroll.bonus.dao.PdBonDeductionDao;
import jp.mosp.payroll.bonus.dao.PdBonSumDao;
import jp.mosp.payroll.bonus.dao.PhBounsDao;
import jp.mosp.payroll.bonus.dao.PmDetailBaDao;
import jp.mosp.payroll.bonus.dao.PmDetailBdDao;
import jp.mosp.payroll.bonus.dao.PmDetailBsDao;
import jp.mosp.payroll.bonus.dto.PhBounsDto;
import jp.mosp.payroll.bonus.dto.PmDetailBaDto;
import jp.mosp.payroll.bonus.dto.PmDetailBdDto;
import jp.mosp.payroll.bonus.dto.PmDetailBsDto;
import jp.mosp.payroll.bonus.vo.BonusCardVo;
import jp.mosp.payroll.dao.CmPaymentMeansDao;
import jp.mosp.payroll.dao.PtCurrentDao;
import jp.mosp.payroll.dto.CmPaymentMeansDto;
import jp.mosp.payroll.dto.DetailDto;
import jp.mosp.payroll.dto.PtCurrentDto;
import jp.mosp.system.dao.MKaisyaDao;
import jp.mosp.system.dto.MKaisyaDto;

import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;

public class BonusCardAction extends PayrollAction {

	// コマンド
	private static final String CMD_BONUS_CARD_SHOW           = "P2011";
	private static final String CMD_BONUS_CARD_REGSIT         = "P2012";
	private static final String CMD_BONUS_CARD_SELECT         = "P2013";
	private static final String CMD_BONUS_CARD_TAX            = "P2014";
	private static final String CMD_BONUS_CARD_TOTAL          = "P2015";
	private static final String CMD_BONUS_CARD_SELECT_ANOTHER = "P2016";
	
	private boolean BounsDataFlg = false;
	
	// 計算用
	public		int	sumAllowance	= 0;
	public		int	sumDeduction	= 0;
	public		int	sumDatail		= 0;

	protected int bank1Amount		= 0;	// 銀行1振込額
	protected int bank2Amount		= 0;	// 銀行2振込額
	protected int cashAmount		= 0;	// 現金支給額

	/**
	 * Actionの初期化を行う。<br><br>
	 * 以下の処理を行う。
	 * <ul><li>
	 * {@link PayrollAction#PayrollAction()}
	 * </li></ul>
	 */
	public BonusCardAction() {
		super();
	}
	
	/* (non-Javadoc)
	 * @see jp.mosp.common.common.BaseAction#getSpecificVo()
	 */
	@Override
	protected BaseVo getSpecificVo() {
		return new BonusCardVo();
	}
	
	/**
	 * アクション
	 */
	public void action() throws Exception {
		
		Employee employee;

		// DBコネクション取得
		getConnection();
		// PAYROLL権限確認
		confirmPayrollAuth();
		// VOの取得及び設定
		prepareVo();
		BonusCardVo vo =  (BonusCardVo)getVo();
		vo = (BonusCardVo)getStoredVo(vo.getClassName());
		if (vo == null || cmd.equals(CMD_BONUS_CARD_SHOW)) {
			vo = new BonusCardVo();
			storeVo(vo.getClassName(), vo);
		}

		// VO及びフォワード先URLの設定
		vo.initVo(cfg, msg, cmd, aspUser, user);
		vo.clearMessage();
		vo.clearErrField();
		setVo(vo);
		setUrl(vo.getRetUrl());

		//表示明細項目テーブルに項目名を設定する。
		vo.aryPltCalcStatus  = BonusConst.getCalcStatusArray();
		vo.aryStation = getStationArrayAll();

		setAryDetailName();
		
		vo.setParams(request);
		if (vo.getPltYear() == null) {
			setYearMonth(vo, getCalcCurrent(),true);
		} else {
			setYearMonth(vo, getCalcCurrent(),false);
		}
		if (!key1.equals("") && key1 != null) {
			vo.setHidKCode(key1);
			vo.setTxtChangeKCode(key1);
		} else {
			vo.setHidKCode(vo.getTxtChangeKCode());
		}

		Date targetMonth = MospUtility.getDate(	vo.getHidTargetYear() +	'/' + 
									vo.getHidTargetMonth() + '/' +vo.getHidTargetDay());
			// コマンド毎の処理
		if (cmd.equals(CMD_BONUS_CARD_SHOW)) {
			setYearMonth  (vo, getCalcCurrent(),true);
			// 画面表示
			show(vo);
		} else if (cmd.equals(CMD_BONUS_CARD_SELECT)) {
			// 人事情報取得
			employee = getEmployee(vo.getTxtChangeKCode());
			if(null == employee){
				vo.clearPayData();
				String errMessage = MospUtility.getMessage(msg, "WU2103", ""); /* Message WU2103:社員履歴データがありません。 */
				setNextCmd(CMD_BONUS_CARD_SHOW);
				addErrMessage(errMessage);
				throw new MospException(BonusConst.EX_RETIRED, errMessage);
			}else{
				// 選択
				if (vo.getPltYear() == null) {
					setYearMonth(vo, getCalcCurrent(),true);
				} else {
					setYearMonth(vo, getCalcCurrent(),false);
				}
				if (!key1.equals("") && key1 != null) {
					vo.setHidKCode(key1);
					vo.setTxtChangeKCode(key1);
				} else {
					vo.setHidKCode(vo.getTxtChangeKCode());
				}
				show(vo.getTxtChangeKCode(), targetMonth , employee);
			}
		} else if (cmd.equals(CMD_BONUS_CARD_SELECT_ANOTHER)) {
			/*** 暫定首絞め ***/
			String errMessage = MospUtility.getMessage(msg, "WU1120", "");
			addErrMessage(errMessage);
			throw new MospException(BonusConst.EX_NOT_CURRENT, errMessage);

		} else if (cmd.equals(CMD_BONUS_CARD_REGSIT)) {
			// 人事情報取得
			employee = getEmployee(vo.getTxtChangeKCode());
			if(null == employee){
				String errMessage = MospUtility.getMessage(msg, "WU2103", ""); /* Message WU2103:社員履歴データがありません。 */
				setNextCmd(CMD_BONUS_CARD_SHOW);
				addErrMessage(errMessage);
				throw new MospException(BonusConst.EX_RETIRED, errMessage);
			}else{
				// 登録
				regist( employee, targetMonth );
			}
		} else if (cmd.equals(CMD_BONUS_CARD_TAX)) {
			// 計算
			calculate(vo.getTxtChangeKCode() ,  targetMonth);
		} else if (cmd.equals(CMD_BONUS_CARD_TOTAL)) {
			// 支払い合計
			cardTotal(vo.getTxtChangeKCode() ,  targetMonth);
		} else {
			throw new MospException(MospConst.EX_CMD_INVALID);
		}
	}
	/**
	 * 新規登録画面表示
	 * @param vo 対象VO
	 * @return データ挿入対象DTO
	 * @throws Exception
	 */
	public void show(BonusCardVo vo) throws Exception {
		// 対象年月設定
		setTargetMonth(vo);
	}
	
	/**
	 * 対象年月、支給日設定
	 * @param vo          対象VO
	 * @param targetMonth 設定年月
	 * @throws Exception
	 */
	public void setTargetMonth(BonusCardVo vo) throws Exception {
		vo.setPayDay( vo.getPltYear(), vo.getPltMonth(), vo.getPltDay());
		vo.setTargetMonth( vo.getPltYear(), vo.getPltMonth());
	}
	
	
	/**
	 * 画面表示処理を行う。<br><br>
	 * @param 対象社員コード
	 * @param 対象年月
	 * @throws Exception 
	 */
	private void show(String kCode, Date targetMonth , Employee employee) throws Exception {
		// VO取得
		BonusCardVo vo = (BonusCardVo)getVo();
			// 賞与情報取得
			Bonus bonus = getBonus(kCode, targetMonth);
			// VOフィールド設定
			vo.setFields(employee, bonus);
	}
	
	
	/**
	 * 賞与伝票インスタンスを取得、設定する。<br><br>
	 * kCode、calcDateをキーとして給与情報を取得し、{@link #payment}に格納する。
	 * @param kCode     社員コード
	 * @param calcMonth 計算年月
	 * @return 給与伝票
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws SQLException 
	 */
	protected Bonus getBonus(
			String kCode, Date payDate
	) throws SQLException, IllegalAccessException, NoSuchFieldException {
		PhBounsDto header = new PhBounsDao(
				cfg, cmd, aspUser, user, conn).findForKey(kCode, payDate);
		if (header == null) {
			return null;
		}else{
			return new Bonus(
					header,
					new PmDetailBaDao(cfg, cmd, aspUser, user, conn).findForSlip(header.getSlipCode()),
					new PmDetailBdDao(cfg, cmd, aspUser, user, conn).findForSlip(header.getSlipCode()),
					new PmDetailBsDao(cfg, cmd, aspUser, user, conn).findForSlip(header.getSlipCode()),
					new PdBonAllowanceDao(cfg, cmd, aspUser, user, conn).find(kCode, payDate),
					new PdBonDeductionDao(cfg, cmd, aspUser, user, conn).find(kCode, payDate),
					new PdBonSumDao      (cfg, cmd, aspUser, user, conn).find(kCode, payDate)
			);

		}
	}

	/**
	 * 登録処理を行う。<br><br>
	 * @throws Exception 
	 */
	private void regist(Employee employee , Date targetMonth) throws Exception {
		sumDatail		= 0;	// 総支払額
		bank1Amount		= 0;	// 銀行1振込額
		bank2Amount		= 0;	// 銀行2振込額
		cashAmount		= 0;	// 現金支給額

		
		BonusCardVo vo = (BonusCardVo)getVo();
		
		// 賞与情報取得
		Bonus bonus = getBonus(vo.getTxtChangeKCode(), targetMonth);
		
		if(vo.arySum[0][2].equals("") || vo.arySum[0][2].equals("0")){
			String errMessage = MospUtility.getMessage(msg, BonusConst.MSG_BONUS_CALC_NG, "");
			addErrMessage(errMessage);
			throw new MospException(BonusConst.EX_NOT_CURRENT, errMessage);
		}else{
			sumDatail = (Integer.valueOf( vo.arySum[3][2])) + 
			            (Integer.valueOf( vo.arySum[4][2])) + 
			            (Integer.valueOf( vo.arySum[5][2]));
			if(sumDatail == 0){
				String errMessage = MospUtility.getMessage(msg, BonusConst.MSG_BONUS_FIX_NG, "");
				addErrMessage(errMessage);
				throw new MospException(BonusConst.EX_NOT_CURRENT, errMessage);
			}
		}
		
		if(sumDatail != 0){
			if(null == bonus){
				bonus = new Bonus();
				BounsDataFlg = true;
				//パラメータ設定
				for (int i = 0; i < vo.arySum.length; i++) {
					if (vo.arySum[i][2].equals("")) {
						String errMessage = MospUtility.getMessage(msg, BonusConst.MSG_BONUS_CALC_NG, "");
						addErrMessage(errMessage);
						throw new MospException(BonusConst.EX_NOT_CURRENT, errMessage);
					}
				}
				vo.setDtoFields2(employee, bonus, targetMonth);
			
			} else {
				// パラメータ設定
				vo.setDtoFields(bonus);
			}
			//合計計算
			calcTotal(getEmployee(vo.getTxtChangeKCode()), bonus);
			// 登録
			registPayment(bonus);
			// コミット
			commit();
			// メッセージ設定
			setMessage(MospUtility.getMessage(msg, "IC0001", ""));
			// 画面表示処理
			show( vo.getTxtChangeKCode(), targetMonth, employee);
		}

	
	}

	
	/**
	 * 明細配列を取得する。
	 * @param list             取得対象リスト
	 * @param checkDisplayType 0印字区分確認要否
	 * @return 明細配列
	 */
	protected String[][] getAryDetail(List<?> list, boolean checkDisplayType) {
		String[][] aryDetail = new String[list.size()][3];
		for (int i = 0; i < list.size(); i++) {
			DetailDto dto = (DetailDto)list.get(i);
			aryDetail[i][0] = dto.getDetailCode();
			aryDetail[i][1] = dto.getDetailAbbr();
			aryDetail[i][2] = "0";
			if (dto instanceof PmDetailBsDto) {
				aryDetail[i][2] = String.valueOf(((PmDetailBsDto)dto).getAmount());
			}
			if (checkDisplayType && dto.getDisplayType() == PayrollConst.DETAIL_DISP_NONE) {
				if (String.valueOf(aryDetail[i][2]).equals("0")) {
					aryDetail[i][1] = "";
					aryDetail[i][2] = "";
				}
			}
		}
		return aryDetail;
	}
	
	/**
	 * 所属コード取得(M_KAISYA)
	 * @return 所属コードリスト
	 * @throws SQLException
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 */
	protected String[][] getStationArrayAll() throws SQLException, NoSuchFieldException, IllegalAccessException {
		// DAOの準備
		MKaisyaDao mKaisyaDao = new MKaisyaDao();
		
		mKaisyaDao.initDao(cfg, cmd, aspUser, user, conn);
		// 情報の取得
		List< MKaisyaDto > listStation = mKaisyaDao.findAll();
		// 配列の作成
		String[][] aryStation = new String[listStation.size()][2];
		for (int i = 0; i < listStation.size(); i++) {
			aryStation[i][0] = listStation.get(i).getId();
			aryStation[i][1] = listStation.get(i).getKaiMei();
		}
		return aryStation;
	}
	
	/**
	 * 年月設定
	 * @param vo          設定対象VO
	 * @param calcCurrent 計算月
	 */
	private void setYearMonth(BonusCardVo vo, Date calcCurrent,boolean isSetPulldown) {
		// プルダウン取得
		vo.aryPltYear  = getYearArray(MospUtility.getYear(calcCurrent));
		vo.aryPltMonth = getMonthArray();
		vo.aryPltDay   = getDayArray();
		if (isSetPulldown) {
			// 年月設定
			vo.setPltYear(vo.getHidTargetYear());
			vo.setPltMonth(vo.getHidTargetMonth());
			vo.setPltDay(vo.getHidTargetDay());
		} else {
			//年月設定
			vo.setPltYear(vo.getHidTargetYear());
			vo.setPltMonth(vo.getHidTargetMonth());
			vo.setPltDay(vo.getHidTargetDay());
		}
	}

	/**
	 * 年プルダウン取得(前後1年)
	 * @param year 基準年
	 * @return 年プルダウン用文字列配列
	 */
	protected String[][] getYearArray(int year) {
		String[][] aryYear = new String[3][2];
		aryYear[0][0] = String.valueOf(year - 1);
		aryYear[0][1] = String.valueOf(year - 1);
		aryYear[1][0] = String.valueOf(year);
		aryYear[1][1] = String.valueOf(year);
		aryYear[2][0] = String.valueOf(year + 1);
		aryYear[2][1] = String.valueOf(year + 1);
		return aryYear;
	}

	/**
	 * 計算月取得
	 * @return 計算月
	 * @throws Exception
	 */
	protected Date getCalcCurrent() throws Exception {
		// DAO準備
		PtCurrentDao dao = new PtCurrentDao(cfg, cmd, aspUser, user, conn);
		dao.initDao(cfg, cmd, aspUser, user, conn);
		PtCurrentDto dto = dao.findForKey(
							PayrollConst.OFFICE_ALL,
							PayrollConst.CALC_BONUS,
							getCurrent(PayrollConst.OFFICE_ALL, PayrollConst.CALC_PAYMENT));
		if (dto != null) {
			return dto.getCalcDate();
		}
		return new Date();
	}

	/**
	 * 画面明細の項目名の取得と設定
	 * @return 計算月
	 * @throws Exception
	 */
	protected void setAryDetailName() throws Exception{

		BonusCardVo vo = (BonusCardVo)getVo();

		// DAO準備
		PmDetailBaDto baDto;
		PmDetailBdDto bdDto;
		PmDetailBsDto bsDto;
		PmDetailBaDao baDao = new PmDetailBaDao(cfg, cmd, aspUser, user, conn);
		PmDetailBdDao bdDao = new PmDetailBdDao(cfg, cmd, aspUser, user, conn);
		PmDetailBsDao bsDao = new PmDetailBsDao(cfg, cmd, aspUser, user, conn);
		
		// 支払項目名の設定
		for (int i = 0; i < vo.aryAllowance.length ; i++) {
			baDto = baDao.findForKey( vo.aryAllowance[i][0]);
			if(null != baDto){
				if(baDto.getDeleteFlag() == 0){
					vo.aryAllowance[i][1] = baDto.getDetailName();
					vo.aryAllowance[i][2] = "0";
				}
			}
		}
		// 控除項目名の設定
		for (int i = 0; i < vo.aryDeduction.length ; i++) {
			bdDto = bdDao.findForKey( vo.aryDeduction[i][0]);
			if(null != bdDto){
				if(bdDto.getDeleteFlag() == 0){
					vo.aryDeduction[i][1] = bdDto.getDetailName();
					vo.aryDeduction[i][2] = "0";
				}
			}
		}

		// 支払総額項目名の設定
		for (int i = 0; i < vo.arySum.length ; i++) {
			bsDto = bsDao.findForKey( vo.arySum[i][0]);
			if(null != bsDto){
				if(bsDto.getDeleteFlag() == 0){
					vo.arySum[i][1] = bsDto.getDetailName();
					vo.arySum[i][2] = "0";
				}
			}
		}
	}
	
	/**
	 * 合計を計算する。
	 * @param employee 社員情報
	 * @param payment  給与伝票
	 */
	protected void calcTotal(Employee employee, Bonus bonus) {
		bonus.calcSocInsTotal();
		bonus.calcTaxation();
		bonus.setIncomeTax(bonus.getDeductionAmount(BonusConst.DTL_BON_DEDUCTION_06));
		bonus.calcAllowance();
		bonus.calcDeduction();
		bonus.calcPaymentTotal();
		calcDivideAccounts(employee, bonus);
	}

	/**
	 * 各銀行への振込額及び現金支給額を計算する。
	 * @param employee 社員情報
	 * @param payment  給与伝票
	 */
	private void calcDivideAccounts(Employee employee, Bonus bonus) {
		// 変数宣言
		int bank1Amount = 0;
		int bank2Amount = 0;
		int cashAmount  = 0;
		// 支給方法情報取得(支給方法連番順)
		List<CmPaymentMeansDto> list = employee.getPaymentMeans();
		// 差引支給額取得
		int total = bonus.getPaymentTotal();
		// 支給情報毎の処理
		int currentAmount = total;
		for (Iterator<CmPaymentMeansDto> it = list.iterator(); it.hasNext();) {
			CmPaymentMeansDto dto = it.next();
			// 振分金額取得
			int amount = getdividedAmount(dto, total, currentAmount);
			// 振分金額設定
			if (dto.getPaymentMeans().equals(PayrollConst.PAYMENT_MEANS_ACCOUNT)) {
				// 振込の場合
				if (dto.getMeansSequence() == PayrollConst.PAYMENT_MEANS_SEQ_1
						|| dto.getMeansSequence() == PayrollConst.PAYMENT_MEANS_SEQ_3) {
					bank1Amount += amount;
				} else {
					bank2Amount += amount;
				}
			} else {
				// 振込以外(現金)の場合
				cashAmount += amount;
			}
			// 残額計算
			currentAmount -= amount;
		}
		// 残額を現金に設定
		cashAmount += currentAmount;
		// 給与情報設定
		bonus.setBank1PayAmount(bank1Amount);
		bonus.setBank2PayAmount(bank2Amount);
		bonus.setCashPayAmount (cashAmount );
	}

	/**
	 * 振分支給額取得
	 * @param dto           支給方法DTO
	 * @param totalAmount   振分総額
	 * @param currentAmount 振分元金額(残額)
	 */
	private int getdividedAmount(
			CmPaymentMeansDto dto, int totalAmount, int currentAmount
	) {
		// 支給情報が設定されていない場合
		if (dto == null) {
			return 0;
		}
		// 全額の場合
		if (dto.getAmountType().equals(PayrollConst.AMOUNT_TYPE_ALL)) {
			return currentAmount;
		}
		// 残額の場合
		if (dto.getAmountType().equals(PayrollConst.AMOUNT_TYPE_REST)) {
			return currentAmount;
		}
		// 振分支給額
		int dividingAmount = 0;
		// 金額区分毎の処理
		if (dto.getAmountType().equals(PayrollConst.AMOUNT_TYPE_AMOUNT)) {
			// 定額の場合
			dividingAmount = dto.getFixedAmount();
		} else if (dto.getAmountType().equals(PayrollConst.AMOUNT_TYPE_RATIO)) {
			// 定率の場合
			// 振分総額 * 振分率 / 100
			dividingAmount = (int)MospUtility.round(
					dto.getFixedAmount() / 100 * totalAmount, 0, BigDecimal.ROUND_HALF_UP);
		}
		// 振分元金額以上の場合
		if (dividingAmount > currentAmount) {
			dividingAmount = currentAmount;
		}
		return dividingAmount;
	}

	/**
	 * 賞与情報を登録する。<br><br>
	 * @param payment 給与情報
	 * @throws IllegalAccessException 
	 * @throws NoSuchFieldException 
	 * @throws SQLException 
	 * @throws MospException 
	 */
	private void registPayment(
			Bonus bonus
	) throws SQLException, NoSuchFieldException, IllegalAccessException, MospException {
		// DAO準備
		PhBounsDao      phBounsDao      = new PhBounsDao     (cfg, cmd, aspUser, user, conn);
		PdBonAllowanceDao pdBonAllowanceDao = new PdBonAllowanceDao(cfg, cmd, aspUser, user, conn);
		PdBonDeductionDao pdBonDeductionDao = new PdBonDeductionDao(cfg, cmd, aspUser, user, conn);
		PdBonSumDao       pdBonTotalDao     = new PdBonSumDao      (cfg, cmd, aspUser, user, conn);
		// 賞与ヘッダー更新
		if (BounsDataFlg == false){
			phBounsDao.update(bonus.getHeader(), true);
		} else {
			phBounsDao.insert(bonus.getHeader(), true);
		}
		// 賞与明細削除
		pdBonAllowanceDao.delete(bonus.getKCode(), bonus.getCalcMonth());
		pdBonDeductionDao.delete(bonus.getKCode(), bonus.getCalcMonth());
		pdBonTotalDao    .delete(bonus.getKCode(), bonus.getCalcMonth());
		// 賞与明細登録
		pdBonAllowanceDao.insert(bonus.getAllowanceList());
		pdBonDeductionDao.insert(bonus.getDeductionList());
		pdBonTotalDao    .insert(bonus.getSumList      ());
	}

	/**
	 * 賞与の計算を行う。<br><br>
	 * @param kCode       計算対象社員コード
	 * @param targetMonth 計算対象年月
	 * @throws Exception
	 */
	protected void calculate(String kCode, Date targetPaydate) throws Exception {
		BonusCardVo vo = (BonusCardVo)getVo();

		// DAO準備

		// 人事情報取得
		Employee employee = getEmployee(kCode);
		if(null == employee){
			String errMessage = MospUtility.getMessage(msg, "WU2103", ""); /* Message WU2103:社員履歴データがありません。 */
			setNextCmd(CMD_BONUS_CARD_SHOW);
			addErrMessage(errMessage);
			throw new MospException(BonusConst.EX_RETIRED, errMessage);
		}else{

			// 明細値計算
			calcDetails(vo);
			// 賞与調整
//			adjustPayment(employee, payment, mapParams);
			// 法定控除計算
//			calcLegalDeduction(employee, payment);
			// 合計計算
//			calcTotal(employee, vo);
			// 明細設定
//			updateList(vo , false);
		}
	}


	/**
	 * 明細値の計算を行う。<br><br>
	 * @param kCode       人事情報インスタンスのポインタ
	 * @param targetMonth 計算対象年月
	 * @throws Exception
	 */
	protected void calcDetails(BonusCardVo vo) throws Exception {
		// 計算用ワークエリアの初期化
		sumAllowance	= 0;
		sumDeduction	= 0;
		sumDatail		= 0;

		// 支払項目の計算
		for (int i = 0; i < vo.aryAllowance.length ; i++) {
			sumAllowance += Integer.valueOf(vo.aryAllowance[i][2]);
		}
		// 控除項目の計算
		for (int i = 0; i < vo.aryDeduction.length ; i++) {
			sumDeduction += Integer.valueOf(vo.aryDeduction[i][2]);
		}

		// 支払総額項目の設定
		vo.arySum[0][2] =  String.valueOf(sumAllowance);
		vo.arySum[1][2] =  String.valueOf(sumDeduction);  
		if( sumAllowance < sumDeduction){
			String errMessage = MospUtility.getMessage(msg, BonusConst.MSG_BONUS_TATAL_OVER , "");
			addErrMessage(errMessage);
			throw new MospException(BonusConst.EX_NOT_CURRENT, errMessage);
		}else{
			sumDatail = sumAllowance - sumDeduction;
			vo.arySum[2][2] =  String.valueOf(sumDatail);
		}
	}	


	/**
	 * 賞与の計算を行う。<br><br>
	 * @param kCode       計算対象社員コード
	 * @param targetMonth 計算対象年月
	 * @throws Exception
	 */
	protected void cardTotal(String kCode, Date targetPaydate) throws Exception {
		// 初期化
		bank1Amount = 0;
		bank2Amount = 0;
		cashAmount  = 0;
		BonusCardVo vo = (BonusCardVo)getVo();

		// DAO&DTOの準備
		CmPaymentMeansDao cmPaymentMeansDao = new CmPaymentMeansDao();
		cmPaymentMeansDao.initDao(cfg, cmd, aspUser, user, conn);
		List<CmPaymentMeansDto> cmPaymentMeansDto_l = 
			cmPaymentMeansDao.findForEmployeeAllowance(kCode, BonusConst.ALLOWANCE_TYPE_BONUS); 
			
		// 支給方法情報取得(支給方法連番順)
		// 支給情報毎の処理
		if( vo.arySum[2][2].equals("") || vo.arySum[2][2].equals("0")){
			String errMessage = MospUtility.getMessage(msg, BonusConst.MSG_BONUS_CALC_NG , "");
			addErrMessage(errMessage);
			throw new MospException(BonusConst.EX_NOT_CURRENT, errMessage);
		}else{
			int currentAmount =    Integer.valueOf(vo.arySum[2][2]);
			for (Iterator<CmPaymentMeansDto> it = cmPaymentMeansDto_l.iterator(); it.hasNext();) {
				CmPaymentMeansDto dto = it.next();
				// 振分金額取得
				int amount = getdividedAmount(dto, currentAmount, currentAmount);
				// 振分金額設定
				if (dto.getPaymentMeans().equals(BonusConst.PAYMENT_MEANS_ACCOUNT)) {
					// 振込の場合
					if (dto.getMeansSequence() == BonusConst.PAYMENT_MEANS_SEQ_1
						|| dto.getMeansSequence() == BonusConst.PAYMENT_MEANS_SEQ_3) {
						bank1Amount += amount;
					} else {
						bank2Amount += amount;
					}
				} else {
					// 振込以外(現金)の場合
					cashAmount += amount;
				}
				// 残額計算
				currentAmount -= amount;
			}
			// 残額を現金に設定
			cashAmount += currentAmount;

			for (int i = 0; i < vo.arySum.length ; i++) {
				if(vo.arySum[i][0].equals("BS011")){
						vo.arySum[i][2] = String.valueOf(bank1Amount);
				}else if(vo.arySum[i][0].equals("BS012")){
					vo.arySum[i][2] = String.valueOf(bank2Amount);					
				}else if(vo.arySum[i][0].equals("BS013")){
					vo.arySum[i][2] = String.valueOf(cashAmount);					
				}
			}
		}
	}

}

