/*********************************************************************
*   All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JKKejbKK0161KRCK
*   ソースファイル名：JKKejbKK0161KRCK.java
*   作成者          ：富士通
*   日付            ：2011年04月21日
*＜機能概要＞
*   サービス契約内訳の関連制約部品クラス
*＜修正履歴＞
*   バージョン  修正日      修正者      修正内容
*   v1.00.00    2011/04/21  富士通      新規作成
*	v5.00.00	2013/04/01	FJ）沖田	OT-2013-0000463
*	v5.00.01	2013/04/05	FJ）竹内	OT-2013-0000463
*   v5.00.02    2013/05/20  FJ）寺本    IT1-2013-0001205
*   v6.00.00    2014/01/05  FJ）寺園    OM-2013-0004893
**********************************************************************/

package eo.ejb.common.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.util.JPCUtilCommon;
import eo.ejb.cbm.entity.KK0081ETMsg;
import eo.ejb.cbm.entity.KK0161ETMsg;
import eo.ejb.cbm.entity.KK0191ETMsg;
import eo.ejb.cbm.entity.KK0351ETMsg;
import eo.ejb.cbm.entity.KK0781ETMsg;
import eo.ejb.common.JKKModelCommon;
import eo.ejb.common.JKKModelConst;
import eo.ejb.common.db.JKKejbKK0081DBABase;
import eo.ejb.common.db.JKKejbKK0161DBABase;
import eo.ejb.common.db.JKKejbKK0351DBABase;
import eo.ejb.common.db.JKKejbKK0781DBABase;

/**
 * <p>
 * サービス契約内訳の関連制約部品クラスです。
 * </p>
 * @author 富士通
 */
public class JKKejbKK0161KRCK extends JKKejbKK0161DBABase
{

	/** サービス提供中ステータス */
	private static final String STATUS_TEIKYO = "100";
	
	/** サービス契約ステータス：020(照査済) */
	private static final String SVC_KEI_STS_SHOSASUMI = "020";

	/** サービス契約ステータス：030(締結済) */
	private static final String SVC_KEY_STA_TEIKETSUMI = "030";

	/** サービスコード(電話サービス) */
	private static final String SVC_CD_TEL = "02";
	
	/** 番ポ工事ステータス：番ポ工事取消(090) */
	private static final String BMP_KOJI_STAT_BMPKJ_CL = "090";
	
	/** 番ポ申込書タイプコード：廃止(6) */
	private static final String TU_T_BMP_KOJI_HAISHI = "6";
	
	/** 有無（有） */
	private static final String UM_ARI = "1";

	/**
	 * <p>
	 * 新しいJKKejbKK0161KRCKを作成します。
	 * </p>
	 */
	public JKKejbKK0161KRCK()
	{
		super();
	}

	/**
	 * <p>
	 * サービス契約内訳カレントレコードの存在チェックを行います。
	 * </p>
	 * @param inMsg 処理対象のメッセージ
	 * @param svcKeiUcwkNo サービス契約内訳番号
	 * @return カレントレコードが存在する場合はtrue
	 */
	public boolean isExistsCurrent(CAANMsg inMsg, String svcKeiUcwkNo)
	{
		if (svcKeiUcwkNo == null)
		{
			return true;
		}

		// カレントレコード検索パラメータの設定
		CAANMsg msg = new CAANMsg(KK0161ETMsg.class.getName());
		msg.set(KK0161ETMsg.SVC_KEI_UCWK_NO, svcKeiUcwkNo);
		msg.set(KK0161ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));

		// カレントレコードの検索
		CAANMsg ret = new JKKejbKK0161DBABase().findByCurrent(msg);

		if (ret == null)
		{
			return false;
		}

