/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatAKKapKeistatJdg
*	ソースファイル名	：JBSbatAKKapKeistatJdg.java
*	作成者				：富士通　
*	作成日				：2013年03月05日
*＜機能概要＞
*　割賦契約状態判定部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v4.00.00	2013/03/05   高橋		新規作成
*	v4.00.01	2013/05/03   高橋		【ANK-1464-00-00】料金検証不具合対応 割賦一括請求年月更新時の不具合事象対応
*	v5.00.00	2013/07/06   黒木		【ANK-1464-00-00】料金検証不具合対応 締結済時の日付判定追加
*	v5.00.01	2013/07/22   高橋		【ANK-1464-00-00】料金検証不具合対応 完了済時の判定追加対応
*	v9.00.00	2014/07/10   前田		【OM-2014-0002411】分割払い最終月の料金計算日の対応
*	v9.01.00	2014/08/14   前田		【OM-2014-0002774】分割払い最終月の料金計算日の対応
*********************************************************************/
package eo.business.service;

import java.math.BigDecimal;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JACbatSchdlUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatAKIFM019;
import eo.common.constant.JACStrConst;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.util.JBSbatDateUtil;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatAKKapKeistatJdg extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/

	
	/** 退避．請求年月 */
	private String tmpSeikyYm = null;
	
	/** 退避．月初日 */
	private String tmpMonStaDay = null;
	
	/** 退避．月末日 */
	private String tmpMonEndDay = null;
	
	/** 退避．料金計算日 */
	private String tmpEventYmd = null;
	
	/** 固定値：日付差分フラグ（両日付を差に含める） */
	private static final String DIFF_NAI_FLG 		= "1";
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][initial]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][initial][opeDate=" + super.opeDate + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][initial][freeItem=" + super.freeItem + "]");
		
		// スケジュール取得
		this.getSchdlInfo();
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][initial]");

		/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @param inMap　入力電文
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][inMap=" + inMap.getMap().toString() + "]");
		
		// 検証対象契約情報（状態判定済み）出力
		JBSbatOutputItem outputItem = new JBSbatOutputItem();
		// 料金検証契約状態
		String wkPrcKnsKeiStat = JACStrConst.PRCKNS_KEI_STAT_CD_SP;
		// 課金継続月数
		int wkChrgKeizoku = 0;
		
		// 割賦契約状態判定（料金検証契約状態の設定）
		wkPrcKnsKeiStat =  getKapKeiStatJdg(inMap);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][料金検証契約状態コード:" + wkPrcKnsKeiStat + "]");
		
		// 料金検証契約状態が設定された場合
		if(!(JACStrConst.PRCKNS_KEI_STAT_CD_SP.equals(wkPrcKnsKeiStat)))
		{
			// 課金継続月数の算出
			wkChrgKeizoku = getChrgKeizoku(inMap);
		}
		
		// 検証対象割賦契約情報（状態判定済み）出力
		this.makeOutputInfo(inMap, wkPrcKnsKeiStat, wkChrgKeizoku, outputItem);

		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][execute]");

		
		return outputItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
	
	/**
	 * 料金スケジュール定義アクセス部品を使用してスケジュール情報を取得する。
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void getSchdlInfo() throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getSchdlInfo]");
		
		JACbatSchdlUtil schdlUtil = new JACbatSchdlUtil(commonItem);
		try
		{
			// 請求年月
			this.tmpSeikyYm 		= schdlUtil.getBillDate(super.opeDate, JACStrConst.EVENT_CD_PRC_CALC_DAY);
			// 月初日[0] 月末日[1]
			String[] ymd 		= schdlUtil.getUseStrEnd(this.tmpSeikyYm, JACStrConst.EVENT_CD_USE_STAYMD, JACStrConst.EVENT_CD_USE_ENDYMD);
			this.tmpMonStaDay 	= ymd[0];
			this.tmpMonEndDay 	= ymd[1];
			// 料金計算日
			this.tmpEventYmd 	= schdlUtil.getUseStrEnd(this.tmpSeikyYm, JACStrConst.EVENT_CD_USE_STAYMD, JACStrConst.EVENT_CD_PRC_CALC_DAY)[1];
			
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getSchdlInfo][請求年月=" + this.tmpSeikyYm + "]");
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getSchdlInfo][月初日=" + this.tmpMonStaDay + "]");
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getSchdlInfo][月末日=" + this.tmpMonEndDay + "]");
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getSchdlInfo][料金計算日=" + this.tmpEventYmd + "]");
			
		}
		finally
		{
			schdlUtil.close();
		}
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getSchdlInfo]");
		return;
	}
	
	/**
	 * 割賦契約状態判定を行い、料金検証契約状態コードを返却します。
	 * @param inMap　入力電文
	 * @return String[] [0]:料金検証契約状態コード 
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private String getKapKeiStatJdg(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getKapKeiStatJdg]");
		
		String returnData = JACStrConst.PRCKNS_KEI_STAT_CD_SP;
		
		// 判定条件取得
		String kapKeiStat 			= inMap.getString(JBSbatAKIFM019.SVC_KEI_STAT);				// 割賦契約ステータス
		String kapSeikyStaYm 		= inMap.getString(JBSbatAKIFM019.KAP_SEIKY_STA_YM);			// 割賦請求開始年月
		String kapSeikyEndYmd	 	= inMap.getString(JBSbatAKIFM019.KAP_SEIKY_ENDYMD);			// 割賦請求終了年月日
		String kapIktSikySwchYm 	= inMap.getString(JBSbatAKIFM019.KAP_IKT_SIKY_SWCH_YM);		// 割賦一括請求切替年月
		String kapKeiChrgStaYmd 	= inMap.getString(JBSbatAKIFM019.KAP_KEI_CHRG_STAYMD);		// 割賦契約課金開始年月日
		String kapKeiDslYmd 		= inMap.getString(JBSbatAKIFM019.KAP_KEI_DSL_YMD);			// 割賦契約解約年月日
		BigDecimal kapPayZanCnt 	= inMap.getBigDecimal(JBSbatAKIFM019.KAP_PAY_ZAN_CNT);		// 割賦支払残回数
		BigDecimal kapSeikyZumiCnt 	= inMap.getBigDecimal(JBSbatAKIFM019.KAP_SEIKY_ZUMI_CNT);	// 割賦請求済回数
		
		// 割賦契約ステータスが完了済の場合
		if(JACStrConst.KAP_KEI_STAT_FIN_ZUMI.equals(kapKeiStat))
		{
			// 割賦一括請求切替年月が null、空文字以外の場合、
			if(!isNullOrKaraMoji(kapIktSikySwchYm))
			{
				// 請求年月 ＝ 割賦一括請求切替年月 の場合
				if(this.tmpSeikyYm.compareTo(kapIktSikySwchYm) == 0)
				{
					// OM-2014-0002411 MOD START
					// // 割賦一括切替請求月
					// returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_IKTSWCH_SEIYM;
					// 空（設定なし）
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_SP;
					//  OM-2014-0002411 MOD END
					return returnData;
				}
				// OM-2014-0002774 ADD START
				if(this.tmpSeikyYm.compareTo(kapIktSikySwchYm) > 0)
				{
					// 空（設定なし）
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_SP;
					
					return returnData;
				}
				// OM-2014-0002774 ADD END
			}
			
			// 割賦請求開始年月が null、空文字以外の場合、
			if(!isNullOrKaraMoji(kapSeikyStaYm))
			{
				// 請求対象月 ＝ 割賦請求開始年月
				if(this.tmpSeikyYm.compareTo(kapSeikyStaYm) == 0)
				{
					// 初回請求月
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_FIRST_SEIYM;
					return returnData;
				}
			}
			
			// OM-2014-0002411 ADD START
			// 割賦請求終了年月日がnull、空文字以外の場合
			if(!isNullOrKaraMoji(kapSeikyEndYmd))
			{
				// 請求年月末日 = 割賦請求終了年月日
				if(this.tmpMonEndDay.compareTo(kapSeikyEndYmd) == 0)
				{
					// 割賦支払残回数が0
					if(BigDecimal.ZERO.compareTo(kapPayZanCnt) == 0)
					{
						// 継続請求月
						returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_KZ_SEIYM;
						return returnData;
					}
				}
			}
			// OM-2014-0002411 ADD END
			
		}
		// 割賦契約ステータスが締結済の場合
		else if(JACStrConst.KAP_KEI_STAT_TIKT.equals(kapKeiStat))
		{
			// 割賦請求終了年月日が null、空文字以外の場合、
			if(!isNullOrKaraMoji(kapSeikyEndYmd))
			{
				// 請求対象月の月初日 ＞ 割賦請求終了始年月日
				if(this.tmpMonStaDay.compareTo(kapSeikyEndYmd) > 0)
				{
					// 空（設定なし）
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_SP;
					return returnData;
				}
			}	

			// 割賦一括請求切替年月が null、空文字以外の場合、
			if(!isNullOrKaraMoji(kapIktSikySwchYm))
			{
				// 請求年月 ＝ 割賦一括請求切替年月 の場合
				if(0 == this.tmpSeikyYm.compareTo(kapIktSikySwchYm))
				{
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_IKTSWCH_SEIYM;
					return returnData;
				}
				// 請求年月 ＞ 割賦一括請求切替年月の場合
				else if (this.tmpSeikyYm.compareTo(kapIktSikySwchYm) > 0)
				{
					// 空（設定なし）
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_SP;
					return returnData;
				}
			}	

			// 割賦契約課金開始年月日がnull、空文字以外の場合
			if(!isNullOrKaraMoji(kapKeiChrgStaYmd))
			{
				// 請求対象月の月初日　＜＝　割賦契約課金開始年月日　＜＝　請求対象月の月末日
				if(this.tmpMonStaDay.compareTo(kapKeiChrgStaYmd) <= 0 && 
						this.tmpMonEndDay.compareTo(kapKeiChrgStaYmd) >= 0)
				{
					// 初回請求月
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_FIRST_SEIYM;
					return returnData;
				}
				// 請求対象月の月初日 ＞ 割賦契約課金開始年月日 かつ 割賦支払残回数が０より大きい場合
				if(this.tmpMonStaDay.compareTo(kapKeiChrgStaYmd) > 0 &&
						BigDecimal.ZERO.compareTo(kapPayZanCnt) < 0)
				{
					// 割賦請求済回数が０の場合
					if(BigDecimal.ZERO.compareTo(kapSeikyZumiCnt) == 0)
					{
						// 初回請求月
						returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_FIRST_SEIYM;
						return returnData;
					}
					else
					{
						// 継続請求月
						returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_KZ_SEIYM;
						return returnData;
					}
				}
			}
		}
		// 割賦契約ステータスが解約済の場合
		else if(JACStrConst.KAP_KEI_STAT_DSL.equals(kapKeiStat))
		{
			// 割賦契約解約年月日、割賦契約課金開始年月日がnull、空文字以外の場合
			if(!isNullOrKaraMoji(kapKeiDslYmd) && !isNullOrKaraMoji(kapKeiChrgStaYmd))
			{
				// 請求対象年月日末日 ＜＝ 割賦契約解約年月日の場合 
				if(this.tmpMonEndDay.compareTo(kapKeiDslYmd) <= 0)
				{
					// 請求対象月の月初日　＜＝　割賦契約課金開始年月日　＜＝　請求対象月の月末日
					if(this.tmpMonStaDay.compareTo(kapKeiChrgStaYmd) <= 0 &&
							this.tmpMonEndDay.compareTo(kapKeiChrgStaYmd) >= 0)
					{
						// 初回請求月
						returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_FIRST_SEIYM;
						return returnData;
					}
					else if(this.tmpMonStaDay.compareTo(kapKeiChrgStaYmd) > 0)
					{
						// 継続請求月
						returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_KZ_SEIYM;
						return returnData;
					}
					
				}
				// 請求対象年月日末日 ＞ 割賦契約解約年月日の場合  
				else
				{
					// 割賦契約解約月
					returnData = JACStrConst.PRCKNS_KEI_STAT_CD_KAP_DSL_SEIYM;
					return returnData;

				}
			}
		}
		
		// 上記以外は設定なし
		return returnData;
	}
	
	/**
	 * 割賦請求開始年月、割賦請求終了年月日、請求年月により、以下の様に算出する。
	 * @param inMap　入力電文
	 * @return String[] [0]:課金継続月数 [1]:課金継続日数
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private int getChrgKeizoku(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getChrgKeizoku]");
		
		// ワーク．課金継続月数
		int wkMonCnt = 0;
		
		// 判定条件取得
		String kapSeikyStaYm 	= inMap.getString(JBSbatAKIFM019.KAP_SEIKY_STA_YM);
		String kapSeikyEndYmd 	= inMap.getString(JBSbatAKIFM019.KAP_SEIKY_ENDYMD);

		// 割賦請求開始年月が空文字、 ＮＵＬＬ以外の場合
		if(!isNullOrKaraMoji(kapSeikyStaYm))
		{
			// 割賦請求終了年月日が空文字、 ＮＵＬＬ以外の場合	
			if(!isNullOrKaraMoji(kapSeikyEndYmd))
			{
				// 割賦請求終了年月日より年月を取得
				String kapSeikyEndYm = kapSeikyEndYmd.substring(0, 6);
					
				// 割賦請求終了年月が請求年月より小さい場合
				if(this.tmpSeikyYm.compareTo(kapSeikyEndYm) > 0)
				{
					// ワーク．課金継続月数 ← 割賦請求開始年月から割賦請求終了年月までの経過月数（共にその月を含む）
					wkMonCnt = JBSbatDateUtil.monthDiff(kapSeikyEndYm, kapSeikyStaYm, DIFF_NAI_FLG);
					
				}
				else
				{
					// ワーク．課金継続月数 ← 割賦請求開始年月から請求年月までの経過月数（共にその月を含む）
					wkMonCnt = JBSbatDateUtil.monthDiff(this.tmpSeikyYm, kapSeikyStaYm, DIFF_NAI_FLG);
				}
			}
			else
			{
				// ワーク．課金継続月数 ← 割賦請求開始年月から請求年月までの経過月数（共にその月を含む）
				wkMonCnt = JBSbatDateUtil.monthDiff(this.tmpSeikyYm, kapSeikyStaYm, DIFF_NAI_FLG);
				
			}

		}
		// 割賦請求開始年月がnullの場合はワーク．課金継続月数には初期値の0が返却される。
		
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getChrgKeizoku][ワーク．課金継続月数=" + wkMonCnt + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getChrgKeizoku]");
		return wkMonCnt;
	}
	
	/**
	 * 検証対象契約情報（状態判定済み）出力します。
	 * @param inMap       入力電文
	 * @param prcKnsKeiStat     料金検証契約状態コード
	 * @param useDayCnt   月中利用日数
	 * @param outputItem  出力情報
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void makeOutputInfo(JBSbatServiceInterfaceMap inMap, String prcKnsKeiStat, int useDayCnt
			,  JBSbatOutputItem outputItem) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeOutputInfo]");
		assert inMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeOutputInfo][inMap=" + inMap.toString() + "]") : true;
		
		JBSbatServiceInterfaceMap outMap = new JBSbatServiceInterfaceMap();
		// 入力電文コピー
		outMap.getMap().putAll(inMap.getMap());
		// 差分設定
		outMap.set(JBSbatAKIFM019.PRCKNS_KEI_STAT_CD,	prcKnsKeiStat);	// 料金検証契約状態コード
		outMap.set(JBSbatAKIFM019.CHRG_KEIZOKU_MON_CNT,	useDayCnt);		// 月中利用日数
		
		// 出力フラグ設定
		outMap.setOutFlg(true);
		
		outputItem.addOutMapList(outMap);

		assert outMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makeOutputInfo][outMap = " + outMap.getMap().toString() + "]") : true;
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeOutputInfo]");

		return;
	}

	/**
	 * 文字列がnullか空文字かどうかを判定します。
	 * @param tmpString   比較文字列
	 * @return boolean true:nullか空文字 false::nullか空文字以外
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	
	private boolean isNullOrKaraMoji(String tmpString) throws Exception
	{
		if(tmpString != null && !JACStrConst.KARA_MOJI.equals(tmpString.trim()))
		{
			return false;
		}
		return true;

	}
	
}
