/*******************************************************************************
 *  All Rights reserved,Copyright (c) K-Opticom
 ********************************************************************************
 *＜プログラム内容＞
 *  システム名      ：eo顧客基幹システム
 *  モジュール名    ：JKKejbKK1681SecProc
 *  ソースファイル名：JKKejbKK1681SecProc.java
 *  作成者          ：富士通
 *  日付            ：2013年05月23日
 *＜機能概要＞
 *  異動予約に対する副次処理を行う部品です。
 *＜修正履歴＞
 *  バージョン  修正日      修正者      修正内容
 *  v4.00.00    2013/05/23  FJ)竹内     新規作成
 *  v4.00.01    2013/07/10  FJ)竹内     ST4-2013-0000508
 *
 ********************************************************************************/

package eo.ejb.common.db;

import java.util.ArrayList;
import java.util.List;

import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;

import eo.ejb.cbm.entity.KK0351ETMsg;
import eo.ejb.cbm.entity.KK0351LE;
import eo.ejb.cbm.entity.KK0401ETMsg;
import eo.ejb.cbm.entity.KK0401LE;
import eo.ejb.cbm.entity.KK1681ETMsg;
import eo.ejb.cbm.entity.KK1681LE;
import eo.ejb.common.JKKModelCommon;
import eo.ejb.common.JKKModelConst;

/**
 * <p>
 * 異動予約に対する副次処理部品クラスです。
 * </p>
 * @author 富士通
 *
 */
public class JKKejbKK1681SecProc extends JKKejbKK1681DBABase
{

	/**
	 * コンストラクタです。
	 */
	public JKKejbKK1681SecProc()
	{
		super();
	}

