/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKejbKK0491SecProc
*	ソースファイル名：JKKejbKK0491SecProc.java
*	作成者			：富士通
*	日付			：2011年03月14日
*＜機能概要＞
*	請求契約に対する副次処理を行う部品
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/03/14	富士通		新規作成
*   v4.00.00    2013/04/25  FJ)竹内     IT1-2013-0001052
*   v15.00.00   2015/08/26  FJ)余野木  【OM-2015-0001257】対応
*
**********************************************************************/

package eo.ejb.common.db;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

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.fw.AgentDispatchContext;

import eo.ejb.cbm.entity.KK0441ETMsg;
import eo.ejb.cbm.entity.KK0491ETMsg;
import eo.ejb.cbm.entity.KK0491LE;
import eo.ejb.cbm.entity.KK1681ETMsg;
import eo.ejb.cbm.entity.KK1681LE;
import eo.ejb.cbs.cbsmsg.EKK0321C020CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0491C060CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0491C190CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0501C070CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0501C090CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0521C120CBSMsg;
import eo.ejb.common.JKKModelCommon;
import eo.ejb.common.JKKModelConst;
import eo.ejb.common.edit.JKKejbKK1681NumberParts;
import eo.ejb.common.entity.JKKejbIdoRsvAccess;
import eo.ejb.common.rule.JKKejbRule0083001;

/**
 * <p>
 * 請求契約に対する副次処理を行う部品です。
 * </p>
 * @author 富士通
 */
public class JKKejbKK0491SecProc extends JKKejbKK0491DBABase
{

	/**
	 * コンストラクタです。
	 */
	public JKKejbKK0491SecProc()
	{
		super();
	}

