/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JCHSeikyOtokgkShokaiCC
*	ソースファイル名：JCHSeikyOtokgkShokaiCC.java
*	作成者			：FJ)吉田あ
*	日付			：2023年10月20日
*＜機能概要＞
*	請求料金お得額照会(CMP)の共通コンポーネントクラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*   v68.00.00	2023/10/20	FJ)吉田あ	【ANK-4500-00-00】ANK-4500-00-00_eoマイページへのお得額表示・プラン見直しシミュレーション機能実装
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
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.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.JCHStringUtil;
import eo.common.util.JPCUtilCommon;
import eo.ejb.cbs.cbsmsg.ECH0891B010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECH0891B010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECH0961B010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECH0961B010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0011A010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0011A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK0491A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0311B010CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0311B010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0321A010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0321B010CBSMsg;

/**
 * 請求情報お得額照会(CMP)の共通コンポーネントクラスです。
 * <br>
 * @author FJ
 */
public class JCHSeikyOtokgkShokaiCC extends AbstractCommonComponent
{
	/*
	 * ============
	 * CCパラメータ
	 * ============
	 */
	/** CC共通パラメータ：ボディ情報 */
	public static final String BODY_INFO = "BODY_INFO";
	
	/** CC入力パラメータ：SYSID */
	public static final String IN_SYSID = "sysid";
	/** CC入力パラメータ：請求契約番号 */
	public static final String IN_BILLING_CONTRACTNUMBER = "billingContractNumber";
	
	/** CC出力パラメータ：請求契約番号 */
	public static final String OUT_BILLING_CONTRACT_NUMBER = "billingContractNumber";
	/** CC出力パラメータ：お得額累計 */
	public static final String OUT_TOTAL_PROFIT_AMOUNT = "totalProfitAmount";
	/** CC出力パラメータ：月別お得額リスト */
	public static final String OUT_BILLING_BILLING_LIST = "billingList";
	/** CC出力パラメータ：年月 */
	public static final String OUT_YEAR_MONTH = "yearMonth";
	/** CC出力パラメータ：月額料金 */
	public static final String OUT_MONTHLY_AMOUNT = "monthlyAmount";
	/** CC出力パラメータ：割引前月額料金 */
	public static final String OUT_UNDISCOUNTED_MONTHLY_AMOUNT = "undiscountedMonthlyAmount";
	/** CC出力パラメータ：お得月額料金 */
	public static final String OUT_PROFIT_MONTHLY_AMOUNT = "profitMonthlyAmount";
	/** CC出力パラメータ：サービスリスト */
	public static final String OUT_SERVICE_LIST= "serviceList";
	/** CC出力パラメータ：整理番号 */
	public static final String OUT_ORGANIZE_NUMBER = "organizeNumber";
	/** CC出力パラメータ：サービス種別 */
	public static final String OUT_SERVICE_CATEGORY = "serviceCategory";
	/** CC出力パラメータ：お得額明細リスト */
	public static final String OUT_PROFIT_DETAIL_LIST = "profitDetailList";
	/** CC出力パラメータ：料金グループコード */
	public static final String OUT_FEE_GROUP_CODE = "feeGroupCode";
	/** CC出力パラメータ：料金コースコード */
	public static final String OUT_FEE_COURSE_CODE = "feeCourseCode";
	/** CC出力パラメータ：料金サービスコード */
	public static final String OUT_FEE_SERVICE_CODE = "feeServiceCode";
	/** CC出力パラメータ：料金項目コード */
	public static final String OUT_FEE_ITEM_CODE = "feeItemCode";
	/** CC出力パラメータ：お得額 */
	public static final String OUT_PROFIT_AMOUNT = "profitAmount";
	/** CC出力パラメータ：お得額名称 */
	public static final String OUT_PROFIT_NAME = "profitName";
	/** CC出力パラメータ：お得額説明 */
	public static final String OUT_PROFIT_EXPLANATION = "profitExplanation";
	
	/** CC出力パラメータ：エラー情報 */
	public static final String ERROR_INFO = "ERROR_INFO";
	/** CC出力パラメータ：エラーコード */
	public static final String ERROR_CODE = "errorCode";
	/** CC出力パラメータ：エラーメッセージ */
	public static final String ERROR_MESSAGE = "errorMessage";
	
	/*
	 * ==============
	 * テンプレートID
	 * ==============
	 */
	/** テンプレートID：システムパラメータ管理一覧照会 */
	private static final String TEMPLATE_ID_EZM0311B010 = "EZM0311B010";
	/** テンプレートID：お客様一意照会 */
	private static final String TEMPLATE_ID_ECK0011A010 = "ECK0011A010";
	/** テンプレートID：請求契約一意照会 */
	private static final String TEMPLATE_ID_EKK0491A010 = "EKK0491A010";
	/** テンプレートID：月別請求契約_お客様一覧照会 */
	private static final String TEMPLATE_ID_ECH0891B010 = "ECH0891B010";
	/** テンプレートID：お得額表示管理一覧照会 */
	private static final String TEMPLATE_ID_ECH0961B010 = "ECH0961B010";
	/** テンプレートID：業務パラメータ管理一覧照会 */
	private static final String TTEMPLATE_ID_EZM0321B010 = "EZM0321B010";;
	
	/*
	 * ========
	 * 共通定数
	 * ========
	 */
	/** リターンメッセージ取得キー */
	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";
	
