/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom  					 *
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatCHOrosiSyokeiReShukei
*	ソースファイル名	：JBSbatCHOrosiSyokeiReShukei.java
*	作成者				：富士通　
*	作成日				：2018年11月17日
*＜機能概要＞
*　卸先事業者向け小計行再集計処理です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*   v39.00.00	2018/11/17  FJ)星野		【ANK-3478-02-00】新規作成
*   v45.00.00	2019/07/29  FJ)中原		【ANK-3636-00-00】料金項目出力名称.表示順の桁数変更対応
*********************************************************************/
package eo.business.service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatCHIFM292;
import eo.business.util.table.JBSbatCH_M_PRC_KMK_OPUT_NM;
import eo.common.constant.JPCBatchMessageConstant;
import eo.framework.application.JBSbatBusinessError;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.util.JBSbatStringUtil;

/**
* 卸先事業者向け小計行再集計処理です。 <p>
*<BR>
* @author 富士通
*/
public class JBSbatCHOrosiSyokeiReShukei extends JBSbatBusinessService
{
	/** テーブル(料金項目出力名称)*/
	private static final String D_TBL_NAME_CH_M_PRC_KMK_OPUT_NM = "CH_M_PRC_KMK_OPUT_NM";

	/** SQL定義キー(CH_SELECT_007)*/
	private static final String CH_M_PRC_KMK_OPUT_NM_CH_SELECT_007 = "CH_SELECT_007";

	/** テーブルアクセスクラス(料金項目出力名称)*/
	private JBSbatSQLAccess db_CH_M_PRC_KMK_OPUT_NM = null;
	
	/** 料金項目コード 小計行 */
	private static final String PRC_KMK_CD_SYOKEI = "01900801601";
	
