/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKejbEKK0341C110Edit
*	ソースファイル名：JKKejbEKK0341C110Edit.java
*	作成者			：富士通
*	日付			：2011年08月01日
*＜機能概要＞
*	機器提供サービス契約機器設置完了編集部品クラス
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/11/11	富士通		新規作成
*	v7.00.00	2014/02/18	FJ）小島	OM-2014-0000517
*	v8.00.00	2014/04/14	FJ）宇野	OM-2014-0001430
*	v8.00.01	2014/04/29	FJ）宇野	OM-2014-0001529、OM-2014-0001536
*	v8.00.02	2014/05/09	FJ）宇野	OM-2014-0001836
*
**********************************************************************/

package eo.ejb.common.edit;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import com.fujitsu.futurity.model.base.CAANConnectionMgr;
import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.JSYejbConnection;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.util.JPCDateUtil;
import eo.ejb.cbm.entity.CH0501ETMsg;
import eo.ejb.cbm.entity.KK0081ETMsg;
import eo.ejb.cbm.entity.KK0251ETMsg;
import eo.ejb.cbm.entity.KK0341ETMsg;
import eo.ejb.cbm.entity.KK0791ETMsg;
import eo.ejb.cbs.cbsmsg.EKK0341C110CBSMsg;
import eo.ejb.common.JKKModelCommon;
import eo.ejb.common.db.JKKejbKK0081DBABase;
import eo.ejb.common.db.JKKejbKK0251DBABase;
import eo.ejb.common.db.JKKejbKK0341DBABase;
import eo.ejb.common.db.JKKejbKK0791DBABase;
import eo.ejb.common.rule.JKKejbRule0067001;
import eo.ejb.common.rule.JKKejbRule0075001;

/**
 * <p>
 * 機器提供サービス契約の相関ルール処理を呼び出す為の編集を行う部品クラスです。
 * </p>
 * @author 富士通
 */
public class JKKejbEKK0341C110Edit
{

	/** 相関ルール呼出区分（RULE0075_開始日設定(機器提供サービス)） */
	private static final String RULE0075 = "RULE0075";

	/** 相関ルール呼出区分（RULE0067_課金開始日設定(機器提供サービス)） */
	private static final String RULE0067 = "RULE0067";

	/** 親契約識別コード（サービス契約回線内訳） */
	private static final String OYA_KEI_SKBT_CD_02 = "02";

	/**
	 * コンストラクタです。
	 */
	public JKKejbEKK0341C110Edit()
	{
	}