	/* 
	 * ============
	 * 資産固有定数
	 * ============
	 */
	/** 定数：システムパラメータ設定値1.お得額表示管理参照可否フラグ */
	private static final String CONST_OTKGK_DSPKNR_SNSHO_KH = "0";
	/** 定数：お得額表示管理参照可能範囲 */
	private static final String  CONST_OTKDSPKNR_SNSHO_SCP = "OTKDSPKNR_SNSHO_SCP";
	/** 定数：お得額データ種別(お得額データ種別コード1：月額料金) */
	private static final String CONST_OTOKGK_DATA_SBT1 = "1";
	/** 定数：お得額データ種別(お得額データ種別コード2：割引前月額料金) */
	private static final String CONST_OTOKGK_DATA_SBT2 = "2";
	/** 定数：お得額データ種別(お得額データ種別コード3：お得月額料金) */
	private static final String CONST_OTOKGK_DATA_SBT3 = "3";
	/** 定数：お得額データ種別(お得額データ種別コード4：お得額明細) */
	private static final String CONST_OTOKGK_DATA_SBT4 = "4";
	/** 定数：お得額集計区分(お得額集計区分2：即割) */
	private static final String CONST_OTOKGK_SHUK_DIV2 = "2";
	/** 定数：お得額集計区分(お得額集計区分3：長割) */
	private static final String CONST_OTOKGK_SHUK_DIV3 = "3";
	/** 定数：お得額集計区分(お得額集計区分4：キャンペーン) */
	private static final String CONST_OTOKGK_SHUK_DIV4 = "4";
	/** 定数：エラーメッセージ(API利用不可エラー) */
	private static final String CONST_ERROR_MSG_API_SNSHFAIL = "API利用不可エラー";
	/** 定数：エラーメッセージ(お客様が見つかりません) */
	private static final String CONST_ERROR_MSG_NOTFOUND_CUST = "お客様がみつかりません。";
	/** 定数：エラーメッセージ(請求先が見つかりません) */
	private static final String CONST_ERROR_MSG_NOTFOUND_SEIKYKEI = "請求先がみつかりません。";
	
	/*
	 * ==============
	 * グローバル変数
	 * ==============
	 */
	/** 業務処理用work */
	HashMap<Object, Object> workMap = new HashMap<Object, Object>();
	
	/*
	 * ============================================
	 * workMap用key定数(SIF結果は必要時にテンプレートIDを使用)
	 * ============================================
	 */
	/** (workMap用)お得額表示制御 */
	private static final String WORK_OTKGAK_DSP_CTRL = "OTK_AMNT_DSP_CTRL";
	/** (workMap用)過去24ヶ月分の年月 */
	private static final String WORK_YEAR_MONTH_LIST = "WORK_YEAR_MONTH_LIST";
	
	/*
	 * ==========================
	 * 資産固有定数（内部処理用）
	 * ==========================
	 */
	/**
	 * 定数：業務パラメータID：お得額対象置換割＿置き換え処理用
	 * ※お得額の計算対象となる置換割の料金項目とお得額名称を判別するために使用
	 */
	private static final String CONST_CH_OTK_TG_CKNWR_ = "CH_OTK_TG_CKNWR_";
	