		return true;
	}

	/**
	 * <p>
	 * 電話オプション共通の申込可否判定を行う。
	 * </p>
	 * 
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param opSvcKeiNo オプションサービス契約番号
	 * @return 指定されたオプションサービス契約番号に紐づくオプションサービス契約のカレントレコードの
	 *          サービス契約内訳番号に紐付くサービス契約内訳カレントレコードのサービス契約内訳ステータスが
	 *          100(サービス提供中)の場合true。それ以外の場合はfalse。
	 */
	public boolean isTelOpMskmKahi(CAANMsg inMsg, AgentDispatchContext inContext, String opSvcKeiNo)
	{
		// オプションサービス契約番号がnullの場合、チェックを行わず正常終了
		if (null == opSvcKeiNo)
		{
			return true;
		}
		
		// 内部スキーマメッセージを作成(オプションサービス契約)
		CAANMsg inMsgKK0351 = new CAANMsg(KK0351ETMsg.class.getName());

		// パラメータ設定
		inMsgKK0351.set(KK0351ETMsg.OP_SVC_KEI_NO, opSvcKeiNo);
		inMsgKK0351.set(KK0351ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));
		
		// オプションサービス契約のカレントレコードを取得する。
		CAANMsg curMsgKK0351 = new JKKejbKK0351DBABase().findByCurrent(inMsgKK0351);

		// オプションサービス契約のカレントレコードが取得できなかった場合false
		if (null == curMsgKK0351)
		{
			return false;
		}

		// 取得したオプションサービス契約の"サービス契約内訳番号"がnullの場合、チェックを行わず正常終了
		if (curMsgKK0351.isNull(KK0351ETMsg.SVC_KEI_UCWK_NO))
		{
			return true;
		}

		// 内部スキーマメッセージを作成(サービス契約内訳)
		CAANMsg inMsgKK0161 = new CAANMsg(KK0161ETMsg.class.getName());

		// パラメータ設定
		inMsgKK0161.set(KK0161ETMsg.SVC_KEI_UCWK_NO, curMsgKK0351.getString(KK0351ETMsg.SVC_KEI_UCWK_NO));
		inMsgKK0161.set(KK0161ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));

		// サービス契約内訳のカレントレコードを取得する。
		CAANMsg curMsgKK0161 = new JKKejbKK0161DBABase().findByCurrent(inMsgKK0161);

		// サービス契約内訳のカレントレコードが取得できなかった場合false
		if (null == curMsgKK0161)
		{
			return false;
		}

		// サービス契約内訳ステータスが"サービス提供中"の場合、正常終了
		if (STATUS_TEIKYO.equals(curMsgKK0161.getString(KK0161ETMsg.SVC_KEI_UCWK_STAT)))
		{
			return true;
		}

		return false;
	}

	/**
	 * <p>
	 * サービス契約内訳番号、サービス契約内訳ステータス"照査済"、"締結済"、"サービス提供中"に紐づく
	 * サービス契約内訳のカレントレコードの存在チェックを行う。
	 * </p>
	 * 
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param svcKeiUcwkNo サービス契約内訳番号
	 * @return カレントレコードのサービス契約内訳ステータスが"照査済"または"締結済"または"サービス提供中"の場合true
	 *          それ以外の場合、false
	 */
	public boolean isExistSvcKeiUcwk(CAANMsg inMsg, AgentDispatchContext inContext, String svcKeiUcwkNo)
	{
		// サービス契約内訳番号が未設定の場合、チェックを行わず正常終了
		if (null == svcKeiUcwkNo)
		{
			return true;
		}

		// 内部スキーマメッセージを作成
		CAANMsg inETMsg = new CAANMsg(KK0161ETMsg.class.getName());
		inETMsg.set(KK0161ETMsg.SVC_KEI_UCWK_NO, svcKeiUcwkNo);
		inETMsg.set(KK0161ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));
		
		// サービス契約内訳のカレントレコードを取得する。
		CAANMsg retETMsg = new JKKejbKK0161DBABase().findByCurrent(inETMsg);

		// カレントレコードが存在しない場合、false
		if (null == retETMsg)
		{
			return false;
		}

		// サービス契約内訳ステータスが"照査済"、"締結済"、"サービス提供中"以外の場合、false
		if (!STATUS_TEIKYO.equals(retETMsg.getString(KK0161ETMsg.SVC_KEI_UCWK_STAT))
				&& !SVC_KEI_STS_SHOSASUMI.equals(retETMsg.getString(KK0161ETMsg.SVC_KEI_UCWK_STAT))
				&& !SVC_KEY_STA_TEIKETSUMI.equals(retETMsg.getString(KK0161ETMsg.SVC_KEI_UCWK_STAT)))
		{
			return false;
		}
		
		return true;
	}

	/**
	 * 契約状態提供中チェック処理
	 * <p>
	 * 対象のサービス契約内訳のカレントレコードのサービス契約内訳ステータスが"サービス提供中"であるかのチェックを行う
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 対象のサービス契約内訳ステータスが"サービス提供中"の場合、true
	 *          上記以外の場合はfalse。
	 */
	public boolean isSvcKeiUcwkStatTk(CAANMsg inMsg, AgentDispatchContext inContext)
	{		
		// カレント検索用のサービス契約内訳の内部スキーマメッセージ作成
		CAANMsg inETMsg = new CAANMsg(KK0161ETMsg.class.getName());
		inETMsg.set(KK0161ETMsg.SVC_KEI_UCWK_NO, inMsg.getObject(KK0161ETMsg.SVC_KEI_UCWK_NO));
		inETMsg.set(KK0161ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));

		// カレント検索を行う。
		CAANMsg outETMsg = new JKKejbKK0161DBABase().findByCurrent(inETMsg);

		// 処理結果の判定
		if (outETMsg != null)
		{
			// サービス契約内訳ステータスが"サービス提供中"の場合、trueを返却
			if (STATUS_TEIKYO.equals(outETMsg.getString(KK0161ETMsg.SVC_KEI_UCWK_STAT)))
			{
				return true;
			}
		}

		return false;
	}
	
	/**
	 * <p>
	 * 番ポ工事取消ステータスチェック処理（サービス契約内訳）
	 * 対象のサービス契約内訳に紐付く番ポ工事取消ステータスのチェックを行う。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 番ポ有無が「有」かつ、番ポ工事．番ポ工事ステータスが"090"(番ポ工事取消)以外かつ番ポ工事.番ポ申込書タイプコードが"6"のレコードが1件でも存在した場合エラー false
	 *          上記以外 true
	 */
	public boolean isChkBmpkjClStat(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		// 開始ログ出力
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbKK0161KRCK#isChkBmpkjClStat");

		String svcKeiUcwkNo = inMsg.getString(KK0161ETMsg.SVC_KEI_UCWK_NO);
		if (svcKeiUcwkNo == null || "".equals(svcKeiUcwkNo))
		{
			return true;
		}

		// サービス契約内訳メッセージ生成
		CAANMsg svcKeiUcwkMsg = new CAANMsg(KK0161ETMsg.class.getName());

		// サービス契約内訳設定
		svcKeiUcwkMsg.set(KK0161ETMsg.SVC_KEI_UCWK_NO, svcKeiUcwkNo);
		svcKeiUcwkMsg.set(KK0161ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));

		// サービス契約内訳カレント検索を行う
		CAANMsg curSvcKeiucwkMsg = findByCurrent(svcKeiUcwkMsg);

		if (svcKeiUcwkMsg == null)
		{
			return true;
		}

		String svcKeiNo = curSvcKeiucwkMsg.getString(KK0161ETMsg.SVC_KEI_NO);

		if (svcKeiNo == null || "".equals(svcKeiNo))
		{
			return true;
		}

		// サービス契約メッセージ生成
		CAANMsg svcMsg = new CAANMsg(KK0081ETMsg.class.getName());

		// サービス契約設定
		svcMsg.set(KK0081ETMsg.SVC_KEI_NO, svcKeiNo);
		svcMsg.set(KK0081ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));

		// サービス契約カレント検索を行う
		CAANMsg curSvcMsg = new JKKejbKK0081DBABase().findByCurrent(svcMsg);

		if (curSvcMsg == null)
		{
			return true;
		}

		// サービスコード「02:電話サービス」の場合
		if (SVC_CD_TEL.equals(curSvcMsg.getString(KK0081ETMsg.SVC_CD)))
		{

			JKKejbKK0081KRCK kk0081KRCK = new JKKejbKK0081KRCK();
			
			// サービス契約内訳（サービス契約番号）取得処理
			ArrayList<Map<String, String>> rsltMapList = kk0081KRCK.getSvcKeiUcwkSvcKeiNo(inMsg, inContext);

			for (int i = 0; i < rsltMapList.size(); i++)
			{
				// 番ポ有無「1:有」の場合
				if (UM_ARI.equals(rsltMapList.get(i).get(KK0191ETMsg.BMP_UM)))
				{
					// 番ポ工事．番ポ工事ステータスが番ポ工事.番ポ申込書タイプコードが"6"かつ"090"(番ポ工事取消)以外で
					// 番ポ工事を検索しレコードが存在すればエラー
					int cnt = kk0081KRCK.getTuBmpKojiClCnt(inMsg, inContext, rsltMapList.get(i).get(KK0161ETMsg.SVC_KEI_UCWK_NO), TU_T_BMP_KOJI_HAISHI, BMP_KOJI_STAT_BMPKJ_CL);
					if ( cnt > 0 )
					{
						return false;
					}
				}
			}
		}
		return true;
	}

	/**
	 * <p>
	 * サービス契約内訳有効数チェック処理
	 * 対象の「サービス契約内訳」(電話番号)が回復することにより、親「サービス契約」(電話契約)配下の「サービス契約内訳」(電話番号)が２件(２番号)を超えないこと。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param svcKeiUcwkNo サービス契約内訳番号
	 * @return true:チェックＯＫ、false:チェックＮＧ
	 */
	public boolean isChkYukoSvcKeiUtwkTelNo(CAANMsg inMsg, AgentDispatchContext inContext, String svcKeiUcwkNo)
	{
		// 開始ログ出力
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), "call:JKKejbKK0161KRCK#isChkYukoSvcKeiUtwkTelNo");

		// サービス契約内訳番号が未設定(未採番)の場合、処理を終了する
		if (svcKeiUcwkNo == null || "".equals(svcKeiUcwkNo))
		{
			return true;
		}

		String opeDate = JKKModelCommon.getOpeDate(inMsg);
		JKKejbKK0161DBABase kk161DBABase = new JKKejbKK0161DBABase();

		// サービス契約内訳カレント検索を行う
		CAANMsg curSvcKeiucwkMsg = kk161DBABase.getKK0161Current(svcKeiUcwkNo, opeDate);

		String svcKeiNo = curSvcKeiucwkMsg.getString(KK0161ETMsg.SVC_KEI_NO);

		// サービス契約カレント検索を行う
		CAANMsg curSvcMsg = new JKKejbKK0081DBABase().getKK0081Current(svcKeiNo, opeDate);

		// サービスコードが"電話サービス"以外の場合、チェック対象外
		if (!JKKModelConst.SVC_CD_TEL.equals(curSvcMsg.getString(KK0081ETMsg.SVC_CD)))
		{
			return true;
		}

		/* ----------------------------------------------------------------------------------------------------
		 * 該当の電話契約で使用する電話番号(下記@Aの条件を満たす)が2件以上存在した場合エラー
		 * 当該電話番号が回復することにより、１つの電話契約に対して３つの電話番号が使用可能となることを抑止するため。
		 * @解約済・キャンセル済を除く
		 * A電話番号変更中の新電話番号(継続後契約変更手続中フラグ = "変更手続中である")を除く
		 * ---------------------------------------------------------------------------------------------------- */
		// 検索条件：サービス契約内訳.継続後契約変更手続中フラグ = "変更手続中でない"
		HashMap<String, String[]> searchJknMap = new HashMap<String, String[]>();
		searchJknMap.put(KK0161ETMsg.KEIZK_AF_KEI_CHGECHU_FLG, new String[]{JKKModelConst.KEI_CHGECHU_FLG_NO_CHGECHU});

		// 該当の「サービス契約」の配下の「サービス契約内訳」を取得する。
		CAANMsg[] svcKeiUcwkList = kk161DBABase.getKK0161bySvcKei(svcKeiNo, searchJknMap, opeDate);

		// 解約済、キャンセル済を除外する
		svcKeiUcwkList = kk161DBABase.getKK0161OutDsLCl(svcKeiUcwkList);

		// 解約済み・キャンセル済みを除外した、有効な内訳レコードが2件以上存在した場合、エラーとする
		if (svcKeiUcwkList.length  > 1)
		{
			return false;
		}

		// 上記以外は正常
		return true;
	}

	/**
	 * <p>
	 * 回復可能期間チェックを行います。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param kbn 区分（回復系：1、キャンセル取消系：2）
	 * @return true:チェックＯＫ、false:チェックＮＧ
	 */
	public boolean kaihkValidChk(CAANMsg inMsg, AgentDispatchContext inContext, Object kbn)
	{
		String opeDate = JKKModelCommon.getOpeDate(inMsg);

		// 異動区分が光電話・番号回復以外の場合は処理しない
		if (!JKKModelConst.IDO_DIV_HIKARI_TELNO_KAIHK.equals(inMsg.getString(KK0161ETMsg.IDO_DIV)))
		{
			return true;
		}
		
		// 内部スキーマメッセージを作成
		CAANMsg kk0161ETMsg = new CAANMsg(KK0161ETMsg.class.getName());
		kk0161ETMsg.set(KK0161ETMsg.SVC_KEI_UCWK_NO, inMsg.getString(KK0161ETMsg.SVC_KEI_UCWK_NO));
		kk0161ETMsg.set(KK0161ETMsg.RSV_APLY_YMD, opeDate);
		
		// サービス契約内訳のカレントレコードを取得する。
		CAANMsg kk0161Current = new JKKejbKK0161DBABase().findByCurrent(kk0161ETMsg);

		// カレントレコードが存在しない場合、false
		if (null == kk0161Current)
		{
			return false;
		}

		// 内部スキーマメッセージを作成
		CAANMsg kk0081ETMsg = new CAANMsg(KK0081ETMsg.class.getName());
		kk0081ETMsg.set(KK0081ETMsg.SVC_KEI_NO, kk0161Current.getString(KK0161ETMsg.SVC_KEI_NO));
		kk0081ETMsg.set(KK0081ETMsg.RSV_APLY_YMD, opeDate);

		// 「サービス契約」のカレントレコードの検索
		CAANMsg kk0081Current = new JKKejbKK0081DBABase().findByCurrent(kk0081ETMsg);

		// カレントレコードが存在しない場合、false
		if (kk0081Current == null)
		{
			return false;
		}
		
		// 該当の「サービス契約」が指定する「料金グループ」のカレント検索用のメッセージを作成
		CAANMsg kk0781ETMsg = new CAANMsg(KK0781ETMsg.class.getName());
		kk0781ETMsg.set(KK0781ETMsg.PRC_GRP_CD, kk0081Current.getString(KK0081ETMsg.PRC_GRP_CD));
		kk0781ETMsg.set(KK0781ETMsg.RSV_APLY_YMD, opeDate);

		// 料金グループのカレント検索を行う
		CAANMsg kk0781Current = getCurrentKK0781(inMsg, kk0781ETMsg);
		
		if (kk0781Current == null)
		{
			return false;
		}
		
		String judgeYmd = null;
		// 回復系の場合
		if ("1".equals(kbn))
		{
			// サービス契約内訳.サービス解約年月日または、料金グループ.回復可能期間が未設定の場合、エラー
			if (kk0161Current.isNull(KK0161ETMsg.SVC_DSL_YMD) || kk0781Current.isNull(KK0781ETMsg.KAIHK_PSB_PRD))
			{
				return false;
			}
			// 判定日の算出（サービス契約内訳.サービス解約年月日＋料金グループ.回復可能期間）
			judgeYmd = JKKModelCommon.addDay(inMsg, inContext, kk0161Current.getString(KK0161ETMsg.SVC_DSL_YMD), 
					kk0781Current.getString(KK0781ETMsg.KAIHK_PSB_PRD));
		}
		
		// キャンセル取消系の場合
		if ("2".equals(kbn))
		{
			// サービス契約内訳.サービスキャンセル年月日または、料金グループ.キャンセル取消可能期間が未設定の場合、エラー
			if (kk0161Current.isNull(KK0161ETMsg.SVC_CANCEL_YMD) || kk0781Current.isNull(KK0781ETMsg.CANCEL_CL_PSB_PRD))
			{
				return false;
			}
			// 判定日の算出（サービス契約内訳.サービスキャンセル年月日＋料金グループ.キャンセル取消可能期間）
			judgeYmd = JKKModelCommon.addDay(inMsg, inContext, kk0161Current.getString(KK0161ETMsg.SVC_CANCEL_YMD), 
					kk0781Current.getString(KK0781ETMsg.CANCEL_CL_PSB_PRD));
		}

		// 判定日 ＜ 運用年月日の場合、エラーとする
		if (JPCUtilCommon.isPastDate(judgeYmd, opeDate, "0"))
		{
			// エラー
			return false;
		}
		// 正常
		return true;
	}

	/**
	 * <p>
	 * 料金グループのカレントを検索します。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inETMsg  サービス契約のカレントレコードメッセージキャリア 
	 * @return 取得した料金グループのメッセージキャリア
	 */
	private CAANMsg getCurrentKK0781(CAANMsg inMsg, CAANMsg inETMsg)
	{
		// 料金グループのカレント検索用のメッセージを作成
		CAANMsg inKK0781Msg = new CAANMsg(KK0781ETMsg.class.getName());
		inKK0781Msg.set(KK0781ETMsg.PRC_GRP_CD, inETMsg.getString(KK0781ETMsg.PRC_GRP_CD));
		inKK0781Msg.set(KK0781ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));

		// 料金グループのカレント検索を行う
		CAANMsg kk0781ETMsg = new JKKejbKK0781DBABase().findByCurrent(inKK0781Msg);

		// 有効期限の確認を行う。
		if (kk0781ETMsg.getString(KK0781ETMsg.PRC_GRP_TSTAYMD).compareTo(JKKModelCommon.getOpeDate(inMsg)) > 0)
		{
			return null;
		}

		if (kk0781ETMsg.getString(KK0781ETMsg.PRC_GRP_TENDYMD).compareTo(JKKModelCommon.getOpeDate(inMsg)) < 0)
		{
			return null;
		}

		return kk0781ETMsg;
	}
}
