/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatACWribAplyUpplJdg
*	ソースファイル名	：JBSbatACWribAplyUpplJdg.java
*	作成者				：富士通　
*	作成日				：2012年02月28日
*＜機能概要＞
*　割引適用上限判定部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2012/02/28   富士通		新規作成
*	v3.00		2012/08/02   FJ)本多	【ST2-2012-0001323対応】業務パラメータ設定値変更、上限判定のパターン追加
*	v4.00		2013.05/11   FJ)早崎	【IT1-2013-00001197】
*	v5.00		2013/09/19   FJ)小柴	【OM-2013-0002370】アンマッチ時のデータ取得ＳＱＬに条件を追加
*	v8.00		2013/12/13   FJ)鈴木	【ANK-1794-00-00】L2-MVNO対応（請求書電話番号表示（LC含む））
*********************************************************************/
package eo.business.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JACbatParamUtil;
import eo.business.common.JACbatSchdlUtil;
import eo.business.common.JBSbatBusinessService;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.item.JBSbatOutputItem;
import eo.business.common.JBSbatMatchServiceInterface;
import eo.business.util.file.JBSbatACIFM128;
import eo.business.util.file.JBSbatACIFM129;
import eo.business.util.file.JBSbatACIFM130;
import eo.business.util.table.JBSbatKK_T_SVC_KEI;
import eo.common.constant.JACStrConst;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatACWribAplyUpplJdg extends JBSbatBusinessService implements JBSbatMatchServiceInterface
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/** テーブル(サービス契約)*/
	private static final String D_TBL_NAME_KK_T_SVC_KEI = "KK_T_SVC_KEI";

	/** SQL定義キー(AC_SELECT_017)*/
	private static final String KK_T_SVC_KEI_AC_SELECT_017 = "AC_SELECT_017";

	/** テーブルアクセスクラス(サービス契約)*/
	private JBSbatSQLAccess db_KK_T_SVC_KEI = null;

	/** キーマッチ処理フラグ*/
	private boolean matchProcFlg;

	/** マスタファイル処理フラグ*/
	private boolean mastProcFlg;

	/** トランファイル処理フラグ*/
	private boolean tranProcFlg;
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/

	/**▼▼▼▼▼▼クラス変数追加 開始▼▼▼▼▼▼*/
	
	/** マッチングカウント */
	private long matchCnt 									= 0;

	/** トランカウント */
	private long tranCnt									= 0;
	
	/** 退避．トランキー（請求契約番号＋請求年月＋割引サービスコード） */
	private String tmpTranKey								= null;
	
	/** 退避．請求契約番号 */
	private String tmpSeiKeiNo								= null;
	
	/** 退避．月末日 */
	private String monEndDay								= null;
	
	/** 退避．検索実行フラグ（true：実行済み、false：実行前） */
	private boolean selectActFlg							= false;
	
	/** 割引適用上限判定マップ（キー：料金グループコード＋料金コースコード＋料金サービスコード、値：｛割引サービスコード, 上限契約数｝） */
	private HashMap<String, ArrayList<String[]>> jdgMap	= null;
	
	/** 契約上限数マップ（キー：割引サービスコード、値：上限契約数） */
	private HashMap<String, Long> keiUpplCntMap			= null;
	
	/** マッチ対象未存在フラグ */
	private boolean notMatchFlg							= false;

	
	/**▲▲▲▲▲▲クラス変数追加 終了▲▲▲▲▲▲*/
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);

		// DBアクセスクラスを生成します
		db_KK_T_SVC_KEI = new JBSbatSQLAccess(commonItem, D_TBL_NAME_KK_T_SVC_KEI);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
		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.getMonEndDay();
		
		// 割引適用上限判定マップ作成
		this.getWrbSvcTanka();
		
		this.keiUpplCntMap = new HashMap<String, Long>();
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][initial]");
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @param mastMap　入力電文
	 * @param tranMap　入力電文
	 * @param outputInItem  入力情報
	 * @return JBSbatOutputItem 出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap mastMap, JBSbatServiceInterfaceMap tranMap, JBSbatOutputItem outputInItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute]");
		assert 	mastMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][mastMap=" + mastMap.getMap().toString() + "]") : true;
		assert 	tranMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][tranMap=" + tranMap.getMap().toString() + "]") : true;
		assert 	this.keiUpplCntMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][keiUpplCntMap=" + this.keiUpplCntMap.toString() + "]") : true;
		
		// 入力Ｔ　≠　null　かつ、退避．請求契約番号　≠　入力Ｔ．請求契約番号の場合
		if(null != this.tmpSeiKeiNo && null != tranMap && !this.tmpSeiKeiNo.equals(tranMap.getString(JBSbatACIFM129.SEIKY_KEI_NO)))
		{
			// 退避．検索実行フラグ　←　false
			this.selectActFlg = false;
			// 退避．契約上限数マップ　クリア
			this.keiUpplCntMap.clear();
			// 退避．請求契約番号　更新
			this.tmpSeiKeiNo = tranMap.getString(JBSbatACIFM129.SEIKY_KEI_NO);
		}
		
		// マッチングキー
		String[] matchingKey 	= null;
		
		// マッチングキー取得
		matchingKey = getMatchingKey(mastMap, tranMap);
		
		// 入力Ｍのみ存在する
		if (mastMap != null && tranMap == null)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍのみ存在する]");
			// マッチングカウントクリア
			this.matchCnt = 0;
			this.setMastProcFlg(true);
		}
		// 入力Ｔのみ存在する
		else if (mastMap == null && tranMap != null)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｔのみ存在する]");
			
			// マッチ対象未存在フラグ ← true
			notMatchFlg = true;
			
			// 入力Ｔ．マッチングキー　≠　退避．トランキー
			if(!matchingKey[1].equals(this.tmpTranKey))
			{
				// トランカウント　←　0
				this.tranCnt = 0;
				// 退避．トランキー　更新
				this.tmpTranKey = matchingKey[1];
			}
			this.tranCnt++;
			// 割引適用上限再判定
			this.hanneiKeiUpplCnt(outputInItem, null, tranMap);
			
			// マッチ対象未存在フラグ ← false
			notMatchFlg = false;
			
			this.setTranProcFlg(true);
		}
		// 入力Ｍ、入力Ｔともに存在する
		else
		{
			// マッチング処理
			// 入力Ｍ＝入力Ｔ（マッチ）
			if (matchingKey[0].compareTo(matchingKey[1]) == 0)
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍ、入力Ｔともに存在する][入力Ｍ＝入力Ｔ（マッチ）]");
				// マッチングカウントアップ
				this.matchCnt++;
				// 退避.マッチングカウント ≦ 入力M.上限契約数
				if(this.matchCnt <= Long.parseLong(mastMap.getString(JBSbatACIFM128.UPPL_KEI_CNT)))
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMatchingKey][マッチングカウント=" + this.matchCnt + "]");
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMatchingKey][入力M.上限契約数=" + mastMap.getString(JBSbatACIFM128.UPPL_KEI_CNT) + "]");
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][割引適用可]");
					// 出力情報作成
					makeOutInfo(tranMap, JACStrConst.WRIB_TKY_K, outputInItem);
				}
				else
				{
					// 割引適用上限再判定
					this.hanneiKeiUpplCnt(outputInItem, mastMap, tranMap);
				}
				this.setMatchProcFlg(true);
			}
			// 入力Ｍ＜入力Ｔ
			else if (matchingKey[0].compareTo(matchingKey[1]) < 0)
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍ、入力Ｔともに存在する][入力Ｍ＜入力Ｔ]");
				// マッチングカウントクリア
				this.matchCnt = 0;
				this.setMastProcFlg(true);
			}
			// 入力Ｍ＞入力Ｔ
			else
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍ、入力Ｔともに存在する][入力Ｍ＞入力Ｔ]");
				this.setTranProcFlg(true);
				
				// マッチ対象未存在フラグ ← true
				notMatchFlg = true;
				
				// 入力Ｔ．マッチングキー　≠　退避．トランキー
				if(!matchingKey[1].equals(this.tmpTranKey))
				{
					// トランカウント　←　0
					this.tranCnt = 0;
					// 退避．トランキー更新
					this.tmpTranKey = matchingKey[1];
				}
				this.tranCnt++;
				// 割引適用上限再判定
				this.hanneiKeiUpplCnt(outputInItem, null, tranMap);
				
				// マッチ対象未存在フラグ ← false
				notMatchFlg = false;
			}
		}
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][execute]");
		
		return outputInItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		// DBアクセスクラスをクローズします
		db_KK_T_SVC_KEI.close();
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][terminal]");
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][terminal]");

	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	
	/**
	 * @return mastProcFlg を戻します。
	 */
	public boolean isMastProcFlg()
	{
		return mastProcFlg;
	}

	/**
	 * @return matchProcFlg を戻します。
	 */
	public boolean isMatchProcFlg()
	{
		return matchProcFlg;
	}

	/**
	 * @return tranProcFlg を戻します。
	 */
	public boolean isTranProcFlg()
	{
		return tranProcFlg;
	}

	/**
	 * @param mast_ProcFlg 設定する mastProcFlg。
	 */
	public void setMastProcFlg(boolean mast_ProcFlg)
	{
		this.mastProcFlg = mast_ProcFlg;
	}

	/**
	 * @param match_ProcFlg 設定する matchProcFlg。
	 */
	public void setMatchProcFlg(boolean match_ProcFlg)
	{
		this.matchProcFlg = match_ProcFlg;
	}

	/**
	 * @param tran_ProcFlg 設定する tranProcFlg。
	 */
	public void setTranProcFlg(boolean tran_ProcFlg)
	{
		this.tranProcFlg = tran_ProcFlg;
	}

	/**
	 * SQLKEY(AC_SELECT_017)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 * 
	 * 3.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 *		 	課金先．請求契約番号
	 *		 	課金先．課金先適用開始年月日
	 *		 	課金先．課金先適用終了年月日
	 *		 	サービス契約．予約適用年月日
	 *		 	サービス契約．サービス契約ステータス
	 *		 	サービス契約．サービス契約ステータス
	 *		 	サービス契約．サービス契約ステータス
	 *		 	サービス契約．照査年月日
	 *		 	サービス契約．照査取消年月日
	 * </pre>
	 * <p>
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeKK_T_SVC_KEI_AC_SELECT_017(Object[] param) throws Exception
	{
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());
		paramList.setValue(param[2].toString());
		paramList.setValue(param[3].toString());
		paramList.setValue(param[4].toString());
		paramList.setValue(param[5].toString());
		paramList.setValue(param[6].toString());
		paramList.setValue(param[7].toString());
		paramList.setValue(param[8].toString());

		// DBアクセスを実行します
		db_KK_T_SVC_KEI.selectBySqlDefine(paramList, KK_T_SVC_KEI_AC_SELECT_017);
	}
	
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
	
	/**
	 * 料金スケジュール定義アクセス部品より、
	 * 月末日を取得します
	 * @throws Exception        業務サービス内で発生した例外全般。
	 */
	private void getMonEndDay() throws Exception
	{
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getMonEndDay]");
		
		JACbatSchdlUtil su = new JACbatSchdlUtil(commonItem);
		
		try
		{
			// 請求年月を取得します。
			// 引数（バッチ運用日, "03"（料金計算日））
			String seikyYm = su.getBillDate(super.opeDate, JACStrConst.EVENT_CD_PRC_CALC_DAY);
			
			assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMonEndDay][料金計算年月=" + seikyYm + "]");
			
			// 月末日を取得します。
			// 引数（料金計算年月日, "01"（利用開始日）, "02"（利用終了年月日））
			this.monEndDay = su.getUseStrEnd(seikyYm, JACStrConst.EVENT_CD_USE_STAYMD, JACStrConst.EVENT_CD_USE_ENDYMD)[1];
			
			assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMonEndDay][月末日=" + this.monEndDay + "]");
		}
		finally
		{
			su.close();
		}
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getMonEndDay]");
		return;
	}
	
	/**
	 * 割引適用上限判定マップ作成
	 * @throws Exception        業務サービス内で発生した例外全般。
	 */
	private void getWrbSvcTanka() throws Exception
	{
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getWrbSvcTanka]");
		
		JACbatParamUtil paramUtil = new JACbatParamUtil(commonItem);
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getWrbSvcTanka][業務パラメータ管理．検索条件：" + JACStrConst.WKPRA_KK_UPPL_KS + ", " + super.opeDate + "]");
		
		HashMap<String, String> dbMap = null;
		
		try
		{
			// 業務パラメータ取得
			dbMap = paramUtil.getGyoumuParameterMap2(JACStrConst.WKPRA_KK_UPPL_KS, super.opeDate);
		}
		finally
		{
			paramUtil.close();
		}
		
		// 割引適用上限判定マップ　生成
		this.jdgMap = new HashMap<String, ArrayList<String[]>>();
		
		// キーセット（業務パラメータID）
		Set<String> keySet = dbMap.keySet();
		// 反復子
		Iterator<String> iterator = keySet.iterator();
		
		while(iterator.hasNext())
		{
			String mapKey = iterator.next();
			
			// 業務パラメータ管理．設定値を":"で文字分割
			String[] workParamValue = dbMap.get(mapKey).split(JACStrConst.COLON);
			
			// 料金グループコード＋料金コースコード
			String workParmId = mapKey.substring(11);
			
			// (1)割引サービスコード
			// (2)上限契約数
			// (3)料金プランコード
			// (1)、(2)、(3)*nの繰り返し
			for(String trgStr : workParamValue)
			{
				
				String[] clm = trgStr.split(JACStrConst.COMMA);
				
				// 1つ目：割引サービスコード
				String wribSvcCd	= clm[0];
				
				// 2つ目：上限契約数
				String upplKeiCnt	= clm[1];
				
				String[] valStr = {wribSvcCd, upplKeiCnt};
				
				// 3つ目以降：料金グループコード
				for (int j = 2; clm.length > j; j++)
				{
					StringBuffer keyBuf = new StringBuffer();
					
					// （料金グループコード＋料金コースコード）
					keyBuf.append(workParmId);
					// 料金プランコード
					keyBuf.append(clm[j]);
					
					String key = keyBuf.toString();
					
					// 既にある場合
					if (this.jdgMap.containsKey(key))
					{
						// マップから取り出したListを更新する。
						ArrayList<String[]> valList = this.jdgMap.get(key);
						valList.add(valStr);
					}
					// ない場合
					else
					{
						// Listを初期化し、マップに格納する。
						ArrayList<String[]> valList = new ArrayList<String[]>();
						valList.add(valStr);
						this.jdgMap.put(key, valList);
					}
				}
			}
		}
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getWrbSvcTanka]");
	}
	
	/**
	 * マッチングキーリストを取得します。
	 * @param  mastMap   割引サービスコード・上限契約数
	 * @param  tranMap   上限割引対象データ
	 * @return String[]  配列[0]:マッチングキー(マスタ)、配列[1]:マッチングキー(トラン) 
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private String[] getMatchingKey(JBSbatServiceInterfaceMap mastMap, JBSbatServiceInterfaceMap tranMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getMatchingKey]");
		
		// マッチングキーリスト(配列[0]:マッチングキー(マスタ) 、配列[1]:マッチングキー(トラン) 
		String[] macthKeyList 		= new String[2];
		
		StringBuffer keyBufMast 	= new StringBuffer();
		if (mastMap != null)
		{
			keyBufMast.append(mastMap.getString(JBSbatACIFM128.SEIKY_KEI_NO)); 	// 請求先番号
			keyBufMast.append(mastMap.getString(JBSbatACIFM128.SEIKY_YM)); 		// 請求年月
			keyBufMast.append(mastMap.getString(JBSbatACIFM128.WRIB_SVC_CD)); 	// 割引サービスコード
		}
		macthKeyList[0] = keyBufMast.toString();
		
		StringBuffer keyBufTran = new StringBuffer();
		if (tranMap != null)
		{
			keyBufTran.append(tranMap.getString(JBSbatACIFM129.SEIKY_KEI_NO)); 	// 請求先番号
			keyBufTran.append(tranMap.getString(JBSbatACIFM129.SEIKY_YM)); 		// 請求年月
			keyBufTran.append(tranMap.getString(JBSbatACIFM129.WRIB_SVC_CD)); 	// 割引サービスコード
		}
		macthKeyList[1] = keyBufTran.toString();
	
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMatchingKey][mastKey=" + macthKeyList[0] + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMatchingKey][tranKey=" + macthKeyList[1] + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getMatchingKey]");
	
		return macthKeyList;
	}
	
	/**
	 * 退避．検索実行フラグをもとに、退避．割引上限判定マップを検索し、
	 * 該当レコードがあった場合、契約上限数に反映します。
	 * 又、反映後の契約数をもとに再度割引上限判定を行います。
	 * 
	 * @param outputInItem 出力情報
	 * @param mastMap      割引サービスコード・上限契約数
	 * @param tranMap      上限割引対象データ
	 * @throws Exception   業務サービス内で発生した例外全般
	 */
	private void hanneiKeiUpplCnt(JBSbatOutputItem outputInItem, JBSbatServiceInterfaceMap mastMap, JBSbatServiceInterfaceMap tranMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][hanneiKeiUpplCnt]");
		
		// 退避．検索実行フラグ　＝　falseの場合
		if(!this.selectActFlg)
		{
			// 上限割引対象データの値をもとに、サービス契約を検索します。
			this.selectSvcKei(tranMap);
			// サービス契約の検索結果をもとに退避．割引適用上限判定マップを検索し、
			// 退避．契約上限マップを作成します。
			this.makeKeiUpplMap();
			
			this.selectActFlg = true;
			
			this.tmpSeiKeiNo = tranMap.getString(JBSbatACIFM129.SEIKY_KEI_NO);
		}
		
		// 退避．契約上限マップ、割引サービスコード・上限契約数、上限割引対象データをもとに
		// 反映後の上限契約数を取得します。
		this.hanneiUpplKeiCnt(outputInItem, mastMap, tranMap);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][hanneiKeiUpplCnt]");
		return;
	}
	
	/**
	 * 上限割引対象データの値をもとに、サービス契約を検索します。
	 * 
	 * @param tranMap    上限割引対象データ
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void selectSvcKei(JBSbatServiceInterfaceMap tranMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][selectSvcKei]");
		
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		
		// 課金先．請求契約番号
		paramList.setValue(tranMap.getString(JBSbatACIFM129.SEIKY_KEI_NO));
		// 課金先．課金先適用開始年月日
		paramList.setValue(super.opeDate);
		// 課金先．課金先適用終了年月日
		paramList.setValue(super.opeDate);
		// サービス契約．予約適用年月日
		paramList.setValue(this.monEndDay);
		// サービス契約．サービス契約ステータス
		paramList.setValue(JACStrConst.SVC_KEI_STAT_SYOSA);
		// サービス契約．サービス契約ステータス
		paramList.setValue(JACStrConst.SVC_KEI_STAT_TIKT);
		// サービス契約．サービス契約ステータス
		paramList.setValue(JACStrConst.SVC_KEI_STAT_SVCTK);
		// サービス契約．照査年月日
		paramList.setValue(this.monEndDay);
		// サービス契約．照査取消年月日
		paramList.setValue(this.monEndDay);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][selectSvcKei][検索条件=" + paramList.getList().toString() + "]");
		
		this.executeKK_T_SVC_KEI_AC_SELECT_017(paramList.getList().toArray());
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][selectSvcKei]");
		return;
	}
	
	/**
	 *  サービス契約の検索結果をもとに退避．割引適用上限判定マップを検索し、
	 *  退避．契約上限マップを作成します。
	 *  
	 * @throws Exception   業務サービス内で発生した例外全般
	 */
	private void makeKeiUpplMap() throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeKeiUpplMap]");
		
		JBSbatCommonDBInterface dbMap = this.db_KK_T_SVC_KEI.selectNext();
		
		// 取得件数分以下の処理を繰り返します
		while(null != dbMap)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makeKeiUpplMap][サービス契約検索結果情報=" + dbMap.getMap().toString() + "]");
			
			// 退避．割引適用上限判定マップのキーを作成する。
			String mapKey = this.makeKeiUpplMapKey(dbMap);
			// 退避．割引適用上限判定マップのキーに該当キーが含まれる場合
			if(this.jdgMap.containsKey(mapKey))
			{
				// 契約上限数リスト
				ArrayList<String[]> mapValue = this.jdgMap.get(mapKey);
				
				// 契約上限数リスト．値（[0]割引サービスコード、[1]契約上限数）
				for(String[] trgStr : mapValue)
				{
					// 契約上限数マップのキーに割引サービスコードが含まれる場合
					if(this.keiUpplCntMap.containsKey(trgStr[0]))
					{
						// 契約上限数マップの該当レコード．値　＋＝　契約上限数
						this.keiUpplCntMap.put(trgStr[0], this.keiUpplCntMap.get(trgStr[0]) + Long.parseLong(trgStr[1]));
					}
					// 上記以外の場合
					else
					{
						// 契約上限数マップの該当レコードに値を設定
						// キー：割引サービスコード、値：契約上限数
						this.keiUpplCntMap.put(trgStr[0], Long.parseLong(trgStr[1]));
					}
				}
			}
			dbMap = this.db_KK_T_SVC_KEI.selectNext();
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeKeiUpplMap]");
		return;
	}
	
	/**
	 * 引数で渡されたマップをもとに、
	 * 退避．割引適用上限判定マップのキーを作成し、返却します。
	 * 
	 * @param trgMap 対象情報
	 * @return String 退避．割引適用上限判定マップのキー（料金グループコード＋料金コースコード＋料金サービスコード）
	 * @throws Exception   業務サービス内で発生した例外全般
	 */
	private String makeKeiUpplMapKey(JBSbatCommonDBInterface trgMap) throws Exception
	{
		StringBuffer rtnBuf = new StringBuffer();
		
		// 料金コースコード
		String pcrsCd = trgMap.getString(JBSbatKK_T_SVC_KEI.PCRS_CD);
		// 料金プランコード
		String pplanCd = trgMap.getString(JBSbatKK_T_SVC_KEI.PPLAN_CD);
		
		// 料金コースコードがnullの場合
		if(null == pcrsCd)
		{
			// 料金コースコード　←　ALLスペース
			pcrsCd = JACStrConst.PCRS_CD_SP;
		}
		// 料金プランコードがnullの場合
		if(null == pplanCd)
		{
			// 料金プランコード
			pplanCd = JACStrConst.PPLAN_CD_SP;
		}
		
		// 料金グループコード
		rtnBuf.append(trgMap.getString(JBSbatKK_T_SVC_KEI.PRC_GRP_CD));
		// 料金コースコード
		rtnBuf.append(pcrsCd);
		// 料金プランコード
		rtnBuf.append(pplanCd);
		
		return rtnBuf.toString();
	}
	
	/**
	 * 退避．契約上限マップ、割引サービスコード・上限契約数、上限割引対象データをもとに
	 * 反映後の上限契約数を取得し、再度割引適用上限判定を行います。
	 * 
	 * @param outputInItem 出力情報
	 * @param mastMap      割引サービスコード・上限契約数
	 * @param tranMap      上限割引対象データ
	 * @throws Exception   業務サービス内で発生した例外全般
	 */
	private void hanneiUpplKeiCnt(JBSbatOutputItem outputInItem, JBSbatServiceInterfaceMap mastMap, JBSbatServiceInterfaceMap tranMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][hanneiUpplKeiCnt]");
		
		// 割引適用可否（初期値："0"（否））
		String wribTkyKh = JACStrConst.WRIB_TKY_H;
		
		// 退避．契約上限数マップに値が設定されている場合
		if(!this.keiUpplCntMap.isEmpty())
		{
			// 割引サービスコード
			String wriSvcCd = tranMap.getString(JBSbatACIFM129.WRIB_SVC_CD);
			
			// 契約上限数マップのキーに割引サービスコードが含まれる場合
			if(this.keiUpplCntMap.containsKey(wriSvcCd))
			{
				// 反映後上限契約数（初期値：割引上限数マップ．該当レコードの値）
				long upplCnt = this.keiUpplCntMap.get(wriSvcCd);
				// 入力Ｍ　≠　nullの場合
				if(null != mastMap)
				{
					// 反映後上限契約数　＋＝　入力Ｍ．上限契約数
					upplCnt += Long.parseLong(mastMap.getString(JBSbatACIFM128.UPPL_KEI_CNT));
					
					// 反映後上限契約数　≧　マッチングカウントの場合
					if(upplCnt >= this.matchCnt)
					{
						// 割引適用可否　←　"1"（可）
						wribTkyKh = JACStrConst.WRIB_TKY_K;
					}
				}
				// 上記以外の場合
				else
				{
					// 反映後上限契約数　≧　トランカウントの場合
					if(upplCnt >= this.tranCnt)
					{
						// 割引適用可否　←　"1"（可）
						wribTkyKh = JACStrConst.WRIB_TKY_K;
					}
				}
			}
		}
		
		// マッチ時 または 割引適用可否≠"0"（否）の場合
		if(!notMatchFlg || !wribTkyKh.equals(JACStrConst.WRIB_TKY_H))
		{
			// 出力情報作成
			this.makeOutInfo(tranMap, wribTkyKh, outputInItem);
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][hanneiUpplKeiCnt]");
	}
	
	
	/**
	 * 上限判定割引料金情報作成
	 * 
	 * @param tranMap      入力電文
	 * @param wribTkyKh    割引適用可否
	 * @param outputInItem 入力情報
	 * @throws Exception   業務サービス内で発生した例外全般
	 */
	private void makeOutInfo(JBSbatServiceInterfaceMap tranMap, String wribTkyKh, JBSbatOutputItem outputInItem) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeOutInfo]");
		
		JBSbatServiceInterfaceMap outBean = new JBSbatServiceInterfaceMap();
		outBean.set(JBSbatACIFM130.SEIKY_KEI_NO, 			tranMap.get(JBSbatACIFM129.SEIKY_KEI_NO)); 				// 01.請求先番号
		outBean.set(JBSbatACIFM130.SEIKY_YM, 				tranMap.get(JBSbatACIFM129.SEIKY_YM)); 					// 02.請求年月
		outBean.set(JBSbatACIFM130.WRIB_SVC_KEI_NO, 		tranMap.get(JBSbatACIFM129.WRIB_SVC_KEI_NO)); 			// 03.割引サービス契約番号
		outBean.set(JBSbatACIFM130.WRISVC_TRGT_KEI_NO, 		tranMap.get(JBSbatACIFM129.WRISVC_TRGT_KEI_NO)); 		// 04.割引サービス対象契約番号
		outBean.set(JBSbatACIFM130.SVC_NO, 					tranMap.get(JBSbatACIFM129.SVC_NO)); 					// 05.サービス番号
		outBean.set(JBSbatACIFM130.SVC_CD, 					tranMap.get(JBSbatACIFM129.SVC_CD)); 					// 06.サービス識別
		outBean.set(JBSbatACIFM130.PCRS_CD, 				tranMap.get(JBSbatACIFM129.PCRS_CD)); 					// 07.料金コースコード
		outBean.set(JBSbatACIFM130.PRC_SVC_CD, 				tranMap.get(JBSbatACIFM129.PRC_SVC_CD)); 				// 08.料金サービスコード
		outBean.set(JBSbatACIFM130.PRC_KMK_CD, 				tranMap.get(JBSbatACIFM129.PRC_KMK_CD)); 				// 09.料金項目コード
		outBean.set(JBSbatACIFM130.COLLECT_PATTERN_CD, 		tranMap.get(JBSbatACIFM129.COLLECT_PATTERN_CD)); 		// 10.徴収パターンコード
		outBean.set(JBSbatACIFM130.PRC, 					tranMap.get(JBSbatACIFM129.PRC)); 						// 11.料金
		outBean.set(JBSbatACIFM130.USE_STAYMD, 				tranMap.get(JBSbatACIFM129.USE_STAYMD)); 				// 12.利用開始日
		outBean.set(JBSbatACIFM130.USE_ENDYMD, 				tranMap.get(JBSbatACIFM129.USE_ENDYMD)); 				// 13.利用終了日
		outBean.set(JBSbatACIFM130.SVC_STAYMD, 				tranMap.get(JBSbatACIFM129.SVC_STAYMD)); 				// 14.サービス開始日
		outBean.set(JBSbatACIFM130.FIRST_CHRG_STAYMD, 		tranMap.get(JBSbatACIFM129.FIRST_CHRG_STAYMD)); 		// 15.初回課金開始日
		outBean.set(JBSbatACIFM130.SVC_DSL_YMD, 			tranMap.get(JBSbatACIFM129.SVC_DSL_YMD)); 				// 16.サービス解約日
		outBean.set(JBSbatACIFM130.SVC_DLRE, 				tranMap.get(JBSbatACIFM129.SVC_DLRE)); 					// 17.サービス解約理由
		outBean.set(JBSbatACIFM130.SVC_KAIHK_DAY, 			tranMap.get(JBSbatACIFM129.SVC_KAIHK_DAY)); 			// 18.サービス回復日
		outBean.set(JBSbatACIFM130.USE_DAY_CNT, 			tranMap.get(JBSbatACIFM129.USE_DAY_CNT)); 				// 19.利用日数
		outBean.set(JBSbatACIFM130.USE_FAIL_DAY_CNT, 		tranMap.get(JBSbatACIFM129.USE_FAIL_DAY_CNT)); 			// 20.利用不可日数
		outBean.set(JBSbatACIFM130.AIT_DIV, 				tranMap.get(JBSbatACIFM129.AIT_DIV)); 					// 21.相対区分
		outBean.set(JBSbatACIFM130.SIME_DAY, 				tranMap.get(JBSbatACIFM129.SIME_DAY)); 					// 22.締め日
		outBean.set(JBSbatACIFM130.USE_FAIL_APLY_KH, 		tranMap.get(JBSbatACIFM129.USE_FAIL_APLY_KH)); 			// 23.利用不可適用可否
		outBean.set(JBSbatACIFM130.MAEUKE_SOSAI_YUSEN_JUN, 	tranMap.get(JBSbatACIFM129.MAEUKE_SOSAI_YUSEN_JUN)); 	// 24.前受相殺優先順位
		outBean.set(JBSbatACIFM130.WRIB_YUSEN_JUN, 			tranMap.get(JBSbatACIFM129.WRIB_YUSEN_JUN)); 			// 25.割引優先順位
		outBean.set(JBSbatACIFM130.SEIRI_NO, 				tranMap.get(JBSbatACIFM129.SEIRI_NO)); 					// 26.整理番号
		outBean.set(JBSbatACIFM130.UPPL_JUDGE_YUSEN_JUN, 	tranMap.get(JBSbatACIFM129.UPPL_JUDGE_YUSEN_JUN)); 		// 27.上限判定優先順位
		outBean.set(JBSbatACIFM130.DSP_JUN, 				tranMap.get(JBSbatACIFM129.DSP_JUN)); 					// 28.表示順
		outBean.set(JBSbatACIFM130.WRIB_SVC_CD, 			tranMap.get(JBSbatACIFM129.WRIB_SVC_CD)); 				// 29.割引サービスコード
		outBean.set(JBSbatACIFM130.WRIB_TKY_KH, 			wribTkyKh); 											// 30.割引適用可否
		outBean.set(JBSbatACIFM130.SVC_DTL_SKBT_NO, 		tranMap.get(JBSbatACIFM129.SVC_DTL_SKBT_NO)); 			// 31.サービス詳細識別番号

		outBean.setOutFlg(true);
		
		outputInItem.addOutMapList(outBean);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeOutInfo]");
	}
}
