/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKBatTekkyoKanrenIdoRsvCl
*	ソースファイル名：JKKBatTekkyoKanrenIdoRsvCl.java
*	作成者			：富士通
*	日付			：2014年02月28日
*＜機能概要＞
*	撤去した機器に関連するデータの異動予約を取り消す部品
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v6.00.00	2014/02/28	FJ)小野		新規作成
**********************************************************************/
package eo.business.common;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import eo.business.util.table.JBSbatKK_T_IDO_RSV;
import eo.business.util.table.JBSbatKK_T_KKTK_SVC_KEI;
import eo.business.util.table.JBSbatKK_T_OP_SVC_KEI;
import eo.common.constant.JPCBatchMessageConstant;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.log.JBSbatLogPrintControl;
import eo.framework.log.JBSbatLogUtil;
import eo.framework.util.JBSbatStringUtil;

/**
* 撤去した機器に関連するデータの異動予約を取り消す部品です。 <p>
*<BR>
* @author 富士通
*/
public class JKKBatTekkyoKanrenIdoRsvCl
{
	/** 機器提供サービス契約番号を指定した異動予約検索番号 */
	private static final String IDO_RSV_SELECT_FOR_KKTK_SVC_KEI = "KK_SELECT_067";
	
	/** サービス契約内訳番号を指定した異動予約検索番号 */
	private static final String IDO_RSV_SELECT_FOR_SVC_KEI_UCWK = "KK_SELECT_068";
	
	/**オプションサービス契約番号を指定した異動予約検索番号 */
	private static final String IDO_RSV_SELECT_FOR_OP_SVC_KEI = "KK_SELECT_069";

	private static final HashMap<String, JBSbatSQLAccess> DB_ACCESS_POOL = new HashMap<String, JBSbatSQLAccess>();
	
	/**
	 * DBコネクションのクローズ処理
	 * 
	 * @throws Exception
	 */
	public static void close() throws Exception
	{
		Iterator<String> it = DB_ACCESS_POOL.keySet().iterator();
		while (it.hasNext())
		{
			String key = it.next();
			JBSbatSQLAccess dbAccess = DB_ACCESS_POOL.get(key);
			if (dbAccess != null)
			{
				dbAccess.close();
			}
			DB_ACCESS_POOL.put(key, null);
		}
	}
	
	/**
	 * DBアクセスクラスの生成
	 * @param commonItem
	 * @param table_name
	 * @return
	 * @throws Exception
	 */
	private JBSbatSQLAccess getDBAccess(JBSbatCommonItem commonItem, String table_name) throws Exception
	{
		if (DB_ACCESS_POOL.get(table_name) == null)
		{
			DB_ACCESS_POOL.put(table_name, new JBSbatSQLAccess(commonItem, table_name));
		}
		return DB_ACCESS_POOL.get(table_name);
	}
	
	/**
	 * 指定されたサービス契約のサブタイプの登録を行います。<br>
	 * 
	 * @param pCommonItem バッチ共通電文
	 * @param pKktkSvcKeiNo 機器提供サービス契約番号
	 * @throws Exception
	 */
	protected void updateKK1681(JBSbatCommonItem pCommonItem, String pKktkSvcKeiNo) throws Exception 
	{
		
		// ==========  機器提供サービス契約番号に紐付く予約取消処理 ===========
		
		// 機器提供サービス契約番号で異動予約を検索。結果があったら取消処理
		List<String> idoRsvNoList = getIdoRsvNo(getDBAccess(pCommonItem, JBSbatKK_T_IDO_RSV.TABLE_NAME), pCommonItem, IDO_RSV_SELECT_FOR_KKTK_SVC_KEI, pKktkSvcKeiNo);
		updateIdoRsvCancel(getDBAccess(pCommonItem, JBSbatKK_T_IDO_RSV.TABLE_NAME), idoRsvNoList, pCommonItem.getOpeDate());
		// ================================================================
		
		// 機器提供サービス契約番号で機器提供サービス契約を検索し、サービス契約内訳番号を取得
		String svcKeiUcwkNo = getSvcKeiUcwkFromKktkSvcKei(getDBAccess(pCommonItem, JBSbatKK_T_KKTK_SVC_KEI.TABLE_NAME), pCommonItem, pKktkSvcKeiNo);
		
		// サービス契約内訳番号が取得できた場合
		if (!"".equals(svcKeiUcwkNo))
		{
			// ==========  サービス契約内訳番号に紐付く予約取消処理 ===========
			// サービス契約内訳番号で異動予約を検索。結果があったら取消処理
			idoRsvNoList = getIdoRsvNo(getDBAccess(pCommonItem, JBSbatKK_T_IDO_RSV.TABLE_NAME), pCommonItem, IDO_RSV_SELECT_FOR_SVC_KEI_UCWK, svcKeiUcwkNo);
			updateIdoRsvCancel(getDBAccess(pCommonItem, JBSbatKK_T_IDO_RSV.TABLE_NAME), idoRsvNoList, pCommonItem.getOpeDate());
			// ================================================================
			
			// ==========  オプションサービス契約番号に紐付く予約取消処理 ===========
			// サービス契約内訳番号でオプションサービス契約を検索し、オプションサービス契約番号を取得（複数件取得。無い場合もあり）
			List<String> opSvcKeiNoList = getOpSvcKeiBySvcKeiUcwkNo(getDBAccess(pCommonItem, JBSbatKK_T_OP_SVC_KEI.TABLE_NAME), pCommonItem, svcKeiUcwkNo);
			// オプションサービス契約番号で異動予約を検索。結果があったら取消処理
			for(String opSvcKeiNo : opSvcKeiNoList)
			{
				idoRsvNoList = getIdoRsvNo(getDBAccess(pCommonItem, JBSbatKK_T_IDO_RSV.TABLE_NAME), pCommonItem, IDO_RSV_SELECT_FOR_OP_SVC_KEI, opSvcKeiNo);
				updateIdoRsvCancel(getDBAccess(pCommonItem, JBSbatKK_T_IDO_RSV.TABLE_NAME), idoRsvNoList, pCommonItem.getOpeDate());
			}
			// ================================================================
		}
	}
	