	/**
	 * <p>
	 * 機器提供サービス契約のサービス開始年月日を算出・取得する
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return サービス開始年月日
	 */
	public Object getStaYmd(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		// 入力値「サービス開始年月日」が設定されている場合、入力値を開始年月日とする
		if (!inMsg.isNull(EKK0341C110CBSMsg.SVC_STA_YMD))
		{
			return inMsg.getString(EKK0341C110CBSMsg.SVC_STA_YMD);
		}

		// 相関ルールRULE0075_開始日設定(機器提供サービス)を実行する
		String staYmd = this.staYmdRuleRun(inMsg, inContext, RULE0075, null);
		
		// 開始年月日が取得できなかった場合、エラー処理を行う。
		if(null == staYmd || "".equals(staYmd))
		{
			// 相関エラーのステータスを設定
			inMsg.set(EKK0341C110CBSMsg.KKTK_SVC_KEI_NO_ERR, "EC");
			inMsg.set(EKK0341C110CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			
			return null;
		}

		return staYmd;
	}
	
	/**
	 * <p>
	 * 機器提供サービス契約のサービス課金開始年月日を算出・取得する
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return サービス課金開始年月日
	 */
	public Object getChrgStaYmd(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		// 入力値「サービス課金開始年月日」が設定されている場合、入力値を課金開始年月日とする
		if (!inMsg.isNull(EKK0341C110CBSMsg.SVC_CHRG_STAYMD))
		{
			return inMsg.getString(EKK0341C110CBSMsg.SVC_CHRG_STAYMD);
		}

		// 相関ルールから機器提供サービス契約のサービス開始年月日を算出し取得する
		String staYmd = (String)getStaYmd(inMsg, inContext);
		
		// 開始年月日が取得できなかった場合、エラー処理を行う。
		if(null == staYmd || "".equals(staYmd))
		{
			// 関連エラーのステータスを設定
			inMsg.set(EKK0341C110CBSMsg.KKTK_SVC_KEI_NO_ERR, "EC");
			inMsg.set(EKK0341C110CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			
			return null;
		}

		// 相関ルールRULE0067_課金開始日設定(機器提供サービス)を実行する
		String chrgStaYmd = this.staYmdRuleRun(inMsg, inContext, RULE0067, staYmd);
		
		// 課金開始年月日が取得できなかった場合、エラー処理を行う。
		if(null == chrgStaYmd || "".equals(chrgStaYmd))
		{
			// 関連エラーのステータスを設定
			inMsg.set(EKK0341C110CBSMsg.KKTK_SVC_KEI_NO_ERR, "EC");
			inMsg.set(EKK0341C110CBSMsg.STATUS, StatusCodes.RELATION_ERR);
			
			return null;
		}

		return chrgStaYmd;
	}

	/**
	 * <p>
	 * 機器提供サービスの開始日設定(または課金開始日設定)の相関ルールを呼び出し、開始日(または課金開始日)を算出する
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param ruleCallKbn 相関ルール呼出区分（"RULE0075"：開始日設定(機器提供サービス)、"RULE0067"：課金開始日設定(機器提供サービス)）
	 * @param kk0341SvcStaYmd 機器提供サービス契約．サービス開始年月日（相関ルール呼出区分が課金開始日設定の場合のみ設定）
	 * @return 算出された開始日(または課金開始日)
	 */
	private String staYmdRuleRun(CAANMsg inMsg, AgentDispatchContext inContext, String ruleCallKbn, String kk0341SvcStaYmd)
	{
		// 機器提供サービス契約のカレント検索を行う
		CAANMsg kk0341Msg = getCurrentKK0341(inMsg);
		
		// 存在しない場合
		if(null == kk0341Msg)
		{
			return null;
		}
		
		// 「機器提供サービス契約」の親契約識別コードが"サービス契約回線内訳"の場合
		if (OYA_KEI_SKBT_CD_02.equals(kk0341Msg.getString(KK0341ETMsg.OYA_KEI_SKBT_CD)))
		{
			// 親「サービス契約回線内訳」のカレント検索を行う
			CAANMsg kk0251Msg = getCurrentKK0251(inMsg, kk0341Msg.getString(KK0341ETMsg.SVC_KEI_KAISEN_UCWK_NO));
			
			// 存在しない場合
			if(null == kk0251Msg)
			{
				return null;
			}
			
			// 運用日付
			String opeDate = JKKModelCommon.getOpeDate(inMsg);
			
			// 該当の「サービス契約回線内訳」を使用している「サービス契約」を取得する
			CAANMsg[] kk0081MsgList = new JKKejbKK0081DBABase().getKK0081bySvcKeiKaisenUcwk(
					kk0251Msg.getString(KK0251ETMsg.SVC_KEI_KAISEN_UCWK_NO), null, opeDate, "1");
			
			// 当該「機器提供サービス契約」の機器提供サービスを付加可能な「料金コース」を取得する
			CAANMsg[] kk0791MsgList = new JKKejbKK0791DBABase().getKK0791byKktkSvc(kk0341Msg.getString(KK0341ETMsg.KKTK_SVC_CD), opeDate);
			
			// 当該「機器提供サービス契約」の機器提供サービス付加の対象となる料金コースコードリスト
			ArrayList<String> pcrsCdList = new ArrayList<String>();
			for (CAANMsg kk0791Msg : kk0791MsgList)
			{
				pcrsCdList.add(kk0791Msg.getString(KK0791ETMsg.PCRS_CD));
			}
			
			// 機器提供サービス契約.サービス開始年月日
			String svcStaYmd = null;
			
			for (CAANMsg kk0081Msg : kk0081MsgList)
			{
				// 処理対象の「サービス契約」(料金コースコード)が当該「機器提供サービス契約」の付加対象外である場合、次の「サービス契約」へ
				if (!pcrsCdList.contains(kk0081Msg.getString(KK0081ETMsg.PCRS_CD)))
				{
					continue;
				}
				
				// ルールにパラメータを設定してルールを実行する
				String rule0075StaYmd = ruleRun(inMsg, kk0341Msg, kk0081Msg, inContext, ruleCallKbn, kk0341SvcStaYmd);
				
				if (!(null == rule0075StaYmd || "".equals(rule0075StaYmd)))
				{
					// RULE0075_開始日設定(機器提供サービス)で算出した開始日のうち、最小日付を機器提供サービス契約.サービス開始年月日とする
					if (null == svcStaYmd || rule0075StaYmd.compareTo(svcStaYmd) < 0)
					{
						svcStaYmd = rule0075StaYmd;
					}
				}
			}
			return svcStaYmd;
		}
		// 「機器提供サービス契約」の親契約識別コードが"サービス契約回線内訳"以外("サービス契約"、"サービス契約内訳"、"オプションサービス契約")の場合
		else
		{
			// 取得した機器提供サービス契約のサービス契約番号をキーにサービス契約をカレント検索する
			CAANMsg kk0081Msg = getCurrentKK0081(inMsg, kk0341Msg.getString(KK0341ETMsg.SVC_KEI_NO));
			
			// サービス契約が取得できない場合
			if (kk0081Msg == null)
			{
				return null;
			}
			
			// ルールにパラメータを設定してルールを実行する
			return ruleRun(inMsg, kk0341Msg, kk0081Msg, inContext, ruleCallKbn, kk0341SvcStaYmd);
		}
	}
	
	/**
	 * <p>
	 * 機器提供サービス契約のカレントを検索します。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @return 取得した機器提供サービス契約
	 */
	private CAANMsg getCurrentKK0341(CAANMsg inMsg)
	{
		// カレント検索用のメッセージを作成
		CAANMsg inETMsg = new CAANMsg(KK0341ETMsg.class.getName());
		inETMsg.set(KK0341ETMsg.KKTK_SVC_KEI_NO, inMsg.getString(EKK0341C110CBSMsg.KKTK_SVC_KEI_NO));
		inETMsg.set(KK0341ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));
		
		// 機器提供サービス契約のカレント検索を行う
		return new JKKejbKK0341DBABase().findByCurrent(inETMsg);
	}
	
	/**
	 * <p>
	 * サービス契約のカレントを検索します。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param svcKeiNo 検索対象となるサービス契約番号
	 * @return 取得したサービス契約
	 */
	private CAANMsg getCurrentKK0081(CAANMsg inMsg, Object svcKeiNo)
	{
		// カレント検索用のメッセージを作成
		CAANMsg inETMsg = new CAANMsg(KK0081ETMsg.class.getName());
		inETMsg.set(KK0081ETMsg.SVC_KEI_NO, svcKeiNo);
		inETMsg.set(KK0081ETMsg.RSV_APLY_YMD, JKKModelCommon.getOpeDate(inMsg));
		
		// サービス契約のカレント検索を行う
		return new JKKejbKK0081DBABase().findByCurrent(inETMsg);
	}
	
	/**
	 * <p>
	 * サービス契約回線内訳のカレントを検索します。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param svcKeiKaisenUcwkNo 検索対象となるサービス契約回線内訳番号
	 * @return 取得したサービス契約回線内訳
	 */
	private CAANMsg getCurrentKK0251(CAANMsg inMsg, Object svcKeiKaisenUcwkNo)
	{
		// カレント検索用のメッセージを作成
		CAANMsg inETMsg = new CAANMsg(KK0251ETMsg.class.getName());
		inETMsg.set(KK0251ETMsg.SVC_KEI_KAISEN_UCWK_NO, svcKeiKaisenUcwkNo);
		
		// サービス契約回線内訳のカレント検索を行う
		return new JKKejbKK0251DBABase().findByCurrent(inETMsg);
	}
	
	/**
	 * 機器提供サービスの開始日設定(または課金開始日設定)の相関ルールにパラメータを設定して実行します。
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param kk0341Msg 機器提供サービス契約のメッセージキャリア
	 * @param kk0081Msg サービス契約のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param ruleCallKbn 相関ルール呼出区分（"RULE0075"：開始日設定(機器提供サービス)、"RULE0067"：課金開始日設定(機器提供サービス)）
	 * @param kk0341SvcStaYmd 機器提供サービス契約．サービス開始年月日（相関ルール呼出区分が課金開始日設定の場合のみ設定）
	 * @return ルールを実行して取得される開始日(または課金開始日)
	 */
	private String ruleRun(CAANMsg inMsg, CAANMsg kk0341Msg, CAANMsg kk0081Msg, AgentDispatchContext inContext, String ruleCallKbn, String kk0341SvcStaYmd)
	{
		// 相関ルールRULE0075_開始日設定(機器提供サービス)を呼び出す場合
		if (RULE0075.equals(ruleCallKbn))
		{
			// 相関ルールの呼び出す為にインスタンス生成する
			JKKejbRule0075001 instance = new JKKejbRule0075001(inMsg);
			
			// ルールを呼び出す。
			// サービスコードを設定する
			instance.setSvc_cd(kk0081Msg.getString(KK0081ETMsg.SVC_CD));
			
			// 機器提供サービスコードを設定する
			instance.setKktk_svc_cd(kk0341Msg.getString(KK0341ETMsg.KKTK_SVC_CD));
			
			// 異動区分を設定する
			instance.setIdo_div(inMsg.getString(EKK0341C110CBSMsg.IDO_DIV));
			
			// サービス開始年月日(サービス契約)を設定する
			instance.setKk0081_svc_sta_ymd(kk0081Msg.getString(KK0081ETMsg.SVC_STA_YMD));
			
			// サービス利用開始希望年月日を設定する
			instance.setSvc_use_sta_kibo_ymd(kk0341Msg.getString(KK0341ETMsg.SVC_USE_STA_KIBO_YMD));
			
			// 機器提供サービス契約番号を設定する
			instance.setKktk_svc_kei_no(kk0341Msg.getString(KK0341ETMsg.KKTK_SVC_KEI_NO));
			
			// 機器変更番号を設定する
			instance.setKiki_Chg_No(kk0341Msg.getString(KK0341ETMsg.KIKI_CHG_NO));
			
			// 申込明細番号を設定する
			instance.setMskm_dtl_no(kk0341Msg.getString(KK0341ETMsg.MSKM_DTL_NO));
			
			// サービス開始起算年月日を設定する
			instance.setSvc_Sta_Kisan_Ymd(inMsg.getString(EKK0341C110CBSMsg.SVC_STA_KISAN_YMD));
			
			// 料金計算日より求めた請求年月の末日を設定する
			String ch0501_seiky_ymd = this.getCH0501SeikyYmd(inMsg, inContext);
			if (ch0501_seiky_ymd == null)
			{
				return null;
			}
			instance.setCh0501_seiky_ymd(ch0501_seiky_ymd);
			
			// 元のサービス契約の料金グループコードを設定する
			instance.setKk0081_Prc_Grp_Cd(kk0081Msg.getString(KK0081ETMsg.PRC_GRP_CD));
			
			// ルールを実行する
			return instance.getStaYmd();
		}
		// 相関ルールRULE0067_課金開始日設定(機器提供サービス)を呼び出す場合
		else if (RULE0067.equals(ruleCallKbn))
		{
			// 相関ルールの呼び出しクラスを生成する
			JKKejbRule0067001 instance = new JKKejbRule0067001(inMsg);
			
			// サービスコードを設定する
			instance.setSvc_cd(kk0081Msg.getString(KK0081ETMsg.SVC_CD));
			
			// 機器提供サービスコードを設定する
			instance.setKktk_svc_cd(kk0341Msg.getString(KK0341ETMsg.KKTK_SVC_CD));
			
			// 機器提供種別コードを設定する
			instance.setKktk_sbt_cd(kk0341Msg.getString(KK0341ETMsg.KKTK_SBT_CD));
			
			// 異動区分を設定する
			instance.setIdo_div(inMsg.getString(EKK0341C110CBSMsg.IDO_DIV));
			
			// サービス開始年月日を設定する
			instance.setSvc_sta_ymd(kk0341SvcStaYmd);
			
			// 元のサービス契約の料金グループコードを設定する
			instance.setKk0081_Prc_Grp_Cd(kk0081Msg.getString(KK0081ETMsg.PRC_GRP_CD));
			
			// 元のサービス契約のサービス課金開始年月日を設定する
			String svc_chrg_sta_ymd = kk0081Msg.getString(KK0081ETMsg.SVC_CHRG_STAYMD);
			instance.setKk0081_Svc_Chgsta_Ymd(svc_chrg_sta_ymd);
			
			// 料金計算日より求めた請求年月の末日を設定する
			String ch0501_seiky_ymd = this.getCH0501SeikyYmd(inMsg, inContext);
			if (ch0501_seiky_ymd == null)
			{
				return null;
			}
			
			// 多機能ルータでバッチから実行された場合、親のサービス契約が締結済みで実行される為
			// 課金開始日のNULL判定を行っています
			if (svc_chrg_sta_ymd != null)
			{
				// 請求年月の末日以前／以降を設定する
				// 元のサービス契約のサービス課金開始年月日＜＝料金計算日より求めた請求年月の末日
				if (svc_chrg_sta_ymd.compareTo(ch0501_seiky_ymd) <= 0)
				{
					instance.setSeikyu_Ym_Zengo("1");
				}
				// 元のサービス契約のサービス課金開始年月日＞料金計算日より求めた請求年月の末日
				else
				{
					instance.setSeikyu_Ym_Zengo("0");
				}
			}

			
			return instance.getChrgStaYmd();
		}
		
		return null;
	}
	
	/**
	 * <p>
	 * 料金計算日より求めた請求年月に末日を付与して返却します
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @return 請求年月の末日
	 * </p>
	 */
	private String getCH0501SeikyYmd(CAANMsg inCBSMsg, AgentDispatchContext inContext)
	{
		// コネクション
		Connection con1 = null;

		// プリペアステートメント
		PreparedStatement pstmt = null;

		// リザルトセット
		ResultSet rsltQuery = null;

		try
		{
			//コネクション取得
			con1 = JSYejbConnection.getConnection(CH0501ETMsg.getTableName());

			// SQL文
			StringBuffer sql_Buff = new StringBuffer();
			sql_Buff.append(" SELECT ")
					.append("     CH0501.SEIKY_YM AS SEIKY_YM ")
					.append(" FROM ")
					.append("     CH_M_PRC_SCHDL_TEIGI CH0501 ")
					.append(" WHERE ")
					.append("         CH0501.EVENT_CD = '03' ")
					.append("     AND CH0501.EVENT_YMD= ")
					.append("         (SELECT MAX(CH0501_MAX.EVENT_YMD)  ")
					.append("            FROM CH_M_PRC_SCHDL_TEIGI CH0501_MAX  ")
					.append("           WHERE CH0501_MAX.MK_FLG = '0'  ")
					.append("             AND CH0501_MAX.EVENT_CD = CH0501.EVENT_CD ")
					.append("             AND CH0501_MAX.EVENT_YMD < ? ")
					.append("         ) ");

			//prepareStatementにSQL文をセット
			pstmt = con1.prepareStatement(sql_Buff.toString());

			//ログ出力(SQL文の出力)
			JSYejbLog.outlog(inContext, JSYejbLog.DBACCESS, this.getClass(), sql_Buff);

			// パラメータの設定(運用日付を指定)
			CAANJDBCUtil.setParam(pstmt, 1, JKKModelCommon.getOpeDate(inCBSMsg));

			// ResultSetの取得
			rsltQuery = pstmt.executeQuery();

			// 検索結果が0件の場合
			if (rsltQuery == null)
			{
				return null;
			}

			String seikyYm = null;

			// 請求年月を取得する
			if (rsltQuery.next())
			{
				seikyYm = rsltQuery.getString("SEIKY_YM");
			}
			
			// 請求年月を元に末日を付与して返却します
			return seikyYm.concat(JPCDateUtil.getEndOfMonth(seikyYm));
		}
		catch (SQLException se)
		{
			throw new CAANRuntimeException(se);
		}
		finally
		{
			// 資源の解放
			try
			{
				if (rsltQuery != null)
				{
					rsltQuery.close();
				}
				if (pstmt != null)
				{
					pstmt.close();
				}
				if (con1 != null)
				{
					CAANConnectionMgr.getInstance().close(con1);
				}
			}
			catch (SQLException se)
			{
				throw new CAANRuntimeException(se);
			}
		}
	}
}
