/*********************************************************************
*   All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JEKK2811C260ETDA
*   ソースファイル名：JEKK2811C260ETDA.java
*   作成者          ：富士通
*   日付            ：2013年11月19日
*＜機能概要＞
*   機器オプションサービス契約料金プラン変更確定処理部品クラス
*＜修正履歴＞
*   バージョン  修正日      修正者      修正内容
*   v7.00.00    2013/11/19  富士通      新規作成
*   v8.00.00    2014/04/22  FJ)小島     OM-2014-0001444
*   v8.00.01    2014/05/01  FJ)小島     OM-2014-0001444
*   v9.00.01    2014/06/23  FJ)中野     OM-2014-0001904
**********************************************************************/

package eo.ejb.common.db;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.ejb.cbm.entity.KK1681ETMsg;
import eo.ejb.cbm.entity.KK1681LE;
import eo.ejb.cbm.entity.KK2811ETMsg;
import eo.ejb.cbs.cbsmsg.EKK2811C260CBSMsg;
import eo.ejb.cbs.mainproc.JKKejbIdoRsvUtil;
import eo.ejb.common.JKKModelCommon;
import eo.ejb.common.JKKModelConst;
import eo.ejb.common.edit.JKKejbKK2811SvcStaYmdStti;
import eo.ejb.common.rule.JKKejbRule0083001;

/**
 * <p>
 * 機器オプションサービス契約料金プラン変更確定処理部品クラスです。
 * </p>
 * @author 富士通
 */
public class JEKK2811C260ETDA
{

	/** 相関ルールチェックエラーフラグ&エラー返却項目(異動対象スキーマ判定相関ルール) */
	private static final String[] CORR_IDOJDG = {"EA", EKK2811C260CBSMsg.KKOP_SVC_KEI_NO_ERR};

	/** 関連チェックエラーフラグ&エラー返却項目(オプションサービス契約 開始日確定チェック) */
	private static final String[] KRCK_OP_CHRG_START_DECIDED_ERR = {"EC", EKK2811C260CBSMsg.KKOP_SVC_KEI_NO_ERR};
	
	/**
	 * <p>
	 * 新しいJEKK2811C260ETDAを作成します。
	 * </p>
	 */
	public JEKK2811C260ETDA()
	{
	}

