/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JACJuryoLineShokaiCC
*	ソースファイル名：JACJuryoLineShokaiCC.java
*	作成者			：FJ)中原
*	日付			：2019年1月24日
*＜機能概要＞
*	従量情報照会(LINE)の共通コンポーネントクラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*   v41.00.00   2019/1/24   FJ)中原     【ANK-3355-00-00】LINE情報連携
*	v41.00.01	2019/03/08	FJ)中原		【IT2-2019-0000020】FTTH補正通信量合計を追加
*	v41.00.02	2019/03/14	FJ)中原		【IT1-2019-0000042】請求金額が「999999999999」の場合システムエラー
*	v41.00.03	2019/03/15	FJ)吉田		【ANK-3355-09-00】LINE情報連携
*	v41.01.00	2019/04/08	FJ)中原		【ST-2019-0000003】ＮＥＴ通信料の出力範囲不正
*	v43.00.00	2019/05/29	FJ)吉田		【ANK-3629-00-00】LINE-ID連携：認証解除登録対応
*   v45.00.00   2019/07/24  FJ)吉田     【ANK-3636-00-00】消費増税対応（8%⇒10%）
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.bp.x21.bpm.ServiceComponentRequestInvoker;
import com.fujitsu.futurity.bp.x21.bpm.db.SessionHandle;
import com.fujitsu.futurity.bp.x21.bpm.exception.RequestParameterException;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.cc.AbstractCommonComponent;
import com.fujitsu.futurity.bp.x21.cc.exception.SCCallException;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.common.x01.sc.SCControlMapKeys;
import com.fujitsu.futurity.mapping.bp.common.TemplateErrorUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;
import com.fujitsu.futurity.model.common.check.DatetimeCheck;
import com.fujitsu.futurity.model.common.check.HalfCharCheck;
import com.fujitsu.futurity.model.common.check.LengthCheck;

import eo.common.constant.JACStrConst;
import eo.common.constant.JCKStrConst;
import eo.common.constant.JKKStrConst;
import eo.common.constant.JPCModelConstant;
import eo.common.util.JKKStringUtil;
import eo.ejb.cbs.cbsmsg.ECK0011A010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0011A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0081A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0081B042CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B042CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0321B012CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0321B012CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EAC0171B030CBSMsg;
import eo.ejb.cbs.cbsmsg.EAC0171B030CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EAC0601B040CBSMsg;
import eo.ejb.cbs.cbsmsg.EAC0601B040CBSMsg1List;


/**
 * 請求情報照会(LINE)の共通コンポーネントクラスです。
 * <br>
 * @author FJ
 */
public class JACJuryoLineShokaiCC extends AbstractCommonComponent
{
	/** CCパラメータ：SYSID */
	public static final String SYSID = "sysid";
	/** CCパラメータ：抽出対象請求年月 */
	public static final String CHSHT_TG_SEIKY_YM = "chsht_tg_seiky_ym";
	/** CCパラメータ：ボディ情報 */
	public static final String BODY_INFO = "BODY_INFO";
	/** CCパラメータ：会員種別コード */
	public static final String MEMBER_SBT_CD = "member_sbt_cd";
	/** CCパラメータ：従量データ */
	public static final String JURYOLIST = "juryo_list";
	/** CCパラメータ：請求先番号 */
	public static final String SEIKY_KEI_NO = "seiky_kei_no";
	/** CCパラメータ：データ通信量結果コード */
	public static final String DATA_TSRYO_KK_CD = "data_tsryo_kk_cd";
	/** CCパラメータ：データ通信量 */
	public static final String DATA_TSRYO = "data_tsryo";
	/** CCパラメータ：電気使用量結果コード */
	public static final String EOELEC_USE_KK_CD = "eoelec_use_kk_cd";
	/** CCパラメータ：電気使用量 */
	public static final String EOELEC_USE = "eoelec_use";

	/** CCパラメータ：エラー情報 */
	public static final String ERROR_INFO = "ERROR_INFO";
	/** CCパラメータ：エラーコード */
	public static final String ERROR_CODE = "errCode";
	/** CCパラメータ：エラーメッセージ */
	public static final String ERROR_MESSAGE = "errMessage";

	 /** テンプレートID：お客様一意照会 */
	private static final String TEMPLATE_ID_ECK0011A010 = "ECK0011A010";
 	/** テンプレートID：請求契約番号一覧照会(CMP) */
	private static final String TEMPLATE_ID_EKK0321B012 = "EKK0321B012";
 	/** テンプレートID：サービス契約番号(代表)一覧照会(CMP) */
	private static final String TEMPLATE_ID_EKK0081B042 = "EKK0081B042";
	/** テンプレートID：サービス契約一意照会 */
	private static final String TEMPLATE_ID_EKK0081A010 = "EKK0081A010";

	/** テンプレートID：一時金一覧照会（請求年月） */
	private static final String TEMPLATE_ID_EAC0171B030 = "EAC0171B030";
	/** テンプレートID：通信量合計請求年月一覧照会(請求契約番号) */
	private static final String TEMPLATE_ID_EAC0601B040 = "EAC0601B040";

