/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom  					 *
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatACVbPrcFamilyPackGengaku
*	ソースファイル名	：JBSbatACVbPrcFamilyPackGengaku.java
*	作成者				：富士通　
*	作成日				：2011年08月01日
*＜機能概要＞
*　ＶＢ料金ファミリーパック減額部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/08/01   富士通		新規作成
*	v5.00.00	2013/02/04   浜口		ANK-1420-00-00：ウイルスバスターマルチデバイス版導入対応
*	v5.01.00	2013/07/09   FJ) 桑島	【TG1-2013-0000662】請求年月対応
*	v5.0２.00	2013/08/09   FJ) 狭間	【TG1-2013-0000976】性能改善の為、ファミリーパック契約サービス契約番号リストをアンロード化
*********************************************************************/
package eo.business.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JACbatParamUtil;
import eo.business.common.JACbatSchdlUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.common.JBSbatInterface;
import eo.business.util.file.JBSbatACIFM043;
import eo.business.util.file.JBSbatACIFM242;
import eo.business.util.table.JBSbatAC_M_TEGAK_PRC;
import eo.business.util.table.JBSbatCH_M_PRC_KMK_CS_CHGE;
import eo.common.constant.JACStrConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.common.util.JPCUtilCommon;
import eo.framework.application.JBSbatBusinessException;
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.file.JBSbatDefFileUtil;
import eo.framework.file.JBSbatInputFileUtil;
import eo.framework.util.JBSbatAplConst;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatACVbPrcFamilyPackGengaku extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/** テーブル(定額料金)*/
	private static final String D_TBL_NAME_AC_M_TEGAK_PRC = "AC_M_TEGAK_PRC";

	/** テーブル(一時金)*/
	private static final String D_TBL_NAME_AC_T_ICJKN = "AC_T_ICJKN";
	
	/** SQL定義キー(AC_SELECT_003)*/
	private static final String AC_M_TEGAK_PRC_AC_SELECT_003 = "AC_SELECT_003";

	/** テーブルアクセスクラス(定額料金)*/
	private JBSbatSQLAccess db_AC_M_TEGAK_PRC = null;

	/** テーブルアクセスクラス(一時金)*/
	private JBSbatSQLAccess db_AC_T_ICJKN = null;

	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/
	
	/** VB機能識別コード*/
	private String vbSkbtCd = null;
	
	/** VBM機能識別コード*/
	private String vbmSkbtCd = null;
	
	/** VB減額料金 */ 
	private BigDecimal vbGenPrc = BigDecimal.ZERO;
	
	/** VB減額料合算額 */ 
	private BigDecimal vbTotalGen = BigDecimal.ZERO;
	
	/** VB減額料合算額0フラグ */ 
	private boolean zeroFlg = false;
	
	/** ファミリーパック判定用料金コースコード */
	private String csChgeFp = null;
	
	/** 退避キー（請求先番号） */
	private String saveKey = null;
	
	/** 退避．VB料金項目情報格納マップ*/
	private HashMap<String, String> vbPrcKmkMap = null;
	
	/** 退避．消込前料金格納マップ*/
	private HashMap<String, BigDecimal> vbKskmMiPrcMap = null;
	
	/** 同一リスト */
	private ArrayList<JBSbatServiceInterfaceMap> equalList = null;
	
	/** FPリスト（ファミリーパック契約サービス契約番号リスト(全件)）全請求契約番号分 */
	private HashSet<String> fpListAll = null;
	
	/** FPリスト（ファミリーパック契約サービス契約件数リスト）全請求契約番号分 */
	private HashMap<String, Object> fpListCnt = null;
	
	/** 退避．請求年月 */
	private String tmpSeikyYm = null;
	
	/** 群締め日 */
	private String wk_GunEnd 	= null;
	
	/** フリー項目のファイル名 */
	private String[] freeFiles = null;
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		
		// DBアクセスクラスを生成します
		db_AC_M_TEGAK_PRC = new JBSbatSQLAccess(commonItem, D_TBL_NAME_AC_M_TEGAK_PRC);
		db_AC_T_ICJKN = new JBSbatSQLAccess(commonItem, D_TBL_NAME_AC_T_ICJKN);
		
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
		
		equalList = new ArrayList<JBSbatServiceInterfaceMap>();
		fpListAll = new HashSet<String>();
		vbKskmMiPrcMap = new HashMap<String, BigDecimal>();
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "バッチ運用日：" + super.opeDate);
		
		JACbatSchdlUtil schdlUtil = new JACbatSchdlUtil(commonItem);
		
		try
		{
			// 請求年月
			this.tmpSeikyYm 		= schdlUtil.getBillDate(super.opeDate, JACStrConst.EVENT_CD_PRC_CALC_DAY);
			
			// 群月初日、群締め日　←　JACbatSchdlUtil.getUseStrEnd(請求年月, イベントコード("01"（利用開始日））, イベントコード（"02"（利用終了日））)
			String[] rtn = schdlUtil.getUseStrEnd(this.tmpSeikyYm, JACStrConst.EVENT_CD_USE_STAYMD, JACStrConst.EVENT_CD_USE_ENDYMD);
			
			this.wk_GunEnd = rtn[1];
			
		}
		finally
		{
			// クローズ
			schdlUtil.close();
		}
			
		// パラメータ取得クラス生成
		JACbatParamUtil paramUtil = new JACbatParamUtil(commonItem);
		
		// 業務パラメータ情報を取得する
		// ファミリーパック判定用サービスコード取得用の料金コースコード取得
		csChgeFp = paramUtil.getGyoumuParameter(JACStrConst.WKPARA_AC_WKS_FP_PRC_CRS);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "業パラ（ファミリー）：" + csChgeFp);
		
		// ウイルスバスター利用額の業務機能識別コード取得
		vbSkbtCd = paramUtil.getGyoumuParameter(JACStrConst.WKPARA_AC_WKS_VB_USE_AMNT);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "業パラ（VB）：" + vbSkbtCd);
		
		// ウイルスバスターマルチデバイス版利用額の業務機能識別コード取得
		vbmSkbtCd = paramUtil.getGyoumuParameter(JACStrConst.WKPARA_AC_WKS_VBM_USE_AMNT);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "業パラ（VBM）：" + vbmSkbtCd);
		
		paramUtil.close();
		
		// VB減額料金・ウイルスバスター利用料金情報取得
		vbGenPrc = getTegakuPrc(vbSkbtCd, vbmSkbtCd);
		// VB減額料金がマイナス値の場合
		if (BigDecimal.ZERO.compareTo(vbGenPrc) > 0)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][initial]VB減額料金がマイナスの場合(" + vbGenPrc + ")、" +
					"VB減額料金の符号反転(" + vbGenPrc + ")→(" + vbGenPrc.negate() + ")");
			vbGenPrc = vbGenPrc.negate();		// VB減額料金の符号反転
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "VB減額料金（1件分）：" + vbGenPrc);
		
		// ファイル名を取得
		String freeItem = commonItem.getFreeItem();
		freeFiles = freeItem.split(JACStrConst.FREE_DIV);
				
		// ファミリーパック契約サービス契約番号リスト(全件)を取得
		getfpListAllFile(freeFiles[1], freeFiles[0]);
		
		/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * ファミリーパック契約サービス契約番号リスト(全件)を取得
	 * @param fileDef データファイル定義
	 * @param fileName データファイル名
	 * @throws Exception 
	 */
	private void getfpListAllFile(String fileDef, String fileName) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getfpListAllFile]");

		// データファイルオブジェクト
		JBSbatInputFileUtil inFileObj = null;

		// ファイルオープン
		inFileObj = new JBSbatInputFileUtil(fileName);
		
		// ファイル定義オブジェクト作成
		JBSbatDefFileUtil defFileUtl =
			new JBSbatDefFileUtil(JBSbatAplConst.getAplConstValue("IND") + fileDef, inFileObj);
		inFileObj.setEncode(JACStrConst.ENCODE_MS932);
		inFileObj.createReader();

		// リストを初期化
		this.fpListAll = new HashSet<String>();
		this.fpListCnt = new HashMap<String, Object>();

		int recCnt = 0;
		int recCntseikyKeiNo = 0;
		String seikyKeiNoMem = "";
		
		while(true)
		{
			// １行読み込み
			String lineDate = inFileObj.readLine();
			if(null == lineDate)
			{
				break;
			}
			recCnt++;
			
			// DEFファイルを使用し、入力データを分割
			JBSbatServiceInterfaceMap recMap = defFileUtl.lineToObject(lineDate, inFileObj, recCnt);

			// 請求契約番号を追加
			String seikyKeiNo = recMap.getString(JBSbatACIFM242.SEIKY_KEI_NO);

			// サービス契約番号を追加
			String svcKeiNo = recMap.getString(JBSbatACIFM242.SVC_KEI_NO);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getfpListAllFile]seikyKeiNo=" + seikyKeiNo);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getfpListAllFile]svcKeiNo=" + svcKeiNo);
			
			// 請求契約番号でキーブレイクをおこなう
			if(!seikyKeiNoMem.equals(seikyKeiNo))
			{
				
				// １レコード目以降
				if(recCnt > 1)
				{
					// ファミリーパック契約サービス契約件数リストを追加
					String seikyKeiNoBuf = seikyKeiNoMem.toString();
					int cntBuf = recCntseikyKeiNo;
					this.fpListCnt.put(seikyKeiNoBuf, cntBuf);
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getfpListAllFile]recCntseikyKeiNo=" + recCntseikyKeiNo);
					
					// 件数リスト用カウンタを初期化
					recCntseikyKeiNo = 0;
				}
				
				// キーブレイク用請求契約番号を退避
				seikyKeiNoMem = seikyKeiNo;
			}
			
			// 件数リスト用カウンタをアップ
			recCntseikyKeiNo ++;
			
			// ファミリーパック契約サービス契約番号リストを追加
			this.fpListAll.add(seikyKeiNoMem + svcKeiNo);
		}
		if(recCntseikyKeiNo > 0)
		{
			this.fpListCnt.put(seikyKeiNoMem, recCntseikyKeiNo);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getfpListAllFile]recCntseikyKeiNo=" + recCntseikyKeiNo);
			recCntseikyKeiNo = 0;
		}
		
		// ファイルクローズ
		inFileObj.close();
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getfpListAllFile]fpListCnt=" + fpListCnt.size());
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getfpListAllFile]");
	}

	/**
	 * 主処理
	 * @param inMap　入力電文
	 * @param outputInItem 入力情報
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap, JBSbatOutputItem outputInItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		
		// 入力がnull（ファイルを読み終わったとき）のとき、退避しているレコードをすべて出力する
		if(inMap == null)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力＝null");
			// 減額判定
			gengakuJudge(outputInItem);
			return outputInItem;
		}
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力：" + JPCUtilCommon.convMapToString(inMap.getMap()));
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "請求契約番号：" + inMap.getString(JBSbatACIFM043.SEIKY_KEI_NO));
		
		// キー作成
		String key = inMap.getString(JBSbatACIFM043.PRC_KMK_CD);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute] ウイルスバスター利用料金検索キー：" + key);
		
		// 入力がVBかVBMでない、もしくは、一時金料金＜０　の場合、出力
		if(!vbPrcKmkMap.containsKey(key)
				|| inMap.getBigDecimal(JBSbatACIFM043.ICJKN_PRC).compareTo(BigDecimal.ZERO) < 0)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力がVBでない、もしくは、一時金料金＜０　のため減額せずに出力");
			inMap.setOutFlg(true);
			outputInItem.addOutMapList(inMap);
		}
		// 入力がVBの場合
		else
		{
			// 入力キー取得
			String inKey = inMap.getString(JBSbatACIFM043.SEIKY_KEI_NO);
			
			// 退避キー＝null（1件目）　の場合
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "退避キー：" + saveKey);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力キー：" + inKey);
			if(saveKey == null)
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "退避キー＝null");
				// ダミーレコード作製
				outputInItem.addOutMapList(new JBSbatServiceInterfaceMap());
				
				// 入力レコードを同一リストに退避
				equalList.add(inMap);
				
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力を同一リストに退避");
				
				// キー作成
				// 一時金登録番号＋一時金更新枝番
				String pKKey = makeStr(inMap.getString(JBSbatACIFM043.ICJKN_ADD_SEQ),
						inMap.getString(JBSbatACIFM043.ICJKN_UPD_SEQ));
				//消しこみ前の金額を退避
				vbKskmMiPrcMap.put(pKKey, inMap.getBigDecimal(JBSbatACIFM043.ICJKN_PRC));
				
				saveKey = inKey;
			}
			// 退避キー≠入力キー　の場合
			else if(!saveKey.equals(inKey))
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "退避キー≠入力キー");
				// 減額判定
				gengakuJudge(outputInItem);
				
				// リスト初期化
				equalList = new ArrayList<JBSbatServiceInterfaceMap>();
				vbTotalGen = BigDecimal.ZERO;
				vbKskmMiPrcMap = new HashMap<String, BigDecimal>();
				
				saveKey = inKey;
				
				// 入力レコードを同一リストに退避
				equalList.add(inMap);
				
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力を同一リストに退避");
				
				// キー作成
				// 一時金登録番号＋一時金更新枝番
				String pKKey = makeStr(inMap.getString(JBSbatACIFM043.ICJKN_ADD_SEQ),
						inMap.getString(JBSbatACIFM043.ICJKN_UPD_SEQ));
				//消しこみ前の金額を退避
				vbKskmMiPrcMap.put(pKKey, inMap.getBigDecimal(JBSbatACIFM043.ICJKN_PRC));
				
			}
			// 上記以外（退避キー＝入力キー　の場合）
			else
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "退避キー＝入力キー");
				// 入力レコードを同一リストに退避
				equalList.add(inMap);
				
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力を同一リストに退避");
				
				// キー作成
				// 一時金登録番号＋一時金更新枝番
				String pKKey = makeStr(inMap.getString(JBSbatACIFM043.ICJKN_ADD_SEQ),
						inMap.getString(JBSbatACIFM043.ICJKN_UPD_SEQ));
				//消しこみ前の金額を退避
				vbKskmMiPrcMap.put(pKKey, inMap.getBigDecimal(JBSbatACIFM043.ICJKN_PRC));
				
			}
		}
		return outputInItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		// DBアクセスクラスをクローズします
		db_AC_M_TEGAK_PRC.close();
		db_AC_T_ICJKN.close();
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * 料金情報、定額料金データを取得します。
	 * @param wKinoSkbtVb  業務機能識別コード(VB)
	 * @param wKinoSkbtVbm 業務機能識別コード(VBM)
	 * @return BigDecimal  減額金額
	 * @throws Exception
	 */
	private BigDecimal getTegakuPrc(String wKinoSkbtVb, String wKinoSkbtVbm) throws Exception
	{
		// ＤＢアクセス用のパラメータ定義
		JBSbatCommonDBInterface dbList = new JBSbatCommonDBInterface();
		
		// 対象キーの設定
		dbList.setValue(super.systemCode); 					// システムコード
		dbList.setValue(wKinoSkbtVb); 						// 業務機能識別コード(VB)
		dbList.setValue(wKinoSkbtVbm); 						// 業務機能識別コード(VBM)
		dbList.setValue(JACStrConst.CHSHT_CHG_CD_CST); 		// 抽出変換コード（抽出のみ） 
		dbList.setValue(this.wk_GunEnd); 					// 群締め日
		dbList.setValue(super.systemCode); 					// システムコード
		dbList.setValue(this.wk_GunEnd); 					// 群締め日
		
		// 定額料金データ取得
		executeAC_M_TEGAK_PRC_AC_SELECT_003(dbList.getList().toArray());
		
		// 定額料金データ取得結果
		JBSbatCommonDBInterface csChgeMap = db_AC_M_TEGAK_PRC.selectNext();
		
		//減額金額を退避
		BigDecimal genPrc = csChgeMap.getBigDecimal(JBSbatAC_M_TEGAK_PRC.PRC);
		
		vbPrcKmkMap = new HashMap<String, String>();
		
		if(csChgeMap == null)
		{
			String[] msgParam = new String[]{JBSbatAC_M_TEGAK_PRC.TABLE_NAME, wKinoSkbtVb};
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EACB0260CH, msgParam);
		}
		//料金情報をMAPに保持
		while(csChgeMap != null)
		{
			// キー作成
			String key = csChgeMap.getString(JBSbatCH_M_PRC_KMK_CS_CHGE.PRC_KMK_CD);
			// 値作成
			String Value = csChgeMap.getString(JBSbatCH_M_PRC_KMK_CS_CHGE.WORK_KINO_SKBT_CD);
			
			// キー・取得した情報をマップに格納
			vbPrcKmkMap.put(key, Value);
			
			// 次レコード取得
			csChgeMap = db_AC_M_TEGAK_PRC.selectNext(); 
		}
		//減額金額を返却
		return genPrc;
	}
	
	/**
	 * 減額判定
	 * 
	 * @param outputInItem 出力電文
	 * @throws Exception
	 */
	private void gengakuJudge(JBSbatOutputItem outputInItem)throws Exception
	{
		// 同一リストをソート
		this.sortListMap();
		
		// 同一リストの件数取得
		int equalListSize = equalList.size();
		int listCount = 0;
		zeroFlg = false;
		
		String inSeiKeiNo = equalList.get(listCount).getString(JBSbatACIFM043.SEIKY_KEI_NO);

		// ファミリーパック契約サービス契約件数リストから請求契約番号単位のサービス契約件数を取得
		Object fpListCntValue = fpListCnt.get(inSeiKeiNo);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "サービス契約件数＝" + fpListCntValue);
		if(fpListCntValue == null)
		{
			fpListCntValue = "0";
		}
		int svcKeiCnt = Integer.valueOf(fpListCntValue.toString());
		
		// サービス契約件数が0の場合
		if(svcKeiCnt == 0)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "FPリスト(全件)＝空のため全件出力");
			listCount = 0;
			// 同一リストの件数分繰り返す
			while(listCount != equalListSize)
			{
				// 出力
				JBSbatServiceInterfaceMap inRec = equalList.get(listCount);
				inRec.setOutFlg(true);
				outputInItem.addOutMapList(inRec);
				
				listCount += 1;
			}
			return;
		}

		// 減額料合算額
		vbTotalGen = vbGenPrc.multiply(new BigDecimal(svcKeiCnt));
		
		//// ファミリーパック契約あり かつ ウイルスバスター契約の場合
		listCount = 0;
		// 減額料合算額が0円になるまで、もしくは同一リストの件数分繰り返す
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, 
		"減額料合算額≦０になるまで、ファミリーパック契約あり かつ VB契約のレコードの減額処理を行う");
		while(listCount != equalListSize && !zeroFlg)
		{
			JBSbatServiceInterfaceMap inRec = equalList.get(listCount);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, listCount + 1 + "件目");
			// キー作成
			String key = inRec.getString(JBSbatACIFM043.PRC_KMK_CD);
			// 業務機能識別コードを取得
			String wkKinoSkbtCd = vbPrcKmkMap.get(key);

			// ファミリーパックに契約している かつ VB契約の場合
			if(fpListAll.contains(inSeiKeiNo + inRec.getString(JBSbatACIFM043.SVC_KEI_NO)) && vbSkbtCd.equals(wkKinoSkbtCd))
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．サービス契約番号："
						+ inRec.getString(JBSbatACIFM043.SVC_KEI_NO));
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "ファミリーパック契約あり かつVB契約");

				// 減額計算
				inRec = gengakuCalc(inRec);
			}
			listCount += 1;
		}
		//// ファミリーパック契約あり かつ ウイルスバスターマルチデバイス契約の場合
		listCount = 0;
		// 減額料合算額が0円になるまで、もしくは同一リストの件数分繰り返す
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, 
		"減額料合算額≦０になるまで、ファミリーパック契約あり かつ VBM契約のレコードの減額処理を行う");
		while(listCount != equalListSize && !zeroFlg)
		{
			JBSbatServiceInterfaceMap inRec = equalList.get(listCount);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, listCount + 1 + "件目");
			// キー作成
			String key = inRec.getString(JBSbatACIFM043.PRC_KMK_CD);
			// 業務機能識別コードを取得
			String wkKinoSkbtCd = vbPrcKmkMap.get(key);

			// ファミリーパックに契約している かつ VBM契約の場合
			if(fpListAll.contains(inSeiKeiNo + inRec.getString(JBSbatACIFM043.SVC_KEI_NO)) && vbmSkbtCd.equals(wkKinoSkbtCd))
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．サービス契約番号："
						+ inRec.getString(JBSbatACIFM043.SVC_KEI_NO));
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "ファミリーパック契約あり かつVBM契約");

				// 減額計算
				inRec = gengakuCalc(inRec);
			}
			listCount += 1;
		}
		
		//// ファミリーパック契約なし かつ ウイルスバスター契約の場合
		listCount = 0;
		// 減額料合算額が0円になるまで、もしくは同一リストの件数分繰り返す
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, 
		"減額料合算額≦０になるまで、ファミリーパック契約なし かつ VB契約のレコードの減額処理を行う");
		while(listCount != equalListSize && !zeroFlg)
		{
			JBSbatServiceInterfaceMap inRec = equalList.get(listCount);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, listCount + 1 + "件目");
			// キー作成
			String key = inRec.getString(JBSbatACIFM043.PRC_KMK_CD);
			// 業務機能識別コードを取得
			String wkKinoSkbtCd = vbPrcKmkMap.get(key);
			
			// ファミリーパックに契約していない  かつ VB契約の場合
			if(!fpListAll.contains(inSeiKeiNo + inRec.getString(JBSbatACIFM043.SVC_KEI_NO)) && vbSkbtCd.equals(wkKinoSkbtCd))
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．サービス契約番号："
						+ inRec.getString(JBSbatACIFM043.SVC_KEI_NO));
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "ファミリーパック契約なし かつVB契約");

				// 減額計算
				inRec = gengakuCalc(inRec);
			}
			listCount += 1;
		}

		//// ファミリーパック契約なし かつ ウイルスバスターマルチデバイス契約の場合
		listCount = 0;
		// 減額料合算額が0円になるまで、もしくは同一リストの件数分繰り返す
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, 
		"減額料合算額≦０になるまで、ファミリーパック契約なし かつ VBM契約のレコードの減額処理を行う");
		while(listCount != equalListSize && !zeroFlg)
		{
			JBSbatServiceInterfaceMap inRec = equalList.get(listCount);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, listCount + 1 + "件目");
			// キー作成
			String key = inRec.getString(JBSbatACIFM043.PRC_KMK_CD);
			// 業務機能識別コードを取得
			String wkKinoSkbtCd = vbPrcKmkMap.get(key);
			
			// ファミリーパックに契約していない  かつ VBM契約の場合
			if(!fpListAll.contains(inSeiKeiNo + inRec.getString(JBSbatACIFM043.SVC_KEI_NO)) && vbmSkbtCd.equals(wkKinoSkbtCd))
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．サービス契約番号："
						+ inRec.getString(JBSbatACIFM043.SVC_KEI_NO));
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "ファミリーパック契約なし かつVBM契約");

				// 減額計算
				inRec = gengakuCalc(inRec);
			}
			listCount += 1;
		}

		listCount = 0;
		// 同一リストの件数分繰り返す
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "同一リスト内のレコード全件出力");
		while(listCount != equalListSize)
		{
			// 金額が残った内訳についてファイル出力する。（金額が0円になった内訳についてはファイル出力しない。）
			JBSbatServiceInterfaceMap inRec = equalList.get(listCount);
			if(BigDecimal.ZERO.equals(inRec.getBigDecimal(JBSbatACIFM043.ICJKN_PRC)))
			{
				inRec.setOutFlg(false);
				
				// キー作成
				// 一時金登録番号＋一時金更新枝番
				String key = makeStr(inRec.getString(JBSbatACIFM043.ICJKN_ADD_SEQ),
										inRec.getString(JBSbatACIFM043.ICJKN_UPD_SEQ));
				BigDecimal trkmZumiSnst = vbKskmMiPrcMap.get(key);
				// 一時金スキーマのステータスを更新
				setUpdKmk(inRec, JACStrConst.ICJKN_TRKM_RSLT_NON, trkmZumiSnst, BigDecimal.ZERO);
			}
			else
			{
				inRec.setOutFlg(true);
			}
			outputInItem.addOutMapList(inRec);
			listCount += 1;
		}
	}
	
	/**
	 * 減額計算
	 * 
	 * @param inRec 減額計算前レコード
	 * @return JBSbatServiceInterfaceMap 減額計算後レコード
	 * @throws Exception
	 */
	private JBSbatServiceInterfaceMap gengakuCalc(JBSbatServiceInterfaceMap inRec)throws Exception
	{
		BigDecimal inPrc = inRec.getBigDecimal(JBSbatACIFM043.ICJKN_PRC);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "VB減額料合算額：" + vbTotalGen);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．一時金料金：" + inPrc);
		if(inPrc.compareTo(vbTotalGen) >= 0)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．一時金料金≧VB減額料合算額");
			BigDecimal vbUsePrc = inRec.getBigDecimal(JBSbatACIFM043.ICJKN_PRC).subtract(vbTotalGen);
			
			inRec.setBigDecimal(JBSbatACIFM043.ICJKN_PRC, vbUsePrc);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "計算後料金：" + vbUsePrc + "をセット");

			zeroFlg = true;
		}
		else
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．一時金料金＜VB減額料合算額");
			vbTotalGen = vbTotalGen.subtract(inPrc);
			
			//消しこみ後の金額として0をセット
			inRec.setBigDecimal(JBSbatACIFM043.ICJKN_PRC, BigDecimal.ZERO);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "計算後料金：0をセット");
		}
		return inRec;
	}
	
	/**
	 * 文字を連結します
	 * @param string　文字
	 * @return strBuf　連結した文字列
	 */
	private String makeStr(String ...string)
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeStr]");
		
		StringBuffer strBuf = new StringBuffer();
		for(String str:string){
			strBuf.append(str);
		}
		assert strBuf != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][makeStr][strBuf = " + strBuf.toString() + "]") : true;
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeStr]");
		
		return strBuf.toString();
	}
	
	/**
	 * 対象リストを以下のキーでソートします。
	 * 
	 * ソートキー：サービス契約番号
	 * 
	 * @throws Exception 業務サービス内で発生した例外全般 
	 */
	private void sortListMap() throws Exception
	{
		if(this.equalList == null || this.equalList.size() == 0)
		{
			return;
		}
		
		Collections.sort(this.equalList, new Comparator<JBSbatServiceInterfaceMap>()
		{
			
			/**
			 * <p>
			 * ソート用。
			 * </p>
			 * @param o1 入力1
			 * @param o2 入力2
			 * @return int compareTo結果
			 */
			@Override public int compare(JBSbatServiceInterfaceMap o1, JBSbatServiceInterfaceMap o2) 
			{
				// キー取得
				String o1Key = o1.get(JBSbatACIFM043.SVC_KEI_NO).toString();
				String o2Key = o2.get(JBSbatACIFM043.SVC_KEI_NO).toString();
				
					// 入力１．キー．compareTo（入力２．キー）を返却
				return o1Key.compareTo(o2Key);
			}
		});
		return;
	}

	/**
	 * 一時金スキーマを更新します。
	 * 
	 * @param tranMap        入力電文
	 * @param icjknTrkmRslt  一時金取込結果
	 * @param trkmZumi       取込済額
	 * @param trkmZan        取込残額
	 * @throws Exception
	 */
	private void setUpdKmk(JBSbatServiceInterfaceMap tranMap, String icjknTrkmRslt, BigDecimal trkmZumi, BigDecimal trkmZan) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][setUpdKmk]");
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "一時金登録番号(" + tranMap.getString(JBSbatACIFM043.ICJKN_ADD_SEQ) 
				+ ") 一時金更新枝番(" + tranMap.getString(JBSbatACIFM043.ICJKN_UPD_SEQ) + ") <-Update " 
				+ "一時金取込結果(" + icjknTrkmRslt + ") 取込済額(" + trkmZumi + ") 取込残額(" + trkmZan + ")");

		JBSbatCommonDBInterface setParam = new JBSbatCommonDBInterface();
		
		// 一時金.一時金取込ステータス
		setParam.setValue(JACStrConst.ICJKN_TRKM_STAT_CHU);
		// 一時金.一時金取込結果
		setParam.setValue(icjknTrkmRslt);
		// 一時金.取込済額
		setParam.setValue(trkmZumi);
		// 一時金.取込残額
		setParam.setValue(trkmZan);
		// 一時金.更新年月日時分秒
		setParam.setValue(JBSbatInterface.getSystemDateTimeStamp());
		// 一時金.更新オペレータアカウント
		setParam.setValue(super.batchUserId);
		
		JBSbatCommonDBInterface whereParam = new JBSbatCommonDBInterface();
		// 一時金.一時金登録番号
		whereParam.setValue(tranMap.getString(JBSbatACIFM043.ICJKN_ADD_SEQ));
		// 一時金.一時金更新枝番
		whereParam.setValue(tranMap.getString(JBSbatACIFM043.ICJKN_UPD_SEQ));
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setUpdKmk][setParam = " + setParam.getList().toString() + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setUpdKmk][whereParam = " + whereParam.getList().toString() + "]");

		// 更新実行
		executeAC_T_ICJKN_PKUPDATE(setParam.getList().toArray(), whereParam.getList().toArray());
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][setUpdKmk]");
	}
	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	
	/**
	 * SQLKEY(AC_SELECT_003)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 * 
	 * 3.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 *		 	システムコード
	 *		 	業務機能識別コード
	 *		 	業務機能識別コード
	 *		 	抽出変換コード
	 *		 	バッチ運用日
	 *		 	バッチ運用日
	 * </pre>
	 * <p>
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeAC_M_TEGAK_PRC_AC_SELECT_003(Object[] param) throws Exception
	{
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());
		paramList.setValue(param[2].toString());
		paramList.setValue(param[3].toString());
		paramList.setValue(param[4].toString());
		paramList.setValue(param[5].toString());
		paramList.setValue(param[6].toString());

		// DBアクセスを実行します
		db_AC_M_TEGAK_PRC.selectBySqlDefine(paramList, AC_M_TEGAK_PRC_AC_SELECT_003);
	}

	/**
	 * PK(ＰＫ　更新)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数で設定項目マップを作ります。<br>
	 *
	 * 2.引数で条件マップを作ります。<br>
	 *
	 * 3.DBアクセスを実行します。<br>
	 * 
	 * 4.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		setParam:設定したい項目の(項目、値)を(key、value)として、setParamマップに入れます。項目キーは以下に説明します。
	 *		 	一時金取込ステータス
	 *		 	一時金取込結果
	 *		 	一時金取込済額
	 *		 	一時金取込残額
	 *		 	更新年月日時分秒
	 *		 	更新オペレータアカウント
	 *		whereParam:PK項目の(項目、値)を(key、value)として,格納された配列です。PK項目は以下に説明します。
	 *		 	ICJKN_ADD_SEQ
	 *		 	ICJKN_UPD_SEQ
	 * </pre>
	 * <p>
	 * @param setParam 設定項目の値。
	 * @param whereParam 条件項目の値。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeAC_T_ICJKN_PKUPDATE(Object[] setParam, Object[] whereParam) throws Exception
	{
		// 設定値のマップを作成します
		JBSbatCommonDBInterface setMap = new JBSbatCommonDBInterface();
		setMap.setValue("ICJKN_TRKM_STAT", setParam[0]);
		setMap.setValue("ICJKN_TRKM_RSLT_CD", setParam[1]);
		setMap.setValue("TRKM_ZUMI_AMNT", setParam[2]);
		setMap.setValue("TRKM_ZAN_AMNT", setParam[3]);
		setMap.setValue("UPD_DTM", setParam[4]);
		setMap.setValue("UPD_OPEACNT", setParam[5]);
		
		// 条件のマップを作成します
		JBSbatCommonDBInterface whereMap = new JBSbatCommonDBInterface();
		whereMap.setValue("ICJKN_ADD_SEQ", whereParam[0]);
		whereMap.setValue("ICJKN_UPD_SEQ", whereParam[1]);

		// DBアクセスを実行します
		db_AC_T_ICJKN.updateByPrimaryKeys(whereMap, setMap);
	}
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
}