	/**
	 * <p>
	 * 異動予約スキーマの予約を取り消します。
	 * </p>
	 * @param inMsg 予約検索の結果を保持するメッセージキャリア
	 * @param opeDate 運用日付
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	public void updateKK1681ClRsv(CAANMsg inMsg, String opeDate, String updDtm, String updOpeAct)
	{
		// 更新用メッセージ作成
		CAANMsg inETMsg = new CAANMsg(KK1681ETMsg.class.getName());

		inETMsg.set(KK1681ETMsg.IDO_RSV_NO, inMsg.getString(KK1681ETMsg.IDO_RSV_NO));
		inETMsg.set(KK1681ETMsg.IDO_RSV_STAT_CD, JKKModelConst.IDO_RSV_STAT_CD_CL_ZM);
		inETMsg.set(KK1681ETMsg.IDO_RSV_CL_YMD, opeDate);
		inETMsg.set(KK1681ETMsg.UPD_DTM, updDtm);
		inETMsg.set(KK1681ETMsg.UPD_OPEACNT, updOpeAct);

		// 更新を行う
		new JKKejbDBAUtil(inETMsg).update(inETMsg);
	}

	/**
	 * <p>
	 * 入力の異動予約リストから、対象の契約を回復(または解約取消)する際に、予約取消対象となる「異動予約」を取得します。<br>
	 * </p>
	 * 予約適用年月日が到来済、かつ予約未反映の「異動予約」(※)が予約取消対象となる。<br>
	 * ※「異動予約」の予約適用年月日が到来時に、対象の契約が【解約済】であった場合、予約反映処理がスキップされるため。<br>
	 * @param kk1681MsgList 異動予約リスト
	 * @param opeDate 運用日付
	 * @return 異動予約明細
	 */
	public List<CAANMsg> getIdoRsvForKaihkJiRsvCl(List<CAANMsg> kk1681MsgList, String opeDate)
	{
		/* ------------------------------------------------------------------------------------------------------------------------
		 * 回復(または解約取消)時の予約取消対象となる「異動予約」の条件
		 * @異動予約状態コード＝"未反映"or"予約手続中"、かつ 予約適用年月日≦基準年月日
		 * A異動区分が"オプション引継"、"解約"、"休止受付"、"休止変更・予約取消"、"機器契約変更"(※)、"オプション設定"
		 *   ※異動予約詳細コードが"機器解約"の場合のみ
		 * ------------------------------------------------------------------------------------------------------------------------ */

		List<CAANMsg> outList = new ArrayList<CAANMsg>();
		for (CAANMsg kk1681Msg : kk1681MsgList)
		{
			String idoDiv = kk1681Msg.getString(KK1681ETMsg.IDO_DIV);
			String idoRsvDtlCd = kk1681Msg.getString(KK1681ETMsg.IDO_RSV_DTL_CD);

			// 条件@の絞り込み
			// 異動予約リスト(【予約手続中】、【未反映】、【異動予約対象外(予約適用年月日が未来日)】)から、
			// 予約適用年月日が未来日(nullを含む)の「異動予約」を除外する。
			String rsvAplyYmd = kk1681Msg.getString(KK1681ETMsg.RSV_APLY_YMD);
			if (rsvAplyYmd == null || JKKModelCommon.isFutureDate(rsvAplyYmd, opeDate, "0"))
			{
				if (JKKModelConst.IDO_DIV_PAUSE_CHG_RSV_CL.equals(idoDiv)
						&& isExistsSameMskmPauseRsv(kk1681MsgList, kk1681Msg.getString(KK1681ETMsg.MSKM_DTL_NO), opeDate))
				{
					// ※特例として、以下1),2)を満たす場合は、未来日予約であっても予約取消を行う。
					// 1)サービス休止解除の「異動予約」(異動区分が"休止変更・予約取消")である。
					// 2)1)と同一申込のサービス休止の「異動予約」(異動区分が"休止受付")が予約取消対象である。
				}
				else
				{
					// 該当の「異動予約」を予約取消対象外とする。
					continue;
				}
			}

			// 条件Aの絞り込み
			if (JKKModelConst.IDO_DIV_OP_HKTGI.equals(idoDiv)
					|| JKKModelConst.IDO_DIV_DSL.equals(idoDiv)
					|| JKKModelConst.IDO_DIV_PAUSE_UK.equals(idoDiv)
					|| JKKModelConst.IDO_DIV_PAUSE_CHG_RSV_CL.equals(idoDiv)
					|| (JKKModelConst.IDO_DIV_KIKI_KEI_CHG.equals(idoDiv) && JKKModelConst.IDO_RSV_DTL_CD_KIKI_DSL.equals(idoRsvDtlCd))
					|| JKKModelConst.IDO_DIV_OP_SET.equals(idoDiv))
			{
				outList.add(kk1681Msg);
			}
		}

		return outList;
	}

