/*******************************************************************************
 *	All Rights reserved,Copyright (c) K-Opticom
 ********************************************************************************
 *＜プログラム内容＞
 *	システム名		：eo顧客基幹システム
 *	モジュール名	：JEKK0021C130TPMA
 *	ソースファイル名：JEKK0021C130TPMA.java
 *	作成者			：富士通
 *	日付			：2017年07月11日
 *＜機能概要＞
 *	申込書イメージ付替登録用独自処理部品です。
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	ｖ33.00.00	2017/07/11	FJ)鈴木		【ANK-3097-00-00】申込書イメージ付け替え機能の実装＜随時削減策＞
 *
 ********************************************************************************/

package eo.ejb.cbs.mainproc;

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 java.util.List;

import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
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.AgentDispatchContext;
import com.fujitsu.futurity.model.ejb.common.fw.TemplateMainHandler;

import eo.common.constant.JPCModelConstant;
import eo.common.util.JKKStringUtil;
import eo.ejb.cbm.entity.KK0021ETMsg;
import eo.ejb.cbm.entity.KK0081ETMsg;
import eo.ejb.cbs.cbsmsg.EKK0021C130CBSMsg;
import eo.ejb.common.db.JKKejbExclusiveProcKK2111;
import eo.ejb.common.db.JKKejbKK0021SecProc;
import eo.ejb.common.entity.JKKejbKK0021KRCK;
import eo.ejb.common.entity.JKKejbKK0081KRCK;

/**
 * <p>
 * 申込書イメージ付替登録処理部品クラスです。
 * </p>
 * @author 富士通
 */
public class JEKK0021C130TPMA implements TemplateMainHandler
{
	/** マップキー：世代登録年月日時分秒 */
	private static final String MAP_KEY_GENE_ADD_DTM = "MAP_KEY_GENE_ADD_DTM";
	/** マップキー：申込明細番号 */
	private static final String MAP_KEY_MSKM_DTL_NO = "MAP_KEY_MSKM_DTL_NO";
	/** マップキー：申込書番号 */
	private static final String MAP_KEY_MSKMSHO_NO = "MAP_KEY_MSKMSHO_NO";
	/** マップキー：申込書明細番号 */
	private static final String MAP_KEY_MSKMSHO_DTL_NO = "MAP_KEY_MSKMSHO_DTL_NO";
	/** マップキー：申込書明細番号 */
	private static final String MAP_KEY_MSKM_FORM_CD = "MAP_KEY_MSKM_FORM_CD";
	
	/** エラーフラグ */
	private static final String ERR_EA_FLG = "EA";
	/** エラーフラグ */
	private static final String ERR_EB_FLG = "EB";

	/** エラーフラグ設定項目名 */
	private static final String MOTO_UPD_DTM_BF_ERR = "moto_upd_dtm_bf_err";
	/** エラーフラグ設定項目名 */
	private static final String SAKI_UPD_DTM_BF_ERR = "saki_upd_dtm_bf_err";
	
	/** 無効フラグ（有効） */
	private static final String MK_FLG_YUKO = "0";