	/**
	 * <p>
	 * 請求契約予約取消処理を行います。
	 * </p>
	 * @param cbsMsg 入力CBSMsg
	 * @param seikyWayNoKoza 請求方法番号(口座)
	 * @param seikyWayNoCrecard 請求方法番号(クレジットカード)
	 * @param updPtn 更新パターン(1:口振手続キャンセル/2:口振審査結果NG登録/3:クレジット請求手続キャンセル/4:クレジット審査結果NG登録)
	 */
	public void seikyKeiRsvCl(CAANMsg cbsMsg, String seikyWayNoKoza, String seikyWayNoCrecard, String updPtn)
	{
		String opeDate = JKKModelCommon.getOpeDate(cbsMsg);

		/* ----------------------------------------------------------------------------------------------------
		 * 該当の「口座」または「クレジットカード」に紐づく「請求契約」の予約レコードを取得
		 * ※抽出条件がバラバラです。本来は、統一されるべきだが、調整が必要のため、そのままにしておく。。。
		 * ---------------------------------------------------------------------------------------------------- */
		CAANMsg[] otETMsgList = null;
		// 口振手続キャンセル、口振審査結果NG登録の場合
		if ("1".equals(updPtn) || "2".equals(updPtn))
		{
			// 該当の「口座」に紐づく「請求契約」の予約レコードを取得
			CAANMsg inETMsg = new CAANMsg(KK0491ETMsg.class.getName());
			inETMsg.set(KK0491ETMsg.SEIKY_WAY_NO_KOZA, seikyWayNoKoza);
			if ("2".equals(updPtn))
			{
				inETMsg.set(KK0491ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_TTDK_CHU);
			}
			inETMsg.set(KK0491ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);
			// なぜか、口振手続キャンセルの場合は、予約適用コードの指定なし。
			// 該当の「請求契約」の全てのレコードを予約取消することになってしまう。
			// 間違いのように思えるが、詳細不明のため、そのままにしておく。。。

			try
			{
				otETMsgList = new KK0491LE().findByCondition(inETMsg);
			}
			catch (CAANException e1)
			{
				throw new CAANRuntimeException(e1);
			}
		}
		// クレジット請求手続キャンセル、クレジット審査結果NG登録の場合
		else if ("3".equals(updPtn) || "4".equals(updPtn))
		{
			ArrayList<CAANMsg> outList = new ArrayList<CAANMsg>();

			// 該当の「クレジットカード」に紐づく「請求契約」を取得する。
			CAANMsg[] kk0491MsgList = new JKKejbKK0491DBABase().getKK0491bySeikyWay(null, seikyWayNoCrecard, null, opeDate);
			for (CAANMsg kk0491Msg : kk0491MsgList)
			{
				// 【請求契約中】以外の場合、予約取消対象外
				if (!JKKModelConst.SEIKY_KEI_STAT_SIKYKEI_CHU.equals(kk0491Msg.getString(KK0491ETMsg.SEIKY_KEI_STAT)))
				{
					continue;
				}
				// なぜか、クレジット請求手続キャンセル、クレジット審査結果NG登録の場合は、カレントの請求契約ステータスを気にしてる。
				// 特に意味はないように思えるが、詳細不明のため、そのままにしておく。。。

				// 取得した請求契約番号の、予約レコードの照会を行う
				CAANMsg inETMsg = new CAANMsg(KK0491ETMsg.class.getName());
				inETMsg.set(KK0491ETMsg.SEIKY_KEI_NO, kk0491Msg.getString(KK0491ETMsg.SEIKY_KEI_NO));
				inETMsg.set(KK0491ETMsg.RSV_APLY_YMD, opeDate);

				CAANMsg[] kk0491RsvList = super.findByReserve(inETMsg);

				for (CAANMsg kk0491Rsv : kk0491RsvList)
				{
					outList.add(kk0491Rsv);
				}
			}
			otETMsgList = outList.toArray(new CAANMsg[0]);
		}
		else
		{
			throw new CAANRuntimeException("未定義の更新パターンです。");
		}

		try
		{
			/* --------------------------------------------------
			 * 該当の「請求契約」予約を取消
			 * -------------------------------------------------- */
			CAANMsg updateETMsg = new CAANMsg(KK0491ETMsg.class.getName());
			updateETMsg.set(KK0491ETMsg.RSV_CL_YMD, opeDate);
			updateETMsg.set(KK0491ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_CL);
			updateETMsg.set(KK0491ETMsg.UPD_DTM, cbsMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			updateETMsg.set(KK0491ETMsg.UPD_OPEACNT, cbsMsg.getString(JCMConstants.OPERATOR_ID_KEY));

			for (CAANMsg otETMsg : otETMsgList)
			{
				// 請求契約番号
				updateETMsg.set(KK0491ETMsg.SEIKY_KEI_NO, otETMsg.getString(KK0491ETMsg.SEIKY_KEI_NO));
				// 世代登録年月日時分秒
				updateETMsg.set(KK0491ETMsg.GENE_ADD_DTM, otETMsg.getString(KK0491ETMsg.GENE_ADD_DTM));
				
				super.update(updateETMsg);
				
				// 自動予約取消ワークに登録します
				this.createKK2791GymSchema(otETMsg, JKKModelConst.AUTO_RSV_CL_STAT_CD_CL_ZM, cbsMsg);
			}
		}
		catch (CAANException e1)
		{
			throw new CAANRuntimeException(e1);
		}
	}

	/**
	 * <p>
	 * 審査結果OK登録時「請求契約」予約結果更新<br>
	 * 該当の「口座」または「クレジットカード」に紐づく「請求契約」の予約を確定します。
	 * </p>
	 * @param cbsMsg CBSメッセージ
	 * @param seikyWayNoKoza 請求方法番号(口座)
	 * @param seikyWayNoCrecard 請求方法番号(クレジットカード)
	 * @param rsvAplyYmd 予約適用年月日
	 * @param updPtn 更新パターン(1:口振審査結果OK登録/2:クレジット審査結果OK登録/3:審査済クレジットカードOK登録)
	 */
	public void seikyRsvRsltUpdForTtdk(CAANMsg cbsMsg, String seikyWayNoKoza, String seikyWayNoCrecard, String rsvAplyYmd, String updPtn)
	{
		// 予約適用年月日が未定の場合、予約確定処理は行わない
		if (rsvAplyYmd == null)
		{
			return;
		}

		/* ----------------------------------------------------------------------------------------------------
		 * 該当の「口座」または「クレジットカード」に紐づく「請求契約」の予約レコードを取得
		 * ---------------------------------------------------------------------------------------------------- */
		CAANMsg inETMsg = new CAANMsg(KK0491ETMsg.class.getName());

		// 口振審査結果OK登録の場合
		if ("1".equals(updPtn))
		{
			inETMsg.set(KK0491ETMsg.SEIKY_WAY_NO_KOZA, seikyWayNoKoza);
		}
		// クレジット審査結果OK登録の場合
		else if ("2".equals(updPtn))
		{
			inETMsg.set(KK0491ETMsg.SEIKY_WAY_NO_CRECARD, seikyWayNoCrecard);
			inETMsg.set(KK0491ETMsg.SEIKY_KEI_STAT, JKKModelConst.SEIKY_KEI_STAT_SIKYKEI_CHU);
			// なぜか、クレジット審査結果OK登録の場合だけ、請求契約ステータス＝"請求契約中"を検索条件に加えている。
			// 特に意味はないように思えるが、詳細不明のため、そのままにしておく。。。
		}
		// 審査済クレジットカードOK登録の場合
		else if ("3".equals(updPtn))
		{
			inETMsg.set(KK0491ETMsg.SEIKY_WAY_NO_CRECARD, seikyWayNoCrecard);
		}
		else
		{
			throw new CAANRuntimeException("未定義の更新パターンです。");
		}
		inETMsg.set(KK0491ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_TTDK_CHU);
		inETMsg.set(KK0491ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		try
		{
			CAANMsg[] otETMsgList = new KK0491LE().findByCondition(inETMsg);

			/* --------------------------------------------------
			 * 該当の「請求契約」予約を確定
			 * -------------------------------------------------- */
			CAANMsg updateETMsg = new CAANMsg(KK0491ETMsg.class.getName());
			updateETMsg.set(KK0491ETMsg.RSV_APLY_YMD, rsvAplyYmd);
			updateETMsg.set(KK0491ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_FIX);
			updateETMsg.set(KK0491ETMsg.UPD_DTM, cbsMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
			updateETMsg.set(KK0491ETMsg.UPD_OPEACNT, cbsMsg.getString(JCMConstants.OPERATOR_ID_KEY));

			for (CAANMsg otETMsg : otETMsgList)
			{
				// 請求契約番号
				updateETMsg.set(KK0491ETMsg.SEIKY_KEI_NO, otETMsg.getString(KK0491ETMsg.SEIKY_KEI_NO));
				// 世代登録年月日時分秒
				updateETMsg.set(KK0491ETMsg.GENE_ADD_DTM, otETMsg.getString(KK0491ETMsg.GENE_ADD_DTM));

				super.update(updateETMsg);
			}
		}
		catch (CAANException e1)
		{
			throw new CAANRuntimeException(e1);
		}
	}

	/**
	 * <p>
	 * 該当の「請求契約」(および「請求契約」に紐づく「異動予約」)に関する予約を取り消します。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param seikyKeiNo 対象の請求契約番号
	 * @param seikyKeiNoNew 対象の請求契約番号(併合/分割先)（請求先情報併合／分割の場合のみ設定）
	 * @param stdYmd 基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)
	 */
	public void rsvClSeikyKei(CAANMsg inCBSMsg, String seikyKeiNo, String seikyKeiNoNew, String stdYmd)
	{
		// 予約取消対象となる「異動予約」の異動予約番号リスト
		String[] idoRsvNoList = getRsvClTgIdoRsvNoList(seikyKeiNo, seikyKeiNoNew, stdYmd);
		if (idoRsvNoList != null)
		{
			// 請求契約更新(予約取消)処理を実行
			updateKK0491RsvCl(inCBSMsg, seikyKeiNo, null, stdYmd);

			// 分割・併合先の請求契約の更新(予約取消)処理を実行
			updateKK0491RsvClForBnktHeigo(inCBSMsg, idoRsvNoList);

			// 異動予約更新(予約取消)処理を実行
			updateKK1681RsvCl(inCBSMsg, idoRsvNoList);
		}
	}

	/**
	 * <p>
	 * 予約取消対象となる「異動予約」の異動予約番号リストを取得します。
	 * </p>
	 * @param seikyKeiNo 対象の請求契約番号
	 * @param seikyKeiNoNew 対象の請求契約番号(併合/分割先)（請求先情報併合／分割の場合のみ設定）
	 * @param stdYmd 基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)
	 * @return 異動予約番号リスト（チェックNGの場合はnullを返却）
	 */
	private String[] getRsvClTgIdoRsvNoList(String seikyKeiNo, String seikyKeiNoNew, String stdYmd)
	{
		if (stdYmd == null || "".equals(stdYmd))
		{
			throw new CAANRuntimeException("該当の請求契約に関する変更予定日が設定されていません。");
		}

		// 対象の「請求契約」の予約検索を行う
		List<CAANMsg> kk1681MsgList = new JKKejbIdoRsvAccess().getIdoRsvSeikyKeiNo(seikyKeiNo, seikyKeiNoNew, stdYmd);

		// 予約取消対象となる「異動予約」の異動予約番号リスト
		ArrayList<String> idoRsvNoList = new ArrayList<String>();

		for (CAANMsg kk1681Msg : kk1681MsgList)
		{
			// 異動予約詳細コードが"請求契約情報変更／併合／分割"の場合
			if (JKKModelConst.IDO_RSV_DTL_CD_SIKYKEI_CHG.equals(kk1681Msg.getString(KK1681ETMsg.IDO_RSV_DTL_CD)))
			{
				// 異動予約.予約適用年月日が未定、または基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)より未来日の場合
				String rsvAplyYmd = kk1681Msg.getString(KK1681ETMsg.RSV_APLY_YMD);
				if (rsvAplyYmd == null || stdYmd.compareTo(rsvAplyYmd) < 0)
				{
					idoRsvNoList.add(kk1681Msg.getString(KK1681ETMsg.IDO_RSV_NO));
				}
			}
		}

		if(null == idoRsvNoList || 0 >= idoRsvNoList.size())
		{
			return null;
		}

		return idoRsvNoList.toArray(new String[0]);
	}

	/**
	 * <p>
	 * 異動予約登録処理のDBアクセス処理を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param rule0083RsltMap ルールエンジン実行結果格納マップ
	 * @param idoDiv 異動区分
	 * @param rsvAplyYmd 予約適用年月日
	 * @param mskmDtlNo 申込明細番号
	 * @param seikyKeiNo 対象の請求契約番号
	 * @param seikyKeiNoNew 対象の請求契約番号(併合/分割先)（請求先情報併合／分割の場合のみ設定）
	 * @param svcKeiNo サービス契約番号
	 */
	public void createKK1681(CAANMsg inCBSMsg, AgentDispatchContext inContext, HashMap<String, Object> rule0083RsltMap,
			String idoDiv, String rsvAplyYmd, String mskmDtlNo, String seikyKeiNo, String seikyKeiNoNew, String svcKeiNo)
	{
		// ETMsgの作成
		CAANMsg inETMsg = new CAANMsg(KK1681ETMsg.class.getName());
		
		// 異動予約番号(採番)
		inETMsg.set(KK1681ETMsg.IDO_RSV_NO, new JKKejbKK1681NumberParts().getIdoRsvNo(inCBSMsg, inContext));
		// 異動区分
		inETMsg.set(KK1681ETMsg.IDO_DIV, idoDiv);
		// 異動予約詳細コード
		if (rule0083RsltMap == null)
		{
			inETMsg.set(KK1681ETMsg.IDO_RSV_DTL_CD, JKKModelConst.IDO_RSV_DTL_CD_SIKYKEI_CHG);
		}
		else
		{
			inETMsg.set(KK1681ETMsg.IDO_RSV_DTL_CD, rule0083RsltMap.get(JKKejbRule0083001.IDO_RSV_DTL_CD));
		}
		// 予約適用年月日
		inETMsg.set(KK1681ETMsg.RSV_APLY_YMD, rsvAplyYmd);
		// 異動予約状態コード
		if (rule0083RsltMap == null)
		{
			inETMsg.set(KK1681ETMsg.IDO_RSV_STAT_CD, JKKModelConst.IDO_RSV_STAT_CD_IDO_RSV_TG_GAI);
		}
		else
		{
			inETMsg.set(KK1681ETMsg.IDO_RSV_STAT_CD, rule0083RsltMap.get(JKKejbRule0083001.IDO_RSV_STAT_CD));
		}
		// 異動予約反映年月日
		if (rule0083RsltMap != null && JKKModelConst.IDO_RSV_STAT_CD_HANEI_ZM.equals(rule0083RsltMap.get(JKKejbRule0083001.IDO_RSV_STAT_CD)))
		{
			inETMsg.set(KK1681ETMsg.IDO_RSV_HANEI_YMD, JKKModelCommon.getOpeDate(inCBSMsg));
		}
		// 申込明細番号
		inETMsg.set(KK1681ETMsg.MSKM_DTL_NO, mskmDtlNo);
		// 請求契約番号
		inETMsg.set(KK1681ETMsg.SEIKY_KEI_NO, seikyKeiNo);
		// サービス契約番号
		inETMsg.set(KK1681ETMsg.SVC_KEI_NO, svcKeiNo);
		// 併合先請求契約番号
		if (JKKModelConst.IDO_DIV_SEIKY_KEI_HEIGO.equals(idoDiv))
		{
			inETMsg.set(KK1681ETMsg.HEIGO_SK_SEIKY_KEI_NO, seikyKeiNoNew);
		}
		// 分割先請求契約番号
		else if (JKKModelConst.IDO_DIV_SEIKY_KEI_BNKT.equals(idoDiv))
		{
			inETMsg.set(KK1681ETMsg.BUNKATSU_SK_SEIKY_KEI_NO, seikyKeiNoNew);
		}
		inETMsg.set(KK1681ETMsg.ADD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		inETMsg.set(KK1681ETMsg.ADD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		inETMsg.set(KK1681ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		inETMsg.set(KK1681ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		inETMsg.set(KK1681ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		// 異動予約の登録
		JKKejbDBAUtil dba = new JKKejbDBAUtil(inCBSMsg);
		dba.create(inETMsg);

		return;
	}

	/**
	 * <p>
	 * 異動予約更新(予約反映)処理のDBアクセス処理を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param idoRsvNo 予約反映対象の異動予約番号
	 */
	public void updateKK1681RsvHanei(CAANMsg inCBSMsg, String idoRsvNo)
	{
		// ETMsgの作成
		CAANMsg inETMsg = new CAANMsg(KK1681ETMsg.class.getName());

		// 異動予約番号
		inETMsg.set(KK1681ETMsg.IDO_RSV_NO, idoRsvNo);
		// 異動予約反映年月日
		inETMsg.set(KK1681ETMsg.IDO_RSV_HANEI_YMD, JKKModelCommon.getOpeDate(inCBSMsg));
		// 異動予約状態コード
		inETMsg.set(KK1681ETMsg.IDO_RSV_STAT_CD, JKKModelConst.IDO_RSV_STAT_CD_HANEI_ZM);
		inETMsg.set(KK1681ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		inETMsg.set(KK1681ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));

		// 異動予約の更新
		JKKejbDBAUtil dba = new JKKejbDBAUtil(inCBSMsg);
		dba.update(inETMsg);

		return;
	}

	/**
	 * <p>
	 * 異動予約更新(予約取消)処理のDBアクセス処理を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param keyNoList 予約取消対象の異動予約番号のリスト
	 */
	private void updateKK1681RsvCl(CAANMsg inCBSMsg, String[] keyNoList)
	{
		// ETMsgの作成
		CAANMsg inETMsg = new CAANMsg(KK1681ETMsg.class.getName());

		// 異動予約取消年月日
		inETMsg.set(KK1681ETMsg.IDO_RSV_CL_YMD, JKKModelCommon.getOpeDate(inCBSMsg));
		// 異動予約状態コード
		inETMsg.set(KK1681ETMsg.IDO_RSV_STAT_CD, JKKModelConst.IDO_RSV_STAT_CD_CL_ZM);
		inETMsg.set(KK1681ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		inETMsg.set(KK1681ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));

		// 取得した異動予約番号の数だけ更新処理を行う
		for (int i = 0; i < keyNoList.length; i++)
		{
			// 異動予約番号
			inETMsg.set(KK1681ETMsg.IDO_RSV_NO, keyNoList[i]);
			
			// 異動予約番号を使って異動予約を一意検索する(自動予約取消ワーク用）
			CAANMsg kk1681ETInfo = new KK1681LE().findByPrimaryKey(inETMsg);
			// 自動予約取消ワークに登録します
			this.createKK2791IdoRsv(kk1681ETInfo, JKKModelConst.AUTO_RSV_CL_STAT_CD_CL_ZM, inCBSMsg);
			
			// 異動予約の更新
			JKKejbDBAUtil dba = new JKKejbDBAUtil(inCBSMsg);
			dba.update(inETMsg);
		}

		return;
	}

	/**
	 * <p>
	 * 請求契約更新(予約取消)処理のDBアクセス処理を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param seikyKeiNo 請求契約番号
	 * @param mskmDtlNo 申込明細番号
	 * @param stdYmd 基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)
	 */
	private void updateKK0491RsvCl(CAANMsg inCBSMsg, String seikyKeiNo, String mskmDtlNo, String stdYmd)
	{
		// 更新対象の請求契約を抽出(基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)より未来に適用日を迎える請求契約)
		CAANMsg kk0491RsvCond = new CAANMsg(KK0491ETMsg.class.getName());
		kk0491RsvCond.set(KK0491ETMsg.SEIKY_KEI_NO, seikyKeiNo);
		kk0491RsvCond.set(KK0491ETMsg.RSV_APLY_YMD, stdYmd);
		CAANMsg[] kk0491RsvList = new JKKejbKK0491DBABase().findByReserve(kk0491RsvCond);

		if (null == kk0491RsvList || 0 == kk0491RsvList.length)
		{
			// 基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)より未来に適用日を迎える請求契約が存在しない場合
			return;
		}

		// 更新用ETMsgの作成
		CAANMsg kk0491Info = new CAANMsg(KK0491ETMsg.class.getName());
		// 請求契約番号
		kk0491Info.set(KK0491ETMsg.SEIKY_KEI_NO, seikyKeiNo);
		// 予約取消年月日
		kk0491Info.set(KK0491ETMsg.RSV_CL_YMD, JKKModelCommon.getOpeDate(inCBSMsg));
		// 予約適用コード
		kk0491Info.set(KK0491ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_CL);
		kk0491Info.set(KK0491ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		kk0491Info.set(KK0491ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));

		for (CAANMsg kk0491Rsv : kk0491RsvList)
		{
			// 請求契約.申込明細番号
			String kk0491MskmDtlNo = kk0491Rsv.getString(KK0491ETMsg.MSKM_DTL_NO);
			if (mskmDtlNo != null && !"".equals(mskmDtlNo))
			{
				// 請求契約.申込明細番号が指定された申込明細番号と異なるレコードは、予約取消対象外
				if (!mskmDtlNo.equals(kk0491MskmDtlNo))
				{
					continue;
				}
			}
			// 世代登録年月日時分秒
			kk0491Info.set(KK0491ETMsg.GENE_ADD_DTM, kk0491Rsv.getString(KK0491ETMsg.GENE_ADD_DTM));

			// 更新処理
			JKKejbDBAUtil dba = new JKKejbDBAUtil(inCBSMsg);
			dba.update(kk0491Info);
			
			// 自動予約取消ワークに登録します
			this.createKK2791GymSchema(kk0491Rsv, JKKModelConst.AUTO_RSV_CL_STAT_CD_CL_ZM, inCBSMsg);

			// 該当の「請求契約」配下の「請求オプションサービス契約」を取得する。
			CAANMsg[] kk0441MsgList = new JKKejbKK0441DBABase().getKK0441bySeikyKei(seikyKeiNo,
					null, JKKModelCommon.getOpeDate(inCBSMsg));
			for (CAANMsg kk0441Msg : kk0441MsgList)
			{
				// 請求オプションサービス契約の予約レコードを検索し、対象のレコードすべてを更新する
				updateKK0441RsvCl(inCBSMsg, kk0441Msg.getString(KK0441ETMsg.SEIOPSVC_KEI_NO), mskmDtlNo, stdYmd);
			}
		}
	}

	/**
	 * <p>
	 * 請求オプションサービス契約更新(予約取消)処理のDBアクセス処理を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param seiopsvcKeiNo 請求オプションサービス契約番号
	 * @param mskmDtlNo 申込明細番号
	 * @param stdYmd 基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)
	 */
	private void updateKK0441RsvCl(CAANMsg inCBSMsg, String seiopsvcKeiNo, String mskmDtlNo, String stdYmd)
	{
		// 更新対象の請求オプションサービス契約を抽出
		// (基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)より未来に適用日を迎える請求オプションサービス契約)
		CAANMsg kk0441RsvCond = new CAANMsg(KK0441ETMsg.class.getName());
		kk0441RsvCond.set(KK0441ETMsg.SEIOPSVC_KEI_NO, seiopsvcKeiNo);
		kk0441RsvCond.set(KK0441ETMsg.RSV_APLY_YMD, stdYmd);
		CAANMsg[] kk0441RsvList = new JKKejbKK0441DBABase().findByReserve(kk0441RsvCond);

		if (null == kk0441RsvList || 0 == kk0441RsvList.length)
		{
			// 基準年月日(入力.予約適用年月日、または入力.課金先適用開始年月日)より未来に適用日を迎える請求オプションサービス契約が存在しない場合
			return;
		}

		// 更新用ETMsgの作成
		CAANMsg kk0441Info = new CAANMsg(KK0441ETMsg.class.getName());
		// 請求オプションサービス契約番号
		kk0441Info.set(KK0441ETMsg.SEIOPSVC_KEI_NO, seiopsvcKeiNo);
		// 予約取消年月日
		kk0441Info.set(KK0441ETMsg.RSV_CL_YMD, JKKModelCommon.getOpeDate(inCBSMsg));
		// 予約適用コード
		kk0441Info.set(KK0441ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_CL);
		kk0441Info.set(KK0441ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		kk0441Info.set(KK0441ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		// 取得したレコードの更新を行う。
		for (CAANMsg kk0441Rsv : kk0441RsvList)
		{
			// 請求オプションサービス契約.申込明細番号
			String kk0441MskmDtlNo = kk0441Rsv.getString(KK0441ETMsg.MSKM_DTL_NO);
			if (mskmDtlNo != null && !"".equals(mskmDtlNo))
			{
				// 請求オプションサービス契約.申込明細番号が指定された請求契約.申込明細番号と異なるレコードは、予約取消対象外
				if (!mskmDtlNo.equals(kk0441MskmDtlNo))
				{
					continue;
				}
			}
			// 世代登録年月日時分秒
			kk0441Info.set(KK0441ETMsg.GENE_ADD_DTM, kk0441Rsv.getString(KK0441ETMsg.GENE_ADD_DTM));

			// 更新処理
			JKKejbDBAUtil dba = new JKKejbDBAUtil(inCBSMsg);
			dba.update(kk0441Info);
		}
	}

	/**
	 * <p>
	 * 併合・分割時の請求契約の更新(予約取消)処理を行います。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param idoRsvNoList 更新対象の異動予約番号のリスト
	 */
	private void updateKK0491RsvClForBnktHeigo(CAANMsg inCBSMsg, String[] idoRsvNoList) 
	{
		for(int i = 0; i < idoRsvNoList.length; i++)
		{
			CAANMsg keyKK1681 = new CAANMsg(KK1681ETMsg.class.getName());
			keyKK1681.set(KK1681ETMsg.IDO_RSV_NO, idoRsvNoList[i]);
			CAANMsg retKK1681 = new JKKejbKK1681DBABase().findByPrimaryKey(keyKK1681);
			
			if(null == retKK1681)
			{
				continue;
			}

			String heigoSkSeikyKeiNo = retKK1681.getString(KK1681ETMsg.HEIGO_SK_SEIKY_KEI_NO);
			String bunkatsuSkSeikyKeiNo = retKK1681.getString(KK1681ETMsg.BUNKATSU_SK_SEIKY_KEI_NO);
			/* ++++++++++ v15.00.00 追加開始 ++++++++++ */
			// 請求併合処理の場合
			if (JKKModelConst.IDO_DIV_SEIKY_KEI_HEIGO.equals(inCBSMsg.getString(EKK0321C020CBSMsg.IDO_DIV)))
			{
				// 併合先請求契約番号に請求契約番号を設定する(まだ併合先請求契約番号は設定されていないため)
				heigoSkSeikyKeiNo = retKK1681.getString(KK1681ETMsg.SEIKY_KEI_NO);
			}
			/* ++++++++++ v15.00.00 追加終了 ++++++++++ */
			String mskmDtlNo = retKK1681.getString(KK1681ETMsg.MSKM_DTL_NO);
			String opeDate = JKKModelCommon.getOpeDate(inCBSMsg);

			// 異動予約.併合先請求契約番号に紐づく請求契約を更新する
			if (null != heigoSkSeikyKeiNo && !"".equals(heigoSkSeikyKeiNo))
			{
				// 請求契約の更新
				updateKK0491RsvCl(inCBSMsg, heigoSkSeikyKeiNo, mskmDtlNo, opeDate);
			}
			// 異動予約.分割先請求契約番号に紐づく請求契約を更新する
			if (null != bunkatsuSkSeikyKeiNo && !"".equals(bunkatsuSkSeikyKeiNo))
			{
				// 請求契約の更新
				updateKK0491RsvCl(inCBSMsg, bunkatsuSkSeikyKeiNo, mskmDtlNo, opeDate);
			}
		}
	}

	/**
	 * <p>
	 * 自動予約取消ワークに請求契約の予約情報を登録します
	 * </p>
	 * @param kk0491EtMsg ETメッセージ
	 * @param autoRsvClStatCd 自動予約取消状態コード
	 * @param inCBSMsg 入力情報
	 */
	private void createKK2791GymSchema(CAANMsg kk0491EtMsg, String autoRsvClStatCd, CAANMsg inCBSMsg)
	{
		// 自動予約取消ワークＤＢ操作部品のインスタンス化
		JKKejbKK2791ETDA kk2791etda = new JKKejbKK2791ETDA();

		// 取消契機異動区分、取消契機申込明細番号
		setKK2791ClOpty(kk2791etda, inCBSMsg, kk0491EtMsg.getString(KK0491ETMsg.SEIKY_KEI_NO));
		// 請求契約番号
		kk2791etda.setSeiky_kei_no(kk0491EtMsg.getString(KK0491ETMsg.SEIKY_KEI_NO));
		// 予約契機異動区分
		kk2791etda.setRsv_opty_ido_div(kk0491EtMsg.getString(KK0491ETMsg.IDO_DIV));
		// 予約契機申込明細番号
		kk2791etda.setRsv_opty_mskm_dtl_no(kk0491EtMsg.getString(KK0491ETMsg.MSKM_DTL_NO));
		// 予約適用年月日
		kk2791etda.setRsv_aply_ymd(kk0491EtMsg.getString(KK0491ETMsg.RSV_APLY_YMD));
		// 各種スキーマ世代登録年月日時分秒
		kk2791etda.setVari_schma_gene_add_dtm(kk0491EtMsg.getString(KK0491ETMsg.GENE_ADD_DTM));
		// 予約適用コード
		kk2791etda.setRsv_aply_cd(kk0491EtMsg.getString(KK0491ETMsg.RSV_APLY_CD));
		// 登録年月日時分秒
		kk2791etda.setAdd_dtm(inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		// 登録オペレータアカウント
		kk2791etda.setAdd_opeacnt(inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		// 更新年月日時分秒
		kk2791etda.setUpd_dtm(inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		// 更新オペレータアカウント
		kk2791etda.setUpd_opeacnt(inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));

		// 自動予約取消ワークの登録
		kk2791etda.createKK2791(kk0491EtMsg, "KK0491", autoRsvClStatCd);
	}

	/**
	 * <p>
	 * 自動予約取消ワークに異動予約の予約情報を登録します
	 * </p>
	 * @param kk1681EtMsg ETメッセージ
	 * @param autoRsvClStatCd 自動予約取消状態コード
	 * @param inCBSMsg 入力情報
	 */
	private void createKK2791IdoRsv(CAANMsg kk1681EtMsg, String autoRsvClStatCd, CAANMsg inCBSMsg)
	{
		// 自動予約取消ワークＤＢ操作部品のインスタンス化
		JKKejbKK2791ETDA kk2791etda = new JKKejbKK2791ETDA();

		// 取消契機異動区分、取消契機申込明細番号
		setKK2791ClOpty(kk2791etda, inCBSMsg, kk1681EtMsg.getString(KK1681ETMsg.SEIKY_KEI_NO));
		// 登録年月日時分秒
		kk2791etda.setAdd_dtm(inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		// 登録オペレータアカウント
		kk2791etda.setAdd_opeacnt(inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
		// 更新年月日時分秒
		kk2791etda.setUpd_dtm(inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
		// 更新オペレータアカウント
		kk2791etda.setUpd_opeacnt(inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));

		// 自動予約取消ワークの登録
		kk2791etda.createKK2791(kk1681EtMsg, "KK1681", autoRsvClStatCd);
	}

	/**
	 * <p>
	 * 自動予約取消ワークの取消契機異動区分、取消契機申込明細番号を設定します。<br>
	 * サービスIF入力値を優先し、未設定であれば、カレントレコードの値を設定します。
	 * </p>
	 * @param kk2791etda 自動予約取消ワークＤＢ操作部品のインスタンス
	 * @param inCBSMsg 入力情報
	 * @param seikyKeiNo 請求契約番号
	 */
	private void setKK2791ClOpty(JKKejbKK2791ETDA kk2791etda, CAANMsg inCBSMsg, String seikyKeiNo)
	{
		// 対象の「請求契約」カレントレコードを取得
		CAANMsg kk0491Msg = new JKKejbKK0491DBABase().getKK0491Current(seikyKeiNo, JKKModelCommon.getOpeDate(inCBSMsg));

		// カレントレコードの異動区分、申込明細番号を取得
		String idoDiv = kk0491Msg.getString(KK0491ETMsg.IDO_DIV);
		String mskmDtlNo = kk0491Msg.getString(KK0491ETMsg.MSKM_DTL_NO);

		// 各サービスIFの入力値の異動区分、申込明細番号を取得
		String templateID = inCBSMsg.getString(JCMConstants.TEMPLATE_ID_KEY);
		// 課金先請求契約変更
		if ("EKK0321C020".equals(templateID))
		{
			idoDiv = inCBSMsg.getString(EKK0321C020CBSMsg.IDO_DIV);
			mskmDtlNo = inCBSMsg.getString(EKK0321C020CBSMsg.MSKM_DTL_NO);
		}
		// 請求契約内容変更
		else if ("EKK0491C060".equals(templateID))
		{
			idoDiv = inCBSMsg.getString(EKK0491C060CBSMsg.IDO_DIV);
			mskmDtlNo = inCBSMsg.getString(EKK0491C060CBSMsg.MSKM_DTL_NO);
		}
		// 請求契約お客様変更
		else if ("EKK0491C190".equals(templateID))
		{
			idoDiv = inCBSMsg.getString(EKK0491C190CBSMsg.IDO_DIV);
			mskmDtlNo = inCBSMsg.getString(EKK0491C190CBSMsg.MSKM_DTL_NO);
		}
		// 請求支払先変更
		else if ("EKK0491C240".equals(templateID))
		{
		}
		// 口振手続キャンセル
		else if ("EKK0501C070".equals(templateID))
		{
			idoDiv = inCBSMsg.getString(EKK0501C070CBSMsg.IDO_DIV);
		}
		// 口振審査結果NG登録
		else if ("EKK0501C090".equals(templateID))
		{
			idoDiv = inCBSMsg.getString(EKK0501C090CBSMsg.IDO_DIV);
		}
		// クレジット請求手続キャンセル
		else if ("EKK0521C100".equals(templateID))
		{
		}
		// クレジット審査結果NG登録
		else if ("EKK0521C120".equals(templateID))
		{
			idoDiv = inCBSMsg.getString(EKK0521C120CBSMsg.IDO_DIV);
		}
		else
		{
			throw new CAANRuntimeException("自動予約取消ワーク登録処理対象外です。サービスIF:" + templateID);
		}

		// 取消契機異動区分
		kk2791etda.setCl_opty_ido_div(idoDiv);
		// 取消契機申込明細番号
		kk2791etda.setCl_opty_mskm_dtl_no(mskmDtlNo);

		return;
	}
}