	/** 作業用マップのキー：運用日 */
	private static final String WORK_KEY_OPEDATE = "opeDate";
	/** 作業用マップのキー：お客様一意照会明細 */
	private static final String WORK_KEY_ECK0011A010CBSMSGLIST = "ECK0011A010CBSMsg1List";
	// ANK-3636-00-00 MOD START
	/** 電気料金項目コード */
//	private static final String ELE_PRC_KMK_CD = "11204010002";
	private static final String ELE_PRC_KMK_CD = "11204010002,21204010002";
	// ANK-3636-00-00 MOD END
	/** 従量情報結果コード：データあり */
	private static final String JYURYO_INFO_RESULT_0 = "0";
	/** 従量情報結果コード：データなし */
	private static final String JYURYO_INFO_RESULT_1 = "1";
	/** 従量情報結果コード：抽出範囲外 */
	private static final String JYURYO_INFO_RESULT_2 = "2";
	/** 従量情報結果コード：対象サービスなし */
	private static final String JYURYO_INFO_RESULT_3 = "3";
	/** パートナー会員 */
	private static final String PARTNER_CD = "99";
	/** リターンメッセージ取得キー */
	private static final String RETURN_MESSAGE_STRING = "RETURN_MESSAGE_";
	/** リターンメッセージの書式指定文字列 */
	private static final String RETURN_MESSAGE_FORMAT = "%1$04d";
	/** エラー項目接尾辞 */
	private static final String ERRITEM_SUFFIX = "_err";


	/**
	 * 契約情報から従量情報を照会する。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return リクエストパラメータ
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite searchJuryoLine(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		// 従量情報照会(LINE)CCマップ
		Map<String, Object> ccMsg = (Map<String, Object>)param.getData(fixedText);
		// 作業用マップ
		Map<String, Object> work = new HashMap<String, Object>();

		try
		{
			// 運用日
			work.put(WORK_KEY_OPEDATE, JPCBPCommon.getOpeDate(null));
			// 単項目チェック
			if (!checkUnitParam(handle, param, fixedText, ccMsg, work))
			{
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}

			// 関連チェック
			if (!checkParameter(handle, param, fixedText, ccMsg, work))
			{
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}

			// 従量情報検索処理
			searchJyuRyoInfo(handle, param, fixedText, ccMsg, work);

			// 正常終了
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_0000);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);
		}
		catch (Throwable throwable)
		{
			setResponse(param, ccMsg, JKKStrConst.RETURN_CD_9000, JKKStrConst.RETURN_MESSAGE_SYSTEM_ERROR, "");
			throw throwable;
		}

		return param;
	}

	/**
	 * 単項目チェック
	 * @param param
	 * @param ccMsg
	 * @param ekk0081b043Msg
	 * @return チェックの判定
	 * @throws Exception
	 */
	private boolean checkUnitParam(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			Map<String, Object> ccMsg, Map<String, Object> work)
	throws Exception
	{
		// 従量データリスト
		List<Map<String, Object>> jyuRyoList = new ArrayList<Map<String, Object>>();
		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();

		Map<String, Object> bodyMap = new HashMap<String, Object>();
		Map<String, Object> jyuRyoMap = new HashMap<String, Object>();
		String itemName = null;
		String itemValue = null;

		// SYSID
		itemName = SYSID;
		itemValue = (String)ccMsg.get(itemName);
		// 必須チェック
		if ( itemValue == null || "".equals(itemValue) )
		{
			// 必須チェックエラー
			errList.add(getReqErrInfMap());
		}
		else if (!HalfCharCheck.isEnNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getFormErrInfMap());
		}
		else if (!LengthCheck.isLength1Check(itemValue, 10))
		{
			// 桁数チェックエラー
			errList.add(getLenErrInfMap());
		}

		// 抽出対象請求年月
		itemName = CHSHT_TG_SEIKY_YM;
		itemValue = (String)ccMsg.get(itemName);
		// 必須チェック
		if ( itemValue == null || "".equals(itemValue) )
		{
			// 必須チェックエラー
			errList.add(getReqErrInfMap());
		}
		else if (!DatetimeCheck.isYearMonthCheck(itemValue))
		{
			// 属性チェックエラー
			errList.add(getFormErrInfMap());
		}
		else if (!LengthCheck.isLength1Check(itemValue, 6))
		{
			// 桁数チェックエラー
			errList.add(getLenErrInfMap());
		}

		// エラーが存在する場合
		if (errList.size() > 0)
		{
			// 会員種別コード
			bodyMap.put(MEMBER_SBT_CD, "");
			// 抽出対象請求年月
			bodyMap.put(CHSHT_TG_SEIKY_YM, (String)ccMsg.get(CHSHT_TG_SEIKY_YM));
			// 請求先番号
			jyuRyoMap.put(SEIKY_KEI_NO, "");
			// データ通信量結果コード
			jyuRyoMap.put(DATA_TSRYO_KK_CD, "");
			// データ通信量
			jyuRyoMap.put(DATA_TSRYO, "");
			// 電気使用量結果コード
			jyuRyoMap.put(EOELEC_USE_KK_CD, "");
			// 電気使用量
			jyuRyoMap.put(EOELEC_USE, "");

			// ボディ部の設定
			jyuRyoList.add(jyuRyoMap);
			bodyMap.put(JURYOLIST, jyuRyoList);
			ccMsg.put(BODY_INFO, bodyMap);

			ccMsg.put(ERROR_INFO, errList);
			return false;
		}
		
