/*******************************************************************************
*	 All Rights reserved,Copyright (c) K-Opticom 
********************************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JSYejbEKK0081B021TPDA
*	ソースファイル名：JSYejbEKK0081B021TPDA.java
*	作成者			：EKek0043
*	日付			：2011年12月15日
*＜機能概要＞
*	SQLFacility
*	テンプレートDBアクセス部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	ｖ1.00.00
*	ｖ5.00.00	2013/09/02	FJ)寺園		OM-2013-0001391
*
********************************************************************************/

package eo.ejb.cbs.sqlf;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANSQLFacility;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.ejb.common.JSYejbConnection;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.TemplateDBAccessHandler;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import eo.ejb.cbs.cbsmsg.EKK0081B021CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B021CBSMsg1List;
import eo.ejb.cbm.entity.KK0081ETMsg;
import eo.ejb.cbm.entity.KK0321ETMsg;
import eo.ejb.common.JKKModelCommon;

/**
*
*  テンプレートDBアクセス部品　EKK0081B021_SQLF<br>
 * </p>
 * @author 富士通
*/
public class JSYejbEKK0081B021TPDA extends CAANSQLFacility implements TemplateDBAccessHandler
{

	/** 照査前結果コード（照査可能） */
	private static final String RSLT_CD_OK_SHOSA = "00";

	/** 照査前結果コード（サービス契約ステータスエラー） */
	private static final String RSLT_CD_ERR_SVCKEI_STAT = "01";

	/** 照査前結果コード（請求契約番号不一致） */
	private static final String RSLT_CD_ERR_SKYKEI_DISAGR = "02";

	/** 照査前結果コード（SYSID不一致） */
	private static final String RSLT_CD_ERR_SYSID_DISAGR = "03";

	/** サービス契約ステータス（受付済） */
	private static final String SVC_KEI_STAT_RESV = "010";

	/** サービス契約ステータス（キャンセル済） */
	private static final String SVC_KEI_STAT_CANCEL = "920";

	/** ステータスチェック用許容ステータス */
	private static final HashMap<String, String> VALID_STATUS_MAP = new HashMap<String, String>();

	static
	{
		VALID_STATUS_MAP.put(SVC_KEI_STAT_RESV, "受付済");
		VALID_STATUS_MAP.put(SVC_KEI_STAT_CANCEL, "キャンセル済");
	}

	/**
	 * EKK0081B021_SQLF
	 * @param inMsg 入力値の格納されたCBSMsg
	 * @param inContext ディスパッチコンテキスト
	 */
	public void invoke(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		// ＫＥＹ＿申込書番号に紐付くサービス契約の取得
		HashMap<String, ArrayList<String>> retMapKK0081 = getRecordKK0081(inMsg, inContext);

		// データが取得できなかった場合は処理を終了する
		if (retMapKK0081.get(KK0081ETMsg.SVC_KEI_NO).size() < 1)
		{
			setMsg(inMsg, RSLT_CD_ERR_SVCKEI_STAT);
			return;
		}

		// (1)サービス契約ステータスのチェック
		if (!isSvcKeiStatus(retMapKK0081.get(KK0081ETMsg.SVC_KEI_STAT)))
		{
			// チェックエラーの場合、サービス契約ステータスエラーとして処理を終了する
			setMsg(inMsg, RSLT_CD_ERR_SVCKEI_STAT);
			return;
		}

		// ＫＥＹ＿申込書番号に紐付く課金先の取得
		HashMap<String, ArrayList<String>> retMapKK0321 = getRecordKK0321(inMsg, inContext);

		// データが取得できなかった場合は処理を終了する
		if (retMapKK0321.get(KK0321ETMsg.SEIKY_KEI_NO).size() < 1)
		{
			setMsg(inMsg, RSLT_CD_ERR_SVCKEI_STAT);
			return;
		}

		// (2)請求契約番号のチェック
		if (!isSeikyKeiNo(retMapKK0321.get(KK0321ETMsg.SEIKY_KEI_NO)))
		{
			// チェックエラーの場合、請求契約番号不一致エラーとして処理を終了する
			setMsg(inMsg, RSLT_CD_ERR_SKYKEI_DISAGR);
			return;
		}

		// (3)SYSIDのチェック
		if (!isSysid(retMapKK0081.get(KK0081ETMsg.SYSID)))
		{
			// チェックエラーの場合、SYSID不一致エラーとして処理を終了する
			setMsg(inMsg, RSLT_CD_ERR_SYSID_DISAGR);
			return;
		}

		// 全てのチェックが正常だった場合、照査可能とする
		setMsg(inMsg, RSLT_CD_OK_SHOSA);

	}