	/** 
	 * 料金項目出力名称キャッシュ
	 * キー：料金コースコード 値：料金項目出力名称マスタ
	 * */
	private Map<String, JBSbatCommonDBInterface> prcKmkOputNmCashMap = new HashMap<String, JBSbatCommonDBInterface>(); 

	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);

		// DBアクセスクラスを生成します
		db_CH_M_PRC_KMK_OPUT_NM = new JBSbatSQLAccess(commonItem, D_TBL_NAME_CH_M_PRC_KMK_OPUT_NM);
		
		//フリーパラメータ取得
		String[] freeItems = commonItem.getFreeItem().split(";");
		
		// 請求年月の利用終了日
		String seikyEndYmd = freeItems[0];
		
		// 料金項目出力名称マスタのキャッシュ
		cashCH_M_PRC_KMK_OPUT_NM(seikyEndYmd);

		
		
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/** 
	 * 料金項目出力名称マスタのキャッシュ 
	 * @param seikyEndYmd 請求年月の利用終了日
	 * */
	private void cashCH_M_PRC_KMK_OPUT_NM(String seikyEndYmd) throws Exception {
		// 小計行の料金項目出力名称を取得
		executeCH_M_PRC_KMK_OPUT_NM_CH_SELECT_007(new Object[]{seikyEndYmd, seikyEndYmd});
		
		JBSbatCommonDBInterface dbMap = db_CH_M_PRC_KMK_OPUT_NM.selectNext();
		while(dbMap != null){
			// 料金項目出力名称キャッシュに設定 SQLの抽出条件より、料金コースコード毎にユニークとなる想定
			this.prcKmkOputNmCashMap.put(dbMap.getString(JBSbatCH_M_PRC_KMK_OPUT_NM.PCRS_CD), dbMap);
			
			dbMap = db_CH_M_PRC_KMK_OPUT_NM.selectNext();
		}
	}
	
	/**
	 * 主処理
	 * @param inMap　入力電文
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap, JBSbatOutputItem outputInItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		
		// 入力なし（＝最終処理）の場合、集計結果を出力して処理を終了する。
		if (inMap == null) {
			// 退避リスト全件を出力
			outputAll(outputInItem);
			
			return outputInItem;
		}
		
		// 一応エラーチェック 項目数不正のレコードは読み飛ばす
		if(inMap.isInputErrorFlg()){
			// ワーニング出力
			String[] msgParam = new String[]{ "レコード項目数が不正です。" };
			super.logPrint.printBusinessErrorLog(JPCBatchMessageConstant.ECHB1500KW, msgParam);
			
			// 次のデータへスキップ（マイナーアラーム）。
			throw new JBSbatBusinessError();
		}
		
		// 入力の小計行は読み飛ばす
		if(PRC_KMK_CD_SYOKEI.equals(inMap.getString(JBSbatCHIFM292.PRC_KMK_CD))){
			return outputInItem;
		}
		
		// 1件目（退避リストが空のとき）
		if (!outputInItem.isOutMapList()) {
			
			// 新しい小計行を作成
			JBSbatServiceInterfaceMap syokeiMap = newSyokeiMap(inMap);
			
			// 出力電文に小計行を設定（出力フラグはfalse）
			outputInItem.addOutMapList(syokeiMap);
			// 出力電文に入力明細行を設定（出力フラグはfalse）
			outputInItem.addOutMapList(inMap);
			
			// 次のデータへ
			return outputInItem;
		}
		
		// 退避リストにある小計行（ここまでの集計結果）を取得
		JBSbatServiceInterfaceMap tmpSyokeiMap = (JBSbatServiceInterfaceMap)outputInItem.getOutMapList().get(0);

		// 集計キー（入力）
		String inKey = getKey(inMap);
		// 集計キー（退避）
		String tmpSyokeiKey = getKey(tmpSyokeiMap);
		
		// キーブレイク判定
		if (inKey.equals(tmpSyokeiKey)) {
			// キーが一致した場合、金額を集計
			BigDecimal tmpAmnt = tmpSyokeiMap.getBigDecimal(JBSbatCHIFM292.AMNT);
			BigDecimal inAmnt = inMap.getBigDecimal(JBSbatCHIFM292.AMNT);
			tmpSyokeiMap.setBigDecimal(JBSbatCHIFM292.AMNT, tmpAmnt.add(inAmnt) );
			
			// 出力電文に入力明細行を設定（出力フラグはfalse）
			outputInItem.addOutMapList(inMap);
		}else {
			// キーブレイクの場合、ここまでの退避リスト全件を出力
			outputAll(outputInItem);
			
			// 新しい小計行を作成
			JBSbatServiceInterfaceMap syokeiMap = newSyokeiMap(inMap);
			
			// 出力電文に小計行を設定（出力フラグはfalse）
			outputInItem.addOutMapList(syokeiMap);
			// 出力電文に入力明細行を設定（出力フラグはfalse）
			outputInItem.addOutMapList(inMap);
		}

	
		return outputInItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/** 現在退避リストにある全レコードを出力対象とする */
	private void outputAll(JBSbatOutputItem outputInItem) {
		// 退避リスト全件に対して、出力フラグtrueを設定
		for(Object o : outputInItem.getOutMapList()){
			((JBSbatServiceInterfaceMap)o).setOutFlg(true);
		}
	}
	
	/** 
	 * 新しい小計行の作成
	 * @param inMap 小計行の諸元となる明細行
	 * */
	private JBSbatServiceInterfaceMap newSyokeiMap(JBSbatServiceInterfaceMap inMap) throws Exception {
		
		// 明細行の料金プランコースコードを元に、料金コースコードを取得
		String inPplancrsCd = inMap.getString(JBSbatCHIFM292.PPlANCRS_CD);
		String pcrsCd = inPplancrsCd.length()>=3 ? inPplancrsCd.substring(0,3) : "   ";
		
		// 料金コースコードをキーとして、キャッシュから料金項目出力名称を取得
		JBSbatCommonDBInterface prcKmkOputNmMap = getPrcKmkOputNm(pcrsCd);
		
		// 新しい小計行の作成
		JBSbatServiceInterfaceMap syokeiMap = new JBSbatServiceInterfaceMap();
		
		// 卸先事業者コード
		syokeiMap.setString(JBSbatCHIFM292.ORSJGS_CD, inMap.getString(JBSbatCHIFM292.ORSJGS_CD));
		// 請求契約番号
		syokeiMap.setString(JBSbatCHIFM292.SEIKY_KEI_NO, inMap.getString(JBSbatCHIFM292.SEIKY_KEI_NO));
		// 請求年月
		syokeiMap.setString(JBSbatCHIFM292.SEIKY_YM, inMap.getString(JBSbatCHIFM292.SEIKY_YM));
		// サービス契約番号
		syokeiMap.setString(JBSbatCHIFM292.SVC_KEI_NO, inMap.getString(JBSbatCHIFM292.SVC_KEI_NO));
		// 料金項目コード "01900801601"（小計行） 固定
		syokeiMap.setString(JBSbatCHIFM292.PRC_KMK_CD, PRC_KMK_CD_SYOKEI);
		// 料金項目名称
		syokeiMap.setString(JBSbatCHIFM292.PRC_KMK_NM, prcKmkOputNmMap.getString(JBSbatCH_M_PRC_KMK_OPUT_NM.PRC_KMK_NM));
		// 利用開始年月日 未設定
		syokeiMap.setString(JBSbatCHIFM292.USE_STAYMD, "");
		// 利用終了年月日 未設定
		syokeiMap.setString(JBSbatCHIFM292.USE_ENDYMD, "");
		// 金額 明細行の金額を初期設定
		syokeiMap.setBigDecimal(JBSbatCHIFM292.AMNT, inMap.getBigDecimal(JBSbatCHIFM292.AMNT));
		// 表示順 あとでソートに使う項目なので、念のため0埋めしておく
		// ANK-3636-00-00 MOD START
		//syokeiMap.setString(JBSbatCHIFM292.DSP_JUN, JBSbatStringUtil.padNumFormString( prcKmkOputNmMap.getString(JBSbatCH_M_PRC_KMK_OPUT_NM.DSP_JUN), 9) );
		syokeiMap.setString(JBSbatCHIFM292.DSP_JUN, JBSbatStringUtil.padNumFormString( prcKmkOputNmMap.getString(JBSbatCH_M_PRC_KMK_OPUT_NM.DSP_JUN), 12) );
		// ANK-3636-00-00 MOD END
		// 卸料金分類コード
		syokeiMap.setString(JBSbatCHIFM292.OROSI_PRC_BRI_CD, prcKmkOputNmMap.getString(JBSbatCH_M_PRC_KMK_OPUT_NM.OROSI_PRC_BRI_CD));
		// サービス種別
		syokeiMap.setString(JBSbatCHIFM292.SVC_STB_CD, inMap.getString(JBSbatCHIFM292.SVC_STB_CD));
		// ネットサービス契約番号
		syokeiMap.setString(JBSbatCHIFM292.NET_SVC_KEI_NO, inMap.getString(JBSbatCHIFM292.NET_SVC_KEI_NO));
		// 料金プランコースコード 明細行.料金プランコースコードの頭3桁を設定。末尾は空白埋め
		syokeiMap.setString( JBSbatCHIFM292.PPlANCRS_CD, JBSbatStringUtil.fillHalfSpace( pcrsCd, 15, true) );

		return syokeiMap;
	}
	
	/** 
	 * キャッシュから料金項目出力名称のレコードを取得する
	 * @param pcrsCd 料金コースコード 
	 * @return 料金項目出力名称マップ。キャッシュにヒットしない場合は空マップを返却する。
	 * */
	private JBSbatCommonDBInterface getPrcKmkOputNm(String pcrsCd) {
		JBSbatCommonDBInterface prcKmkOputNmMap = this.prcKmkOputNmCashMap.get(pcrsCd);
		if(prcKmkOputNmMap==null){
			prcKmkOputNmMap = new JBSbatCommonDBInterface();
		}
		return prcKmkOputNmMap;
	}
	
	/** 集計キー生成 */
	private String getKey(JBSbatServiceInterfaceMap map) throws Exception {
		// サービス契約番号 + サービス種別コードを返却
		return map.getString(JBSbatCHIFM292.SVC_KEI_NO) + map.getString(JBSbatCHIFM292.SVC_STB_CD);
	}
	
	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		// DBアクセスクラスをクローズします
		db_CH_M_PRC_KMK_OPUT_NM.close();
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * SQLKEY(CH_SELECT_007)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 * 
	 * 3.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 *		 	システムコード
	 *		 	群月末日
	 *			
	 * </pre>
	 * <p>
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeCH_M_PRC_KMK_OPUT_NM_CH_SELECT_007(Object[] param) throws Exception
	{
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());

		// DBアクセスを実行します
		db_CH_M_PRC_KMK_OPUT_NM.selectBySqlDefine(paramList,CH_M_PRC_KMK_OPUT_NM_CH_SELECT_007);
	}
	
}