	/**
	 * <p>
	 * 申込書イメージ付替登録処理部品の呼び出しを行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	*/
	public void execDBAccess(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		JKKejbKK0081KRCK kk0081 = new JKKejbKK0081KRCK();
		
		JKKejbKK0021KRCK kk0021 = new JKKejbKK0021KRCK();
	
		// サービス契約番号（付替先）を設定
		String sakiSvcKeiNo = inCBSMsg.getString("saki_svc_kei_no");
		// 申込書番号(付替先)を設定
		String sakiMskmshoNo = inCBSMsg.getString("saki_mskmsho_no");
		// 更新日付(付替先)を設定
		String sakiUpdDtmBf = inCBSMsg.getString("saki_upd_dtm_bf");
		// サービス契約番号（付替元）を設定
		String motoSvcKeiNo = inCBSMsg.getString("moto_svc_kei_no");
		// 申込書番号(付替元)を設定
		String motoMskmshoNo = inCBSMsg.getString("moto_mskmsho_no");
		// 更新日付(付替元)を設定
		String motoUpdDtmBf = inCBSMsg.getString("moto_upd_dtm_bf");
		
		//サービス契約の存在チェック　サービス契約番号（付替元）
		if (!kk0081.isExistsNonGene(motoSvcKeiNo))
		{
			inCBSMsg.set(JCMConstants.STATUS_INT_KEY, StatusCodes.RELATION_ERR);
			inCBSMsg.set(EKK0021C130CBSMsg.MOTO_SVC_KEI_NO_ERR, "EA");
			return;
		}
		
		//サービス契約の存在チェック　サービス契約番号（付替先）
		if (!kk0081.isExistsNonGene(sakiSvcKeiNo))
		{
			inCBSMsg.set(JCMConstants.STATUS_INT_KEY, StatusCodes.RELATION_ERR);
			inCBSMsg.set(EKK0021C130CBSMsg.SAKI_SVC_KEI_NO_ERR, "EA");
			return;
		}
		
		// 申込書番号存在チェック（付替元）
		if (kk0021.chkMskshoNo(inCBSMsg, inContext, motoMskmshoNo))
		{
			inCBSMsg.set(JCMConstants.STATUS_INT_KEY, StatusCodes.RELATION_ERR);
			inCBSMsg.set(EKK0021C130CBSMsg.MOTO_MSKMSHO_NO_ERR, "EA");
			return;
		}
		
		// 申込書番号存在チェック（付替先）
		if (kk0021.chkMskshoNo(inCBSMsg, inContext, sakiMskmshoNo))
		{
			inCBSMsg.set(JCMConstants.STATUS_INT_KEY, StatusCodes.RELATION_ERR);
			inCBSMsg.set(EKK0021C130CBSMsg.SAKI_MSKMSHO_NO_ERR, "EA");
			return;
		}
		
		//排他制御　サービス契約番号（付替元）
		if (execExclusiveProc(inCBSMsg, inContext, motoSvcKeiNo, motoUpdDtmBf, "1"))
		{
			//処理終了
			return ;
		}
		
		//排他制御　サービス契約番号（付替先）
		if (execExclusiveProc(inCBSMsg, inContext, sakiSvcKeiNo, sakiUpdDtmBf, "2"))
		{
			//処理終了
			return ;
		}

		//元の情報を取得
		List<HashMap<String, String>> motoMskmDtlLst = getMskmDtl(inCBSMsg, motoSvcKeiNo, motoMskmshoNo);

		//先の情報を取得
		List<HashMap<String, String>> sakiMskmDtlLst = getMskmDtl(inCBSMsg, sakiSvcKeiNo, sakiMskmshoNo);

		ArrayList<String> hashLst = new ArrayList<String>(); 

		//元申込書明細番号
		String motoMskmshoDtlNo = "";
		//元申込形態コード
		String motoMskmFormCd = "";
		
		//元の申込書明細番号・申込明細番号・申込書番号重複チェック
		for (HashMap<String, String> mskmDtlObj : motoMskmDtlLst)
		{
			// 申込書明細番号 下記の処理で使用するため保持
			motoMskmshoDtlNo = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKMSHO_DTL_NO));
			// 申込形態コード 下記の処理で使用するため保持
			motoMskmFormCd = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKM_FORM_CD));
			// 申込明細番号
			String motoMskmDtlNolst = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKM_DTL_NO));
			// 申込書番号
			String motoMskmshoNolst = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKMSHO_NO));
			
			// 読み込んだ申込書明細番号・申込明細番号・申込書番号を控える
			if (hashLst.isEmpty()) 
			{
				// 読み込んだ申込書明細番号・申込明細番号・申込書番号を控える
				hashLst.add((String)motoMskmshoDtlNo + motoMskmDtlNolst + motoMskmshoNolst);
			}
			
			for (int idx = 0; idx < hashLst.size(); idx++)
			{
				//申込書明細番号・申込明細番号・申込書番号を結合する
				String hashWork = motoMskmshoDtlNo + motoMskmDtlNolst + motoMskmshoNolst;
				//重複チェック
				if (!hashWork.equals((String)hashLst.get(0)))
				{
					//相違があった場合、エラー
					inCBSMsg.set(EKK0021C130CBSMsg.MOTO_MSKMSHO_NO_ERR, ERR_EB_FLG);
					inCBSMsg.set(JCMConstants.STATUS_INT_KEY, StatusCodes.RELATION_ERR);
					return;
				}
			}
		}
		
		hashLst = new ArrayList<String>(); 
		
		//先申込書明細番号
		String sakiMskmshoDtlNo = "";
		//先申込形態コード
		String sakiMskmFormCd = "";

		//先の申込書明細番号・申込明細番号・申込書番号重複チェック
		for (HashMap<String, String> mskmDtlObj : sakiMskmDtlLst)
		{
			// 申込書明細番号 下記の処理で使用するため保持
			sakiMskmshoDtlNo = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKMSHO_DTL_NO));
			// 申込形態コード 下記の処理で使用するため保持
			sakiMskmFormCd = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKM_FORM_CD));
			// 申込明細番号
			String sakiMskmDtlNolst = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKM_DTL_NO));
			// 申込書番号
			String sakiMskmshoNolst = JKKStringUtil.nullToBlank(mskmDtlObj.get(MAP_KEY_MSKMSHO_NO));
			
			// 読み込んだ申込書明細番号・申込明細番号・申込書番号を控える
			if (hashLst.isEmpty()) 
			{
				// 読み込んだ申込書明細番号・申込明細番号・申込書番号を控える
				hashLst.add((String)sakiMskmshoDtlNo + sakiMskmDtlNolst + sakiMskmshoNolst);
			}
			
			for (int idx = 0; idx < hashLst.size(); idx++)
			{
				//申込書明細番号・申込明細番号・申込書番号を結合する
				String hashWork = sakiMskmshoDtlNo + sakiMskmDtlNolst + sakiMskmshoNolst;
				//重複チェック
				if (!hashWork.equals((String)hashLst.get(0)))
				{
					//相違があった場合、エラー
					inCBSMsg.set(EKK0021C130CBSMsg.SAKI_MSKMSHO_NO_ERR, ERR_EB_FLG);
					inCBSMsg.set(JCMConstants.STATUS_INT_KEY, StatusCodes.RELATION_ERR);
					return;
				}
			}
		}

		////////////// 先→元　更新処理　実行開始
		for (HashMap<String, String> mskmDtlObj : sakiMskmDtlLst)
		{
			// 申込明細番号
			String mskmDtlno = mskmDtlObj.get(MAP_KEY_MSKM_DTL_NO);
			// 世代登録年月日時分秒 
			String geneAddDtm = mskmDtlObj.get(MAP_KEY_GENE_ADD_DTM);
			// 申込書番号
			String mskmshoNo = motoMskmshoNo;
			// 申込書明細番号
			String mskmshoDtlNo = motoMskmshoDtlNo;
			// 申込形態コード
			String mskmFormCd = motoMskmFormCd;

			// 申込明細スキーマの副次処理部品
			JKKejbKK0021SecProc kk0021SecProc = new JKKejbKK0021SecProc();

			//更新処理を行う
			kk0021SecProc.updateKK0021C130(inCBSMsg, mskmDtlno, geneAddDtm, mskmshoNo, mskmshoDtlNo, mskmFormCd);
		}
		//最終更新日付の設定
		inCBSMsg.set(EKK0021C130CBSMsg.SAKI_UPD_DTM,  inCBSMsg.getString(EKK0021C130CBSMsg.OPERATEDATETIME));
		////////////// 先→元　更新処理　実行終了

		////////////// 元→先　更新処理　実行開始
		for (HashMap<String, String> mskmDtlObj : motoMskmDtlLst)
		{
			// 申込明細番号
			String mskmDtlno = mskmDtlObj.get(MAP_KEY_MSKM_DTL_NO);
			// 世代登録年月日時分秒 
			String geneAddDtm = mskmDtlObj.get(MAP_KEY_GENE_ADD_DTM);
			// 申込書番号
			String mskmshoNo = sakiMskmshoNo;
			// 申込書明細番号
			String mskmshoDtlNo = sakiMskmshoDtlNo;
			// 申込形態コード
			String mskmFormCd = sakiMskmFormCd;

			// 申込明細スキーマの副次処理部品
			JKKejbKK0021SecProc kk0021SecProc = new JKKejbKK0021SecProc();

			//更新処理を行う
			kk0021SecProc.updateKK0021C130(inCBSMsg, mskmDtlno, geneAddDtm, mskmshoNo, mskmshoDtlNo, mskmFormCd);

		}
		//最終更新日付の設定
		inCBSMsg.set(EKK0021C130CBSMsg.MOTO_UPD_DTM,  inCBSMsg.getString(EKK0021C130CBSMsg.OPERATEDATETIME));
		inCBSMsg.set(EKK0021C130CBSMsg.UPD_OPEACNT, inCBSMsg.getString(EKK0021C130CBSMsg.OPERATORID));
		////////////// 元→先　更新処理　実行終了
	}
	
	/**
	 * 申込明細を取得します。
	 * 
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param svcKeiNo
	 * @param mskmshoNo
	 * @return List
	 */
	private List<HashMap<String, String>> getMskmDtl(CAANMsg inCBSMsg, String svcKeiNo, String mskmshoNo)
	{
		// コネクション
		Connection con = null;
		// プリペアステートメント
		PreparedStatement pstmt = null;
		// リザルトセット
		ResultSet rsltQuery = null;

		// パラメータ設定リスト
		List<Object> replaceListCnt = new ArrayList<Object>();

		try
		{
			StringBuffer sql_Buff = new StringBuffer();
			sql_Buff.append(" SELECT /*EKK0021C130*/ ")
					.append("     KK0021.MSKM_DTL_NO, ")
					.append("     KK0021.GENE_ADD_DTM, ")
					.append("     KK0021.MSKMSHO_NO, ")
					.append("     KK0021.MSKMSHO_DTL_NO, ")
					.append("     KK0021.MSKM_FORM_CD ")
					.append(" FROM ")
					.append("     KK_T_MSKM_DTL KK0021 ")
					.append(" WHERE ")
					.append("     KK0021.MSKMSHO_NO = ? ")
					.append(" AND KK0021.MK_FLG = '0' ")
					.append(" AND EXISTS (SELECT ")
					.append(" 				1 ")
					.append(" 			FROM ")
					.append(" 				KK_T_SVC_KEI KK0081 ")
					.append(" 			WHERE  KK0081.MSKM_DTL_NO = KK0021.MSKM_DTL_NO ")
					.append(" 			AND KK0081.SVC_KEI_NO = ? ")
					.append(" 			AND KK0081.MK_FLG = '0' ")
					.append(" 			) ")
					.append("ORDER BY ")
					.append("	KK0021.GENE_ADD_DTM DESC");

			//inmsgからサービス契約番号（先・元）と申込書番号（先・元）取得
			replaceListCnt.add(mskmshoNo);
			replaceListCnt.add(svcKeiNo);

			//コネクション取得
			con = JSYejbConnection.getConnection(KK0021ETMsg.getTableName());

			//prepareStatementにSQL文をセット
			pstmt = con.prepareStatement(sql_Buff.toString());

			// PreparedStatementの指定されたパラメータカラムに 指定された値を設定
			for (int idx = 0; idx < replaceListCnt.size(); idx++)
			{
				CAANJDBCUtil.setParam(pstmt, idx + 1, replaceListCnt.get(idx));
			}

			// ResultSetの取得
			rsltQuery = pstmt.executeQuery();

			List<HashMap<String, String>> retList = new ArrayList<HashMap<String, String>>();

			while (rsltQuery.next())
			{
				HashMap<String, String> map = new HashMap<String, String>();
				map.put(MAP_KEY_GENE_ADD_DTM, rsltQuery.getString("GENE_ADD_DTM"));
				map.put(MAP_KEY_MSKM_DTL_NO, rsltQuery.getString("MSKM_DTL_NO"));
				map.put(MAP_KEY_MSKMSHO_NO, rsltQuery.getString("MSKMSHO_NO"));
				map.put(MAP_KEY_MSKMSHO_DTL_NO, rsltQuery.getString("MSKMSHO_DTL_NO"));
				map.put(MAP_KEY_MSKM_FORM_CD, rsltQuery.getString("MSKM_FORM_CD"));
				retList.add(map);
			}
			return retList;

		}
		catch(SQLException e) 
		{
			inCBSMsg.set(EKK0021C130CBSMsg.STATUS, StatusCodes.FIND_DB_ERR);
			throw new CAANRuntimeException(e);
		} 
		finally 
		{
			// 資源の解放
			try
			{
				if(rsltQuery != null)
				{
					rsltQuery.close();
				}
				if(pstmt != null)
				{
					pstmt.close();
				}
			}
			catch(SQLException e)
			{
				inCBSMsg.set(EKK0021C130CBSMsg.STATUS, StatusCodes.FIND_DB_ERR);
				throw new CAANRuntimeException(e);
			}
		}
	}

	
	/**
	 * <p>
	 * サービス契約のスキーマのロック、タイムスタンプチェック、およびタイムスタンプ更新を行います。
	 * サービス契約のスキーマのロックを行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param svcKeiNo
	 * @param updDtmBf
	 * @param syoriKbn "1":サービス契約番号（付替元）"2":サービス契約番号（付替先）
	 * @return boolean
	 */
	public boolean execExclusiveProc(CAANMsg inCBSMsg, AgentDispatchContext inContext, String svcKeiNo, String updDtmBf, String syoriKbn)
	{
		// 必要な項目を保持したETMsgを作成する
		CAANMsg inETMsg = new CAANMsg(KK0081ETMsg.class.getName());

		// プライマリキーを設定
		inETMsg.set(KK0081ETMsg.SVC_KEI_NO, svcKeiNo);

		// 更新情報の設定
		inETMsg.set(KK0081ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		inETMsg.set(KK0081ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));

		// ログの出力
		outLogTs(inETMsg, updDtmBf);

		// サービス契約排他制御排他処理（サービス契約番号）を呼び出し、処理結果がfalseの場合は関連制約エラーとする
		if (!new JKKejbExclusiveProcKK2111().isExProcSvcKeiNo(inETMsg, svcKeiNo, updDtmBf, JPCModelConstant.FUNC_CD_1))
		{
			//サービス契約番号（付替元）
			if ("1".equals(syoriKbn)) 
			{
				inCBSMsg.set(MOTO_UPD_DTM_BF_ERR, ERR_EA_FLG);
			}
			//サービス契約番号（付替先）
			else
			{
				inCBSMsg.set(SAKI_UPD_DTM_BF_ERR, ERR_EA_FLG);
			}
			inCBSMsg.set(JCMConstants.STATUS_INT_KEY, StatusCodes.RELATION_ERR);
			return true;
		}
		return false;
	}
	
	/**
	 * <p>
	 * ログの出力を行います（タイムスタンプチェック処理）。
	 * </p>
	 * @param inETMsg 処理対象のメッセージキャリア（ET）
	 * @param updDtmBf 更新年月日時分秒（更新前）
	 */
	private void outLogTs(CAANMsg inETMsg, String updDtmBf)
	{
		// プライマリキーの出力
		JSYejbLog.println(JSYejbLog.DEBUG, getClass(), "JEKK0021C130TPMA.svc_kei_no=" + inETMsg.getString(KK0081ETMsg.SVC_KEI_NO));

		// 更新年月日時分秒（更新前）の出力
		JSYejbLog.println(JSYejbLog.DEBUG, getClass(), "JEKK0021C130TPMA.upd_dtm_bf=" + updDtmBf);
	}
}