	/**
	 * 契約情報から請求情報を照会する。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return リクエストパラメータ
	 * @throws Throwable 例外が発生した場合
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite execute(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		
		// CCパラメータ
		HashMap ccMsg = (HashMap<String, Object>)param.getData(fixedText);
		
		// レスポンス
		HashMap<String, Object> responseMap = new HashMap<String, Object>();
		
		try
		{
			// システムパラメータ管理一覧照会
			CAANMsg[] ezm0311b010MsgList = null;
			
			// 運用日付
			Object operateDate = param.getControlMapData(SCControlMapKeys.OPE_DATE);
			
			// お得額表示管理参照可能範囲
			String OTKDSPKNR_SNSHO_SCP = null;
			// お得額表示管理参照可能範囲_請求年月_自
			String seikyYm_from = null;
			// お得額表示管理参照可能範囲_請求年月_至
			String seikyYm_to = null;
			
			// システムパラメータ管理一覧照会
			// サービスIF実行
			ezm0311b010MsgList = callEZM0311B010_FUNC1(handle, param, fixedText,
					WORK_OTKGAK_DSP_CTRL, operateDate
			);
			
			// API参照可否チェック
			if (!checkApiSnshKh(handle, param, fixedText, ezm0311b010MsgList))
			{
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}
			
			// 単項目チェック
			if (!checkUnitParam(handle, param, fixedText))
			{
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}
			
			// 関連チェック
			if (!checkParameter(handle, param, fixedText))
			{
				param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_5000);
				return param;
			}
			
			// システムパラメータ管理一覧照会で取得した分レコードを取り出す
			for (int i = 0; i < ezm0311b010MsgList.length; i++)
			{
				// お得額表示管理参照可能範囲を取得
				OTKDSPKNR_SNSHO_SCP = ezm0311b010MsgList[i].getString(EZM0311B010CBSMsg1List.SYS_PARAM_ID);
				
				if (CONST_OTKDSPKNR_SNSHO_SCP.equals(OTKDSPKNR_SNSHO_SCP) ){
					seikyYm_from = ezm0311b010MsgList[i].getString(EZM0311B010CBSMsg1List.SYS_PARAM_SETTE_VALUE_1);
					seikyYm_to = ezm0311b010MsgList[i].getString(EZM0311B010CBSMsg1List.SYS_PARAM_SETTE_VALUE_2);
				}
			}
			
			// 請求情報取得前処理
			getSeikyInfoBf(handle, param, fixedText, seikyYm_from, seikyYm_to);
			
			// 請求情報返却判定処理
			if(!judgeSeikyInfoReturn())
			{
				// 取得対象外なら請求情報は取得せず、年月のみのレスポンスの編集を行う
				responseMap = getResponseMapEmpty(handle, param, fixedText);
			} else {
				// ANK-4500-00 DEL START
//				// 退避させていた月別請求契約_お客様一覧照会明細を取得
//				ArrayList<String> getEch0891_SeikyYmList = (ArrayList<String>) workMap.get(TEMPLATE_ID_ECH0891B010);
				// ANK-4500-00DEL END
				
				// お得額表示管理一覧照会明細
				// サービスIF実行
				CAANMsg[] ech0961b010MsgList = null;
				// ANK-4500-00 MOD START
//				ech0961b010MsgList = callECH0961B010_FUNC1(handle, param, fixedText
//						, (String)ccMsg.get(IN_BILLING_CONTRACTNUMBER)
//						, getEch0891_SeikyYmList
//				);
				ech0961b010MsgList = callECH0961B010_FUNC1(handle, param, fixedText
						, (String)ccMsg.get(IN_BILLING_CONTRACTNUMBER)
				);
				// ANK-4500-00 MOD END
				
				// 業務パラメータ管理一覧照会明細
				// サービスIF実行
				CAANMsg[] ezm0321b010MsgList = null;
				ezm0321b010MsgList = callEZM0321B010_FUNC1(handle, param, fixedText, CONST_CH_OTK_TG_CKNWR_);
				
				// 後続で使用するため業務パラメータ管理一覧照会明細で取得した一覧を退避
				workMap.put(TTEMPLATE_ID_EZM0321B010, ezm0321b010MsgList);
				
				// レスポンスの作成
				// ANK-4500-00 MOD START
//				responseMap = getResponseMap(handle, param, fixedText, ech0961b010MsgList, getEch0891_SeikyYmList);
				responseMap = getResponseMap(handle, param, fixedText, ech0961b010MsgList);
				// ANK-4500-00 MOD END
			}
			
			// ボディ情報にレスポンス内容を設定する
			ccMsg.put(BODY_INFO, responseMap);
			
			// 正常終了
			param.setControlMapData(SCControlMapKeys.RETURN_CODE, JKKStrConst.RETURN_CD_0000);
			param.setControlMapData(SCControlMapKeys.RETURN_MESSAGE, null);
		}
		catch (Throwable throwable)
		{
			// 出力用設定値:エラーリスト
			ArrayList<HashMap<String, String>> errList = new ArrayList<HashMap<String, String>>();
			// エラー情報を格納する
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_9000, JACStrConst.KARA_MOJI));
			ccMsg.put(ERROR_INFO, errList);
			throw throwable;
		}
		
		return param;
	}

	/**
	 * 請求情報を返却するかどうか判定します。
	 * 
	 * @return true:データを取得して返却する false:年月のみ返却する
	 */
	private boolean judgeSeikyInfoReturn() {
		
		
		// お客様一意照会明細
		CAANMsg[] eck0011a010MsgList = (CAANMsg[]) workMap.get(TEMPLATE_ID_ECK0011A010);
		
		// お客様入退会コード
		String custNTaikai = eck0011a010MsgList[0].getString(ECK0011A010CBSMsg1List.CUST_NTAIKAI_CD);
		// 解約後請求書参照可否
		String dslAfSkssnsKh = eck0011a010MsgList[0].getString(ECK0011A010CBSMsg1List.DSL_AF_SKSSNS_KH);
		
		// ======================
		// 請求書参照可否チェック
		// ======================
		// 退会済であれば解約後請求書参照可否から取得可能か判定する
		// お客様入退会コードが「退会済」の場合
		if (!JCHStringUtil.isNullBlank(custNTaikai) && JCKStrConst.CD00260_TAIKAI.equals(custNTaikai))
		{
			// 解約後請求書参照可否が「否」の場合
			if (JCHStringUtil.isNullBlank(dslAfSkssnsKh) || JCKStrConst.CD00003_FAIL.equals(dslAfSkssnsKh))
			{
				// お得額情報を取得しない
				return false;
			}
		}
		
		ArrayList<String> getEch0891_SeikyYmList = new ArrayList<String>();
		// 退避させていた月別請求契約_お客様で取得した請求年月を取得
		getEch0891_SeikyYmList = (ArrayList<String>)workMap.get(TEMPLATE_ID_ECH0891B010);
		
		// 月別請求契約_お客様で取得した請求年月が0件の場合
		if(getEch0891_SeikyYmList.size() == 0)
		{
			// お得額情報を取得しない
			return false;
		}
		
		return true;
	}

	/**
	 * レスポンス情報を設定します。
	 * 
	 * @param handle
	 * @param param
	 * @param fixedText
	 * @param ech0961b010MsgList
	 * @param getEch0891_SeikyYmList
	 * @return
	 */
	@SuppressWarnings("unchecked")
	// ANK-4500-00 MOD START
//	private HashMap<String, Object> getResponseMap(SessionHandle handle,
//			IRequestParameterReadWrite param, String fixedText,
//			CAANMsg[] ech0961b010MsgList,
//			ArrayList<String> getEch0891_SeikyYmLis)
//			throws Throwable
		private HashMap<String, Object> getResponseMap(SessionHandle handle,
			IRequestParameterReadWrite param, String fixedText,
			CAANMsg[] ech0961b010MsgList)
			throws Throwable
	// ANK-4500-00 MOD END
	{
		// CCパラメータ
		HashMap<String, Object> ccMsg = (HashMap<String, Object>)param.getData(fixedText);
		
		// レスポンス格納マップ
		HashMap<String, Object> responseMap = new HashMap<String, Object>();
		
		// 退避させていた過去24ヶ月分の年月を取得する。
		ArrayList<String> yearMonthList = (ArrayList<String>)workMap.get(WORK_YEAR_MONTH_LIST);
		
		// ANK-4500-00 ADD START
		// 退避させていた月別請求契約_お客様一覧照会明細を取得
		ArrayList<String> getEch0891_SeikyYmList = (ArrayList<String>) workMap.get(TEMPLATE_ID_ECH0891B010);
		// ANK-4500-00 ADD END
		
		// 退避用請求年月
		String tmpSeikyYm = "";
		// 退避用整理番号
		String tmpSeiriNo = "";
		// 退避用サービス種別
		String tmpOtokgkSvcSbt = "";
		
		// 返却用月別お得額リスト
		ArrayList<HashMap<String, Object>> billingList = new ArrayList<HashMap<String, Object>>();

		// 一時月別お得額リスト
		ArrayList<HashMap<String, Object>> tmpBillingList = new ArrayList<HashMap<String, Object>>();
		
		// お得額累計値の初期化
		int totalProfitAmntCul = 0;
		
		// お得額表示管理で取得した情報のマッピングを行う
		for(CAANMsg ech0961b010MsgMap : ech0961b010MsgList)
		{
			// ANK-4500-00 ADD START
			// 年月
			String seikyYm = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.SEIKY_YM);
			
			// 月別請求契約_お客様.請求年月とお得額表示管理.請求年月が一致する場合、お得額情報をレスポンスとして設定する
			if(getEch0891_SeikyYmList.contains(seikyYm)){
			// ANK-4500-00 ADD END
				
				// 月別お得額マップ
				HashMap<String, Object> billingMap = new HashMap<String, Object>();
				
				// ANK-4500-00 DEL START
//				// 年月
//				String seikyYm = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.SEIKY_YM);
				// ANK-4500-00 DEL END
				
				// 取得した年月と退避用請求年月と同じ場合、月別お得額リストを取得する
				if(seikyYm.equals(tmpSeikyYm))
				{
					billingMap = tmpBillingList.get(tmpBillingList.size()-1);
				}
				// 取得した年月が退避用請求年月と異なる場合、月別お得額リストを取得する
				else{
					tmpBillingList.add(new HashMap<String, Object>());
					billingMap = tmpBillingList.get(tmpBillingList.size()-1);
					// 請求年月の設定
					billingMap.put(OUT_YEAR_MONTH, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.SEIKY_YM));
					// お得月額料金に"0"を設定する
					billingMap.put(OUT_PROFIT_MONTHLY_AMOUNT, "0");
					// サービスリストの設定
					billingMap.put(OUT_SERVICE_LIST, new ArrayList<HashMap<String, Object>>());
					
					// 退避用請求年月を更新
					tmpSeikyYm = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.SEIKY_YM);
					
					// 退避用整理番号、サービス種別を空に更新する
					tmpSeiriNo = "";
					tmpOtokgkSvcSbt = "";
				}
				