	/**
	 * ＫＥＹ＿申込書番号に紐付くサービス契約の情報を取得します
	 * @param inMsg 入力値の格納されたCBSMsg
	 * @param inContext ディスパッチコンテキスト
	 * @return 実行結果を保持したリスト
	 * 			┣サービス契約番号
	 * 			┣サービス契約ステータス 
	 * 			┗SYSID
	 */
	
	private HashMap<String, ArrayList<String>> getRecordKK0081(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		// コネクション
		Connection con1 = null;
		// プリペアステートメント
		PreparedStatement pstmt = null;
		// リザルトセット
		ResultSet rsltQuery = null;
		
		// パラメータのカウント
		int iPCnt = 0;

		try
		{
			//コネクション取得
			con1 = JSYejbConnection.getConnection(KK0081ETMsg.getTableName());

			// SQL文_基本部1
			StringBuffer sql_Buff = new StringBuffer();
			sql_Buff.append(" SELECT  ")
					.append("     KK0081.SVC_KEI_NO  ")
					.append("     , KK0081.SVC_KEI_STAT  ")
					.append("     , KK0081.SYSID  ")
					.append(" FROM  ")
					.append("     KK_T_MSKM_DTL KK0021  ")
					.append("     INNER JOIN KK_T_MSKM KK0011  ")
					.append("     ON KK0011.MSKM_NO = KK0021.MSKM_NO  ")
					.append("     INNER JOIN KK_T_SVC_KEI KK0081  ")
					.append("     ON KK0081.MSKM_DTL_NO = KK0021.MSKM_DTL_NO  ")
					.append(" WHERE  ")
					.append("     KK0021.MSKMSHO_NO = ?  ");
			//入力値が設定されている場合のみ、検索条件を追加（KEY_SYSID）
			if (!inMsg.isNull(EKK0081B021CBSMsg.KEY_SYSID))
			{
				sql_Buff.append(" AND  KK0081.SYSID = ? ");
			}
			sql_Buff.append("     AND (KK0021.MSKM_DTL_NO, KK0021.GENE_ADD_DTM) =  ")
					.append("              (SELECT KK0021_GENE.MSKM_DTL_NO, MAX(KK0021_GENE.GENE_ADD_DTM) AS KK0021_MAX  ")
					.append("               FROM   KK_T_MSKM_DTL KK0021_GENE  ")
					.append("               WHERE  KK0021_GENE.MSKM_DTL_NO = KK0021.MSKM_DTL_NO  ")
					.append("               AND    KK0021_GENE.MK_FLG= '0'  ")
					.append("               GROUP BY KK0021_GENE.MSKM_DTL_NO) ")
					.append("     AND KK0011.MSKM_SBT_CD in ('00001', '00002')  ")
					.append("     AND (KK0011.MSKM_NO, KK0011.GENE_ADD_DTM) =  ")
					.append("              (SELECT KK0011_GENE.MSKM_NO, MAX(KK0011_GENE.GENE_ADD_DTM) AS KK0011_MAX  ")
					.append("               FROM   KK_T_MSKM KK0011_GENE  ")
					.append("               WHERE  KK0011_GENE.MSKM_NO = KK0011.MSKM_NO  ")
					.append("               AND    KK0011_GENE.MK_FLG= '0'  ")
					.append("               GROUP BY KK0011_GENE.MSKM_NO)  ")
					.append("     AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
					.append("              (SELECT  KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
					.append("               FROM   KK_T_SVC_KEI KK0081_GENE  ")
					.append("               WHERE  KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
					.append("               AND    KK0081_GENE.RSV_APLY_YMD <= ?  ")
					.append("               AND    KK0081_GENE.RSV_APLY_CD = '2'  ")
					.append("               AND    KK0081_GENE.MK_FLG= '0'  ")
					.append("               GROUP BY KK0081_GENE.SVC_KEI_NO) ");

			//prepareStatementにSQL文をセット
			pstmt = con1.prepareStatement(sql_Buff.toString());

			//ログ出力(SQL文の出力)
			JSYejbLog.outlog(inContext, JSYejbLog.DBACCESS, this.getClass(), sql_Buff);

			// パラメータの設定(ＫＥＹ＿申込書番号を指定)
			CAANJDBCUtil.setParam(pstmt, ++iPCnt, inMsg.getObject(EKK0081B021CBSMsg.KEY_MSKMSHO_NO));
			//入力値が設定されている場合のみ、パラメータを追加（KEY_SYSID）

			if (!inMsg.isNull(EKK0081B021CBSMsg.KEY_SYSID))
			{
				// パラメータの設定(ＫＥＹ＿ＳＹＳＩＤを指定)
				CAANJDBCUtil.setParam(pstmt, ++iPCnt, inMsg.getObject(EKK0081B021CBSMsg.KEY_SYSID));
			}

			// パラメータの設定(運用日付を指定)
			CAANJDBCUtil.setParam(pstmt, ++iPCnt, JKKModelCommon.getOpeDate(inMsg));

			// ResultSetの取得
			rsltQuery = pstmt.executeQuery();

			// 結果設定用リストの設定
			ArrayList<String> alSvcKeiNo = new ArrayList<String>();
			ArrayList<String> alSvcKeiSt = new ArrayList<String>();
			ArrayList<String> alSysid = new ArrayList<String>();

			// 結果をリストに設定
			while(rsltQuery.next())
			{
				alSvcKeiNo.add(rsltQuery.getString(KK0081ETMsg.SVC_KEI_NO));
				alSvcKeiSt.add(rsltQuery.getString(KK0081ETMsg.SVC_KEI_STAT));
				alSysid.add(rsltQuery.getString(KK0081ETMsg.SYSID));
			}

			// リストをMAPに設定する
			HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();
			retMap.put(KK0081ETMsg.SVC_KEI_NO, alSvcKeiNo);
			retMap.put(KK0081ETMsg.SVC_KEI_STAT, alSvcKeiSt);
			retMap.put(KK0081ETMsg.SYSID, alSysid);

			return retMap;
		}
		catch(SQLException se)
		{
			inMsg.set(EKK0081B021CBSMsg.STATUS, StatusCodes.FIND_DB_ERR);
			throw new CAANRuntimeException(se);
		}
		finally
		{
			// 資源の解放
			try
			{
				if(rsltQuery != null)
				{
					rsltQuery.close();
				}
				if(pstmt != null)
				{
					pstmt.close();
				}
				if(con1 != null)
				{
					closeConnection(con1);
				}
			}
			catch(SQLException se)
			{
				inMsg.set(EKK0081B021CBSMsg.STATUS, StatusCodes.FIND_DB_ERR);
				throw new CAANRuntimeException(se);
			}
		}
	}

	/**
	 * ＫＥＹ＿申込書番号に紐付く請求契約番号を一意にして取得します
	 * @param inMsg 入力値の格納されたCBSMsg
	 * @param inContext ディスパッチコンテキスト
	 * @return 実行結果を保持したリスト
	 * 			┗請求契約番号
	 */
	private HashMap<String, ArrayList<String>> getRecordKK0321(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		// コネクション
		Connection con1 = null;
		// プリペアステートメント
		PreparedStatement pstmt = null;
		// リザルトセット
		ResultSet rsltQuery = null;
		
		// パラメータのカウント
		int iPCnt = 0;

		try
		{
			//コネクション取得
			con1 = JSYejbConnection.getConnection(KK0321ETMsg.getTableName());

			// SQL文_基本部1
			StringBuffer sql_Buff = new StringBuffer();
			sql_Buff.append(" SELECT  ")
					.append("     DISTINCT KK0321.SEIKY_KEI_NO  ")
					.append(" FROM  ")
					.append("     KK_T_MSKM_DTL KK0021  ")
					.append("     INNER JOIN KK_T_MSKM KK0011  ")
					.append("     ON KK0011.MSKM_NO = KK0021.MSKM_NO  ")
					.append("     INNER JOIN KK_T_SVC_KEI KK0081  ")
					.append("     ON KK0081.MSKM_DTL_NO = KK0021.MSKM_DTL_NO  ")
					.append("     INNER JOIN KK_T_KAKINS KK0321  ")
					.append("     ON KK0321.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
					.append(" WHERE  ")
					.append("     KK0021.MSKMSHO_NO = ?  ");
			//入力値が設定されている場合のみ、検索条件を追加（KEY_SYSID）
			if (!inMsg.isNull(EKK0081B021CBSMsg.KEY_SYSID))
			{
				sql_Buff.append(" AND  KK0081.SYSID = ? ");
			}
			sql_Buff.append("     AND KK0321.KAKINS_TSTAYMD <= ?  ")
					.append("     AND KK0321.KAKINS_TENDYMD >= ?  ")
					.append("     AND KK0321.MK_FLG = '0'  ")
					.append("     AND (KK0021.MSKM_DTL_NO, KK0021.GENE_ADD_DTM) =  ")
					.append("              (SELECT KK0021_GENE.MSKM_DTL_NO,MAX(KK0021_GENE.GENE_ADD_DTM) AS KK0021_MAX  ")
					.append("               FROM   KK_T_MSKM_DTL KK0021_GENE  ")
					.append("               WHERE  KK0021_GENE.MSKM_DTL_NO = KK0021.MSKM_DTL_NO  ")
					.append("               AND    KK0021_GENE.MK_FLG= '0' ")
					.append("               GROUP BY KK0021_GENE.MSKM_DTL_NO)  ")
					.append("     AND KK0011.MSKM_SBT_CD in ('00001', '00002')  ")
					.append("     AND (KK0011.MSKM_NO, KK0011.GENE_ADD_DTM) =  ")
					.append("              (SELECT  KK0011_GENE.MSKM_NO, MAX(KK0011_GENE.GENE_ADD_DTM) AS KK0011_MAX  ")
					.append("               FROM   KK_T_MSKM KK0011_GENE  ")
					.append("               WHERE  KK0011_GENE.MSKM_NO = KK0011.MSKM_NO  ")
					.append("               AND    KK0011_GENE.MK_FLG= '0' ")
					.append("               GROUP BY KK0011_GENE.MSKM_NO)  ")
					.append("     AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
					.append("              (SELECT  KK0081_GENE.SVC_KEI_NO,MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
					.append("               FROM   KK_T_SVC_KEI KK0081_GENE  ")
					.append("               WHERE  KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
					.append("               AND    KK0081_GENE.RSV_APLY_YMD <= ?  ")
					.append("               AND    KK0081_GENE.RSV_APLY_CD = '2'  ")
					.append("               AND    KK0081_GENE.MK_FLG= '0'  ")
					.append("               GROUP BY KK0081_GENE.SVC_KEI_NO)  ");

			//prepareStatementにSQL文をセット
			pstmt = con1.prepareStatement(sql_Buff.toString());

			//ログ出力(SQL文の出力)
			JSYejbLog.outlog(inContext, JSYejbLog.DBACCESS, this.getClass(), sql_Buff);

			// パラメータの設定(ＫＥＹ＿申込書番号を指定)
			CAANJDBCUtil.setParam(pstmt, ++iPCnt, inMsg.getObject(EKK0081B021CBSMsg.KEY_MSKMSHO_NO));

			if (!inMsg.isNull(EKK0081B021CBSMsg.KEY_SYSID))
			{
				// パラメータの設定(ＫＥＹ＿ＳＹＳＩＤを指定)
				CAANJDBCUtil.setParam(pstmt, ++iPCnt, inMsg.getObject(EKK0081B021CBSMsg.KEY_SYSID));
			}

			// パラメータの設定(運用日付を指定)
			CAANJDBCUtil.setParam(pstmt, ++iPCnt, JKKModelCommon.getOpeDate(inMsg));
			// パラメータの設定(運用日付を指定)
			CAANJDBCUtil.setParam(pstmt, ++iPCnt, JKKModelCommon.getOpeDate(inMsg));
			// パラメータの設定(運用日付を指定)
			CAANJDBCUtil.setParam(pstmt, ++iPCnt, JKKModelCommon.getOpeDate(inMsg));

			// ResultSetの取得
			rsltQuery = pstmt.executeQuery();

			// 結果設定用リストの設定
			ArrayList<String> alSeikyKeiNo = new ArrayList<String>();

			// 結果をリストに設定
			while(rsltQuery.next())
			{
				alSeikyKeiNo.add(rsltQuery.getString(KK0321ETMsg.SEIKY_KEI_NO));
			}

			// リストをMAPに設定する
			HashMap<String, ArrayList<String>> retMap = new HashMap<String, ArrayList<String>>();
			retMap.put(KK0321ETMsg.SEIKY_KEI_NO, alSeikyKeiNo);

			return retMap;
		}
		catch(SQLException se)
		{
			inMsg.set(EKK0081B021CBSMsg.STATUS, StatusCodes.FIND_DB_ERR);
			throw new CAANRuntimeException(se);
		}
		finally
		{
			// 資源の解放
			try
			{
				if(rsltQuery != null)
				{
					rsltQuery.close();
				}
				if(pstmt != null)
				{
					pstmt.close();
				}
				if(con1 != null)
				{
					closeConnection(con1);
				}
			}
			catch(SQLException se)
			{
				inMsg.set(EKK0081B021CBSMsg.STATUS, StatusCodes.FIND_DB_ERR);
				throw new CAANRuntimeException(se);
			}
		}
	}

	/**
	 * サービス契約ステータスの設定値を判定します。
	 * @param inMsg 入力値の格納されたCBSMsg
	 * @param svcKeiStatList サービス契約ステータスのリスト
	 * @return 受付済、キャンセル済以外が含まれていた場合false、
	 *          すべてキャンセル済だった場合false、
	 *          それ以外の場合true。
	 */
	private boolean isSvcKeiStatus(ArrayList<String> svcKeiStatList)
	{
		// キャンセル済フラグ
		boolean cancelFlg = false;

		// 明細内の全てのステータスをチェック
		for (int i = 0; i < svcKeiStatList.size(); i++)
		{
			// ステータスの取得
			String strStat = svcKeiStatList.get(i);

			// 「受付済」、「キャンセル済」以外が含まれていた場合はfalseを返却する
			if (!VALID_STATUS_MAP.containsKey(strStat))
			{
				return false;
			}

			// 「キャンセル済」以外だった場合は、フラグをtrueにする
			if (!SVC_KEI_STAT_CANCEL.equals(strStat))
			{
				cancelFlg = true;
			}
		}

		// フラグ値をそのまま返却する
		return cancelFlg;
	}

	/**
	 * 請求契約番号の設定値を判定します。
	 * @param inMsg 入力値の格納されたCBSMsg
	 * @param seikyKeiNoList 請求契約番号のリスト
	 * @return リスト内に請求契約番号が複数存在する場合はfalse。それ以外の場合はtrue。
	 */
	private boolean isSeikyKeiNo(ArrayList<String> seikyKeiNoList)
	{
		// リストが2件以上の場合はfalseを返却する
		if (seikyKeiNoList.size() > 1)
		{
			return false;
		}

		// それ以外の場合はtrueを返却する
		return true;
	}

	/**
	 * SYSIDの設定値を判定します。
	 * @param inMsg 入力値の格納されたCBSMsg
	 * @param sysidList SYSIDのリスト
	 * @return リスト内のSYSIDがすべて一致する場合はtrue。一致しない場合はfalse。
	 */
	private boolean isSysid(ArrayList<String> sysidList)
	{
		// 基準SYSIDの取得
		String strSysidBase = sysidList.get(0);

		// 明細内の全てのSYSIDをチェック（2件目以降）
		for (int i = 1; i < sysidList.size(); i++)
		{
			// 基準SYSIDと異なる場合はfalseを返却する
			if (!strSysidBase.equals(sysidList.get(i)))
			{
				return false;
			}
		}

		// SYSIDがすべて一致した場合はtrueを返却する
		return true;
	}

	/**
	 * 取得結果の明細に照査前結果コードを設定する。
	 * @param inMsg 入力値の格納されたCBSMsg
	 * @param rsltCd 照査前結果コード
	 */
	private void setMsg(CAANMsg inMsg, String rsltCd)
	{
		// 明細1件目に照査前結果コードを設定する
		CAANMsg[] outMsg1 = new CAANMsg[1];
		outMsg1[0] = new CAANMsg(EKK0081B021CBSMsg1List.class.getName());
		outMsg1[0].set(EKK0081B021CBSMsg1List.SHOSA_BF_RSLT_CD, rsltCd);

		// inMsg(CBSMsg)に明細をセット
		inMsg.set("EKK0081B021CBSMsg1List", outMsg1);
	}
}