		return true;

	}

	/**
	 * 関連チェックを行います。<br>
	 * ※後続処理に必要な情報の取得も行う。
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 請求情報照会(LINE)CCマップ
	 * @param work 作業用マップ
	 * @return チェックエラーの場合はfalse、チェックOKの場合はtrue
	 * @throws Throwable 例外が発生した場合
	 */
	private boolean checkParameter(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			Map<String, Object> ccMsg, Map<String, Object> work)
	throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		// 運用日
		String opeDate = (String)work.get(WORK_KEY_OPEDATE);
		// お客様一意照会明細
		CAANMsg[] eck0011a010MsgList = null;

		// 関連チェック(SYSID存在チェック、会員種別コードチェック、退会済チェック)
		// お客様一意照会
		Object[][] eck0011a010In =
		{
			{ECK0011A010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0011A010}
			// 機能コード
			, {ECK0011A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
			// ＫＥＹ＿ＳＹＳＩＤ
			, {ECK0011A010CBSMsg.KEY_SYSID, (String)ccMsg.get(SYSID)}
			// ＫＥＹ＿予約適用年月日
			, {ECK0011A010CBSMsg.KEY_RSV_APLY_YMD, opeDate}
		};
		// サービスIF実行
		eck0011a010MsgList = callSC(handle, scCall, param, fixedText, eck0011a010In)
				.getCAANMsgList(ECK0011A010CBSMsg.ECK0011A010CBSMSG1LIST);

		// SYSIDが取得できない場合
		String memberSbtCd = "";
		// ▼▼▼ ANK-3355-09-00 ADD START ▼▼▼
		String orsJgsCd = "";
		// ▲▲▲ ANK-3355-09-00 ADD END ▲▲▲
		if (eck0011a010MsgList == null || eck0011a010MsgList.length == 0)
		{
			// SYSID存在チェックエラー
			setResponse(param, ccMsg, JKKStrConst.RETURN_CD_2001, "", "");
			return false;
		}
		else {
			// 会員種別コードのチェック
			memberSbtCd = eck0011a010MsgList[0].getString(ECK0011A010CBSMsg1List.MEMBER_SBT_CD);
			// ▼▼▼ ANK-3355-09-00 ADD START ▼▼▼
			orsJgsCd = eck0011a010MsgList[0].getString(ECK0011A010CBSMsg1List.ORSJGS_CD);
			// ▲▲▲ ANK-3355-09-00 ADD END ▲▲▲
			// マスター会員（個人）:10、マスター会員（法人）:20以外もしくは卸事業者コードが空以外の場合エラー
			if ( memberSbtCd != null && (
					// ▼▼▼ ANK-3355-09-00 MOD START ▼▼▼
//					 !JCKStrConst.CD00039_MASTER_KOJIN.equals(memberSbtCd) &&
//					 !JCKStrConst.CD00039_MASTER_HOJIN.equals(memberSbtCd) )  )
					 (!JCKStrConst.CD00039_MASTER_KOJIN.equals(memberSbtCd) &&
					 !JCKStrConst.CD00039_MASTER_HOJIN.equals(memberSbtCd) )  ||
					 !JKKStringUtil.isNullBlank(orsJgsCd) )  )
					// ▲▲▲ ANK-3355-09-00 MOD END ▲▲▲
			{
				// 会員種別コードチェックエラー
				setResponse(param, ccMsg, JKKStrConst.RETURN_CD_2003, "", "");
				return false;
			}

			// 退会済のチェック
			String custNTaikai = eck0011a010MsgList[0].getString(ECK0011A010CBSMsg1List.CUST_NTAIKAI_CD);
			// 退会済の場合、
			if ( custNTaikai != null && JCKStrConst.CD00260_TAIKAI.equals(custNTaikai) )
			{
				// 退会済チェックエラー
				setResponse(param, ccMsg, JKKStrConst.RETURN_CD_2004, "", "");
				return false;
			}
		}

		// 抽出対象請求年月の過去日範囲チェック
		// 抽出対象請求年月がオンライン運用日・年月を基準に25ヶ月以上過去の場合エラー
		if (JCCBPCommon.subtractMonth(opeDate.substring(0, 6) + "01", (String)ccMsg.get(CHSHT_TG_SEIKY_YM) + "01") >= 25 )
		{
			// 抽出対象請求年月の過去日範囲チェックエラー
			setResponse(param, ccMsg, JKKStrConst.RETURN_CD_2002, "", "" );
			return false;
		}

		// 関連チェック(抽出対象請求年月のチェック）
		// 抽出対象請求年月の未来日チェック
		// 抽出対象請求年月がオンライン運用日・年月より未来の場合エラー
		if ( opeDate.substring(0, 6).compareTo((String)ccMsg.get(CHSHT_TG_SEIKY_YM)) < 0 )
		{
			// 抽出対象請求年月の未来日チェックエラー
			setResponse(param, ccMsg, JKKStrConst.RETURN_CD_2005, "", "");
			return false;
		}

		// お客様一意照会明細を作業用マップに設定
		work.put(WORK_KEY_ECK0011A010CBSMSGLIST, eck0011a010MsgList);

		return true;
	}

	/**
	 * 従量情報検索処理を行います。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param ccMsg 従量情報照会(LINE)CCマップ
	 * @param work 作業用マップ
	 * @throws Throwable 例外が発生した場合
	 */
	private void searchJyuRyoInfo(SessionHandle handle, IRequestParameterReadWrite param, String fixedText,
			Map<String, Object> ccMsg, Map<String, Object> work)
	throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		// 運用日
		String opeDate = (String)work.get(WORK_KEY_OPEDATE);
		// お客様一意照会明細
		CAANMsg eck0011a010MsgList = ((CAANMsg[])work.get(WORK_KEY_ECK0011A010CBSMSGLIST))[0];
		// 請求契約番号リスト
		ArrayList<String[]> seikyList = new ArrayList<String[]>();

		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();
		// 従量データリスト
		List<Map<String, Object>> jyuRyoDataList = new ArrayList<Map<String, Object>>();
		Map<String, Object> bodyMap = new HashMap<String, Object>();
		Map<String, Object> jyuryoMap = new HashMap<String, Object>();
		Map<String, String> errMap = new HashMap<String, String>();
		
		// 請求契約番号一覧照会(CMP)明細
		CAANMsg[] ekk0321b012MsgList = null;
		// サービス契約番号(代表)一覧照会(CMP)
		CAANMsg[] ekk0081b042MsgList = null;
		// サービス契約一意照会
		CAANMsg[] ekk0081a010MsgList = null;
		// 一時金一覧照会（利用開始年月）
		CAANMsg[] eac0171b030MsgList = null;
		// 通信量合計請求年月一覧照会(請求契約番号)
		CAANMsg[] eac0601b040MsgList = null;
		// 会員種別コード
		String memberSbtCd = eck0011a010MsgList.getString(ECK0011A010CBSMsg1List.MEMBER_SBT_CD);
		String orsJgsCd = eck0011a010MsgList.getString(ECK0011A010CBSMsg1List.ORSJGS_CD);

		// 請求契約番号の取得判定
		// 請求契約番号一覧照会(CMP)
		Object[][] ekk0321b012In =
		{
			{EKK0321B012CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0321B012}
			// 機能コード
			, {EKK0321B012CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1}
			// ＫＥＹ＿ＳＹＳＩＤ
			, {EKK0321B012CBSMsg.KEY_SYSID, (String)ccMsg.get(SYSID)}
		};
		// サービスIF実行
		ekk0321b012MsgList = callSC(handle, scCall, param, fixedText, ekk0321b012In)
				.getCAANMsgList(EKK0321B012CBSMsg.EKK0321B012CBSMSG1LIST);

		// 請求契約のレコードが取得出来た場合
		if(ekk0321b012MsgList != null && ekk0321b012MsgList.length > 0)
		{
			for(int i = 0; i < ekk0321b012MsgList.length; i++)
			{
				String seikyKeiNo = ekk0321b012MsgList[i].getString(EKK0321B012CBSMsg1List.SEIKY_KEI_NO);
			// 請求契約情報リスト(請求契約番号・ネット有無・電気有無）
				String[] seikyInfoList =  new String[]{seikyKeiNo ,JACStrConst.UM_NASHI ,JACStrConst.UM_NASHI};
					// サービス契約番号(代表)一覧照会(CMP)
				Object[][] ekk0081b042In =
				{
					{EKK0081B042CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0081B042}
					// 機能コード
					, {EKK0081B042CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
					// ＫＥＹ＿請求契約番号
					, {EKK0081B042CBSMsg.KEY_SEIKY_KEI_NO, seikyKeiNo}
				};
				// サービスIF実行
				ekk0081b042MsgList = callSC(handle, scCall, param, fixedText, ekk0081b042In)
						.getCAANMsgList(EKK0081B042CBSMsg.EKK0081B042CBSMSG1LIST);
				if(ekk0081b042MsgList != null && ekk0081b042MsgList.length > 0)
				{
					for(int j = 0; j < ekk0081b042MsgList.length; j++)
					{
						//ワーク領域設定用サービス契約番号
						String svcKeiNo = ekk0081b042MsgList[j].getString(EKK0081B042CBSMsg1List.SVC_KEI_NO);
						// サービス契約一意照会
						Object[][] ekk0081a010In =
						{
							{EKK0081A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0081A010}
							// 機能コード
							, {EKK0081A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
							// ＫＥＹ＿サービス契約番号
							, {EKK0081A010CBSMsg.KEY_SVC_KEI_NO, svcKeiNo}
							// ＫＥＹ＿予約適用年月日
							, {EKK0081A010CBSMsg.KEY_RSV_APLY_YMD, opeDate}
						};
						// サービスIF実行
						ekk0081a010MsgList = callSC(handle, scCall, param, fixedText, ekk0081a010In)
								.getCAANMsgList(EKK0081A010CBSMsg.EKK0081A010CBSMSG1LIST);

						// サービス契約が取得できた場合
						if (ekk0081a010MsgList != null && ekk0081a010MsgList.length > 0)
						{
							String svcKeiStat = ekk0081a010MsgList[0].getString(EKK0081A010CBSMsg1List.SVC_KEI_STAT);
							String svcCd = ekk0081a010MsgList[0].getString(EKK0081A010CBSMsg1List.SVC_CD);
							// インターネットサービス、もしくは電気サービス
							if ( JKKStrConst.CD00130_01.equals(svcCd) ||  JKKStrConst.CD00130_05.equals(svcCd) ) 
							{
								// 「受付済(010)」、「照査済(020)」、「締結済(030)」、「休止・中断中(210)」、「利用停止中(220)」、「解約済(910)」、「キャンセル済(920)」以外の場合
								if ( (!JKKStrConst.CD00037_UK_ZM.equals(svcKeiStat) && !JKKStrConst.CD00037_SHOSA_ZUMI.equals(svcKeiStat) &&  
									// ANK-3629-00-00 MOD START
//								     !JKKStrConst.CD00037_CNC_ZM.equals(svcKeiStat) &&  !JKKStrConst.CD00037_CANCEL_ZM.equals(svcKeiStat) ) )
								     !JKKStrConst.CD00037_CNC_ZM.equals(svcKeiStat) &&  !JKKStrConst.CD00037_CANCEL_ZM.equals(svcKeiStat) &&
								     !JKKStrConst.CD00037_STAT_PAUSE.equals(svcKeiStat) &&  !JKKStrConst.CD00037_STAT_STP.equals(svcKeiStat) &&
								     !JKKStrConst.CD00037_DSL_ZM.equals(svcKeiStat)
								) )
									// ANK-3629-00-00 MOD END
								{
									// インターネットサービス有
									if ( JKKStrConst.CD00130_01.equals(svcCd) )
									{
										seikyInfoList[1] = JACStrConst.UM_ARI;
									}
									// 電気サービス有
									if ( JKKStrConst.CD00130_05.equals(svcCd) )
									{
										seikyInfoList[2] = JACStrConst.UM_ARI;
									}
								}
							}
						}
					}
				}
				// インターネットサービスもしくは電気サービスのいずれかがありの場合、請求情報を設定する
				if ( JACStrConst.UM_ARI.equals(seikyInfoList[1])  || JACStrConst.UM_ARI.equals(seikyInfoList[2] ) )
				{
					seikyList.add(seikyInfoList);
				}
			}
		}
		// 請求契約存在チェック 対象データが存在しない場合は空を返却する
		if ( seikyList.size() == 0 )
		{
			if ( memberSbtCd != null && (JCKStrConst.MMB_SBT_CD_MASTER_KOJIN.equals(memberSbtCd) ) && orsJgsCd != null )
			{
				setResponse(param, ccMsg, "", "", PARTNER_CD);
			}
			else
			{
				setResponse(param, ccMsg, "", "", memberSbtCd);
			}
			return;
		}
		
		// 従量情報の取得
		// 請求契約リスト
		for (String[] seikyKeiNoTmp : seikyList)
		{
			// データ通信量結果コード
			String dataUseResultCd = "";
			// データ通信量合計
			String dataUseSum = "";
			// 電気使用量結果コード
			String elecUseResultCd = "";
			// 電気使用量合計
			String elecUseSum = "";

			// 電気使用量結果コード：対象サービスなし
			if ( JACStrConst.UM_NASHI.equals(seikyKeiNoTmp[2]) )
			{
				elecUseResultCd = JYURYO_INFO_RESULT_3;
				elecUseSum = "";
			}
			// 電気契約が存在する場合
			else
			{
				// 一時金一覧照会（利用開始年月）
				Object[][] eac0171b030In =
				{
					{EAC0171B030CBSMsg.TEMPLATEID, TEMPLATE_ID_EAC0171B030}
					// 機能コード
					, {EAC0171B030CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1}
					// ＫＥＹ＿請求契約番号
					, {EAC0171B030CBSMsg.KEY_SEIKY_KEI_NO, seikyKeiNoTmp[0]}
					// ＫＥＹ＿利用開始年月
					, {EAC0171B030CBSMsg.KEY_USE_STAYM, (String)ccMsg.get(CHSHT_TG_SEIKY_YM)}
					// ＫＥＹ＿料金項目コード
					, {EAC0171B030CBSMsg.KEY_PRC_KMK_CD, ELE_PRC_KMK_CD}
				};
				// サービスIF実行
				eac0171b030MsgList = callSC(handle, scCall, param, fixedText, eac0171b030In)
						.getCAANMsgList(EAC0171B030CBSMsg.EAC0171B030CBSMSG1LIST);

				// 一時金一覧照会のレコードが取得出来た場合
				if(eac0171b030MsgList != null && eac0171b030MsgList.length > 0)
				{
					// IT1-2019-0000042 MOD START
					//int elecUseSumTmp = 0;
					long elecUseSumTmp = 0;
					// IT1-2019-0000042 MOD END
					for(int m = 0; m < eac0171b030MsgList.length; m++)
					{
						// 一時金料金
						// IT1-2019-0000042 MOD START
						//int icjknPrc = Integer.parseInt(nullToZero(eac0171b030MsgList[m].getString(EAC0171B030CBSMsg1List.ICJKN_PRC)));
						long icjknPrc = Long.parseLong(nullToZero(eac0171b030MsgList[m].getString(EAC0171B030CBSMsg1List.ICJKN_PRC)));
						// IT1-2019-0000042 MOD END
						// 一時金取込ステータス
						String icjknTrkmStat = eac0171b030MsgList[m].getString(EAC0171B030CBSMsg1List.ICJKN_TRKM_STAT);
						// 一時金取込ステータスが（取込済）の場合、合算する
						if ( JACStrConst.ICJKN_TRKM_STAT_ZUMI.equals(icjknTrkmStat) )
						{
							elecUseSumTmp = elecUseSumTmp + icjknPrc;
						}
					}
					// 電気使用量結果コード：対象サービスあり
					if ( elecUseSumTmp > 0 )
					{
						elecUseResultCd = JYURYO_INFO_RESULT_0;
						// IT1-2019-0000042 MOD START
						//elecUseSum = Integer.toString(elecUseSumTmp);
						elecUseSum = Long.toString(elecUseSumTmp);
						// IT1-2019-0000042 MOD END
					}
					// 電気使用量結果コード：料金確定前(レコードが存在するが、取込済以外のみの場合
					else
					{
						elecUseResultCd = JYURYO_INFO_RESULT_2;
						elecUseSum = "";
					}
				}
				// 電気使用量結果コード：データなし
				else
				{
					elecUseResultCd = JYURYO_INFO_RESULT_1;
					elecUseSum = "0";
				}
			}
					
			// ネット契約が存在しない場合
			if ( JACStrConst.UM_NASHI.equals(seikyKeiNoTmp[1]))
			{
				dataUseResultCd = JYURYO_INFO_RESULT_3;
				dataUseSum = "";
			}
			// 抽出対象請求年月がオンライン運用日・年月を4ヶ月以前の場合
			// ST-2019-0000003 MOD START
			//else if (JCCBPCommon.subtractMonth(opeDate.substring(0, 6) + "01", (String)ccMsg.get(CHSHT_TG_SEIKY_YM) + "01") >= 4 )
			else if (JCCBPCommon.subtractMonth(opeDate.substring(0, 6) + "01", (String)ccMsg.get(CHSHT_TG_SEIKY_YM) + "01") >= 3 )
			// ST-2019-0000003 MOD END
			{
				dataUseResultCd = JYURYO_INFO_RESULT_2;
				dataUseSum = "";
			}
			// ネット契約が存在する場合
			else
			{
				// 通信量合計請求年月一覧照会(請求契約番号)
				Object[][] eac0601b040In =
				{
					{EAC0601B040CBSMsg.TEMPLATEID, TEMPLATE_ID_EAC0601B040}
					// 機能コード
					, {EAC0601B040CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1}
					// ＫＥＹ＿請求契約番号
					, {EAC0601B040CBSMsg.KEY_SEIKY_KEI_NO, seikyKeiNoTmp[0]}
					// ＫＥＹ＿請求年月
					, {EAC0601B040CBSMsg.KEY_SEIKY_YM, (String)ccMsg.get(CHSHT_TG_SEIKY_YM)}
				};
				// サービスIF実行
				eac0601b040MsgList = callSC(handle, scCall, param, fixedText, eac0601b040In)
						.getCAANMsgList(EAC0601B040CBSMsg.EAC0601B040CBSMSG1LIST);

				// 一時金一覧照会のレコードが取得出来た場合
				if(eac0601b040MsgList != null && eac0601b040MsgList.length > 0)
				{
					// IT1-2019-0000042 MOD START
					//int dataUseSumTmp = 0;
					long dataUseSumTmp = 0;
					// IT1-2019-0000042 MOD END
					for(int n = 0; n < eac0601b040MsgList.length; n++)
					{
						// 利用通信量合計
						// IT1-2019-0000042 MOD START
						//int useTsryoGk = Integer.parseInt(nullToZero(eac0601b040MsgList[n].getString(EAC0601B040CBSMsg1List.USE_TSRYO_GK)));
						long useTsryoGk = Long.parseLong(nullToZero(eac0601b040MsgList[n].getString(EAC0601B040CBSMsg1List.USE_TSRYO_GK)));
						// IT1-2019-0000042 MOD END
						// IT2-2019-0000020 MOD START
						// 補正通信量合計
						// IT1-2019-0000042 MOD START
						//int hoseiTsryoGk = Integer.parseInt(nullToZero(eac0601b040MsgList[n].getString(EAC0601B040CBSMsg1List.HOSEI_TSRYO_GK)));
						long hoseiTsryoGk = Long.parseLong(nullToZero(eac0601b040MsgList[n].getString(EAC0601B040CBSMsg1List.HOSEI_TSRYO_GK)));
						// IT1-2019-0000042 MOD END
						//dataUseSumTmp = dataUseSumTmp + useTsryoGk;
						dataUseSumTmp = dataUseSumTmp + useTsryoGk + hoseiTsryoGk;
						// IT2-2019-0000020 MOD END
					}
					// データ通信量結果コード：対象サービスあり
					dataUseResultCd = JYURYO_INFO_RESULT_0;
					// IT1-2019-0000042 MOD START
					//dataUseSum = Integer.toString(dataUseSumTmp);
					dataUseSum = Long.toString(dataUseSumTmp);
					// IT1-2019-0000042 MOD END
				}
				// データ通信量結果コード：対象サービスなし
				else
				{
					dataUseResultCd = JYURYO_INFO_RESULT_1;
					dataUseSum = "0";
				}
			}
			
			// 従量データリストにマッピング
			jyuRyoDataList.add(setJyuRyoMap( seikyKeiNoTmp[0], dataUseResultCd, dataUseSum, elecUseResultCd, elecUseSum ));
	
		}
		bodyMap.put(JURYOLIST, jyuRyoDataList);
		// 会員種別コードがパートナー会員の場合、９９を設定する
		if ( memberSbtCd != null && (JCKStrConst.MMB_SBT_CD_MASTER_KOJIN.equals(memberSbtCd) ) && orsJgsCd != null )
		{
			bodyMap.put(MEMBER_SBT_CD, PARTNER_CD);
		}
		else
		{
			bodyMap.put(MEMBER_SBT_CD, memberSbtCd);
		}
		// 抽出対象請求年月
		bodyMap.put(CHSHT_TG_SEIKY_YM, (String)ccMsg.get(CHSHT_TG_SEIKY_YM));
		ccMsg.put(BODY_INFO, bodyMap);
		// エラーコード
		errMap.put(ERROR_CODE, "");
		// エラーメッセージ
		errMap.put(ERROR_MESSAGE, "");
		errList.add(errMap);
		ccMsg.put(ERROR_INFO, errList);

		return;
	}

	/**
	 * レスポンス項目を設定します。
	 * <br>
	 * @param ccMsg 従量情報照会(LINE)CCマップ
	 * @param returnCode リターンコード
	 * @param returnMessage リターンメッセージ
	 * @param memberSbtCd 会員種別コード
	 */
	private void setResponse(IRequestParameterReadWrite param,  Map<String, Object> ccMsg, String errCode, String errMessage, String memberSbtCd)
	throws Exception
	{
		// 従量データリスト
		List<Map<String, Object>> jyuRyoList = new ArrayList<Map<String, Object>>();
		// エラーリスト
		List<Map<String, String>> errList = new ArrayList<Map<String, String>>();

		Map<String, Object> bodyMap = new HashMap<String, Object>();
		Map<String, Object> jyuRyoMap = new HashMap<String, Object>();
		Map<String, String> errMap = new HashMap<String, String>();

		// 会員種別コード
		bodyMap.put(MEMBER_SBT_CD, memberSbtCd);
		// 抽出対象請求年月
		bodyMap.put(CHSHT_TG_SEIKY_YM, (String)ccMsg.get(CHSHT_TG_SEIKY_YM));
		// 請求先番号
		jyuRyoMap.put(SEIKY_KEI_NO, "");
		if ( "".equals(errCode) )
		{
			// データ通信量結果コード
			jyuRyoMap.put(DATA_TSRYO_KK_CD, JYURYO_INFO_RESULT_3);
			// データ通信量
			jyuRyoMap.put(DATA_TSRYO, "");
			// 電気使用量結果コード
			jyuRyoMap.put(EOELEC_USE_KK_CD, JYURYO_INFO_RESULT_3);
			// 電気使用量
			jyuRyoMap.put(EOELEC_USE, "");
		}
		else
		{
			// データ通信量結果コード
			jyuRyoMap.put(DATA_TSRYO_KK_CD, "");
			// データ通信量
			jyuRyoMap.put(DATA_TSRYO, "");
			// 電気使用量結果コード
			jyuRyoMap.put(EOELEC_USE_KK_CD, "");
			// 電気使用量
			jyuRyoMap.put(EOELEC_USE, "");
		}

		// ボディ部の設定
		jyuRyoList.add(jyuRyoMap);
		bodyMap.put(JURYOLIST, jyuRyoList);
		ccMsg.put(BODY_INFO, bodyMap);

		// エラーコード
		errMap.put(ERROR_CODE, errCode);
		// エラーメッセージ
		errMap.put(ERROR_MESSAGE, errMessage);
		errList.add(errMap);
		ccMsg.put(ERROR_INFO, errList);
		

	}
	
	/**
	 * 従量データをマッピング
	 * 
	 * @param jyuryoMap 従量データマップ
	 * @param dataTsryoKkCd データ通信量結果コード
	 * @param dataTsryo データ通信量
	 * @param elecTsryoKkCd 電気使用量結果コード
	 * @param elecTsryo 電気使用量
	 * @return setJyuRyoMap
	 */
	public static Map<String, Object> setJyuRyoMap(String seikyKeiNo, String dataTsryoKkCd, String dataTsryo, String elecTsryoKkCd, String elecTsryo)
	{
		// 従量データリスト
		Map<String, Object> jyuryoMap = new HashMap<String, Object>();
		jyuryoMap.put(SEIKY_KEI_NO, seikyKeiNo);
		jyuryoMap.put(DATA_TSRYO_KK_CD, dataTsryoKkCd);
		jyuryoMap.put(DATA_TSRYO, dataTsryo);
		jyuryoMap.put(EOELEC_USE_KK_CD, elecTsryoKkCd);
		jyuryoMap.put(EOELEC_USE, elecTsryo);

		return jyuryoMap;
	}
		

	/**
	 * SC(サービスインターフェイス）を呼び出します。
	 * @param handle セッションハンドル
	 * @param scCall SC呼び出し部品
	 * @param param リクエストパラメータ
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @return サービスインターフェイス実行結果
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	private CAANMsg callSC(SessionHandle handle, 
							ServiceComponentRequestInvoker scCall, 
							IRequestParameterReadWrite param, 
							String dataMapKey,
							Object[][] mappingData) throws Throwable
	{
		HashMap<String, Object> paramMap = editInMsg(param, mappingData);

		Map<?, ?> result = scCall.run(paramMap, handle);

		CAANMsg[] templates = (CAANMsg[])result.get(JCMConstants.TEMPLATE_LIST_KEY);

		CAANMsg msg = templates[0];

		// リターンコード取得
		Object RETURN_CODE = result.get(JCMConstants.RET_CD_INT_KEY);

		int status = msg.getInt(JCMConstants.STATUS_INT_KEY);

		editErrorInfoCom(param, templates, (Integer)RETURN_CODE, dataMapKey);

		//エラー情報のマップを取得
		ArrayList<Object> errList = (ArrayList<Object>)param.getControlMapData(SCControlMapKeys.ERROR_INFO);

		if (null == errList)
		{
			errList = new ArrayList<Object>();
		}

		// コントロールマップに設定
		param.setControlMapData(SCControlMapKeys.ERROR_INFO, TemplateErrorUtil.getErrorInfo(result, errList));

		// 異常の場合、SCCallExceptionを生成してスローする
		if(!("0".equals(RETURN_CODE.toString()) && 0 == status))
		{
			throw new SCCallException("戻り値不正", RETURN_CODE.toString(), status);
		}

		return msg;
	}

	/**
	 * 共通項目のメッセージを作成します。
	 * @param param リクエストパラメータ
	 * @param mappingData マッピングデータ
	 * @return HashMap<String, Object>
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	private HashMap<String, Object> editInMsg(IRequestParameterReadWrite param,
												Object[][] mappingData) throws RequestParameterException
	{
		HashMap<String, Object> paramMap = new HashMap<String, Object>();

		// 【取得元：電文ヘッダ(ヘッダ)】
		// 電文ID
		paramMap.put(JCMConstants.TRANZACTION_ID_KEY, param.getTelegramID());

		// ユースケースID
		paramMap.put(JCMConstants.USECASE_ID_KEY, param.getUsecaseID());

		// オペレーションID
		paramMap.put(JCMConstants.OPERATION_ID_KEY, param.getOperationID());

		// サービス呼び出し区分
		paramMap.put(JCMConstants.CALL_TYPE_KEY, param.getCallType());

		// 【取得元：ユーザエリア(コントロールマップ)】
		// 依頼先ホスト名
		paramMap.put(JCMConstants.CLIENT_HOST_NAME_KEY, param.getControlMapData(SCControlMapKeys.REQ_HOSTNAME));

		// 依頼元IPアドレス
		paramMap.put(JCMConstants.CLIENT_IP_ADDRESS_KEY, param.getControlMapData(SCControlMapKeys.REQ_HOSTIP));

		// 依頼元画面ID
		paramMap.put(JCMConstants.INVOKE_GAMEN_ID_KEY, param.getControlMapData(SCControlMapKeys.REQ_VIEWID));

		// オペレータID
		paramMap.put(JCMConstants.OPERATOR_ID_KEY, param.getControlMapData(SCControlMapKeys.OPERATOR_ID));

		String svcIf = (String)mappingData[0][1];

		CAANMsg template = new CAANMsg(String.format("eo.ejb.cbs.cbsmsg.%sCBSMsg", svcIf));

		// オペレータID
		template.set(JCMConstants.OPERATOR_ID_KEY, param.getControlMapData(SCControlMapKeys.OPERATOR_ID));

		// 運用日付
		template.set(JCMConstants.OPERATE_DATE_KEY, param.getControlMapData(SCControlMapKeys.OPE_DATE));

		// 運用日時
		template.set(JCMConstants.OPERATE_DATETIME_KEY, param.getControlMapData(SCControlMapKeys.OPE_TIME));
		
		for (int i = 0; i < mappingData.length; i++)
		{
			if (mappingData[i][1] instanceof CAANMsg[])
			{
				template.set((String)mappingData[i][0], (CAANMsg[])mappingData[i][1]);
			}
			else
			{
				if ("".equals(mappingData[i][1]))
				{
					template.setNull((String)mappingData[i][0]);
				}
				else
				{
					template.set((String)mappingData[i][0], mappingData[i][1]);
				}
			}
		}

		CAANMsg[] templates = new CAANMsg[1];

		templates[0] = template;

		paramMap.put(JCMConstants.TEMPLATE_LIST_KEY, templates);

		return paramMap;
	}

	/**
	 * エラー情報を取得します。
	 * @param param リクエストパラメータ
	 * @param templates CAANMsgクラス
	 * @param errorCode リターンコード
	 * @param dataMapKey パラメータキー
	 * @return IRequestParameterReadWrite
	 * @throws RequestParameterException リクエストパラメータの操作でエラーが発生した場合
	 */
	@SuppressWarnings("unchecked")
	private IRequestParameterReadWrite editErrorInfoCom(IRequestParameterReadWrite param,
														CAANMsg[] templates, 
														int errorCode,
														String dataMapKey) throws RequestParameterException
	{
		CAANMsg template = templates[0];

		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		if (0 != errorCode)
		{
			templateStatus = 9000;
		}

		if (null == JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + String.format(RETURN_MESSAGE_FORMAT, templateStatus)))
		{
			templateStatus = 0;
		}

		int bpStatus = 0;

		Object obj = param.getControlMapData(SCControlMapKeys.RETURN_CODE);
		
		if (null == obj)
		{
			bpStatus = -1;
		}
		else
		{
			bpStatus = Integer.parseInt((String)param.getControlMapData(SCControlMapKeys.RETURN_CODE));
		}

		if (templateStatus > bpStatus)
		{
			// BPにサービスコンポーネントのステータスを設定する。
			String formatStatus = String.format(RETURN_MESSAGE_FORMAT, templateStatus);
			
			String message = JCMAPLConstMgr.getString(RETURN_MESSAGE_STRING + formatStatus);
			
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, formatStatus);
			
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, message);
		}

		// ユーザデータ情報
		HashMap<String, Object> inMap = (HashMap<String, Object>)param.getData(dataMapKey);

		HashMap map = template.getHashMap();
		Iterator it = map.keySet().iterator();
		while (it.hasNext())
		{
			String key = (String)it.next();
			Object value = map.get(key);
			if (value instanceof HashMap[])
			{
				HashMap[] childMapList = (HashMap[])value;
				for (HashMap childMap : childMapList)
				{
					Iterator childIt = childMap.keySet().iterator();
					while (childIt.hasNext())
					{
						String childKey = (String)childIt.next();
						if (childKey.endsWith(ERRITEM_SUFFIX))
						{
							int keyIdx = childKey.lastIndexOf(ERRITEM_SUFFIX);
							if (inMap.containsKey(childKey.substring(0, keyIdx)))
							{
								inMap.put(childKey, childMap.get(childKey));
							}
						}
					}
				}
			}
			else
			{
				if (key.endsWith(ERRITEM_SUFFIX))
				{
					int keyIdx = key.lastIndexOf(ERRITEM_SUFFIX);
					if (inMap.containsKey(key.substring(0, keyIdx)))
					{
						inMap.put(key, map.get(key));
					}
				}
			}
		}

		return param;
	}

	/**
	 * 単項目チェックの必須エラーマップ作成メソッドです。
	 * 
	 * @return returnMap
	 */
	public static Map<String, String> getReqErrInfMap()
	{
		Map<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1001);
		returnMap.put(ERROR_MESSAGE, "");
		
		return returnMap;
	}
	
	/**
	 * 単項目チェックの属性エラーマップ作成メソッドです。
	 * 
	 * @return returnMap
	 */
	public static Map<String, String> getFormErrInfMap()
	{
		Map<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1002);
		returnMap.put(ERROR_MESSAGE, "");
		
		return returnMap;
	}
	
	/**
	 * 単項目チェックの桁数エラーマップ作成メソッドです。
	 * 
	 * @return returnMap
	 */
	public static Map<String, String> getLenErrInfMap()
	{
		Map<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, JKKStrConst.RETURN_CD_1003);
		returnMap.put(ERROR_MESSAGE, "");
		
		return returnMap;
	}

	/**
	 * nullを"0"に置き換え
	 * 
	 * @param str 置き換え対象文字列
	 * @return
	 */
	public static String nullToZero(String str)
	{
		if (str == null)
		{
			return "0";
		}
		return str;
	}
}