	/**
	 * <p>
	 * 入力の異動予約リストに、サービス休止解除の「異動予約」と
	 * 同一申込のサービス休止の「異動予約」(予約適用年月日が過去日)が存在するかどうか判定します。<br>
	 * </p>
	 * @param kk1681MsgList 異動予約リスト
	 * @param mskmDtlNo サービス休止解除の「異動予約」の申込明細番号
	 * @param opeDate 運用日付
	 * @return true:同一申込のサービス休止の「異動予約」(予約適用年月日が過去日)が存在する場合、false:それ以外
	 */
	private boolean isExistsSameMskmPauseRsv(List<CAANMsg> kk1681MsgList, String mskmDtlNo, String opeDate)
	{
		for (CAANMsg kk1681Msg : kk1681MsgList)
		{
			// 予約適用年月日が未来日(nullを含む)の「異動予約」を除外する。
			String rsvAplyYmd = kk1681Msg.getString(KK1681ETMsg.RSV_APLY_YMD);
			if (rsvAplyYmd == null || JKKModelCommon.isFutureDate(rsvAplyYmd, opeDate, "0"))
			{
				continue;
			}

			// 異動区分が"休止受付"(サービス休止)、かつ申込明細番号が入力(サービス休止解除の「異動予約」の申込明細番号)と同一である場合
			if (JKKModelConst.IDO_DIV_PAUSE_UK.equals(kk1681Msg.getString(KK1681ETMsg.IDO_DIV))
					&& mskmDtlNo.equals(kk1681Msg.getString(KK1681ETMsg.MSKM_DTL_NO)))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * <p>
	 * 「異動予約」の取消に伴い、該当の「異動予約」と同時に作成された各種契約のインスタンスを削除する。<br>
	 * ※予約が取消になったにも関わらず、同時に作成された契約の情報が画面表示されてしまうなどの不具合が生じるため。
	 * </p>
	 * @param kk1681Msg 取消対象の異動予約のメッセージキャリア
	 * @param opeDate 運用日付
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	public void deleteInstanceForRsvCl(CAANMsg kk1681Msg, String opeDate, String updDtm, String updOpeAct)
	{
		// 各種スキーマのＤＢアクセス部品をインスタンス化
		JKKejbKK0351DBABase kk0351db = new JKKejbKK0351DBABase();
		JKKejbKK0401DBABase kk0401db = new JKKejbKK0401DBABase();

		String idoDiv = kk1681Msg.getString(KK1681ETMsg.IDO_DIV);
		String idoRsvDtlCd = kk1681Msg.getString(KK1681ETMsg.IDO_RSV_DTL_CD);

		// 異動区分が"オプション設定"の場合
		if (JKKModelConst.IDO_DIV_OP_SET.equals(idoDiv))
		{
			// 異動予約詳細コードが"オプション開始"の場合
			if (JKKModelConst.IDO_RSV_DTL_CD_OP_STA.equals(idoRsvDtlCd))
			{
				// 該当の「オプションサービス契約」を削除
				String opSvcKeiNo = kk1681Msg.getString(KK1681ETMsg.OP_SVC_KEI_NO);
				deleteOpSvcKeiForRsvCl(opSvcKeiNo, updDtm, updOpeAct);
			}
			// 異動予約詳細コードが"サブオプション開始"の場合
			else if (JKKModelConst.IDO_RSV_DTL_CD_SBOP_STA.equals(idoRsvDtlCd))
			{
				// 該当の「サブオプションサービス契約」を削除
				String opSvcKeiNo = kk1681Msg.getString(KK1681ETMsg.OP_SVC_KEI_NO);
				String sbopSvcKeiNo = kk1681Msg.getString(KK1681ETMsg.SBOP_SVC_KEI_NO);
				deleteSbopSvcKeiForRsvCl(opSvcKeiNo, sbopSvcKeiNo, updDtm, updOpeAct);
			}
		}
		// 異動区分が"オプション引継"の場合
		else if (JKKModelConst.IDO_DIV_OP_HKTGI.equals(idoDiv))
		{
			// オプション引継先サービス契約番号
			String opHktgiSkSvcKeiNo = kk1681Msg.getString(KK1681ETMsg.OP_HKTGI_SK_SVC_KEI_NO);

			// 引継先の「サービス契約」配下の「オプションサービス契約」を取得する。
			CAANMsg[] kk0351MsgList = kk0351db.getKK0351bySvcKei(opHktgiSkSvcKeiNo, null, opeDate, "3");

			// 引継先として新規作成された「オプションサービス契約」のみ削除する。
			for (CAANMsg kk0351Msg : kk0351MsgList)
			{
				// 該当の「オプションサービス契約」が引継対象である場合(「異動予約」と同一申込にて作成されている場合)
				String opSvcKeiNo = kk0351Msg.getString(KK0351ETMsg.OP_SVC_KEI_NO);
				if (isSameMskmOpByIdoRsv(opSvcKeiNo, kk1681Msg))
				{
					// 該当の「オプションサービス契約」を削除
					deleteOpSvcKeiForRsvCl(opSvcKeiNo, updDtm, updOpeAct);
				}

				// 該当の「オプションサービス契約」配下の「サブオプションサービス契約」を取得する。
				CAANMsg[] kk0401MsgList = kk0401db.getKK0401byOpSvcKei(opSvcKeiNo, null, opeDate);

				// 引継先として新規作成された「サブオプションサービス契約」のみ削除する。
				for (CAANMsg kk0401Msg : kk0401MsgList)
				{
					// 該当の「サブオプションサービス契約」が引継対象である場合(「異動予約」と同一申込にて作成されている場合)
					String sbopSvcKeiNo = kk0401Msg.getString(KK0401ETMsg.SBOP_SVC_KEI_NO);
					if (isSameMskmSbopByIdoRsv(opSvcKeiNo, sbopSvcKeiNo, kk1681Msg))
					{
						// 該当の「サブオプションサービス契約」を削除
						deleteSbopSvcKeiForRsvCl(opSvcKeiNo, sbopSvcKeiNo, updDtm, updOpeAct);
					}
				}
			}
		}

		// その他の異動区分の場合は、削除処理対象外
		return;
	}

	/**
	 * <p>
	 * 該当の「オプションサービス契約」が、対象の「異動予約」と同一申込にて作成された「オプションサービス契約」かどうかを判定する。
	 * </p>
	 * @param opSvcKeiNo オプションサービス契約番号
	 * @param kk1681Msg 「異動予約」のメッセージキャリア
	 * @return true:対象の「異動予約」と同一申込にて作成された「オプションサービス契約」である場合、false:それ以外
	 */
	private boolean isSameMskmOpByIdoRsv(String opSvcKeiNo, CAANMsg kk1681Msg)
	{
		// 対象の「オプションサービス契約」の履歴世代レコードのうち、「異動予約」の異動区分、申込明細番号に紐づくレコードを取得
		CAANMsg searchKey = new CAANMsg(KK0351ETMsg.class.getName());
		searchKey.set(KK0351ETMsg.OP_SVC_KEI_NO, opSvcKeiNo);
		searchKey.set(KK0351ETMsg.IDO_DIV, kk1681Msg.getString(KK1681ETMsg.IDO_DIV));
		searchKey.set(KK0351ETMsg.MSKM_DTL_NO, kk1681Msg.getString(KK1681ETMsg.MSKM_DTL_NO));
		searchKey.set(KK0351ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		CAANMsg[] kk0351CondInfoList = null;
		try
		{
			kk0351CondInfoList = new KK0351LE().findByCondition(searchKey);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}

		// １件でも存在する場合、対象の「異動予約」と同一申込にて作成された「オプションサービス契約」である
		if (kk0351CondInfoList.length > 0)
		{
			return true;
		}

		return false;
	}

	/**
	 * <p>
	 * 該当の「サブオプションサービス契約」が、対象の「異動予約」と同一申込にて作成された「サブオプションサービス契約」かどうかを判定する。
	 * </p>
	 * @param opSvcKeiNo オプションサービス契約番号
	 * @param sbopSvcKeiNo サブオプションサービス契約番号
	 * @param kk1681Msg 「異動予約」のメッセージキャリア
	 * @return true:対象の「異動予約」と同一申込にて作成された「サブオプションサービス契約」である場合、false:それ以外
	 */
	private boolean isSameMskmSbopByIdoRsv(String opSvcKeiNo, String sbopSvcKeiNo, CAANMsg kk1681Msg)
	{
		// 対象の「サブオプションサービス契約」の履歴世代レコードのうち、「異動予約」の異動区分、申込明細番号に紐づくレコードを取得
		CAANMsg searchKey = new CAANMsg(KK0401ETMsg.class.getName());
		searchKey.set(KK0401ETMsg.OP_SVC_KEI_NO, opSvcKeiNo);
		searchKey.set(KK0401ETMsg.SBOP_SVC_KEI_NO, sbopSvcKeiNo);
		searchKey.set(KK0401ETMsg.IDO_DIV, kk1681Msg.getString(KK1681ETMsg.IDO_DIV));
		searchKey.set(KK0401ETMsg.MSKM_DTL_NO, kk1681Msg.getString(KK1681ETMsg.MSKM_DTL_NO));
		searchKey.set(KK0401ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		CAANMsg[] kk0401CondInfoList = null;
		try
		{
			kk0401CondInfoList = new KK0401LE().findByCondition(searchKey);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}

		// １件でも存在する場合、対象の「異動予約」と同一申込にて作成された「サブオプションサービス契約」である
		if (kk0401CondInfoList.length > 0)
		{
			return true;
		}

		return false;
	}

	/**
	 * <p>
	 * 対象の「オプションサービス契約」を削除(全履歴世代レコードを論理削除)します。
	 * </p>
	 * @param opSvcKeiNo 削除対象の「オプションサービス契約」のオプションサービス契約番号
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	private void deleteOpSvcKeiForRsvCl(String opSvcKeiNo, String updDtm, String updOpeAct)
	{
		// 対象の「オプションサービス契約」の全履歴世代レコードを取得
		CAANMsg searchKey = new CAANMsg(KK0351ETMsg.class.getName());
		searchKey.set(KK0351ETMsg.OP_SVC_KEI_NO, opSvcKeiNo);
		searchKey.set(KK0351ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		CAANMsg[] kk0351CondInfoList = null;
		try
		{
			kk0351CondInfoList = new KK0351LE().findByCondition(searchKey);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}

		// 対象の「オプションサービス契約」を削除(全履歴世代レコードを論理削除)する。
		JKKejbKK0351ETDA kk0351Etda = new JKKejbKK0351ETDA();
		for (CAANMsg kk0351CondInfo : kk0351CondInfoList)
		{
			kk0351Etda.deleteKK0351(kk0351CondInfo, updDtm, updOpeAct);
		}
	}

	/**
	 * <p>
	 * 対象の「サブオプションサービス契約」を削除(全履歴世代レコードを論理削除)します。
	 * </p>
	 * @param opSvcKeiNo 削除対象の「サブオプションサービス契約」のオプションサービス契約番号
	 * @param sbopSvcKeiNo 削除対象の「サブオプションサービス契約」のサブオプションサービス契約番号
	 * @param updDtm 更新年月日時分秒
	 * @param updOpeAct 更新オペレータアカウント
	 */
	private void deleteSbopSvcKeiForRsvCl(String opSvcKeiNo, String sbopSvcKeiNo, String updDtm, String updOpeAct)
	{
		// 対象の「サブオプションサービス契約」の全履歴世代レコードを取得
		CAANMsg searchKey = new CAANMsg(KK0401ETMsg.class.getName());
		if (opSvcKeiNo != null && !"".equals(opSvcKeiNo))
		{
			// 異動予約.オプションサービス契約番号が設定されていないことがあるので。。。
			searchKey.set(KK0401ETMsg.OP_SVC_KEI_NO, opSvcKeiNo);
		}
		searchKey.set(KK0401ETMsg.SBOP_SVC_KEI_NO, sbopSvcKeiNo);
		searchKey.set(KK0401ETMsg.MK_FLG, JKKModelConst.MK_FLG_YK);

		CAANMsg[] kk0401CondInfoList = null;
		try
		{
			kk0401CondInfoList = new KK0401LE().findByCondition(searchKey);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}

		// 対象の「サブオプションサービス契約」を削除(全履歴世代レコードを論理削除)する。
		JKKejbKK0401ETDA kk0401Etda = new JKKejbKK0401ETDA();
		for (CAANMsg kk0401CondInfo : kk0401CondInfoList)
		{
			kk0401Etda.deleteKK0401(kk0401CondInfo, updDtm, updOpeAct);
		}
	}

}
