/*******************************************************************************
 *	All Rights reserved,Copyright (c) K-Opticom
 ********************************************************************************
 *＜プログラム内容＞
 *	システム名		：eo顧客基幹システム
 *	モジュール名	：JKKejbKK2811SecProc
 *	ソースファイル名：JKKejbKK2811SecProc.java
 *	作成者			：EKek0048
 *	日付			：2013年11月18日
 *＜機能概要＞
 *	機器オプションサービス契約に対する副次処理を行う部品です。
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	v7.00.00	2013/11/18	富士通		新規作成
 *	v7.00.01	2013/12/22	FJ)大山		IT2-2013-0000887
 *	v9.00.00	2014/04/26	FJ)大山		ANK-2054-00-00
 *	v9.00.01	2014/05/02	FJ)大山		ANK-2054-00-00
 *	v61.00.00	2023/04/19	FJ)藤本涼	ANK-4315-00-00
 *
 ********************************************************************************/

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.CAANCreateException;
import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANFinderException;
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.KK0081ETMsg;
import eo.ejb.cbm.entity.KK0241ETMsg;
import eo.ejb.cbm.entity.KK0241LE;
import eo.ejb.cbm.entity.KK0341ETMsg;
import eo.ejb.cbm.entity.KK1681ETMsg;
import eo.ejb.cbm.entity.KK2811ETMsg;
import eo.ejb.cbm.entity.KK2811LE;
import eo.ejb.common.JKKModelCommon;
import eo.ejb.common.JKKModelConst;
import eo.ejb.common.entity.JKKejbIdoRsvAccess;

/**
* <p>
* 機器オプションサービス契約に対する副次処理を行う部品です。
* </p>
* @author 富士通
*/
public class JKKejbKK2811SecProc extends JKKejbKK2811DBABase
{
	/** サービスIFID：照査前機器オプションサービス契約キャンセル取消 */
	private static final String SIF_IF_EKK2811C120 = "EKK2811C120";

	/** サービスIFID：照査後機器オプションサービス契約キャンセル取消 */
	private static final String SIF_IF_EKK2811C130 = "EKK2811C130";


	/**
	 * <p>
	 * 指定された機器オプションサービス契約番号に紐付く予約
	 * （該当の「機器オプションサービス契約」レコードのうち、未来日での予約確定レコード）をキャンセルします。
	 * </p>
	 * @param kkopSvcKeiNo キャンセル対象の機器オプションサービス契約番号
	 * @param opeDate 運用日付
	 * @param svcCancelYmd サービスキャンセル年月日
	 * @param svcCancelRsnCd サービスキャンセル理由コード
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	public void cancelRsvFixRec(String kkopSvcKeiNo, String opeDate,
			String svcCancelYmd, String svcCancelRsnCd, String updDtm, String updOpeAct)
	{
		/* ------------------------------------------------------------------------------------------------------------------------
		 * 予約中の強制解約、および住所変更予約中のキャンセルの場合、回復時に予約情報を反映する必要があるため予約取消は行わない。
		 * ※ただし、未来日・予約確定レコードについては、予約適用年月日が到来した時点で、カレントレコードとなってしまうため、
		 *   以下の更新処理を行う。
		 * (1)予約解約(キャンセル)：解約時に予約レコードを"解約済"とする。
		 * (2)予約回復(キャンセル取消)：回復時に予約レコードを元のステータスに回復する。（現時点では、住所変更中の解約／回復に対してのみ実施する。）
		 * ------------------------------------------------------------------------------------------------------------------------ */
		