	/**
	 * <p>
	 * 機器オプションサービス契約料金プラン変更確定時処理の呼び出しを行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 */
	public void execDBAccess(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{

		// 異動対象スキーマ判定相関ルール
		JKKejbKK2811ETDA kk2811Etda = new JKKejbKK2811ETDA();
		String baseDate = inCBSMsg.getString(EKK2811C260CBSMsg.RSV_APLY_YMD); // 基準日(予約適用年月日)を設定
		List<HashMap<String, Object>> ruleList = kk2811Etda.execSokanOfIdoJdg(inCBSMsg, inContext, baseDate);
		if (null == ruleList)
		{
			// 相関ルールチェックの結果が0件の場合はエラーとする
			setErrInfo(inCBSMsg, StatusCodes.RELATION_ERR, CORR_IDOJDG);
			return;
		}
		
		// 相関ルールチェック結果を格納
		new JKKejbIdoRsvUtil().setOnlyIdoRsvFlg(inCBSMsg, inContext, ruleList);
		
		boolean svcFlg = false;
		String ido_rsv_stat_cd = null;
		
		for (HashMap<String, Object> hm : ruleList)
		{
			if (JKKejbKK2811ETDA.SCHEMAID_IDORSV.equals(hm.get(JKKejbRule0083001.TRGT_SCHEMA_ID)))
			{
				//異動予約状態コードを取得
				ido_rsv_stat_cd = (String)hm.get(JKKejbRule0083001.IDO_RSV_STAT_CD);
			}

			if (JKKejbKK2811ETDA.SCHEMAID_KKOPSVCKEI.equals(hm.get(JKKejbRule0083001.TRGT_SCHEMA_ID)))
			{
				svcFlg = true;
			}
		}
		
		//更新対象の異動予約を取得
		String kkopSvcKeiNo = inCBSMsg.getString(EKK2811C260CBSMsg.KKOP_SVC_KEI_NO);
		CAANMsg[] kk1681MsgList = getIdoRsv(kkopSvcKeiNo, JKKModelConst.IDO_RSV_DTL_CD_KKOP_COURSECHG, JKKModelConst.IDO_RSV_STAT_CD_RSV_TTDK_CHU);
		if(ido_rsv_stat_cd != null)
		{
			//異動予約のDBアクセス
			KK1681Update(inCBSMsg, inContext, ido_rsv_stat_cd, kk1681MsgList);
		}
	
		// サービス契約のDBアクセス
		if(svcFlg)
		{
			// カレントレコード検索パラメータの設定
			CAANMsg msg = new CAANMsg(KK2811ETMsg.class.getName());
			msg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, inCBSMsg.getString(EKK2811C260CBSMsg.KKOP_SVC_KEI_NO));
			msg.set(KK2811ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inCBSMsg));
			
			JKKejbKK2811DBABase kk2811dba = new JKKejbKK2811DBABase();
			CAANMsg kk2811msg = kk2811dba.findByCurrent(msg);
			
			// 開始日の相関ルール
			String idoDiv = kk1681MsgList[0].getString(KK1681ETMsg.IDO_DIV);
			String opeDate = JKKModelCommon.getOpeDate(inCBSMsg);
			
			// 開始日設定(機器オプションサービス)部品呼出
			JKKejbKK2811SvcStaYmdStti kk2811SvcStaYmdStti = new JKKejbKK2811SvcStaYmdStti();
			// 判定結果によって振舞う項目が異なるので要注意
			Map<String, String> retMap = kk2811SvcStaYmdStti.getKkopSvKeiStDate(inCBSMsg, inContext, kkopSvcKeiNo, idoDiv);
			String staYmd = null;

			if (null != retMap)
			{
				// 開始日設定(機器オプションサービス)で算出した機器オプションサービス契約のサービス開始日
				staYmd = retMap.get(JKKejbKK2811SvcStaYmdStti.STD_DT);
				// カレントのプラン開始日を取得
				String curStaYmd = kk2811msg.getString((KK2811ETMsg.PLAN_STAYMD));
				
				// 算出した開始日よりもカレントのプラン開始日が大きい場合はカレントのプラン開始日を設定
				if (curStaYmd != null && curStaYmd.compareTo(staYmd) > 0)
				{
					staYmd = curStaYmd;
				}
			}

			// サービスIF_ID
			String svcIfId = inCBSMsg.getString(EKK2811C260CBSMsg.TEMPLATEID);
			String chrgStaYmd = null;
			if(staYmd != null) {
				chrgStaYmd = kk2811Etda.getChrgStaYmd(inCBSMsg, inContext, kkopSvcKeiNo, idoDiv, staYmd, opeDate, svcIfId);
			}
			
			if(JKKModelConst.KKOP_SVC_KEI_STAT_SVCTK_CHU.equals(kk2811msg.getString(KK2811ETMsg.KKOP_SVC_KEI_STAT)) 
					&& (staYmd == null || chrgStaYmd == null)) {
				// 相関ルールチェックの結果が0件の場合はエラーとする
				setErrInfo(inCBSMsg, StatusCodes.RELATION_ERR, KRCK_OP_CHRG_START_DECIDED_ERR);
				return;
			}

			// 世代登録年月日を退避
			String geneAddDtm = kk2811msg.getString(KK2811ETMsg.GENE_ADD_DTM);
			
			// 機器オプションサービス契約を登録する
			kk2811Create(inCBSMsg, inContext, kk2811msg, kk1681MsgList[0], staYmd, chrgStaYmd);
			
			// 機器オプションサービス契約を更新する
			kk2811Update(inCBSMsg, inContext, geneAddDtm, staYmd, chrgStaYmd);
		}
	}


	/**
	 * <p>
	 * 下記項目を条件の異動予約を取得します。
	 * <br>・機器オプションサービス契約番号
	 * <br>・異動予約詳細コード
	 * <br>・異動予約状態コード
	 * </p>
	 * @param KKOPSvcKeiNo 検索する機器オプションサービス契約番号
	 * @param idoRsvDtlCd 検索する異動予約詳細コード
	 * @param idoRsvStatCd 検索する異動予約状態コード
	 * @return 条件に該当する異動予約
	 *          条件に該当する異動予約がない場合、nullを返却
	 */
	private CAANMsg[] getIdoRsv(String kkopSvcKeiNo, String idoRsvDtlCd, String idoRsvStatCd)
	{
		// 条件を設定
		KK1681LE le = new KK1681LE();
		CAANMsg conditionETMsg = new CAANMsg(KK1681ETMsg.class.getName());
		conditionETMsg.set(KK1681ETMsg.KKOP_SVC_KEI_NO, kkopSvcKeiNo);
		conditionETMsg.set(KK1681ETMsg.IDO_RSV_DTL_CD, idoRsvDtlCd);
		conditionETMsg.set(KK1681ETMsg.IDO_RSV_STAT_CD, idoRsvStatCd);
		conditionETMsg.set(KK1681ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);
		
		CAANMsg[] kk1681MsgList = null;

		try
		{
			kk1681MsgList = le.findByCondition(conditionETMsg);
		}
		catch (CAANException ce)
		{
			// エラーが発生した場合、nullを返却
			throw new CAANRuntimeException();
		}
		if (kk1681MsgList == null || kk1681MsgList.length == 0)
		{
			throw new CAANRuntimeException("料金プラン変更確定対象の機器オプションサービス契約に対する異動予約が存在しません。機器オプションサービス契約番号:" + kkopSvcKeiNo);
		}
		return kk1681MsgList;
	}

	/**
	 * <p>
	 * 異動予約の更新を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param ido_rsv_stat_cd 異動予約状態コード
	 * @param kk1681msg カレントの異動予約
	 */
	private void KK1681Update(CAANMsg inCBSMsg, AgentDispatchContext inContext, String ido_rsv_stat_cd, CAANMsg[] kk1681msg)
	{
		String opeDate = JKKModelCommon.getOpeDate(inCBSMsg);

		// 異動予約更新用Msg生成
		CAANMsg update1681ETMsg = new CAANMsg(KK1681ETMsg.class.getName());

		String insRsvAplyYmd = null;

		//入力値「予約適用年月日」＜運用日付の場合、運用日付で更新する
		if (JKKModelCommon.isPastDate(inCBSMsg.getString(EKK2811C260CBSMsg.RSV_APLY_YMD), opeDate, "0"))
		{
			insRsvAplyYmd = JKKModelCommon.getOpeDate(inCBSMsg);
		}
		// 上記以外の場合、入力値「予約適用年月日」で更新する
		else
		{
			insRsvAplyYmd = inCBSMsg.getString(EKK2811C260CBSMsg.RSV_APLY_YMD);
		}
		
		// 取得した異動予約番号の数だけ更新処理を行う
		// 取得件数分ループ処理
		for(CAANMsg msg : kk1681msg)
		{
			// 異動予約番号	IDO_RSV_NO
			update1681ETMsg.set(KK1681ETMsg.IDO_RSV_NO, msg.getString(KK1681ETMsg.IDO_RSV_NO));
			// 予約適用年月日
			update1681ETMsg.set(KK1681ETMsg.RSV_APLY_YMD, insRsvAplyYmd);
			//異動予約状態コードが「反映済」であれば、即時であるため更新する
			if (JKKModelConst.IDO_RSV_STAT_CD_HANEI_ZM.equals(ido_rsv_stat_cd))
			{
				// 異動予約反映年月日
				update1681ETMsg.set(KK1681ETMsg.IDO_RSV_HANEI_YMD, insRsvAplyYmd);
			}
			// 異動予約状態コード
			update1681ETMsg.set(KK1681ETMsg.IDO_RSV_STAT_CD, ido_rsv_stat_cd);
			// 更新年月日時分秒
			update1681ETMsg.set(KK1681ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			// 更新オペレータアカウント
			update1681ETMsg.set(KK1681ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
			
			// 更新処理の実行
			JKKejbDBAUtil dbaUtil1681 = new JKKejbDBAUtil(inCBSMsg);
			dbaUtil1681.update(update1681ETMsg);
		}
		// 返却項目メッセージ生成
		inCBSMsg.set(EKK2811C260CBSMsg.UPD_DTM, update1681ETMsg.getString(KK1681ETMsg.UPD_DTM));
		inCBSMsg.set(EKK2811C260CBSMsg.UPD_OPEACNT, update1681ETMsg.getString(KK1681ETMsg.UPD_OPEACNT));

	}

	
	/**
	 * <p>
	 * 機器オプションサービス契約の登録を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param kk2811msg カレントの機器オプションサービス契約
	 * @param kk1681msg カレントの異動予約
	 * @param staYmd サービス開始日
	 * @param chrgStaYmd サービス課金開始日
	 */
	private void kk2811Create(CAANMsg inCBSMsg, AgentDispatchContext inContext, CAANMsg kk2811msg, CAANMsg kk1681msg, String staYmd, String chrgStaYmd)
	{
		String opeDate = JKKModelCommon.getOpeDate(inCBSMsg);
		
		// 機器オプションサービス契約番号
		kk2811msg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, inCBSMsg.getString(EKK2811C260CBSMsg.KKOP_SVC_KEI_NO));
		// 世代登録年月日時分秒
		kk2811msg.set(KK2811ETMsg.GENE_ADD_DTM, JKKModelCommon.getTransferGeneAddDtm(inCBSMsg, inContext));
		// 料金コースコード
		kk2811msg.set(KK2811ETMsg.PCRS_CD, kk1681msg.getString(KK1681ETMsg.NEW_PCRS_CD));
		// 料金プランコード
		kk2811msg.set(KK2811ETMsg.PPLAN_CD, kk1681msg.getString(KK1681ETMsg.NEW_PPLAN_CD));

		// 申込明細番号
		kk2811msg.set(KK2811ETMsg.MSKM_DTL_NO, kk1681msg.getString(KK1681ETMsg.MSKM_DTL_NO));	
		
		// 予約適用年月日
		if (0 < inCBSMsg.getString(EKK2811C260CBSMsg.RSV_APLY_YMD).compareTo(opeDate))
		{
			kk2811msg.set(KK2811ETMsg.RSV_APLY_YMD, inCBSMsg.getString(EKK2811C260CBSMsg.RSV_APLY_YMD));
		}
		else
		{
			kk2811msg.set(KK2811ETMsg.RSV_APLY_YMD, opeDate);
		}
		
		// 予約適用コード
		kk2811msg.set(KK2811ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_FIX);
		// プラン開始年月日
		kk2811msg.set(KK2811ETMsg.PLAN_STAYMD, staYmd);
		// プラン終了年月日
		kk2811msg.set(KK2811ETMsg.PLAN_ENDYMD, JKKModelConst.DATE_MAX);
		// プラン課金開始年月日
		kk2811msg.set(KK2811ETMsg.PLAN_CHRG_STAYMD, chrgStaYmd);
		// プラン課金終了年月日
		kk2811msg.set(KK2811ETMsg.PLAN_CHRG_ENDYMD, JKKModelConst.DATE_MAX);
		// サービス終了年月日
		kk2811msg.set(KK2811ETMsg.SVC_ENDYMD, JKKModelConst.DATE_MAX);
		// サービス課金終了年月日
		kk2811msg.set(KK2811ETMsg.SVC_CHRG_ENDYMD, JKKModelConst.DATE_MAX);
		// 違約金発生コード
		kk2811msg.set(KK2811ETMsg.PNLTY_HASSEI_CD, kk1681msg.getString(KK1681ETMsg.PNLTY_HASSEI_CD));
		// 異動区分
		kk2811msg.set(KK2811ETMsg.IDO_DIV, kk1681msg.getString(KK1681ETMsg.IDO_DIV));
		// 登録年月日時分秒
		kk2811msg.set(KK2811ETMsg.ADD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		// 登録オペレータアカウント
		kk2811msg.set(KK2811ETMsg.ADD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		// 更新年月日時分秒
		kk2811msg.set(KK2811ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		// 更新オペレータアカウント
		kk2811msg.set(KK2811ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		// 無効フラグ
		kk2811msg.set(KK2811ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);
		
		JKKejbDBAUtil dbaUtil = new JKKejbDBAUtil(inCBSMsg);
		dbaUtil.create(kk2811msg);
		

		inCBSMsg.set(EKK2811C260CBSMsg.GENE_ADD_DTM,      kk2811msg.getString(KK2811ETMsg.GENE_ADD_DTM));
		inCBSMsg.set(EKK2811C260CBSMsg.KKOP_SVC_KEI_STAT, kk2811msg.getString(KK2811ETMsg.KKOP_SVC_KEI_STAT));
		inCBSMsg.set(EKK2811C260CBSMsg.MSKM_DTL_NO,       kk2811msg.getString(KK2811ETMsg.MSKM_DTL_NO));
		inCBSMsg.set(EKK2811C260CBSMsg.RSV_APLY_YMD_O,    kk2811msg.getString(KK2811ETMsg.RSV_APLY_YMD));
		inCBSMsg.set(EKK2811C260CBSMsg.IDO_DIV,           kk2811msg.getString(KK2811ETMsg.IDO_DIV));
		inCBSMsg.set(EKK2811C260CBSMsg.UPD_DTM,           kk2811msg.getString(KK2811ETMsg.UPD_DTM));
		inCBSMsg.set(EKK2811C260CBSMsg.UPD_OPEACNT,       kk2811msg.getString(KK2811ETMsg.UPD_OPEACNT));
		inCBSMsg.set(EKK2811C260CBSMsg.MK_FLG,            kk2811msg.getString(KK2811ETMsg.MK_FLG));
	}
	
	/**
	 * <p>
	 * 機器オプションサービス契約の更新を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param geneAddDtm 世代登録年月日
	 * @param staYmd サービス開始日
	 * @param chrgStaYmd サービス課金開始日
	 */
	private void kk2811Update(CAANMsg inCBSMsg, AgentDispatchContext inContext, String geneAddDtm, String staYmd, String chrgStaYmd)
	{
		// 機器オプションサービス契約を更新する
		CAANMsg inMsg2811 = new CAANMsg(KK2811ETMsg.class.getName());
		
		// 機器オプションサービス契約番号
		inMsg2811.set(KK2811ETMsg.KKOP_SVC_KEI_NO, inCBSMsg.getString(EKK2811C260CBSMsg.KKOP_SVC_KEI_NO));
		// 世代登録年月日時分秒
		inMsg2811.set(KK2811ETMsg.GENE_ADD_DTM, geneAddDtm);
		if(staYmd != null && !"".equals(staYmd)) {
			// プラン終了年月日
			inMsg2811.set(KK2811ETMsg.PLAN_ENDYMD, JKKModelCommon.addDay(inCBSMsg, inContext, staYmd, -1));
		}
		
		if(chrgStaYmd != null && !"".equals(chrgStaYmd)) {
				// プラン課金終了年月日
				inMsg2811.set(KK2811ETMsg.PLAN_CHRG_ENDYMD, JKKModelCommon.addDay(inCBSMsg, inContext, chrgStaYmd, -1));
		}
		// プラン終了種別コード
		inMsg2811.set(KK2811ETMsg.PLAN_END_SBT_CD, JKKModelConst.PLAN_END_SBT_CD_PLAN_CHANGE);
		// 更新年月日時分秒
		inMsg2811.set(KK2811ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		// 更新オペレータアカウント
		inMsg2811.set(KK2811ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		
		JKKejbDBAUtil dbaUtil = new JKKejbDBAUtil(inCBSMsg);
		dbaUtil.update(inMsg2811);
	}
	
	/**
	 * <p>
	 * エラー返却項目にエラーフラグを設定します。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param status エラー時のステータス
	 * @param errInfo[] エラー情報が設定された配列 [0]:エラーフラグ [1]:エラー返却項目
	 */
	private void setErrInfo(CAANMsg inCBSMsg, int status, String[] errInfo)
	{
		inCBSMsg.set(JCMConstants.STATUS_INT_KEY, status);
		inCBSMsg.set(errInfo[1], errInfo[0]);
		return;	
	}
}