	/**
	 * サービス契約内訳番号取得処理です。
	 * @param sqlAccess
	 * @param commonItem
	 * @param kktkSvcKeiNo
	 * @return サービス契約内訳番号
	 */
	private String getSvcKeiUcwkFromKktkSvcKei(JBSbatSQLAccess sqlAccess, JBSbatCommonItem commonItem, String kktkSvcKeiNo) throws Exception
	{
		
		// 機器提供サービス契約番号
		if ("".equals(kktkSvcKeiNo))
		{
			commonItem.getLogPrint().printBusinessErrorLog("SY00001W",new String[]{"機器提供サービス契約番号"});
			throw new Exception("機器提供サービス契約番号が空白です。");
		}
		
		// 返却用
		String result = "";
		
		// 検索キーを設定する
		JBSbatCommonDBInterface map = new JBSbatCommonDBInterface();
		map.setValue(kktkSvcKeiNo);		// 機器提供サービス契約番号
		map.setValue(commonItem.getOpeDate());		// 運用年月日
		
		try
		{
			// 機器提供サービス契約番号、運用年月日を基にレコードを取得する（１機器提供サービス契約のみ取得される想定）
			sqlAccess.selectBySqlDefine(map, "KK_SELECT_182");
			
			// 検索結果取得
			JBSbatCommonDBInterface outMap = sqlAccess.selectNext(); 
			
			// 検索結果あり
			if(null != outMap)
			{
				// サービス契約内訳番号
				result = JBSbatStringUtil.Rtrim(outMap.getString(JBSbatKK_T_KKTK_SVC_KEI.SVC_KEI_UCWK_NO));
			}
		}
		catch (SQLException e)
		{
			throw new Exception( "サービス契約内訳番号取得処理で例外が発生しました。");
		}
		
		return result;
	}
	
	/**
	 * オプションサービス契約番号取得処理です。
	 * サービス契約内訳番号に紐付くオプションサービス契約番号をオプションサービス契約から取得します。
	 * @param sqlAccess
	 * @param commonItem
	 * @param svcKeiUcwkNo
	 * @return オプションサービス契約番号（List<String>） 
	 */
	private List<String> getOpSvcKeiBySvcKeiUcwkNo(JBSbatSQLAccess sqlAccess, JBSbatCommonItem commonItem, String svcKeiUcwkNo) throws Exception
	{
		
		// サービス契約内訳番号
		if ("".equals(svcKeiUcwkNo))
		{
			commonItem.getLogPrint().printBusinessErrorLog("SY00001W",new String[]{"サービス契約内訳番号"});
			throw new Exception("サービス契約内訳番号が空白です。");
		}
		
		// オプションサービス契約番号取得結果
		List<String> resultList = new ArrayList<String>();
		
		// 検索キーを設定する
		JBSbatCommonDBInterface map = new JBSbatCommonDBInterface();
		map.setValue(svcKeiUcwkNo);		// サービス契約内訳番号
		map.setValue(commonItem.getOpeDate());		// 運用年月日
		
		try
		{
			// サービス契約内訳番号、運用年月日を基にレコードを取得する
			sqlAccess.selectBySqlDefine(map, "KK_SELECT_106");
			
			// 検索結果取得
			JBSbatCommonDBInterface outMap = sqlAccess.selectNext(); 
			
			// 検索結果あり
			while(null != outMap)
			{
				// オプションサービス契約番号
				resultList.add(JBSbatStringUtil.Rtrim(outMap.getString(JBSbatKK_T_OP_SVC_KEI.OP_SVC_KEI_NO)));
				outMap = sqlAccess.selectNext();
			}
		}
		catch (SQLException e)
		{
			throw new Exception( "オプションサービス契約番号取得処理で例外が発生しました。");
		}
		
		return resultList;
	}
	