		// 該当の「機器オプションサービス契約」レコードの予約確定レコードを取得する。
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());
		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, kkopSvcKeiNo);
		inETMsg.set(KK2811ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_FIX);
		inETMsg.set(KK2811ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		CAANMsg[] retMsg = null;
		try
		{
			retMsg = new KK2811LE().findByCondition(inETMsg);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}
		
		// 予約キャンセル実行
		for (int i = 0; i < retMsg.length; i++)
		{
			// 予約適用年月日＞運用日付の予約確定レコードのみキャンセルする。
			if (JKKModelCommon.isFutureDate(retMsg[i].getString(KK2811ETMsg.RSV_APLY_YMD), opeDate, "0"))
			{
				updateKK2811CancelRsv(retMsg[i], svcCancelYmd, svcCancelRsnCd, updDtm, updOpeAct);
			}
		}
	}

	/**
	 * <p>
	 * 指定された機器オプションサービス契約番号に紐付く予約
	 * （該当の「機器オプションサービス契約」レコードのうち、未来日での予約確定レコード）を回復します。
	 * </p>
	 * @param kkopSvcKeiNo 回復対象の機器オプションサービス契約番号
	 * @param opeDate 運用日付
	 * @param dslBfKktkSvcKeiStat 解約前機器オプションサービス契約ステータス
	 * @param svcIfId サービスインターフェイスID
	 * @param kaihkYmd 回復年月日
	 * @param svcDslClYmd サービス解約取消年月日
	 * @param svcCancelClYmd サービスキャンセル取消年月日
	 * @param haisoKigenYmd 配送期限年月日
	 * @param haisoArivShiteiYmd 配送到着指定年月日
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	public void kaihkRsvFixRec(String kkopSvcKeiNo, String opeDate,
			String dslBfKktkSvcKeiStat, String svcIfId, String kaihkYmd, String svcDslClYmd, String svcCancelClYmd,
			String haisoKigenYmd, String haisoArivShiteiYmd, String updDtm, String updOpeAct)
	{
		/* ------------------------------------------------------------------------------------------------------------------------
		 * 予約中の強制解約、および住所変更予約中の解約の場合、回復時に予約情報を反映する必要があるため予約取消は行わない。
		 * ※ただし、未来日・予約確定レコードについては、予約適用年月日が到来した時点で、カレントレコードとなってしまうため、
		 *   以下の更新処理を行う。
		 * (1)予約解約(キャンセル)：解約時に予約レコードを"解約済"とする。
		 * (2)予約回復(キャンセル取消)：回復時に予約レコードを元のステータスに回復する。（現時点では、住所変更中の解約／回復に対してのみ実施する。）
		 * ------------------------------------------------------------------------------------------------------------------------ */
		// 該当の「機器オプションサービス契約」レコードの予約確定レコードを取得する。
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());
		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, kkopSvcKeiNo);
		inETMsg.set(KK2811ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_FIX);
		inETMsg.set(KK2811ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		CAANMsg[] retMsg = null;
		try
		{
			retMsg = new KK2811LE().findByCondition(inETMsg);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}

		// 予約回復実行
		for (int i = 0; i < retMsg.length; i++)
		{
			// 住所変更による予約以外は、予約回復の対象外
			if (!JKKModelConst.IDO_DIV_ADCHG_ADD.equals(retMsg[i].getString(KK2811ETMsg.IDO_DIV)))
			{
				continue;
			}
			
			// 予約適用年月日＞運用日付の予約確定レコードのみ回復する。
			if (JKKModelCommon.isFutureDate(retMsg[i].getString(KK2811ETMsg.RSV_APLY_YMD), opeDate, "0"))
			{
				updateKK2811KaihkRsv(retMsg[i], svcIfId, dslBfKktkSvcKeiStat, kaihkYmd, svcDslClYmd, svcCancelClYmd,
						haisoKigenYmd, haisoArivShiteiYmd, updDtm, updOpeAct);
			}
		}
	}

	/**
	 * <p>
	 * 指定された機器オプションサービス契約番号に紐付く、機器オプションサービス契約スキーマの予約レコードを回復します。
	 * </p>
	 * @param inMsg 予約検索の結果を保持するメッセージキャリア
	 * @param svcIfId サービスインターフェイスID
	 * @param dslBfKktkSvcKeiStat 解約前機器オプションサービス契約ステータス
	 * @param kaihkYmd 回復年月日
	 * @param svcDslClYmd サービス解約取消年月日
	 * @param svcCancelClYmd サービスキャンセル取消年月日
	 * @param haisoKigenYmd 配送期限年月日
	 * @param haisoArivShiteiYmd 配送到着指定年月日
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	private void updateKK2811KaihkRsv(CAANMsg inMsg, String svcIfId, String dslBfKktkSvcKeiStat, String kaihkYmd,
			String svcDslClYmd, String svcCancelClYmd, String haisoKigenYmd, String haisoArivShiteiYmd, String updDtm, String updOpeAct)
	{
		// 更新用メッセージ作成
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());

		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, inMsg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO));
		inETMsg.set(KK2811ETMsg.GENE_ADD_DTM, inMsg.getString(KK2811ETMsg.GENE_ADD_DTM));

		if (SIF_IF_EKK2811C120.equals(svcIfId) || SIF_IF_EKK2811C130.equals(svcIfId))
		{
			// 機器オプションサービス契約ステータス
			inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_STAT, dslBfKktkSvcKeiStat);
			// サービスキャンセル年月日
			inETMsg.setNull(KK2811ETMsg.SVC_CANCEL_YMD);
			// サービスキャンセル理由コード
			inETMsg.setNull(KK2811ETMsg.SVC_CANCEL_RSN_CD);
			// サービスキャンセル取消年月日
			inETMsg.set(KK2811ETMsg.SVC_CANCEL_CL_YMD, svcCancelClYmd);
		}
		else
		{
			// 終了年月日初期値
			String initEndYmd = null;
			if (JKKModelConst.KKOP_SVC_KEI_STAT_SVCTK_CHU.equals(dslBfKktkSvcKeiStat)
					|| JKKModelConst.KKOP_SVC_KEI_STAT_PAUSE_STP_CHU.equals(dslBfKktkSvcKeiStat))
			{
				// "サービス提供中"または"休止・中断中"に回復させる場合、終了年月日に最大日付を設定
				initEndYmd = JKKModelConst.DATE_MAX;
			}

			// 機器オプションサービス契約ステータス
			inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_STAT, dslBfKktkSvcKeiStat);
			// サービス終了年月日
			inETMsg.set(KK2811ETMsg.SVC_ENDYMD, initEndYmd);
			// サービス課金終了年月日
			inETMsg.set(KK2811ETMsg.SVC_CHRG_ENDYMD, initEndYmd);
			// プラン終了年月日
			inETMsg.set(KK2811ETMsg.PLAN_ENDYMD, initEndYmd);
			// プラン課金終了年月日
			inETMsg.set(KK2811ETMsg.PLAN_CHRG_ENDYMD, initEndYmd);
			// プラン終了種別コード
			inETMsg.setNull(KK2811ETMsg.PLAN_END_SBT_CD);
			// サービス解約年月日
			inETMsg.setNull(KK2811ETMsg.SVC_DSL_YMD);
			// サービス解約理由コード
			inETMsg.setNull(KK2811ETMsg.SVC_DLRE_CD);
			// サービス解約理由メモ
			inETMsg.setNull(KK2811ETMsg.SVC_DLRE_MEMO);
			// サービス解約手続完了フラグ
			inETMsg.setNull(KK2811ETMsg.SVC_DSL_TTDKI_FIN_FLG);
			// 回復年月日
			if (kaihkYmd != null && !"".equals(kaihkYmd))
			{
				inETMsg.set(KK2811ETMsg.KAIHK_YMD, kaihkYmd);
			}
			// サービス解約取消年月日
			if (svcDslClYmd != null && !"".equals(svcDslClYmd))
			{
				inETMsg.set(KK2811ETMsg.SVC_DSL_CL_YMD, svcDslClYmd);
			}
		}

		inETMsg.set(KK2811ETMsg.UPD_DTM, updDtm);
		inETMsg.set(KK2811ETMsg.UPD_OPEACNT, updOpeAct);

		// 更新を行う
		try
		{
			super.update(inETMsg);
		}
		catch (CAANFinderException cfe)
		{
			throw new CAANRuntimeException(cfe);
		}
	}

	/**
	 * 指定された機器オプションサービス契約番号に紐付く、機器オプションサービス契約スキーマの予約をキャンセルします。
	 * @param inMsg 予約検索の結果を保持するメッセージキャリア
	 * @param svcCancelYmd サービスキャンセル年月日
	 * @param svcDlreCd サービスキャンセル理由コード
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	private void updateKK2811CancelRsv(CAANMsg inMsg, String svcCancelYmd, String svcCancelRsnCd, String updDtm, String updOpeAct)
	{
		// 更新用メッセージ作成
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());

		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, inMsg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO));
		inETMsg.set(KK2811ETMsg.GENE_ADD_DTM, inMsg.getString(KK2811ETMsg.GENE_ADD_DTM));
		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_STAT, JKKModelConst.KKOP_SVC_KEI_STAT_CNCL_ZM);
		inETMsg.set(KK2811ETMsg.SVC_CANCEL_YMD, svcCancelYmd);
		inETMsg.set(KK2811ETMsg.SVC_CANCEL_RSN_CD, svcCancelRsnCd);
		inETMsg.set(KK2811ETMsg.UPD_DTM, updDtm);
		inETMsg.set(KK2811ETMsg.UPD_OPEACNT, updOpeAct);

		// 更新を行う
		try
		{
			super.update(inETMsg);
		}
		catch (CAANFinderException cfe)
		{
			throw new CAANRuntimeException(cfe);
		}
	}
	
	

	/**
	 * <p>
	 * 指定された機器オプションサービス契約番号に紐付く予約の取消、および自動予約取消ワークの登録を行います。
	 * </p>
	 * @param kkopSvcKeiNo 取り消し対象の機器オプションサービス契約番号
	 * @param idoDiv 異動区分
	 * @param mskmDtlNo 申込明細番号
	 * @param opeDate 運用日付
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 * @param autoRsvClStatCd 自動予約取消状態コード("取消済"/"自動予約取消未実施"：予約取消を実施する/しない)
	 */
	public void cancelReserve(String kkopSvcKeiNo, String idoDiv, String mskmDtlNo,
			String opeDate, String updDtm, String updOpeAct, String autoRsvClStatCd)
	{
		// 機器オプションサービス契約スキーマの予約取消

		// 予約検索用メッセージ作成
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());
		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, kkopSvcKeiNo);
		inETMsg.set(KK2811ETMsg.RSV_APLY_YMD, opeDate);

		// 予約検索を行う
		CAANMsg[] retMsgList = super.findByReserve(inETMsg);

		// 取得した予約レコードを全て取り消す
		for (CAANMsg retMsg : retMsgList)
		{
			// 自動予約取消状態コードが"取消済"の場合のみ、予約取消実施
			if (JKKModelConst.AUTO_RSV_CL_STAT_CD_CL_ZM.equals(autoRsvClStatCd))
			{
				updateKK2811ClRsv(retMsg, opeDate, updDtm, updOpeAct);
			}
			// 自動予約取消ワークに登録します
			this.createKK2791GymSchema(retMsg, idoDiv, mskmDtlNo, updDtm, updOpeAct, autoRsvClStatCd);
		}

		// 異動予約スキーマの予約取消

		// 予約検索を行う
		List<CAANMsg> retList = new JKKejbIdoRsvAccess().getIdoRsvKkopSvcKeiNo(kkopSvcKeiNo, opeDate);

		// 予約レコードが存在した場合は取り消す
		for (CAANMsg retIdoRsv : retList)
		{
			// ただし、申込明細番号が同一のものは処理しない
			if (mskmDtlNo != null && !mskmDtlNo.equals(retIdoRsv.getString(KK1681ETMsg.MSKM_DTL_NO)))
			{
				// 自動予約取消状態コードが"取消済"の場合のみ、予約取消実施
				if (JKKModelConst.AUTO_RSV_CL_STAT_CD_CL_ZM.equals(autoRsvClStatCd))
				{
					new JKKejbKK1681SecProc().updateKK1681ClRsv(retIdoRsv, opeDate, updDtm, updOpeAct);
				}
				// 自動予約取消ワークに登録します
				this.createKK2791IdoRsv(retIdoRsv, idoDiv, mskmDtlNo, updDtm, updOpeAct, autoRsvClStatCd);
			}
		}
	}

	/**
	 * 指定された機器オプションサービス契約番号に紐付く、機器オプションサービス契約スキーマの予約を取り消します。
	 * @param inMsg 予約検索の結果を保持するメッセージキャリア
	 * @param opeDate 運用日付
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	private void updateKK2811ClRsv(CAANMsg inMsg, String opeDate, String updDtm, String updOpeAct)
	{
		// 更新用メッセージ作成
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());

		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, inMsg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO));
		inETMsg.set(KK2811ETMsg.GENE_ADD_DTM, inMsg.getString(KK2811ETMsg.GENE_ADD_DTM));
		inETMsg.set(KK2811ETMsg.RSV_CL_YMD, opeDate);
		inETMsg.set(KK2811ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_CL);
		inETMsg.set(KK2811ETMsg.UPD_DTM, updDtm);
		inETMsg.set(KK2811ETMsg.UPD_OPEACNT, updOpeAct);

		// 更新を行う
		try
		{
			super.update(inETMsg);
		}
		catch (CAANFinderException cfe)
		{
			throw new CAANRuntimeException(cfe);
		}
	}
	
	/**
	 * <p>
	 * 自動予約取消ワークに異動予約の予約情報を登録します
	 * </p>
	 * @param kk1681EtMsg ETメッセージ
	 * @param idoDiv 異動区分
	 * @param mskmDtlNo 申込明細番号
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 * @param autoRsvClStatCd 自動予約取消状態コード
	 */
	private void createKK2791IdoRsv(CAANMsg kk1681EtMsg, String idoDiv, String mskmDtlNo, String updDtm, String updOpeAct, String autoRsvClStatCd)
	{
		// 自動予約取消ワークＤＢ操作部品のインスタンス化
		JKKejbKK2791ETDA kk2791etda = new JKKejbKK2791ETDA();

		// 取消契機異動区分
		kk2791etda.setCl_opty_ido_div(idoDiv);
		// 取消契機申込明細番号
		kk2791etda.setCl_opty_mskm_dtl_no(mskmDtlNo);
		// 登録年月日時分秒
		kk2791etda.setAdd_dtm(updDtm);
		// 登録オペレータアカウント
		kk2791etda.setAdd_opeacnt(updOpeAct);
		// 更新年月日時分秒
		kk2791etda.setUpd_dtm(updDtm);
		// 更新オペレータアカウント
		kk2791etda.setUpd_opeacnt(updOpeAct);

		// 自動予約取消ワークの登録
		kk2791etda.createKK2791(kk1681EtMsg, "KK1681", autoRsvClStatCd);
	}

	/**
	 * <p>
	 * 自動予約取消ワークに機器提供サービス契約の予約情報を登録します
	 * </p>
	 * @param kk2811EtMsg ETメッセージ
	 * @param idoDiv 異動区分
	 * @param mskmDtlNo 申込明細番号
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 * @param autoRsvClStatCd 自動予約取消状態コード
	 */
	private void createKK2791GymSchema(CAANMsg kk2811EtMsg, String idoDiv, String mskmDtlNo, String updDtm, String updOpeAct, String autoRsvClStatCd)
	{
		// 自動予約取消ワークＤＢ操作部品のインスタンス化
		JKKejbKK2791ETDA kk2791etda = new JKKejbKK2791ETDA();

		// 取消契機異動区分
		kk2791etda.setCl_opty_ido_div(idoDiv);
		// 取消契機申込明細番号
		kk2791etda.setCl_opty_mskm_dtl_no(mskmDtlNo);
		// 予約契機異動区分
		kk2791etda.setRsv_opty_ido_div(kk2811EtMsg.getString(KK2811ETMsg.IDO_DIV));
		// 予約契機申込明細番号
		kk2791etda.setRsv_opty_mskm_dtl_no(kk2811EtMsg.getString(KK2811ETMsg.MSKM_DTL_NO));
		// 予約適用年月日
		kk2791etda.setRsv_aply_ymd(kk2811EtMsg.getString(KK2811ETMsg.RSV_APLY_YMD));
		// 各種スキーマ世代登録年月日時分秒
		kk2791etda.setVari_schma_gene_add_dtm(kk2811EtMsg.getString(KK2811ETMsg.GENE_ADD_DTM));
		// 予約適用コード
		kk2791etda.setRsv_aply_cd(kk2811EtMsg.getString(KK2811ETMsg.RSV_APLY_CD));
		// 登録年月日時分秒
		kk2791etda.setAdd_dtm(updDtm);
		// 登録オペレータアカウント
		kk2791etda.setAdd_opeacnt(updOpeAct);
		// 更新年月日時分秒
		kk2791etda.setUpd_dtm(updDtm);
		// 更新オペレータアカウント
		kk2791etda.setUpd_opeacnt(updOpeAct);
		// 機器オプションサービス契約番号
		kk2791etda.setKkop_svc_kei_no(kk2811EtMsg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO));

		// 自動予約取消ワークの登録
		kk2791etda.createKK2791(kk2811EtMsg, "KK2811", autoRsvClStatCd);
	}
	

	/**
	 * <p>
	 * 指定された機器オプションサービス契約番号に紐付く予約
	 * （該当の「機器オプションサービス契約」レコードのうち、未来日での予約確定レコード）を解約します。
	 * </p>
	 * @param kkopSvcKeiNo 解約対象の機器オプションサービス契約番号
	 * @param opeDate 運用日付
	 * @param svcEndymd サービス終了年月日
	 * @param svcChrgEndYmd サービス課金終了年月日
	 * @param svcDlreCd サービス解約理由コード
	 * @param svcDlreMemo サービス解約理由メモ
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	public void dslRsvFixRec(String kkopSvcKeiNo, String opeDate,
			String svcEndymd, String svcChrgEndYmd, String svcDlreCd, String svcDlreMemo,
			String updDtm, String updOpeAct)
	{
		/* ------------------------------------------------------------------------------------------------------------------------
		 * 予約中の強制解約、および住所変更予約中の解約の場合、回復時に予約情報を反映する必要があるため予約取消は行わない。
		 * ※ただし、未来日・予約確定レコードについては、予約適用年月日が到来した時点で、カレントレコードとなってしまうため、
		 *   以下の更新処理を行う。
		 * (1)予約解約(キャンセル)：解約時に予約レコードを"解約済"とする。
		 * (2)予約回復(キャンセル取消)：回復時に予約レコードを元のステータスに回復する。（現時点では、住所変更中の解約／回復に対してのみ実施する。）
		 * ------------------------------------------------------------------------------------------------------------------------ */
		
		// 該当の「機器オプションサービス契約」レコードの予約確定レコードを取得する。
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());
		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, kkopSvcKeiNo);
		inETMsg.set(KK2811ETMsg.RSV_APLY_CD, JKKModelConst.RSV_APLY_CD_RSV_FIX);
		inETMsg.set(KK2811ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		CAANMsg[] retMsg = null;
		try
		{
			retMsg = new KK2811LE().findByCondition(inETMsg);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}
		
		// 予約解約実行
		for (int i = 0; i < retMsg.length; i++)
		{
			// 予約適用年月日＞運用日付の予約確定レコードのみ解約する。
			if (JKKModelCommon.isFutureDate(retMsg[i].getString(KK2811ETMsg.RSV_APLY_YMD), opeDate, "0"))
			{
				updateKK2811DslRsv(retMsg[i], svcEndymd, svcChrgEndYmd, svcDlreCd, svcDlreMemo, updDtm, updOpeAct);
			}
		}
	}

	/**
	 * <p>
	 * 指定された機器オプションサービス契約番号に紐付く、機器オプションサービス契約スキーマの予約レコードを解約します。
	 * </p>
	 * @param inMsg 予約検索の結果を保持するメッセージキャリア
	 * @param svcEndymd サービス終了年月日
	 * @param svcChrgEndYmd サービス課金終了年月日
	 * @param svcDlreCd サービス解約理由コード
	 * @param svcDlreMemo サービス解約理由メモ
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	private void updateKK2811DslRsv(CAANMsg inMsg,
			String svcEndymd, String svcChrgEndYmd, String svcDlreCd, String svcDlreMemo,
			String updDtm, String updOpeAct)
	{
		// 更新用メッセージ作成
		CAANMsg inETMsg = new CAANMsg(KK2811ETMsg.class.getName());

		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_NO, inMsg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO));
		inETMsg.set(KK2811ETMsg.GENE_ADD_DTM, inMsg.getString(KK2811ETMsg.GENE_ADD_DTM));
		// 機器オプションサービス契約ステータス
		inETMsg.set(KK2811ETMsg.KKOP_SVC_KEI_STAT, JKKModelConst.KKOP_SVC_KEI_STAT_DSL_ZM);
		// サービス終了年月日
		inETMsg.set(KK2811ETMsg.SVC_ENDYMD, JKKModelCommon.getYmdDslFix(inMsg, svcEndymd));
		// サービス課金終了年月日
		inETMsg.set(KK2811ETMsg.SVC_CHRG_ENDYMD, svcChrgEndYmd);
		// プラン終了年月日
		inETMsg.set(KK2811ETMsg.PLAN_ENDYMD, svcEndymd);
		// プラン課金終了年月日
		inETMsg.set(KK2811ETMsg.PLAN_CHRG_ENDYMD, svcChrgEndYmd);
		// サービス解約年月日
		inETMsg.set(KK2811ETMsg.SVC_DSL_YMD, JKKModelCommon.getYmdDslFix(inMsg, svcEndymd));
		// サービス解約理由コード
		inETMsg.set(KK2811ETMsg.SVC_DLRE_CD, svcDlreCd);
		// サービス解約理由メモ
		inETMsg.set(KK2811ETMsg.SVC_DLRE_MEMO, svcDlreMemo);
		
		inETMsg.set(KK2811ETMsg.UPD_DTM, updDtm);
		inETMsg.set(KK2811ETMsg.UPD_OPEACNT, updOpeAct);
		
		// 更新を行う
		try
		{
			super.update(inETMsg);
		}
		catch (CAANFinderException cfe)
		{
			throw new CAANRuntimeException(cfe);
		}
	}

	/**
	 * <p>
	 * 回線に紐付く機器提供サービス契約のステータスの変更を行います。
	 * </p>
	 * @param inCBSMsg　CBSメッセージ
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param svc_kei_no　サービス契約番号
	 * @param gene_add_dtm　世代登録年月日時分秒
	 */
	public void execFromKktkSvcKei(CAANMsg inCBSMsg, AgentDispatchContext inContext, String svc_kei_no, String gene_add_dtm)
	{
		// サービス契約の照会を行う
		CAANMsg inETMsgCurrent = new CAANMsg(KK0081ETMsg.class.getName());
		inETMsgCurrent.set(KK0081ETMsg.SVC_KEI_NO, svc_kei_no);
		inETMsgCurrent.set(KK0081ETMsg.GENE_ADD_DTM, gene_add_dtm);
		CAANMsg otETMsg = new JKKejbKK0081DBABase().findByPrimaryKey(inETMsgCurrent);
		
		// サービス契約内訳が存在しない場合は終了
		if (otETMsg == null)
		{
			return;
		}

		//紐づくオプションサービス契約・機器提供サービス契約を
		//作成する。
		String mskmDtlNo = otETMsg.getString(KK0081ETMsg.MSKM_DTL_NO);
		String rsvAplyYmd = otETMsg.getString(KK0081ETMsg.RSV_APLY_YMD);
		String pause_stp_cd = otETMsg.getString(KK0081ETMsg.PAUSE_STP_CD);
		String svc_pause_ymd = otETMsg.getString(KK0081ETMsg.SVC_PAUSE_YMD);
		String svc_pause_rsn_cd = otETMsg.getString(KK0081ETMsg.SVC_PAUSE_RSN_CD);
		String svc_pause_rsn_memo = otETMsg.getString(KK0081ETMsg.SVC_PAUSE_RSN_MEMO);
		String svc_pause_rls_ymd = otETMsg.getString(KK0081ETMsg.SVC_PAUSE_RLS_YMD);
		String svc_pause_rls_rsn_cd = otETMsg.getString(KK0081ETMsg.SVC_PAUSE_RLS_RSN_CD);
		String svc_pause_rls_rsn_memo = otETMsg.getString(KK0081ETMsg.SVC_PAUSE_RLS_RSN_MEMO);
		String svc_pause_chrg_sta_ymd = otETMsg.getString(KK0081ETMsg.SVC_PAUSE_CHRG_STA_YMD);
		String idoDiv = otETMsg.getString(KK0081ETMsg.IDO_DIV);
		String svc_kei_stat = otETMsg.getString(KK0081ETMsg.SVC_KEI_STAT);
		String svc_cd = otETMsg.getString(KK0081ETMsg.SVC_CD);

		//サービス契約のステータスが「休止・中断中」の場合、区分にtrueを設定
		//サービス契約のステータスが「休止・中断中」でない場合、区分にfalseを設定
		boolean kbn = true;
		if(!"210".equals(svc_kei_stat))
		{
			kbn = false;
		}

		// 回線対象サービス契約の照会を行う
		CAANMsg inKK0241ETMsg = new CAANMsg(KK0241ETMsg.class.getName());
		inKK0241ETMsg.set(KK0241ETMsg.SVC_KEI_NO, svc_kei_no);
		inKK0241ETMsg.set(KK0241ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);
		KK0241LE kk0241 = new KK0241LE();
		CAANMsg[] otKK0241ETMsg = null;

		try
		{
			otKK0241ETMsg = kk0241.findByCondition(inKK0241ETMsg);
		}
		catch (CAANException e1)
		{
			throw new CAANRuntimeException(e1);
		}

		// サービス契約に紐付く回線対象サービス契約が存在しない場合は終了
		int listCnt = otKK0241ETMsg.length;
		if (listCnt < 1)
		{
			return;
		}

		String svcKeiKaisenUcwkNo = otKK0241ETMsg[0].getString(KK0241ETMsg.SVC_KEI_KAISEN_UCWK_NO);

		kkopSvKeiPause(inCBSMsg, inContext, svc_kei_no, svcKeiKaisenUcwkNo, mskmDtlNo, rsvAplyYmd, 
			pause_stp_cd, svc_pause_ymd, svc_pause_rsn_cd, svc_pause_rsn_memo, 
			svc_pause_rls_ymd, svc_pause_rls_rsn_cd, svc_pause_rls_rsn_memo, 
			svc_pause_chrg_sta_ymd, idoDiv, kbn, svc_cd);
	}

	/**
	 * <p>
	 * 機器提供サービス契約の休止・中断または休止解除・中断解除データを作成します。
	 * </p>
	 * @param inCBSMsg　CBSメッセージ
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param svcKeiNo　サービス契約番号
	 * @param svcKeiKaisenUcwkNo　サービス契約回線内訳番号
	 * @param mskmDtlNo　申込明細番号
	 * @param rsvAplyYmd　予約適用年月日
	 * @param pause_stp_cd　休止中断コード
	 * @param svc_pause_ymd　サービス休止年月日
	 * @param svc_pause_rsn_cd　サービス休止理由コード
	 * @param svc_pause_rsn_memo　サービス休止理由メモ
	 * @param svc_pause_rls_ymd　サービス休止解除年月日
	 * @param svc_pause_rls_rsn_cd　サービス休止解除理由コード
	 * @param svc_pause_rls_rsn_memo　サービス休止解除理由メモ
	 * @param svc_pause_chrg_sta_ymd　サービス休止課金開始年月日
	 * @param idoDiv　異動区分
	 * @param kbn　休止・中断区分フラグ（true:「休止・中断」、false:「休止解除・中断解除」）
	 * @param svc_cd　サービスコード
	 */
	private void kkopSvKeiPause(CAANMsg inCBSMsg, AgentDispatchContext inContext, String svcKeiNo, String svcKeiKaisenUcwkNo,
			String mskmDtlNo, String rsvAplyYmd, String pause_stp_cd, String svc_pause_ymd, String svc_pause_rsn_cd, String svc_pause_rsn_memo,
			String svc_pause_rls_ymd, String svc_pause_rls_rsn_cd, String svc_pause_rls_rsn_memo, 
			String svc_pause_chrg_sta_ymd, String idoDiv, boolean kbn, String svc_cd)
	{
		List<CAANMsg[]> kikiList = new ArrayList<CAANMsg[]>();
		
		HashMap<String, String[]> searchJknMap = new HashMap<String, String[]>();
		JKKejbKK0341DBABase kk0341DBABase = new JKKejbKK0341DBABase();
		
		// 現在使用中の回線に紐づく機器の一覧を取得する。
		CAANMsg[] kk0341ListMsg = kk0341DBABase.getKK0341FromKK0251bySvcKei(svcKeiNo, svc_cd , searchJknMap, JKKModelCommon.getOpeDate(inCBSMsg), "1");

		// 現在使用中のサービス契約に紐づく機器の一覧を取得する。
		CAANMsg[] kk0341ListMsgSvcKei = kk0341DBABase.getKK0341bySvcKei(svcKeiNo, null, JKKModelCommon.getOpeDate(inCBSMsg), "1");
		
		if(kk0341ListMsg != null && kk0341ListMsg.length != 0 ) {
			kikiList.add(kk0341ListMsg);			
		}
		if(kk0341ListMsgSvcKei != null &&  kk0341ListMsgSvcKei.length != 0 ) {
			kikiList.add(kk0341ListMsgSvcKei);			
		}
		
		// 機器提供サービス契約が取得できない場合、処理を終了する。
		if(kikiList == null || kikiList.size() == 0) {
			return;
		}
		
		for(int i = 0 ; i < kikiList.size() ; i ++ ) {
			kk0341ListMsg = kikiList.get(i);
			
			for(CAANMsg kk0341Msg : kk0341ListMsg) {
				String strKKtkSvcKeiNo = kk0341Msg.getString(KK0341ETMsg.KKTK_SVC_KEI_NO);
				String strKKtkSvcCD = kk0341Msg.getString(KK0341ETMsg.KKTK_SVC_CD);
				
				// 機器が多機能ルータ又はＨＧＷでない場合、エラーとする。
				// ANK-4315-00-00 MOD START
//				if(!JKKModelConst.KKTK_SVC_CD_TAKINORT.equals(strKKtkSvcCD) && !JKKModelConst.KKTK_SVC_CD_TABLET.equals(strKKtkSvcCD)) {
				if(!JKKModelConst.KKTK_SVC_CD_TAKINORT.equals(strKKtkSvcCD) && !JKKModelConst.KKTK_SVC_CD_TABLET.equals(strKKtkSvcCD) && !JKKModelConst.KKTK_SVC_CD_HGW.equals(strKKtkSvcCD)) {
				// ANK-4315-00-00 MOD END
					continue;
				}
				
				String searchPattern = "1";
				// ANK-4315-00-00 MOD START
//				if(JKKModelConst.KKTK_SVC_CD_TAKINORT.equals(strKKtkSvcCD)) {
				if(JKKModelConst.KKTK_SVC_CD_TAKINORT.equals(strKKtkSvcCD) || JKKModelConst.KKTK_SVC_CD_HGW.equals(strKKtkSvcCD)) {
				// ANK-4315-00-00 MOD END
					if(JKKModelConst.SVC_CD_NET.equals(svc_cd)) {
						searchPattern = "2";
					} else if(JKKModelConst.SVC_CD_TEL.equals(svc_cd)) {
						searchPattern = "3";				
					} else {
						continue;
					}
				}
				
				// 機器提供サービス契約番号から機器オプションを取得する。
				CAANMsg[] kk2811ListMsg = new JKKejbKK2811DBABase().getKK2811byKktk(strKKtkSvcKeiNo, null, JKKModelCommon.getOpeDate(inCBSMsg), searchPattern);
				
				// 処理済み機器オプションサービス契約保持用
				HashMap<String, String> hash = new HashMap<String, String>();
				try {
					for(CAANMsg kk2811Msg : kk2811ListMsg) {
						
						if (hash.containsKey(kk2811Msg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO)))
						{
							continue;
						}
						// 読み込んだ機器提供サービス契約番号を控える
						hash.put(kk2811Msg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO), kk2811Msg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO));
		
						CAANMsg inMsgKK2811 = new CAANMsg(KK2811ETMsg.class.getName());
						inMsgKK2811.set(KK2811ETMsg.KKOP_SVC_KEI_NO, kk2811Msg.getString(KK2811ETMsg.KKOP_SVC_KEI_NO));
						inMsgKK2811.set(KK2811ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inCBSMsg));
						CAANMsg retCurrent = new JKKejbKK2811DBABase().findByCurrent(inMsgKK2811);
		
						if(retCurrent == null)
						{
							continue;
						}
		
						String stat = retCurrent.getString(KK2811ETMsg.KKOP_SVC_KEI_STAT);
		
						//休止・中断の場合かつカレントステータスが「サービス提供中」の場合、「休止・中断中」のデータを作成する
						//休止解除・中断解除の場合かつステータスが「休止・中断中」の場合、「サービス提供中」のデータを作成する
						if("100".equals(stat) && kbn)
						{
							stat = "210";
						}
						else if("210".equals(stat) && !kbn)
						{
							stat = "100";
						}
						else
						{
							continue;
						}
						
						// 機器提供サービス契約 新規レコード用Msg生成
						CAANMsg create2811Msg = retCurrent;
		
						// 新規レコード用メッセージ設定
						create2811Msg.set(KK2811ETMsg.GENE_ADD_DTM, (String)JKKModelCommon.getTransferGeneAddDtm(inCBSMsg, inContext));
						create2811Msg.set(KK2811ETMsg.KKOP_SVC_KEI_STAT, stat);
						
						create2811Msg.set(KK2811ETMsg.RSV_APLY_YMD, rsvAplyYmd);
						create2811Msg.set(KK2811ETMsg.RSV_APLY_CD, "2");
		
						if(kbn)
						{
							create2811Msg.set(KK2811ETMsg.PAUSE_STP_CD, pause_stp_cd);
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_YMD, svc_pause_ymd);
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_RSN_CD, svc_pause_rsn_cd);
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_RSN_MEMO, svc_pause_rsn_memo);
							create2811Msg.setNull(KK2811ETMsg.SVC_PAUSE_RLS_YMD);
							create2811Msg.setNull(KK2811ETMsg.SVC_PAUSE_RLS_RSN_CD);
							create2811Msg.setNull(KK2811ETMsg.SVC_PAUSE_RLS_RSN_MEMO);
		
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_CHRG_STA_YMD, svc_pause_chrg_sta_ymd);
						}
						else
						{
							create2811Msg.set(KK2811ETMsg.PAUSE_STP_CD, retCurrent.getString(KK0341ETMsg.PAUSE_STP_CD));
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_YMD, retCurrent.getString(KK0341ETMsg.SVC_PAUSE_YMD));
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_RSN_CD, retCurrent.getString(KK0341ETMsg.SVC_PAUSE_RSN_CD));
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_RSN_MEMO, retCurrent.getString(KK0341ETMsg.SVC_PAUSE_RSN_MEMO));
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_RLS_YMD, svc_pause_rls_ymd);
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_RLS_RSN_CD, svc_pause_rls_rsn_cd);
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_RLS_RSN_MEMO, svc_pause_rls_rsn_memo);
		
							create2811Msg.set(KK2811ETMsg.SVC_PAUSE_CHRG_STA_YMD, retCurrent.getString(KK0341ETMsg.SVC_PAUSE_CHRG_STA_YMD));
		
						}
		
						create2811Msg.set(KK2811ETMsg.IDO_DIV, idoDiv);
		
						create2811Msg.set(KK2811ETMsg.ADD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
						create2811Msg.set(KK2811ETMsg.ADD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
						create2811Msg.set(KK2811ETMsg.UPD_DTM, inCBSMsg.getString(JCMConstants.OPERATE_DATETIME_KEY));
						create2811Msg.set(KK2811ETMsg.UPD_OPEACNT, inCBSMsg.getString(JCMConstants.OPERATOR_ID_KEY));
						create2811Msg.setNull(KK2811ETMsg.DEL_DTM);
						create2811Msg.setNull(KK2811ETMsg.DEL_OPEACNT);
						create2811Msg.set(KK2811ETMsg.MK_FLG, "0");
		
						// 登録処理の実行
						create(create2811Msg);
		
					}
				}
			
				catch (CAANCreateException e1)
				{
					throw new CAANRuntimeException(e1);
				}
			}
		}
		
	}
}