				// お得額データ種別
				String otokgkDataSbt = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_DATA_SBT);
				
				// お得額データ種別が"1":月額料金の場合
				if (CONST_OTOKGK_DATA_SBT1.equals(otokgkDataSbt)){
					// 月額料金情報の設定
					billingMap.put(OUT_MONTHLY_AMOUNT, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.AMNT));
				}
				// お得額データ種別が"2":割引前月額料金の場合
				else if (CONST_OTOKGK_DATA_SBT2.equals(otokgkDataSbt)){
					// 割引前月額料金情報の設定
					billingMap.put(OUT_UNDISCOUNTED_MONTHLY_AMOUNT, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.AMNT));
				}
				
				// お得額データ種別が"3":お得月額料金の場合
				else if (CONST_OTOKGK_DATA_SBT3.equals(otokgkDataSbt)){
					// お得月額料金情報の設定
					billingMap.put(OUT_PROFIT_MONTHLY_AMOUNT, Integer.toString(Math.abs(Integer.valueOf(ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.AMNT)))));
					
					// お得額累計の算出
					totalProfitAmntCul += Math.abs(Integer.parseInt(ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.AMNT))); 
				}
				
				// ANK-4500-00-00 ADD START
				// お得額データ種別が"1","2"が0の場合
				if ("0".equals(billingMap.get(OUT_MONTHLY_AMOUNT)) && "0".equals(billingMap.get(OUT_UNDISCOUNTED_MONTHLY_AMOUNT))){
					// サービスリストを設定しない
					billingMap.remove(OUT_SERVICE_LIST);
				}
				// ANK-4500-00-00 ADD END
				
				// お得額データ種別が"4":お得額明細の場合
				else if (CONST_OTOKGK_DATA_SBT4.equals(otokgkDataSbt)){
					
					// サービスリスト
					ArrayList<HashMap<String, Object>> serviceList = (ArrayList<HashMap<String, Object>>)billingMap.get(OUT_SERVICE_LIST);
					// サービスマップ
					HashMap<String, Object> serviceMap = new HashMap<String, Object>();
					
					// 整理番号
					String seiriNo = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.SEIRI_NO);
					// サービス種別
					String otokgkSvcSbt = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_SVC_SBT);
					
					// 取得した整理番号/サービス種別が退避用整理番号/サービス種別と同じ場合、サービスリストを取得する
					if(seiriNo.equals(tmpSeiriNo) && otokgkSvcSbt.equals(tmpOtokgkSvcSbt))
					{
						serviceMap = serviceList.get(serviceList.size()-1);
					}
					// 取得した整理番号/サービス種別が退避用整理番号/サービス種別が異なる場合、サービスリストを作成する
					else{
						serviceList.add(new HashMap<String, Object>());
						serviceMap = serviceList.get(serviceList.size()-1);
						// 整理番号の設定
						serviceMap.put(OUT_ORGANIZE_NUMBER, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.SEIRI_NO));
						// サービス種別の設定
						serviceMap.put(OUT_SERVICE_CATEGORY, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_SVC_SBT));
						// お得額明細リスト
						serviceMap.put(OUT_PROFIT_DETAIL_LIST, new ArrayList<HashMap<String, Object>>());
						
						// 整理番号/サービス種別の一時変数を更新する
						tmpSeiriNo = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.SEIRI_NO);
						tmpOtokgkSvcSbt = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_SVC_SBT);
					}
					// お得額明細リスト
					ArrayList<HashMap<String, Object>>  profitDetailList = (ArrayList<HashMap<String, Object>>)serviceMap.get(OUT_PROFIT_DETAIL_LIST);
					
					// お得額明細マップ
					HashMap<String, Object> tmpBeanMap = new HashMap<String, Object>();
					
					// 料金グループコードの設定 
					tmpBeanMap.put(OUT_FEE_GROUP_CODE, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.PRC_GRP_CD));
					// 料金コースコードの設定
					tmpBeanMap.put(OUT_FEE_COURSE_CODE, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.PCRS_CD));
					// 料金サービスコードの設定
					tmpBeanMap.put(OUT_FEE_SERVICE_CODE, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.PRC_SVC_CD));
					// 料金項目コードの設定
					tmpBeanMap.put(OUT_FEE_ITEM_CODE, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.PRC_KMK_CD));
					// お得額の設定
					tmpBeanMap.put(OUT_PROFIT_AMOUNT, Integer.toString(Math.abs(Integer.valueOf(ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.AMNT)))));
					// お得額名称の設定
					tmpBeanMap.put(OUT_PROFIT_NAME, otkgkNameCkan(handle, param, fixedText, ech0961b010MsgMap));
					// お得額説明の設定
					tmpBeanMap.put(OUT_PROFIT_EXPLANATION, ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_SETMEI));
					
					// お得額明細リストに追加する
					profitDetailList.add(tmpBeanMap);
				}
			// ANK-4500-00 ADD START
			}
			// ANK-4500-00 ADD END
		}
		
		//======================================================================================
		
		// 請求のない年月について、月別お得額リストに年月を追加する
		// 月別お得額リスト表示順カウント用	
		int i = 0;
		
		// 請求年月（24ヶ月分）リストを分解
		for(String yearMonth : yearMonthList){
			
			if(i < tmpBillingList.size()){
				// 月別お得額リストに格納されている年月を取得
				HashMap<String, Object> tmpBillingMap = tmpBillingList.get(i);
				String resYearMonth = (String) tmpBillingMap.get(OUT_YEAR_MONTH);
				
				// 年月が同じ場合、月別お得額リストに請求年月リストに格納されている年月を追加
				if(yearMonth.equals(resYearMonth)){
					billingList.add(tmpBillingMap);
					i++;
				}
				// 年月が異なる場合、月別お得額リストに一時月別お得額リストに格納されている年月を追加
				else{
					// 月別お得額リストに追加するために一時マップを作成
					HashMap<String, Object> tempMap =  new HashMap<String, Object>();
					// 請求年月リストから年月を取得する
					tempMap.put(OUT_YEAR_MONTH, yearMonth);
					billingList.add(tempMap);
				}
			}
			else{
				// 月別お得額リストに追加するために一時マップを作成
				HashMap<String, Object> tempMap =  new HashMap<String, Object>();
				// 請求年月リストから年月を取得する
				tempMap.put(OUT_YEAR_MONTH, yearMonth);
				billingList.add(tempMap);
			}
		}
		
		// レスポンスの設定
		// 請求契約番号
		responseMap.put(OUT_BILLING_CONTRACT_NUMBER, (String)ccMsg.get(IN_BILLING_CONTRACTNUMBER));
		// お得額累計
		responseMap.put(OUT_TOTAL_PROFIT_AMOUNT, Integer.toString(totalProfitAmntCul));
		// 月別お得額リスト
		responseMap.put(OUT_BILLING_BILLING_LIST, billingList);
		
		return responseMap;
	}
	
	/**
	 * API参照可否チェックを行います。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return true:異常なし false:異常あり
	 * @throws Exception 例外が発生した場合
	 */
	private boolean checkApiSnshKh(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, CAANMsg[] ezm0311b010MsgList)
	throws Throwable
	{
		// CCパラメータ
		HashMap<String, Object> ccMsg = (HashMap<String, Object>)param.getData(fixedText);
		
		// 出力用設定値:エラーリスト
		ArrayList<HashMap<String, String>> errList = new ArrayList<HashMap<String, String>>();

		// お得額参照可否フラグ
		String otkDspknr_Snsho_Kh_Flg = null;
		
		// システムパラメータ管理一覧照会で取得した分レコードを取り出す
		for (int i = 0; i < ezm0311b010MsgList.length; i++)
		{
			otkDspknr_Snsho_Kh_Flg = ezm0311b010MsgList[i].getString(EZM0311B010CBSMsg1List.SYS_PARAM_SETTE_VALUE_1);
			
			if(CONST_OTKGK_DSPKNR_SNSHO_KH.equals(otkDspknr_Snsho_Kh_Flg)){
					param.setControlMapData(CONST_OTKGK_DSPKNR_SNSHO_KH, otkDspknr_Snsho_Kh_Flg); 
					// API参照可否チェックエラー
					errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_3001, CONST_ERROR_MSG_API_SNSHFAIL));
					
				// エラーが存在する場合
				if (errList.size() > 0)
				{
					ccMsg.put(ERROR_INFO, errList);
					return false;
				}
			}
		}
			return true;
	}
	
	/**
	 * 単項目チェックを行います。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return true:異常なし false:異常あり
	 * @throws Exception 例外が発生した場合
	 */
	private boolean checkUnitParam(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		
		// CCパラメータ
		HashMap<String, Object> ccMsg = (HashMap<String, Object>)param.getData(fixedText);
		// 出力用設定値:エラーリスト
		ArrayList<HashMap<String, String>> errList = new ArrayList<HashMap<String, String>>();
		
		String itemValue = null;
		String errorMessage = null;
		
		// SYSID
		itemValue = (String)ccMsg.get(IN_SYSID);
		errorMessage = IN_SYSID + JACStrConst.COLON + itemValue;
		// 必須チェック
		if (JCHStringUtil.isNullBlank(itemValue))
		{
			// 必須チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_1001, errorMessage));
		}
		else if (!HalfCharCheck.isEnNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_1002, errorMessage));
		}
		else if (!LengthCheck.isLength1Check(itemValue, 10))
		{
			// 桁数チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_1003, errorMessage));
		}
		
		// 請求契約番号
		itemValue = (String)ccMsg.get(IN_BILLING_CONTRACTNUMBER);
		errorMessage = IN_BILLING_CONTRACTNUMBER + JACStrConst.COLON + itemValue;
		// 必須チェック
		if (JCHStringUtil.isNullBlank(itemValue))
		{
			// 必須チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_1001, errorMessage));
		}
		else if (!HalfCharCheck.isEnNumber1Check(itemValue))
		{
			// 属性チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_1002, errorMessage));
		}
		else if (!LengthCheck.isLength1Check(itemValue, 10))
		{
			// 桁数チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_1003, errorMessage));
		}
		
		// エラーが存在する場合
		if (errList.size() > 0)
		{
			ccMsg.put(ERROR_INFO, errList);
			return false;
		}
		
		return true;
	}

	/**
	 * 関連チェックを行います。<br>
	 * ※後続処理に必要な情報の取得も行う。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return true:異常なし false:異常あり
	 * @throws Throwable 例外が発生した場合
	 */
	private boolean checkParameter(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		
		// CCパラメータ
		HashMap<String, Object> ccMsg = (HashMap<String, Object>)param.getData(fixedText);
		// 返却用設定値:エラーリスト
		ArrayList<HashMap<String, String>> errList = new ArrayList<HashMap<String, String>>();
		
		// お客様一意照会明細
		CAANMsg[] eck0011a010MsgList = null;
		// 請求契約一意照会明細
		CAANMsg[] ekk0491a010MsgList = null;
		
		// お客様一意照会(機能コード2)
		eck0011a010MsgList = callECK0011A010_FUNC2(handle, param, fixedText
				, (String)ccMsg.get(IN_SYSID)
				, JPCBPCommon.getOpeDate(null)
		);
		
		/*
		 *  ＝＝＝SYSID存在チェック＝＝＝
		 */
		// 照会結果が0件の場合エラー
		if (eck0011a010MsgList == null || eck0011a010MsgList.length == 0)
		{
			// SYSID存在チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_2001, CONST_ERROR_MSG_NOTFOUND_CUST));
			ccMsg.put(ERROR_INFO, errList);
			return false;
		}
		
		/*
		 *  ＝＝＝会員種別チェック＝＝＝
		 */
		
		// 卸事業者コード取得
		String orsjgsCd = eck0011a010MsgList[0].getString(ECK0011A010CBSMsg1List.ORSJGS_CD);
		
		// 卸事業者コードが設定されてる（パートナー）の場合エラー
		if (!JCHStringUtil.isNullBlank(orsjgsCd))
		{
			// 会員種別チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_2001, CONST_ERROR_MSG_NOTFOUND_CUST));
			ccMsg.put(ERROR_INFO, errList);
			return false;
		}
		
		// 請求契約一意照会(機能コード2)
		ekk0491a010MsgList = callEKK0491A010_FUNC2(handle, param, fixedText
				, (String)ccMsg.get(IN_BILLING_CONTRACTNUMBER)
				, JPCBPCommon.getOpeDate(null)
		);
		
		/*
		 *  ＝＝＝請求契約番号存在チェック＝＝＝
		 */
		// 照会結果が0件の場合エラー
		if (ekk0491a010MsgList == null || ekk0491a010MsgList.length == 0)
		{
			// 請求契約番号存在チェックエラー
			errList.add(getErrorInfoMap(JKKStrConst.RETURN_CD_2002, CONST_ERROR_MSG_NOTFOUND_SEIKYKEI));
			ccMsg.put(ERROR_INFO, errList);
			return false;
		}
		
		// 後続で使用するためお客様一意照会明細を退避
		workMap.put(TEMPLATE_ID_ECK0011A010, eck0011a010MsgList);
		
		return true;
	}
	
	/**
	 * 請求情報照会処理に使用する情報を取得します。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return 
	 * @throws Throwable 例外が発生した場合
	 */
	private void getSeikyInfoBf(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String seikyYm_from, String seikyYm_to)
	throws Throwable
	{
		
		// CCパラメータ
		HashMap<String, Object> ccMsg = (HashMap<String, Object>)param.getData(fixedText);
		
		// 月別請求契約_お客様一意照会
		CAANMsg[] ech0891b010MsgList = null;
		// 過去24ヶ月分年月リスト
		ArrayList<String> getYmList = new ArrayList<String>();
		// 月別請求契約_お客様で取得した請求年月
		ArrayList<String> getEch0891_SeikyYmList = new ArrayList<String>();
		
		// 過去24ヶ月分の年月を取得する
		getYmList = getSeikyYm(seikyYm_to);
		// 取得した過去24ヶ月分の年月を退避させる
		workMap.put(WORK_YEAR_MONTH_LIST, getYmList);
		
		// 月別請求契約_お客様基準でデータが存在するかチェックする。
		// 月別請求契約_お客様一覧照会
		// サービスIF実行
		ech0891b010MsgList = callECH0891B010_FUNC3(handle, param, fixedText
				, (String)ccMsg.get(IN_SYSID)
				, seikyYm_from
				, seikyYm_to
				, (String)ccMsg.get(IN_BILLING_CONTRACTNUMBER)
		);
		
		// 照会結果が1件以上存在する場合
		if (ech0891b010MsgList != null && ech0891b010MsgList.length > 0)
		{
			// 請求年月を取得する
			for(int j = 0; j < ech0891b010MsgList.length; j++)
			{
				String getSeikyYm= ech0891b010MsgList[j].getString(ECH0891B010CBSMsg1List.SEIKY_YM);
				getEch0891_SeikyYmList.add(getSeikyYm);
			}
		}
		
		// 後続で使用するため月別請求契約_お客様で取得した請求年月を退避
		workMap.put(TEMPLATE_ID_ECH0891B010, getEch0891_SeikyYmList);
	}

	/**
	 * 出力：エラーコードとエラーメッセージをセットした業務エラーマップを返却する。<br>
	 * <br>
	 * @return returnMap
	 */
	public static HashMap<String, String> getErrorInfoMap(String errorCode, String errorMessage)
	{
		HashMap<String, String> returnMap = new HashMap<String, String>();
		
		returnMap.put(ERROR_CODE, errorCode);
		returnMap.put(ERROR_MESSAGE, errorMessage);
		
		return returnMap;
	}

	/**
	 * 出力：月別お得額リストマップを設定します。<br>
	 * 設定値がnull又は空の場合は、パラメータ自体設定しません。<br>
	 * <br>
	 * @param fixedText 
	 * @param param 
	 * @param handle 
	 * @param yearMonth 年月
	 * @param monthlyAmount 月額料金
	 * @param undiscountedMonthlyAmount 割引前月額料金
	 * @param profitMonthlyAmount お得月額料金
	 * @return 出力用月別お得額マップ
	 */
	
	@SuppressWarnings("unchecked")
	private HashMap<String, Object> getResponseMapEmpty(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		// CCパラメータ
		HashMap<String, Object> ccMsg = (HashMap<String, Object>)param.getData(fixedText);
		
		// レスポンス
		HashMap<String, Object> responseMap = new HashMap<String, Object>();
		
		// 退避させていた過去24ヶ月分の年月を取得する。
		ArrayList<String> yearMonthList = (ArrayList<String>)workMap.get(WORK_YEAR_MONTH_LIST);
		
		// 月別お得額リストの作成
		ArrayList<HashMap<String, Object>> billingList = new ArrayList<HashMap<String, Object>>();
		
		// 過去24ヶ月の年月を1ヶ月ずつに分解
		for(String yearMonth : yearMonthList)
		{
			// 月別お得額リストに年月を追加する
			HashMap<String, Object> billingMap = new HashMap<String, Object>();
			billingMap.put(OUT_YEAR_MONTH, yearMonth);
			billingList.add(billingMap);
		}
		
		// レスポンスに請求契約番号を設定
		responseMap.put(OUT_BILLING_CONTRACT_NUMBER, (String)ccMsg.get(IN_BILLING_CONTRACTNUMBER));
		// レスポンスにお得額累計を設定
		responseMap.put(OUT_TOTAL_PROFIT_AMOUNT, 0);
		// レスポンスに月別お得額リストを設定
		responseMap.put(OUT_BILLING_BILLING_LIST, billingList);
		
		return responseMap;
	}

	/**
	 * サービスインターフェース：システムパラメータ一覧照会(機能コード１)を実行します。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param sys_param_bunrui_cd システムパラメータ分類コード
	 * @param operateDate オンライン運用日付
	 * @return 照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] callEZM0311B010_FUNC1(SessionHandle handle, IRequestParameterReadWrite param, String fixedText
				, String sys_param_bunrui_cd
				, Object operateDate
		)
		throws Throwable
		{
			// SC呼び出し部品のインスタンス生成
			ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
			
			Object[][] ezm0311b010In =
			{
				{EZM0311B010CBSMsg.TEMPLATEID, TEMPLATE_ID_EZM0311B010}
				// 機能コード
				, {EZM0311B010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1}
				// ＫＥＹ＿システムパラメータ分類コード
				, {EZM0311B010CBSMsg.KEY_SYS_PARAM_BUNRUI_CD, sys_param_bunrui_cd}
				// ＫＥＹ＿基準年月日
				, {EZM0311B010CBSMsg.KEY_STDARDYMD, operateDate}
			};
			// サービスIF実行
			return callSC(handle, scCall, param, fixedText, ezm0311b010In)
					.getCAANMsgList(EZM0311B010CBSMsg.EZM0311B010CBSMSG1LIST);
	}

	
	/**
	 * サービスインターフェース：お客様一意照会(機能コード２)を実行します。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param sysid SYSID
	 * @param rsvAplyYmd 予約適用年月日
	 * @return 照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] callECK0011A010_FUNC2(SessionHandle handle, IRequestParameterReadWrite param, String fixedText
			, String sysid
			, String rsvAplyYmd
	)
	throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		Object[][] eck0011a010In =
		{
			{ECK0011A010CBSMsg.TEMPLATEID, TEMPLATE_ID_ECK0011A010}
			// 機能コード
			, {ECK0011A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
			// ＫＥＹ＿ＳＹＳＩＤ
			, {ECK0011A010CBSMsg.KEY_SYSID, sysid}
			// ＫＥＹ＿予約適用年月日
			, {ECK0011A010CBSMsg.KEY_RSV_APLY_YMD, rsvAplyYmd}
		};
		// サービスIF実行
		return callSC(handle, scCall, param, fixedText, eck0011a010In)
				.getCAANMsgList(ECK0011A010CBSMsg.ECK0011A010CBSMSG1LIST);
	}
	/**
	 * サービスインターフェース：請求契約一意照会(機能コード２)を実行します。<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @param seikyKeiNo 請求契約番号
	 * @param rsvAplyYmd 予約適用年月日
	 * @return 照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] callEKK0491A010_FUNC2(SessionHandle handle, IRequestParameterReadWrite param, String fixedText
			, String seikyKeiNo
			, String rsvAplyYmd
	)
	throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		Object[][] EKK0490a010In =
		{
			{EKK0491A010CBSMsg.TEMPLATEID, TEMPLATE_ID_EKK0491A010}
			// 機能コード
			, {EKK0491A010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_2}
			// ＫＥＹ＿請求契約番号
			, {EKK0491A010CBSMsg.KEY_SEIKY_KEI_NO, seikyKeiNo}
			// ＫＥＹ＿予約適用年月日
			, {EKK0491A010CBSMsg.KEY_RSV_APLY_YMD, rsvAplyYmd}
		};
		// サービスIF実行
		return callSC(handle, scCall, param, fixedText, EKK0490a010In)
				.getCAANMsgList(EKK0491A010CBSMsg.EKK0491A010CBSMSG1LIST);
	}
	/**
	 * サービスインターフェースを実行します。<br>
	 * 月別請求契約_お客様一覧照会(機能コード3)<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return 照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] callECH0891B010_FUNC3(SessionHandle handle, IRequestParameterReadWrite param, String fixedText
			, String sysid
			, String seikyYm_from
			, String seikyYm_to
			, String seikyKeyNo
	)
	throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		// 月別請求契約_お客様一覧照会
		Object[][] ech0891b010In =
		{
			{ECH0891B010CBSMsg.TEMPLATEID,  TEMPLATE_ID_ECH0891B010}
			// 機能コード
			, {ECH0891B010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_3}
			// ＫＥＹ＿ＳＹＳＩＤ
			, {ECH0891B010CBSMsg.KEY_SYSID, sysid}
			// ＫＥＹ＿請求年月FROM
			, {ECH0891B010CBSMsg.KEY_SEIKYU_YM_FROM, seikyYm_from}
			// ＫＥＹ＿請求年月TO
			, {ECH0891B010CBSMsg.KEY_SEIKYU_YM_TO, seikyYm_to}
			// ＫＥＹ＿請求契約番号
			, {ECH0891B010CBSMsg.KEY_SEIKY_KEI_NO, seikyKeyNo}
		};
		// サービスIF実行
		return callSC(handle, scCall, param, fixedText, ech0891b010In)
				.getCAANMsgList(ECH0891B010CBSMsg.ECH0891B010CBSMSG1LIST);
	}

	/**
	 * サービスインターフェースを実行します。<br>
	 * お得額表示管理一覧照会(機能コード１)<br>
	 * <br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return 照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] callECH0961B010_FUNC1(SessionHandle handle, IRequestParameterReadWrite param, String fixedText
			, String seikyKeiNo
	)
	throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		// お得額表示管理一覧照会
		Object[][] ech0961b010In =
		{
			{ECH0961B010CBSMsg.TEMPLATEID,TEMPLATE_ID_ECH0961B010}
			// 機能コード
			, {ECH0961B010CBSMsg.FUNC_CODE,JPCModelConstant.FUNC_CD_1}
			// ＫＥＹ＿請求契約番号
			, {ECH0961B010CBSMsg.KEY_SEIKY_KEI_NO,seikyKeiNo}
		};
		// サービスIF実行
		return callSC(handle, scCall, param, fixedText, ech0961b010In)
				.getCAANMsgList(ECH0961B010CBSMsg.ECH0961B010CBSMSG1LIST);
	}

	/**
	 * サービスインターフェースを実行します。<br>
	 * 業務パラメータ一覧照会(機能コード１)<br>
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return 照会結果
	 * @throws Throwable 例外が発生した場合
	 */
	private CAANMsg[] callEZM0321B010_FUNC1(SessionHandle handle, IRequestParameterReadWrite param, String fixedText
			, String workParamId
	)
	throws Throwable
	{
		// SC呼び出し部品のインスタンス生成
		ServiceComponentRequestInvoker scCall = new ServiceComponentRequestInvoker();
		
		// 業務パラメータ一覧照会
		Object[][] ezm0321b010In =
		{
			{EZM0321B010CBSMsg.TEMPLATEID, TTEMPLATE_ID_EZM0321B010}
			// 機能コード
			, {EZM0321B010CBSMsg.FUNC_CODE, JPCModelConstant.FUNC_CD_1}
			// ＫＥＹ＿業務パラメータID
			, {EZM0321B010CBSMsg.KEY_WORK_PARAM_ID, workParamId}

		};
		
		return callSC(handle, scCall, param, fixedText, ezm0321b010In)
				.getCAANMsgList(EZM0321B010CBSMsg.EZM0321B010CBSMSG1LIST);
	}
	/**
	 * SC(サービスインターフェイス）を呼び出します。
	 * @param handle セッションハンドル
	 * @param scCall SC呼び出し部品
	 * @param param リクエストパラメータ
	 * @param dataMapKey パラメータキー
	 * @param mappingData マッピングデータ
	 * @return サービスインターフェイス実行結果
	 * @throws Throwable 例外が発生した場合
	 */
	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;
	}
	
	/**
	 * 請求年月計算
	 * 
	 * @param seikyYm_to 請求年月_to
	 * @return 24ヶ月分の請求年月
	 * @throws ParseException 
	 */
	private ArrayList<String> getSeikyYm(String seikyYm_to) throws ParseException
	{
		
		// 請求年月（24ヶ月分）リストを作成
		ArrayList<String> seikyYm24List = new ArrayList<String>();
		
		// 請求年月_至を請求年月（24ヶ月分）リストに格納
		seikyYm24List.add(seikyYm_to);
		
		// 請求年月に1日を付与
		String seikyYmAddDay = seikyYm_to.concat("01");

		for(int i = 1; i <= 23; i++)
		{
			// 請求年月_fromに-1する(降順で)
			String seikyYm = JPCUtilCommon.addMonth(seikyYmAddDay, -i);
			seikyYm24List.add(seikyYm.substring(0, 6));
		}
		
		return seikyYm24List;
	}
	
	/**
	 * お得額名称置換処理
	 * 
	 * @param otokgkShukDiv お得額集計区分
	 * @return monthlyAmount 絶対値に変換したお得額月額料金
	 */
	private String otkgkNameCkan(SessionHandle handle, IRequestParameterReadWrite param, String fixedText
			, CAANMsg ech0961b010MsgMap)
			throws Throwable
	{
		// 退避させていた業務パラメータ管理一覧照会明細を取得する
		CAANMsg[] getzm0321b010MsgList = (CAANMsg[]) workMap.get(TTEMPLATE_ID_EZM0321B010);

		// お得額名称
		String profitName = null;
		
		// お得額名称が置換割（即割、長割）の場合、業務パラメータ管理からお得額名称を取得する。
		if (CONST_OTOKGK_SHUK_DIV2.equals(ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_SHUK_DIV)) 
				||CONST_OTOKGK_SHUK_DIV3.equals(ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_SHUK_DIV)))
		{
			for(int i = 0; i < getzm0321b010MsgList.length; i++)
			{
				// 業務パラメータ設定値には「料金項目コード:即割/長割区分:お得額名称」（21001701601:1:即割, 21001801601:2:長割, ・・・）の形式で値が格納されている。
				String[] work_param_sett_ckanWari = getzm0321b010MsgList[i].getString(EZM0321A010CBSMsg1List.WORK_PARAM_SETTE_VALUE).split(JACStrConst.COLON);
				if (work_param_sett_ckanWari[0].equals(ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.PRC_KMK_CD))){
					// お得額名称を置換する。
					profitName = work_param_sett_ckanWari[2];
				}
			}
				
		}// お得額名称が置換割（キャンペーン）の場合、お得額表示管理からお得額名称を取得する。
		else if (CONST_OTOKGK_SHUK_DIV4.equals(ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.OTOKGK_SHUK_DIV)))
		{
			// お得額名称（キャンペーン）を取得する。
			profitName = ech0961b010MsgMap.getString(ECH0961B010CBSMsg1List.PRC_KMK_NM);
		}
		return profitName;
	}
}