	/**
	 * 異動予約番号取得処理です。
	 * 引数で指定した検索番号と検索条件で異動予約を検索します
	 * @param sqlAccess
	 * @param commonItem
	 * @param selectNo
	 * @param searchCondVal
	 * @return オプションサービス契約番号（List<String>） 
	 */
	private List<String> getIdoRsvNo(JBSbatSQLAccess sqlAccess, JBSbatCommonItem commonItem, String selectNo, String searchCondVal) throws Exception
	{
		
		List<String> resultList = new ArrayList<String>();
		// ログ出力用
		JBSbatLogPrintControl logPrint = commonItem.getLogPrint();
		
		// 検索条件が空の場合は処理しない
		if ("".equals(searchCondVal))
		{
			logPrint.printDebugLog("検索条件が空のため検索なし");
			return resultList;
		}
		
		// 検索キーを設定する
		JBSbatCommonDBInterface map = new JBSbatCommonDBInterface();
		map.setValue(searchCondVal);		// 指定した検索キー（機器提供サービス契約番号 or サービス契約内訳番号 or オプションサービス契約番号）
		
		try
		{
			// 引数で指定された検索キーを基に、指定された検索番号で検索し、レコードを取得する
			sqlAccess.selectBySqlDefine(map, selectNo);
			
			// 検索結果取得
			JBSbatCommonDBInterface outMap = sqlAccess.selectNext(); 
			
			// 検索結果あり
			while(null != outMap)
			{
				// 異動予約番号
				resultList.add(JBSbatStringUtil.Rtrim(outMap.getString(JBSbatKK_T_IDO_RSV.IDO_RSV_NO)));
				
				if(logPrint.chkLogLevel(JBSbatLogUtil.MODE_DEBUG))
				{
					logPrint.printDebugLog("異動予約検索結果");
					logPrint.printDebugLog("異動予約番号："  + JBSbatStringUtil.Rtrim(outMap.getString(JBSbatKK_T_IDO_RSV.IDO_RSV_NO)));
					logPrint.printDebugLog("異動区分：" + JBSbatStringUtil.Rtrim(outMap.getString(JBSbatKK_T_IDO_RSV.IDO_DIV)));
					logPrint.printDebugLog("異動予約詳細コード:" +JBSbatStringUtil.Rtrim(outMap.getString(JBSbatKK_T_IDO_RSV.IDO_RSV_DTL_CD)));
				}
				
				outMap = sqlAccess.selectNext();
			}
		}
		catch (SQLException e)
		{
			throw new Exception( "異動予約番号取得処理で例外が発生しました。");
		}
		
		return resultList;
	}
	
	/**
	 * 異動予約の更新処理をします。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.排他制御をします。<br>
	 *
	 * 2.更新処理を実行します。<br>
	 *
	 * </pre>
	 * <p>
	 * @param idoRsvNo 異動予約番号
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void updateIdoRsvCancel(JBSbatSQLAccess sqlAccess, List<String> idoRsvNoList, String idoRsvClYmd) throws Exception
	{
		
		for(String idoRsvNo : idoRsvNoList)
		{
			JBSbatCommonDBInterface where_map = new JBSbatCommonDBInterface();
			where_map.setValue(JBSbatKK_T_IDO_RSV.IDO_RSV_NO, idoRsvNo);
			
			// 排他検索を行います
			JBSbatCommonDBInterface map = sqlAccess.selectByPrimaryKeysForUpdateWait(where_map);
			
			// 排他検索結果がある場合
			if (map != null)
			{
				JBSbatCommonDBInterface setMap = new JBSbatCommonDBInterface();
				setMap.setValue("IDO_RSV_CL_YMD", idoRsvClYmd);
				setMap.setValue("IDO_RSV_STAT_CD", "02");
				
				// 条件のマップを作成します
				JBSbatCommonDBInterface whereMap = new JBSbatCommonDBInterface();
				whereMap.setValue("IDO_RSV_NO", idoRsvNo);
				
				sqlAccess.updateByPrimaryKeys(whereMap, setMap);
			}
			// 排他エラーの場合
			else
			{
				// 該当レコード無しのエラー
				throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0210CE, 
						new String[]{"異動予約", "異動予約番号" + idoRsvNo});
			}
		}
	}
	
}
