/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatAKCmpGengakuShukHanei
*	ソースファイル名	：JBSbatAKCmpGengakuShukHanei.java
*	作成者				：富士通　
*	作成日				：2013年04月25日
*＜機能概要＞
*　キャンペーン減額集計反映部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v4.00.00	2013/04/25   FJ）高橋	新規作成
*	v9.00.00	2014/04/25   FJ) 前田		【ANK-2054-00-00】スマートリンク端末保障対応
*********************************************************************/
package eo.business.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatAKIFM005;
import eo.business.util.table.JBSbatAK_M_PRCKNS_PRCKMKHN;
import eo.common.constant.JACStrConst;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.db.JBSbatSQLAccess;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatAKCmpGengakuShukHanei extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/** テーブル(料金検証料金項目反映)*/
	private static final String D_TBL_NAME_AK_M_PRCKNS_PRCKMKHN = "AK_M_PRCKNS_PRCKMKHN";

	/** SQL定義キー(AK_SELECT_001)*/
	private static final String AK_M_PRCKNS_PRCKMKHN_AK_SELECT_001 = "AK_SELECT_001";

	/** テーブルアクセスクラス(料金検証料金項目反映)*/
	private JBSbatSQLAccess db_AK_M_PRCKNS_PRCKMKHN = null;
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/
	
	/** 反映処理区分 ＣＰ減額集計*/
	private static final String HANEI_TRN_DIV_CMP_GENGAKU = "2";

	
	/** 退避．料金検証料金項目反映マップ */
	private HashMap<String, String> tmpPrcknsPrckmkhnMap = null;
	
	/** 退避．ブレイクキー */
	private String tmpBreakKey = null;

	/** 退避．集計キー */
	private String tmpshukKey = null;
	
	/** ワーク．集計金額ＭＡＰ */
	private HashMap<String,BigDecimal> wkShukAmntMap  = null;

	/** ワーク．集計対象入力情報ＭＡＰ */
	private HashMap<String,JBSbatServiceInterfaceMap> wkShukTrgtInMap  = null;
	
	/** 退避.想定請求内訳情報（ＣＰ減額料金項目集計後）リスト　*/
	private ArrayList<JBSbatServiceInterfaceMap> soteiSeikyUcwklist	= null;
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);

		// DBアクセスクラスを生成します
		db_AK_M_PRCKNS_PRCKMKHN = new JBSbatSQLAccess(commonItem, D_TBL_NAME_AK_M_PRCKNS_PRCKMKHN);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/

		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.makePrcknsPrckmkhnMap();
		
		this.wkShukAmntMap = new HashMap<String,BigDecimal>();
		this.wkShukTrgtInMap = new HashMap<String,JBSbatServiceInterfaceMap>();
		this.soteiSeikyUcwklist = new ArrayList<JBSbatServiceInterfaceMap> ();
		
		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 inMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][inMap = " + inMap.getMap().toString() + "]") : true;

		// 出力情報
		JBSbatOutputItem outputInItem = new JBSbatOutputItem();
		
		//1件目のレコードの場合
		if(!outputInItem.isOutMapList())
		{
			// ダミーレコードセット
			outputInItem.addOutMapList(new JBSbatServiceInterfaceMap());
		}
		
		// 退避．ブレイクキー ≠ NULL（初回データ以外） の場合
		if(this.tmpBreakKey != null)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][退避．ブレイクキー ≠ NULL（初回データ以外） の場合]");
			
			// 「入力情報 ＝ NULL（最終レコード）」 もしくは
			// 「退避．ブレイクキー ≠ 入力．KEY」 の場合
			if(inMap == null || isKeyBreak(inMap))
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力情報 ＝ NULL（最終レコード） または 退避．ブレイクキー ≠ 入力．KEYの場合]");
				
				// 出力処理を行う。
				this.makeOutInfo(outputInItem);
				
				// 最終レコードの場合
				if(inMap == null)
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][最終レコードの場合]");
					return outputInItem;
				}
				
				// 集計領域を初期化
				this.wkShukAmntMap.clear();
				this.wkShukTrgtInMap.clear();
				this.soteiSeikyUcwklist.clear();
				
			}
		}
		

		// 反映先料金項目コード取得
		String HaneiSakiPrcKmkCd =  getHaneiSakiPrcKmkCd(inMap);
		
		// 反映先料金項目コードが取得できない場合
		if(JACStrConst.KARA_MOJI.equals(HaneiSakiPrcKmkCd))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][退避．出力情報に入力情報をそのまま設定]");
			//退避.出力情報に入力情報をそのまま設定
			this.soteiSeikyUcwklist.add(inMap);
		}
		else
		// 反映先料金項目コードが取得できた場合
		{
		
			// 集計キーを作成
			this.tmpshukKey = this.makeStr(inMap.getString(JBSbatAKIFM005.SEIKY_YM),inMap.getString(JBSbatAKIFM005.SEIKY_KEI_NO), 
								inMap.getString(JBSbatAKIFM005.SVC_KEI_NO), inMap.getString(JBSbatAKIFM005.SVC_DTL_SKBT_NO), HaneiSakiPrcKmkCd);
			
			// 想定金額が退避領域に登録されているか確認
			if(this.wkShukAmntMap.containsKey(this.tmpshukKey))
			{	
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][想定金額を退避領域の想定金額に足し合わせ]");
				// 想定金額を取得
				BigDecimal tmpSouteiAmt = this.wkShukAmntMap.get(this.tmpshukKey);
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][退避．想定金額："+ tmpSouteiAmt +"]");
				
				// 退避．想定金額　＝　退避．想定金額　＋　入力ＩＦ．想定金額
				tmpSouteiAmt = tmpSouteiAmt.add(inMap.getBigDecimal(JBSbatAKIFM005.SOTEI_AMNT));
				
				// 想定料金を退避領域に設定
				this.wkShukAmntMap.put( this.tmpshukKey, tmpSouteiAmt );
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][(足し合わせ後)退避．想定金額："+  this.wkShukAmntMap.get(this.tmpshukKey) +"]");
			}
			else
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][退避領域に想定金額が存在しないため、新規に退避領域に設定]");
				// 想定料金を退避領域に設定
				this.wkShukAmntMap.put( this.tmpshukKey, inMap.getBigDecimal(JBSbatAKIFM005.SOTEI_AMNT) );
				
				// 入力．想定請求内訳情報の料金項目コードを置き換えて退避領域に設定
				JBSbatServiceInterfaceMap editInMap = this.editWkRecodeMap(inMap,HaneiSakiPrcKmkCd);
				this.wkShukTrgtInMap.put( this.tmpshukKey, editInMap );
			
			}
		}
		
		// ブレイクキーの更新
		// （入力ＩＦ）想定請求内訳.請求年月 ＋ （入力ＩＦ）想定請求内訳.請求契約番号 ＋ （入力ＩＦ）想定請求内訳.サービス契約番号 ＋ （入力ＩＦ）想定請求内訳.サービス詳細識別番号
		this.tmpBreakKey = this.makeStr(inMap.getString(JBSbatAKIFM005.SEIKY_YM), 
				inMap.getString(JBSbatAKIFM005.SEIKY_KEI_NO), inMap.getString(JBSbatAKIFM005.SVC_KEI_NO),
				inMap.getString(JBSbatAKIFM005.SVC_DTL_SKBT_NO));
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][execute]");
		return outputInItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/

	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][terminal]");
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		// DBアクセスクラスをクローズします
		db_AK_M_PRCKNS_PRCKMKHN.close();
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][terminal]");
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**
	 * SQLKEY(AK_SELECT_001)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 * 
	 * 3.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 *		 	反映処理区分
	 *		 	料金検証料金項目反映適用開始年月日
	 *		 	料金検証料金項目反映適用終了年月日
	 * </pre>
	 * <p>
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeAK_M_PRCKNS_PRCKMKHN_AK_SELECT_001(Object[] param) throws Exception
	{
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());
		paramList.setValue(param[2].toString());

		// DBアクセスを実行します
		db_AK_M_PRCKNS_PRCKMKHN.selectBySqlDefine(paramList, AK_M_PRCKNS_PRCKMKHN_AK_SELECT_001);
	}
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
	
	/**
	 * 料金検証料金項目反映マスタを検索して、料金検証料金項目反映MAPを作成する。
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void makePrcknsPrckmkhnMap() throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makePrcknsPrckmkhnMap]");

		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
	
		// 反映処理区分
		paramList.setValue(HANEI_TRN_DIV_CMP_GENGAKU);
		// 料金検証料金項目反映適用開始年月日
		paramList.setValue(super.opeDate);
		// 料金検証料金項目反映適用終了年月日
		paramList.setValue(super.opeDate);

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makePrcknsPrckmkhnMap][paramList=" + paramList.getList().toString() + "]");

		// SQL実行
		executeAK_M_PRCKNS_PRCKMKHN_AK_SELECT_001(paramList.getList().toArray());
		JBSbatCommonDBInterface dbMap = db_AK_M_PRCKNS_PRCKMKHN.selectNext();
		

		// 料金検証料金項目反映マスタより、投入料金項目コード：反映料金項目コードのＭＡＰを作成
		
		this.tmpPrcknsPrckmkhnMap = new HashMap<String, String>(); //結果領域の生成
		
		String tihKey = null;	// 退避キー領域
		String key = null;		// キー領域
		String value = null;	// 値領域
		
		// 取得件数分処理を繰り返す
		while(dbMap != null)
		{
			// KEY：投入料金項目コード
			key = dbMap.getString(JBSbatAK_M_PRCKNS_PRCKMKHN.TONYU_PRC_KMK_CD);
			
			// value:反映先料金項目コード
			value = dbMap.getString(JBSbatAK_M_PRCKNS_PRCKMKHN.HANEI_SAKI_PRC_KMK_CD);
			
			if(key == null)
			{
				// キーがnullの場合はスキップ。
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makePrcknsPrckmkhnMap][料金検証料金項目反映.投入料金項目コードがnullのためスキップ]");
				continue;
			}
			
			// キーが同じでない場合
			if(!key.equals(tihKey))
			{			
				this.tmpPrcknsPrckmkhnMap.put(key, value);	// HashMapへ設定
				tihKey = key;								// 退避キーの置き換え
				value = null;								// 初期化
			}
			
			dbMap = db_AK_M_PRCKNS_PRCKMKHN.selectNext();
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makePrcknsPrckmkhnMap][map=" + tmpPrcknsPrckmkhnMap.toString() + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makePrcknsPrckmkhnMap]");
		return;
	}
	
	/**
	 * キーブレイクチェックを行います。
	 * @param inMap　入力電文
	 * @return boolean true：キーブレイクあり false：キーブレイクなし
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private boolean isKeyBreak(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][isKeyBreak]");
		
		boolean jdgFlg = false;
		// 想定請求内訳.請求年月 ＋ 想定請求内訳.請求契約番号 ＋ 想定請求内訳.サービス契約番号 ＋ 想定請求内訳.サービス詳細識別番号
		String inKey = this.makeStr(inMap.getString(JBSbatAKIFM005.SEIKY_YM), 
				inMap.getString(JBSbatAKIFM005.SEIKY_KEI_NO), inMap.getString(JBSbatAKIFM005.SVC_KEI_NO), 
				inMap.getString(JBSbatAKIFM005.SVC_DTL_SKBT_NO));

		// キーブレイクチェックを行う。（ 「退避．ブレイクキー ≠ NULL」 かつ 「退避．ブレイクキー ≠ 入力．KEY」 の場合）
		if(!inKey.equals(this.tmpBreakKey))
		{
			jdgFlg = true;
		}

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][isKeyBreak][返却値 = " + jdgFlg + "]");
		
		return jdgFlg;
	}
	
	/**
	 * 出力共通電文オブジェクトへ出力情報の格納を行う。
	 * 
	 * @param inMap 入力情報
	 * @param outputItem 出力情報
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	
	private void makeOutInfo(JBSbatOutputItem outputItem) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeOutInfo]");

		// 退避分の出力
		for(JBSbatServiceInterfaceMap outMap : this.soteiSeikyUcwklist)
		{
			// 出力フラグ設定
			outMap.setOutFlg(true);
			outputItem.addOutMapList(outMap);
			assert outMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makeOutInfo][出力情報 = " + outMap.getMap().toString() + "]") : true;
		}
		
		// 退避分（集計処理要）の出力
		
		for(String key : this.wkShukTrgtInMap.keySet())
		{
			// 集計した想定金額の取得
			BigDecimal tmpAmt = this.wkShukAmntMap.get(key);
			
			JBSbatServiceInterfaceMap tmpOutMap = this.wkShukTrgtInMap.get(key);
			tmpOutMap.setString( JBSbatAKIFM005.SOTEI_AMNT, tmpAmt);
			
			// 出力フラグ設定
			tmpOutMap.setOutFlg(true);
			outputItem.addOutMapList(tmpOutMap);
			assert tmpOutMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makeOutInfo][出力情報 = " + tmpOutMap.toString() + "]") : true;
		}

		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeOutInfo]");
		return;
	}
	
	/**
	 * 入力の想定請求内訳情報を元に、料金項目コードを置き換えた想定請求内訳情報を編集する。
	 * @param inMap     入力電文
	 * @param prcKmkCd 料金項目コード
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private JBSbatServiceInterfaceMap editWkRecodeMap(JBSbatServiceInterfaceMap inMap, String prcKmkCd) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][editWkRecodeMap]");

		JBSbatServiceInterfaceMap wkInMap = new JBSbatServiceInterfaceMap();
		wkInMap.getMap().putAll(inMap.getMap());
		wkInMap.setString( JBSbatAKIFM005.PRC_KMK_CD, prcKmkCd);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][editWkRecodeMap]");
		return wkInMap;
	}
	
	/**
	 * 反映先料金項目コードを取得します。
	 * @param  inMap 入力情報
	 * @return haneiSakiPrcKmkCd 反映先料金項目コード
	 */
	private String getHaneiSakiPrcKmkCd (JBSbatServiceInterfaceMap inMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getHaneiSakiPrcKmkCd]");
		
		String haneiSakiPrcKmkCd = "";

		// 集計処理を実施
		// 入力．料金項目コードを用い、退避.料金検証料金項目反映ＭＡＰの投入料金項目コードをする。
		String prcKmkCd = inMap.getString(JBSbatAKIFM005.PRC_KMK_CD);
		
		if(this.tmpPrcknsPrckmkhnMap.containsKey(prcKmkCd))
		{
			
			haneiSakiPrcKmkCd = this.tmpPrcknsPrckmkhnMap.get(prcKmkCd);
			
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getHaneiSakiPrcKmkCd][入力料金項目コード：" + prcKmkCd + "]、反映先料金項目コード[" + haneiSakiPrcKmkCd + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getHaneiSakiPrcKmkCd]");
		return haneiSakiPrcKmkCd;
	}
	

	
	
	/**
	 * 文字を連結します。
	 * @param  string 文字
	 * @return strBuf 連結した文字列
	 */
	private String makeStr(String ...string)
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeStr]");
		
		StringBuffer strBuf = new StringBuffer();
		for(String str:string)
		{
			if(str == null)
			{
				strBuf.append(JACStrConst.KARA_MOJI);
			}
			else
			{
				strBuf.append(str);
			}
		}
		
		assert strBuf != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][strBuf][strBuf = " + strBuf.toString() + "]") : true;
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeStr]");
		
		return strBuf.toString();
	}
	

}
