/*********************************************************************
 *  All Rights reserved,Copyright (c) K-Opticom  					 *
 **********************************************************************
 *＜プログラム内容＞
 *	システム名			：eo顧客基幹システム
 *	モジュール名		：JBSbatACWribPrcColJudge
 *	ソースファイル名	：JBSbatACWribPrcColJudge.java
 *	作成者				：富士通　
 *	作成日				：2011年06月15日
 *＜機能概要＞
 *　割引料金事前徴収判定部品です。
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	v5.00		2013/05/24   FJ) 後藤	新規作成
 *	v8.00.00	2014/04/10   FJ) 江森	【OM-2014-0001302】徴収判定のソートキー不正対応
 *	v8.00.01	2014/06/26   FJ) 狭間	【OM-2014-0002078】長期継続利用割引が適用されていない不具合を修正
 *	v10.00.00	2014/10/17   FJ) 桑島	【OM-2014-0003168】料金徴収判定処理にて同一キー項目の判定用に追加項目を追記
 *********************************************************************/
package eo.business.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JACbatParamUtil;
import eo.business.common.JACbatSchdlUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatACIFM058;
import eo.business.util.table.JBSbatAC_M_PRC_COLLECT_JDG;
import eo.common.constant.JACStrConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.common.util.JPCUtilCommon;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.file.JBSbatDefFileUtil;
import eo.framework.file.JBSbatOutputFileUtil;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.util.JBSbatAplConst;
import eo.framework.util.JBSbatDateUtil;

/**
 * (クラスの機能概要) <p>
 *<BR>
 * @author 富士通
 */
public class JBSbatACWribPrcColJudge extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/** テーブル(料金徴収判定)*/
	private static final String D_TBL_NAME_AC_M_PRC_COLLECT_JDG = "AC_M_PRC_COLLECT_JDG";

	/** SQL定義キー(AC_SELECT_001)*/
	private static final String AC_M_PRC_COLLECT_JDG_AC_SELECT_001 = "AC_SELECT_001";

	/** テーブルアクセスクラス(料金徴収判定)*/
	private JBSbatSQLAccess db_AC_M_PRC_COLLECT_JDG = null;
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/

	/**▼▼▼▼▼▼クラス変数追加 開始▼▼▼▼▼▼*/

	/** 徴収月判定区分(徴収月) */
	private static final String		CHOSYUTUKI_HANTEI_KBN_GAITOU	= "1";

	/** 徴収月判定区分(徴収時期未到来) */
	private static final String		CHOSYUTUKI_HANTEI_KBN_MITOURAI	= "2";

	/** 徴収月判定区分(徴収月以外) */
	private static final String		CHOSYUTUKI_HANTEIKBN_TAISHOGAI	= "3";
	
	/** 料金スケジュール定義アクセス部品 */
	private JACbatSchdlUtil schdlUtil = null;

	/** 料金徴収判定マップ */
	private HashMap<ArrayList<String>, JBSbatCommonDBInterface>	prcCollectMap	= null;
	
	/** 料金徴収判定マップ検索キー */
	private ArrayList<String> procMapKey = new ArrayList<String>(2);
	
	/** ブレイクキー （請求先番号＋サービス契約番号＋料金コースコード＋料金サービスコードを保持）*/
	private String 					breakKey					 	= null;

	/** 料金項目(減額)*/
	private String 					prcKmkGen			 			= null;
	
	/** 請求月の暦日数 */
	int calDay;

	/** 群月初日 */
	private String gunStartDate 	= null;
	
	/** 翌群月初日 */
	private String nextGunStartDate 	= null;
	
	/** 全額退避マップ */
	private HashMap<String, ArrayList<JBSbatServiceInterfaceMap>>	allColMap		= null;

	/** 全額DB退避マップ */
	private int finalOutCnt = 0;
	
	/** サービス解約理由（請求先移動）リスト */
	private ArrayList<String> svcDlreIdoList = null;
	
	/** 初回課金開始日用マップ */
	private HashMap<String, String> mapFirstChrgStaymd = null;

	/** 初回徴収開始月用マップ */
	private HashMap<String, String> mapFirstPrcColMon = null;
	
	/** 出力定義ファイル名 */
	private String outDef = null;
	
	/**▲▲▲▲▲▲クラス変数追加 終了▲▲▲▲▲▲*/

	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
		/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);

		// DBアクセスクラスを生成します
		db_AC_M_PRC_COLLECT_JDG = new JBSbatSQLAccess(commonItem, D_TBL_NAME_AC_M_PRC_COLLECT_JDG);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
		
		// フリー項目取得
		String[] freeItems = super.freeItem.split(JACStrConst.SEMI_COLON, -1);
		
		// 出力定義ファイル名
		outDef = freeItems[0];
		
		// 料金スケジュール定義アクセス部品初期処理
		schdlUtil 		= new JACbatSchdlUtil(commonItem);
		
		// TAI-2012-0000054 料金徴収判定情報を初期処理で取得するよう修正
		// 料金徴収判定マスタテーブルより料金徴収判定情報を取得しメモリに格納する
		prcCollectMap	= getBYPrcCollect();
		
		allColMap		= new HashMap<String, ArrayList<JBSbatServiceInterfaceMap>>(101);
		
		// パラメータ取得クラス生成
		JACbatParamUtil paramUtil = new JACbatParamUtil(commonItem);

		// 業務パラメータ情報を取得する
		prcKmkGen = paramUtil.getGyoumuParameter(JACStrConst.WKPARA_AC_PK_GENGAKU);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "料金項目下３桁目（減額） ：" + prcKmkGen);
			
		String[] svcDlreIdo = paramUtil.getGyoumuParameter(JACStrConst.WKPARA_AC_SI_SEIKYU_IDO).split(JACStrConst.COMMA);
		
		svcDlreIdoList = new ArrayList<String>();
		
		for(String svcDlre : svcDlreIdo)
		{
			svcDlreIdoList.add(svcDlre);
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "業パラ．サービス解約理由（請求先異動） ：" + svcDlreIdoList.toString());
		
		// パラメータ取得クラスクローズ
		paramUtil.close();

		// 請求年月を取得する
		String seikyYm = schdlUtil.getBillDate(super.opeDate, JACStrConst.EVENT_CD_RYOKIN_KEISAN_YMD);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "バッチ運用日から取得した請求年月：" + seikyYm);

		// 群月初日、群締め日を取得する
		String[] gunStartEndDate = schdlUtil.getUseStrEnd(seikyYm, JACStrConst.EVENT_CD_USE_STAYMD, JACStrConst.EVENT_CD_USE_ENDYMD);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "群月初日：" + gunStartEndDate[0]);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "群締め日：" + gunStartEndDate[1]);
		// 群月初日
		gunStartDate = gunStartEndDate[0];

		// 請求月の暦日数を取得する（引数：群終了日、群開始日）
		calDay = JPCUtilCommon.subtractDay(gunStartEndDate[1], gunStartEndDate[0]) + 1;
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "請求月の暦日数：" + String.valueOf(calDay));

		// 暦日数取得の月数加減算を行う（引数：ワーク群月初日、加減算数(1)）
		nextGunStartDate = JPCUtilCommon.addMonth(gunStartEndDate[0], 1);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "翌群月初日：" + nextGunStartDate);

		// 初回課金開始日用マップ
		mapFirstChrgStaymd = new HashMap<String, String>();
		// 初回徴収開始月用マップ
		mapFirstPrcColMon = new HashMap<String, String>();
		/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @param inMap　入力電文
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/

		JBSbatOutputItem outputInItem = new JBSbatOutputItem();
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力（料金徴収判定）：" + JPCUtilCommon.convMapToString(inMap.getMap()));
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "請求契約番号：" + inMap.getString(JBSbatACIFM058.SEIKY_KEI_NO));
		
		// ブレイクキー（入力）
		String inKey = inMap.getString(JBSbatACIFM058.COLLECT_PATTERN_CD);  //徴収パターンコード
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力キー（徴収パターンコード）：" + inKey);
		
		// 相対マップから検索する
		// 料金徴収判定データ取得
		JBSbatCommonDBInterface mstData = getPrcCollectMap(inMap);

		// 料金徴収判定スキーマにレコードが存在しない場合（徴収判定対象外）
		if (mstData == null)
		{
			// 入力情報をそのまま出力情報とする
			this.getOutputMap(inMap, inMap.getBigDecimal(JBSbatACIFM058.PRC), outputInItem);

			return outputInItem;
		}

		// 初回課金開始日を取得する
		String firstChrgStaymd	= this.getFirstChrgStaymd(inMap);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "初回課金開始日：" + firstChrgStaymd);

		// 初回徴収開始月を取得する
		String firstPrcColMon	= this.getFirstPrcColMon(inMap, mstData, firstChrgStaymd);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "初回徴収開始月：" + firstPrcColMon);

		// 料金徴収月判定を行う
		String prcColJudgeDiv	= this.getPrcColJudgeDiv(inMap, mstData, firstChrgStaymd, firstPrcColMon);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "料金徴収月判定：" + prcColJudgeDiv);

		// 料金徴収判定を行う
		outputInItem = this.prcColJudge(inMap, mstData, prcColJudgeDiv, firstPrcColMon, outputInItem);

		return outputInItem;
		/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
		/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		// DBアクセスクラスをクローズします
		db_AC_M_PRC_COLLECT_JDG.close();
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
		// 料金スケジュール定義アクセス部品クローズ
		schdlUtil.close();
		
		if(!allColMap.isEmpty())
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "終了処理にて、全額退避マップ内のレコード出力");
			Iterator<ArrayList<JBSbatServiceInterfaceMap>> allColList = allColMap.values().iterator();

			// 退避件数分出力
			while(allColList.hasNext())
			{
				ArrayList<JBSbatServiceInterfaceMap> workList = allColList.next();
				
				for (int i = 0; i < workList.size(); i++)
				{
					JBSbatServiceInterfaceMap allCol = workList.get(i);
					this.getOutputMap(allCol, allCol.getBigDecimal(JBSbatACIFM058.PRC), null);
				}
				
			}
		}
		
		String[] outCntMsg = {"終了処理", String.valueOf(finalOutCnt)};
		super.logPrint.printBusinessErrorLog(JPCBatchMessageConstant.EACB0560AI, outCntMsg);

		/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**
	 * SQLKEY(AC_SELECT_001)で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_PRC_COLLECT_JDG_AC_SELECT_001(Object[] param) throws Exception
	{
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());

		// DBアクセスを実行します
		db_AC_M_PRC_COLLECT_JDG.selectBySqlDefine(paramList, AC_M_PRC_COLLECT_JDG_AC_SELECT_001);
	}
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/

	/**▼▼▼▼▼▼メソッド追加 開始▼▼▼▼▼▼*/

	/**
	 * 徴収パターンコード＆相対番号をキーに料金徴収判定情報を取得します。
	 * 
	 * @param inMap 入力電文
	 * @return JBSbatCommonDBInterface 料金徴収判定データ
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private JBSbatCommonDBInterface getPrcCollectMap(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		String inMapAitDiv = inMap.getString(JBSbatACIFM058.AIT_DIV);
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getPrcCollectMap]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getPrcCollectMap] 相対区分：" + inMapAitDiv);
		
		// TAI-2012-0000054 料金徴収判定情報を徴収パターンコード＋相対番号で取得するよう修正
		procMapKey.clear();		// 徴収判定情報マップを検索するキー情報を構成する
		procMapKey.add(inMap.getString(JBSbatACIFM058.COLLECT_PATTERN_CD)); // 徴収パターンコード
		
		// 相対番号 
		String aitNo = null;
		
		// 相対区分="2"（請求先番号）の場合
		if (JACStrConst.AITAIKBN_SEIKYU.equals(inMapAitDiv))
		{
			aitNo =  inMap.getString(JBSbatACIFM058.SEIKY_KEI_NO); // 請求先番号
		}
		// 相対区分="3"（サービス番号）の場合
		else if(JACStrConst.AITAIKBN_SVC.equals(inMapAitDiv))
		{
			aitNo = inMap.getString(JBSbatACIFM058.SVC_NO); // サービス番号
		}
		// 上記以外の場合
		else
		{
			aitNo = JACStrConst.AITAINO_SPACE; // 相対番号（ALLスペース）
		}
		
		// 請求先番号 or サービス番号 or 相対番号をキーに追加する
		procMapKey.add(aitNo);
		
		// 料金徴収判定データ取得
		JBSbatCommonDBInterface mstMap = prcCollectMap.get(procMapKey);
		
		// 相対区分="2"（請求先番号）または "3"（サービス番号）の場合で、
		// 該当データなしの場合、相対番号をスペースでパディングして再検索
		if (mstMap == null && (JACStrConst.AITAIKBN_SEIKYU.equals(inMapAitDiv) 
				|| JACStrConst.AITAIKBN_SVC.equals(inMapAitDiv)))
		{
			// 対象キー：相対番号の設定
			aitNo = JACStrConst.AITAINO_SPACE; // 相対番号（ALLスペース）
			
			// 相対番号（ALLスペース）を検索キーに置き換える
			procMapKey.clear();
			procMapKey.add(inMap.getString(JBSbatACIFM058.COLLECT_PATTERN_CD)); // 徴収パターンコード
			procMapKey.add(aitNo); // 相対番号の設定
			
			// 料金徴収判定データ取得
			mstMap = prcCollectMap.get(procMapKey);
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getPrcCollectMap] 検索キー：" + JPCUtilCommon.convListToString(procMapKey));
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getPrcCollectMap]");

		return mstMap;
	}
	
	/**
	 * 料金徴収判定マスタテーブルより料金徴収判定情報を取得します。
	 * 
	 * @return 料金徴収判定情報
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private HashMap<ArrayList<String>, JBSbatCommonDBInterface> getBYPrcCollect() throws Exception
	{
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getBYPrcCollect]");
		
		// 戻り値（料金徴収判定情報）
		HashMap<ArrayList<String>, JBSbatCommonDBInterface> prcInfoMap = new HashMap<ArrayList<String>, JBSbatCommonDBInterface>(101);
		
		// ＳＱＬキーを設定する
		JBSbatCommonDBInterface keyList = new JBSbatCommonDBInterface();

		// 対象キーの設定
		keyList.setValue(super.systemCode); 	// システムコード
		keyList.setValue(super.opeDate); 		// バッチ運用日
		
		// 料金徴収判定データ取得
		executeAC_M_PRC_COLLECT_JDG_AC_SELECT_001(keyList.getList().toArray());
		JBSbatCommonDBInterface dbMap = db_AC_M_PRC_COLLECT_JDG.selectNext();

		// 検索結果がなくなるまで繰り返す
		while (dbMap != null)
		{
			// マップキーの再構築
			ArrayList<String> procColKey = new ArrayList<String>(2);
			procColKey.add(dbMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.COLLECT_PATTERN_CD));	// 徴収パターンコード
			procColKey.add(dbMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.AITAI_NO));			// 相対番号

			// 料金徴収判定マップにデータを格納
			prcInfoMap.put(procColKey, dbMap);

			// 次レコード取得
			dbMap = db_AC_M_PRC_COLLECT_JDG.selectNext();
		}
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getBYPrcCollect] マスタ取得件数：" + prcInfoMap.size());
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getBYPrcCollect]");
		// 料金徴収判定情報を返却する
		return prcInfoMap;
	}

	
	/**
	 * 初回課金開始日を取得します。
	 * 
	 * @param inMap 利用料金情報
	 * @return String 初回課金開始日
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private String getFirstChrgStaymd(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		// 初回課金開始日のデータが既に取得済みの場合、HashMapより値を取得する。
		if (mapFirstChrgStaymd.containsKey(inMap.getString(JBSbatACIFM058.FIRST_CHRG_STAYMD)))
		{
			return mapFirstChrgStaymd.get(inMap.getString(JBSbatACIFM058.FIRST_CHRG_STAYMD));
		}

		// 初回課金開始日を取得する（引数：初回課金開始日、イベントコード（利用終了日））
		StringBuffer firstChrgStaymd = new StringBuffer();
		firstChrgStaymd.append(schdlUtil.getBillDate(inMap.getString(JBSbatACIFM058.FIRST_CHRG_STAYMD), 
				JACStrConst.EVENT_CD_USE_ENDYMD));			// 初回課金開始月
		firstChrgStaymd.append(JACStrConst.STR_OF_MONTH); 	// 月初日："01"
		
		// HashMapに値を設定する
		mapFirstChrgStaymd.put(inMap.getString(JBSbatACIFM058.FIRST_CHRG_STAYMD), firstChrgStaymd.toString());
		return firstChrgStaymd.toString();
	}

	/**
	 * 初回料金徴収開始月を取得します。
	 * 
	 * @param inMap 利用料金情報
	 * @param mastMap 料金徴収判定マスタ情報
	 * @param firstChrgStaymd 初回課金開始日
	 * @return String 初回料金徴収開始月
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private String getFirstPrcColMon(JBSbatServiceInterfaceMap inMap, JBSbatCommonDBInterface mastMap, String firstChrgStaymd)
	throws Exception
	{
		// 初回課金開始日のデータが既に取得済みの場合、HashMapより値を取得する。
		StringBuilder key = new StringBuilder();
		key.append(firstChrgStaymd);
		key.append(mastMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.COLLECT_STA_MON_CNT));
		if (mapFirstPrcColMon.containsKey(key.toString()))
		{
			return mapFirstPrcColMon.get(key.toString());
		}

		// 初回料金徴収月を取得する（引数：初回課金開始月初日、加減算数(料金徴収判定マスタ.徴収開始月-1)）
		String firstPrcColMon = JPCUtilCommon.addMonth(firstChrgStaymd,
				(mastMap.getBigDecimal(JBSbatAC_M_PRC_COLLECT_JDG.COLLECT_STA_MON_CNT).intValue() - 1)).substring(0, 6); 	// 初回料金徴収月

		// HashMapに値を設定する
		mapFirstChrgStaymd.put(key.toString(), firstPrcColMon);

		return firstPrcColMon;
	}

	/**
	 * 料金徴収月判定区分を取得します。
	 * 
	 * @param inMap 利用料金情報
	 * @param mastMap 料金徴収判定マスタ情報
	 * @param firstChrgStaymd 初回課金開始日
	 * @param firstPrcColMon 初回料金徴収開始月
	 * @return String 料金徴収月判定区分
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private String getPrcColJudgeDiv(JBSbatServiceInterfaceMap inMap, JBSbatCommonDBInterface mastMap, String firstChrgStaymd,
			String firstPrcColMon) throws Exception
	{
		// 各項目を初期化する
		String prcColJudgeDiv = null;	 // 料金徴収月判定区分（返却値）

		// 料金徴収判定マスタより徴収開始月、徴収サイクルを取得する
		int stMonth = mastMap.getBigDecimal(JBSbatAC_M_PRC_COLLECT_JDG.COLLECT_STA_MON_CNT).intValue();
		int cycle = mastMap.getBigDecimal(JBSbatAC_M_PRC_COLLECT_JDG.COLLECT_CYCLE_MON_CNT).intValue();

		// 利用料金情報.請求年月
		String billDate = inMap.getString(JBSbatACIFM058.SEIKY_YM); 
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "利用料金情報.請求年月：" + billDate);

		// 初回料金徴収月 ＞ 請求年月の場合
		if (firstPrcColMon.compareTo(billDate) > 0)
		{
			// 料金徴収月判定区分に「徴収時期未到来」を設定する
			prcColJudgeDiv = CHOSYUTUKI_HANTEI_KBN_MITOURAI;
			return prcColJudgeDiv;
		}

		// 徴収サイクルが０（初回のみ）の場合
		if (cycle == 0)
		{
			// 請求年月 ＝ 初回料金徴収月の場合
			if (firstPrcColMon.equals(billDate))
			{
				// 料金徴収月判定区分に「徴収月」を設定する
				prcColJudgeDiv = CHOSYUTUKI_HANTEI_KBN_GAITOU;
			}
			else
			{
				// 料金徴収月判定区分に「徴収月以外」を設定する
				prcColJudgeDiv = CHOSYUTUKI_HANTEIKBN_TAISHOGAI;
			}
		}
		else
		{
			// 請求年月初日取得
			StringBuffer seikyYmd = new StringBuffer();
			seikyYmd.append(inMap.getString(JBSbatACIFM058.SEIKY_YM)); 		// 請求年月
			seikyYmd.append(JACStrConst.STR_OF_MONTH); 						// 月初日："01"
			
			// 継続月数を取得する（引数：請求年月、初回課金開始日）
			int monthDiff = JPCUtilCommon.subtractMonth(seikyYmd.toString(), firstChrgStaymd) + 1;
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "継続月数：" + monthDiff);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "徴収開始月：" + stMonth);
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "徴収サイクル：" + cycle);
			
			// ((継続月数 − 料金徴収マスタ.徴収開始月) ÷ 料金徴収マスタ.徴収サイクル) の余り＝0の場合
			if (((monthDiff - stMonth) % cycle) == 0)
			{
				// 料金徴収月判定区分に「徴収月」を設定する
				prcColJudgeDiv = CHOSYUTUKI_HANTEI_KBN_GAITOU;
			}
			else
			{
				// 料金徴収月判定区分に「徴収月以外」を設定する
				prcColJudgeDiv = CHOSYUTUKI_HANTEIKBN_TAISHOGAI;
			}
		}

		return prcColJudgeDiv;
	}
	
	/**
	 * 徴収判定を行います。
	 * 
	 * @param inMap 利用料金情報
	 * @param mastMap 料金徴収判定マスタ情報
	 * @param prcColJudgeDiv 料金徴収月判定区分
	 * @param firstPrcColMon ワーク初回徴収開始月
	 * @param outputItem 出力共通電文
	 * @return JBSbatOutputItem 出力共通電文
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private JBSbatOutputItem prcColJudge(JBSbatServiceInterfaceMap inMap, JBSbatCommonDBInterface mastMap,
			String prcColJudgeDiv, String firstPrcColMon, JBSbatOutputItem outputItem) throws Exception
	{

		// 判定条件を取得する
		String svcDslYmd 	= inMap.getString(JBSbatACIFM058.SVC_DSL_YMD); 			// サービス解約日
		String svcDlre 		= inMap.getString(JBSbatACIFM058.SVC_DLRE); 			// サービス解約理由
		String svcKaihkDay	= inMap.getString(JBSbatACIFM058.SVC_KAIHK_DAY);		// サービス回復日
		String useStaymd	= inMap.getString(JBSbatACIFM058.USE_STAYMD);			// 利用開始日
		String seikyYm		= inMap.getString(JBSbatACIFM058.SEIKY_YM);				// 請求年月（数値）
		String useEndYmd 	= inMap.getString(JBSbatACIFM058.USE_ENDYMD); 			// 利用終了日
		String useEndYmdNextDay 	= JBSbatDateUtil.adjustDate(useEndYmd,1); 		// 利用終了日＋１日
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "入力．サービス解約理由" + svcDlre);

		// 料金項目を設定する
		BigDecimal prc 			= BigDecimal.ZERO; 							// 料金（出力）
		BigDecimal freePrc 		= BigDecimal.ZERO; 							// 料金（出力）
		BigDecimal inPrc		= inMap.getBigDecimal(JBSbatACIFM058.PRC); 	// 料金（入力）

		boolean outputFlg 	= true;		// 出力判定フラグ	
		boolean allColFlg 	= false;	// 全額徴収フラグ
		
		// 解約されていない（利用終了日＋１日　≧　翌群月初日）
		// 回復されていない（サービス回復日未設定　または　サービス回復日＜群月初日　または　サービス回復日≧翌群月初日）
		//（4-1. 通常時の徴収判定）
		if ((useEndYmdNextDay.compareTo(nextGunStartDate) >= 0) 
				&& (JACStrConst.KARA_MOJI.equals(svcKaihkDay) || svcKaihkDay.compareTo(gunStartDate) < 0 || svcKaihkDay.compareTo(nextGunStartDate) >= 0))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "通常時");
			// 料金徴収判定区分＝1（徴収月）の場合
			if (CHOSYUTUKI_HANTEI_KBN_GAITOU.equals(prcColJudgeDiv))
			{
				prc = inPrc;
			}
			// 料金徴収判定区分＝1（徴収月）以外の場合
			else
			{
				// 利用料金情報（徴収判定後）を出力しない
				outputFlg = false;
			}
		}
		
		// （（利用料金情報．利用終了日＋１日　＜　ワーク翌群月初日）　かつ　（利用料金情報．サービス解約理由　＝　"0020"（請求先異動）かつ
		// （サービス解約日　≠　空））　の場合
		// （4-2. 請求先異動による解約）
		else if (useEndYmdNextDay.compareTo(nextGunStartDate) < 0 && svcDlreIdoList.contains(svcDlre) && !JACStrConst.KARA_MOJI.equals(svcDslYmd))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "請求先異動時");
			// 料金徴収判定月区分＝1（徴収月）の場合
			if (CHOSYUTUKI_HANTEI_KBN_GAITOU.equals(prcColJudgeDiv))
			{
				// 異動解約徴収方法コード
				String mcanColWay 	= mastMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.IDO_DSL_CLCTWAY_CD);

				// 無料
				if (JACStrConst.COLLECT_WAY_CD_FREE.equals(mcanColWay))
				{
					prc = freePrc;
				}
				// 全額
				else if (JACStrConst.COLLECT_WAY_CD_ALL.equals(mcanColWay))
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "全額");
					
					allColFlg = true;
				}
				// 日割
				else if (JACStrConst.COLLECT_WAY_CD_HIWARI.equals(mcanColWay))
				{
					prc = inPrc;
				}
				else
				{
					// 利用料金情報（徴収判定後）を出力しない
					outputFlg = false;
				}
			}
			else
			{
				// 利用料金情報（徴収判定後）を出力しない
				outputFlg = false;
			}
		}	

		// （利用料金情報．利用終了日＋１日　＜　ワーク翌群月初日）　かつ　（利用料金情報．請求年月　≦　ワーク初回徴収開始月）　かつ
		// （利用料金情報．サービス解約理由　≠　（　"0020"（請求先異動））かつ　
		// （（利用料金情報．サービス回復日　＝　空）　または　（利用料金情報．サービス回復日　＜　利用料金情報．利用終了日＋１日））かつ
		// （サービス解約日　≠　空））　の場合
		// （4-3. 初月解約時の徴収判定）
		else if (useEndYmdNextDay.compareTo(nextGunStartDate) < 0 && seikyYm.compareTo(firstPrcColMon) <= 0 
				&& !svcDlreIdoList.contains(svcDlre) 
				&& (svcKaihkDay.equals(JACStrConst.KARA_MOJI) || svcKaihkDay.compareTo(useEndYmdNextDay) < 0)
				&& !JACStrConst.KARA_MOJI.equals(svcDslYmd))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "初回解約時");
			// 料金徴収判定月区分＝1（徴収月）または 料金徴収判定月区分＝2（徴収時期未到来）の場合
			if (CHOSYUTUKI_HANTEI_KBN_GAITOU.equals(prcColJudgeDiv) || CHOSYUTUKI_HANTEI_KBN_MITOURAI.equals(prcColJudgeDiv))
			{
				// 初月解約徴収方法コード
				String shgtuCol 	= mastMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.SHGTU_DSL_CLCTWAY_CD);
				
				// 無料
				if (JACStrConst.COLLECT_WAY_CD_FREE.equals(shgtuCol))
				{
					prc = freePrc;
				}
				// 全額
				else if (JACStrConst.COLLECT_WAY_CD_ALL.equals(shgtuCol))
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "全額");
					
					allColFlg = true;
				}
				// 日割
				else if (JACStrConst.COLLECT_WAY_CD_HIWARI.equals(shgtuCol))
				{
					prc = inPrc;
				}
				else
				{
					// 利用料金情報（徴収判定後）を出力しない
					outputFlg = false;
				}
			}
			else
			{
				// 利用料金情報（徴収判定後）を出力しない
				outputFlg = false;
			}
		}

		// （利用料金情報．利用終了日＋１日　＜　ワーク翌群月初日）　かつ　（利用料金情報．請求年月　＞　ワーク初回徴収開始月）　かつ
		// （利用料金情報．サービス解約理由　≠　0020）　かつ　
		// （（利用料金情報．サービス回復日　＝　空）　または（利用料金情報．サービス回復日　＜　利用料金情報．利用終了日＋１日）
		//     または（サービス回復日　＞　ワーク翌群月初日））かつ
		// （サービス解約日　≠　空））　の場合
		// （4-4. 初月以外での解約時の徴収判定）
		else if (useEndYmdNextDay.compareTo(nextGunStartDate) < 0 && seikyYm.compareTo(firstPrcColMon) > 0
				&& !svcDlreIdoList.contains(svcDlre) 
				&& (svcKaihkDay.equals(JACStrConst.KARA_MOJI) || svcKaihkDay.compareTo(useEndYmdNextDay) < 0 || svcKaihkDay.compareTo(nextGunStartDate) > 0)
				&& !JACStrConst.KARA_MOJI.equals(svcDslYmd))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "初回以外での解約時");                                                              
			
			// 料金徴収判定月区分＝1（徴収月）の場合
			if (CHOSYUTUKI_HANTEI_KBN_GAITOU.equals(prcColJudgeDiv))
			{
				// 初月以外解約徴収方法コード 
				String shgtugaiCol 	= mastMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.SHGTUGAI_DSL_CLCTWAY_CD);

				// 無料
				if (JACStrConst.COLLECT_WAY_CD_FREE.equals(shgtugaiCol))
				{
					prc = freePrc;
				}
				// 全額
				else if (JACStrConst.COLLECT_WAY_CD_ALL.equals(shgtugaiCol))
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "全額");
					
					allColFlg = true;
				}
				// 日割
				else if (JACStrConst.COLLECT_WAY_CD_HIWARI.equals(shgtugaiCol))
				{
					prc = inPrc;
				}
				else 
				{
					// 利用料金情報（徴収判定後）を出力しない
					outputFlg = false;
				}
			}
			else
			{
				// 利用料金情報（徴収判定後）を出力しない
				outputFlg = false;
			}
		}

		// （（利用料金情報．利用終了日＋１日　＜　利用料金情報．サービス回復日　＜　ワーク翌群月初日）かつ
		// （サービス解約日　≠　空））　の場合
		// （4-5. 回復時解約契約の徴収判定）
		else if (useEndYmdNextDay.compareTo(svcKaihkDay) < 0  && svcKaihkDay.compareTo(nextGunStartDate) < 0 && !JACStrConst.KARA_MOJI.equals(svcDslYmd))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "回復時解約契約");
			// 料金徴収判定月区分＝1（徴収月）または 料金徴収判定月区分＝2（徴収時期未到来）の場合
			if (CHOSYUTUKI_HANTEI_KBN_GAITOU.equals(prcColJudgeDiv) || CHOSYUTUKI_HANTEI_KBN_MITOURAI.equals(prcColJudgeDiv))
			{
				// 回復時解約契約徴収方法コード
				String kaihkDsl 	= mastMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.KAIHK_DSL_KEI_CLCTWAY_CD);

				// 無料
				if (JACStrConst.COLLECT_WAY_CD_FREE.equals(kaihkDsl))
				{
					prc = freePrc;
				}
				// 全額
				else if (JACStrConst.COLLECT_WAY_CD_ALL.equals(kaihkDsl))
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "全額");
					
					allColFlg = true;
				}
				// 日割
				else if (JACStrConst.COLLECT_WAY_CD_HIWARI.equals(kaihkDsl))
				{
					prc = inPrc;
				}
				else
				{
					// 利用料金情報（徴収判定後）を出力しない
					outputFlg = false;
				}
			}
			else
			{
				// 利用料金情報（徴収判定後）を出力しない
				outputFlg = false;
			}
		}

		// 利用料金情報．利用開始日　＝　利用料金情報．サービス回復日
		//（4-6. 回復契約の徴収判定）
		else if (useStaymd.equals(svcKaihkDay))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "回復契約");
			// 料金徴収判定月区分＝1（徴収月）または 料金徴収判定月区分＝2（徴収時期未到来）の場合
			if (CHOSYUTUKI_HANTEI_KBN_GAITOU.equals(prcColJudgeDiv) || CHOSYUTUKI_HANTEI_KBN_MITOURAI.equals(prcColJudgeDiv))
			{
		 		// 回復契約徴収方法コード
				String kaihkKei 	= mastMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.KAIHK_KEI_CLCTWAY_CD);

				// 無料
				if (JACStrConst.COLLECT_WAY_CD_FREE.equals(kaihkKei))
				{
					prc = freePrc;
				}
				// 全額
				else if (JACStrConst.COLLECT_WAY_CD_ALL.equals(kaihkKei))
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "全額");
					
					allColFlg = true;
				}
				// 日割
				else if (JACStrConst.COLLECT_WAY_CD_HIWARI.equals(kaihkKei))
				{
					prc = inPrc;
				}
				else
				{
					// 利用料金情報（徴収判定後）を出力しない
					outputFlg = false;
				}
			}
			else
			{
				// 利用料金情報（徴収判定後）を出力しない
				outputFlg = false;
			}
		}
		// 4-7. 上記以外の場合
		else
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "その他");
			// 料金徴収判定区分＝1（徴収月）の場合
			if (CHOSYUTUKI_HANTEI_KBN_GAITOU.equals(prcColJudgeDiv))
			{
				// 日割なし
				if (JACStrConst.HIWARI_YH_NON.equals(mastMap.getString(JBSbatAC_M_PRC_COLLECT_JDG.HIWARI_YH)))
				{
					prc = inPrc;
				}
				else
				{
					// 日割計算を行う
					prc = inPrc;
				}
			}
			else
			{
				// 利用料金情報（徴収判定後）を出力しない
				outputFlg = false;
			}
		}

		// 出力判定フラグがtrueの場合、利用料金情報（徴収判定後）を編集する
		if (outputFlg)
		{
			// 全額徴収フラグ ＝ true の場合
			if(allColFlg)
			{
				// ワークキー
				String inKey = inMap.getString(JBSbatACIFM058.SEIKY_KEI_NO); 	// 請求先番号
				
				StringBuffer keyBuf = new StringBuffer();
				
				keyBuf.append(inMap.getString(JBSbatACIFM058.SVC_NO));  		// サービス番号
				keyBuf.append(inMap.getString(JBSbatACIFM058.PCRS_CD)); 		// 料金コースコード
				keyBuf.append(inMap.getString(JBSbatACIFM058.PRC_SVC_CD));	 	// 料金サービスコード
				keyBuf.append(inMap.getString(JBSbatACIFM058.OP_SVKEI_NO));	 	// オプションサービス契約番号
				keyBuf.append(inMap.getString(JBSbatACIFM058.PRC_KMK_CD));		// 料金項目コード
				
				//【OM-2014-0003168】ADD　START
				keyBuf.append(inMap.getString(JBSbatACIFM058.WRIB_SVC_KEI_NO));		// 割引サービス契約番号
				//【OM-2014-0003168】ADD　END
				
				// マップキー
				String mapKey = keyBuf.toString();

				if (breakKey == null)
				{
					ArrayList<JBSbatServiceInterfaceMap> newList = new ArrayList<JBSbatServiceInterfaceMap>();
					newList.add(inMap);
					
					allColMap.put(mapKey, newList);
					
					breakKey = inKey;
				}
				// ブレークキー　≠　ワークキー
				else if (!breakKey.equals(inKey))
				{
					assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "ブレークキー　≠　ワークキー");

					Iterator<ArrayList<JBSbatServiceInterfaceMap>> allColList = allColMap.values().iterator();

					// 退避件数分出力
					while(allColList.hasNext())
					{
						ArrayList<JBSbatServiceInterfaceMap> workList = allColList.next();
						
						for (int i = 0; i < workList.size(); i++)
						{
							JBSbatServiceInterfaceMap allCol = workList.get(i);
							this.getOutputMap(allCol, allCol.getBigDecimal(JBSbatACIFM058.PRC), outputItem);
						}
						
					}

					allColMap.clear();
					
					ArrayList<JBSbatServiceInterfaceMap> newList = new ArrayList<JBSbatServiceInterfaceMap>();
					newList.add(inMap);

					// 全額退避マップに退避
					allColMap.put(mapKey, newList);

					// ブレークキー ← ワークキー
					breakKey = inKey;
				}
				// 上記以外
				else
				{
					ArrayList<JBSbatServiceInterfaceMap> workList = allColMap.get(mapKey);
					
					// 全額退避マップに入力．料金項目コードがキーのレコードがない場合
					if(workList == null || workList.size() == 0)
					{
						ArrayList<JBSbatServiceInterfaceMap> newList = new ArrayList<JBSbatServiceInterfaceMap>();
						newList.add(inMap);
						
						// 全額退避マップに退避
						allColMap.put(mapKey, newList);
					}
					else
					{
						JBSbatServiceInterfaceMap workMap = workList.get(0);
						
						//同料金項目コードの利用開始日　＜　入力．利用開始日　の場合
						if(workMap.getString((JBSbatACIFM058.USE_STAYMD)).compareTo(inMap.getString(JBSbatACIFM058.USE_STAYMD)) < 0)
						{
							// 全額退避マップに退避
							workList.clear();
							workList.add(inMap);
							allColMap.put(mapKey, workList);
						}
						// 利用開始日＋利用終了日＋サービス回復日が同一の場合
						else if(workMap.getString(JBSbatACIFM058.USE_STAYMD).compareTo(inMap.getString(JBSbatACIFM058.USE_STAYMD)) == 0
								&& workMap.getString(JBSbatACIFM058.USE_ENDYMD).compareTo(inMap.getString(JBSbatACIFM058.USE_ENDYMD)) == 0
								&& workMap.getString(JBSbatACIFM058.SVC_KAIHK_DAY).compareTo(inMap.getString(JBSbatACIFM058.SVC_KAIHK_DAY)) == 0)
						{
							// 全額徴収とする
							workList.add(inMap);
						}
					}
				}
			}
			// 上記以外
			else
			{
				this.getOutputMap(inMap, prc, outputItem);
			}
		}
		return outputItem;
	}
	
	/**
	 * 利用料金情報より出力共通電文を取得します。
	 * 
	 * @param inMap 利用料金情報
	 * @param prc 徴収判定後料金
	 * @param gengakuFlg 減額判定フラグ
	 * @param prcFlg  料金項目用フラグ true:徴収判定後料金を料金項目に設定する、false:利用料金情報.料金を料金項目に設定する
	 * @param outputItem 出力共通電文
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void getOutputMap(JBSbatServiceInterfaceMap inMap,
			BigDecimal prc, JBSbatOutputItem outputItem) throws Exception
	{
		// 料金を出力用に編集する
		inMap.setBigDecimal(JBSbatACIFM058.PRC, prc); // 料金

		inMap.setOutFlg(true); // 出力判定フラグtrue

		if(outputItem == null)
		{
			finalOut(inMap);
		}
		else
		{
			// 出力共通電文の出力電文リストに追加する
			outputItem.addOutMapList(inMap);
		}
	}

	/**
	 * 退避しているレコードを出力します。
	 * 
	 * @param outUsePrcMap 出力情報
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void finalOut(JBSbatServiceInterfaceMap outUsePrcMap) throws Exception
	{
		// ファイル出力部品を取得
		JBSbatOutputFileUtil fileUtil = super.commonItem.getOutPutFile();
		// 設定されているエンコード形式を退避
		String enc = fileUtil.getEncode();
		// encodeの形式がSHIFT-JISの場合、MS932に変換
		if (JACStrConst.ENCODE_SJIS.toUpperCase().equals(enc.toUpperCase()))
		{
			enc = JACStrConst.ENCODE_MS932;
		}
		
		// 出力定義ファイル名を取得する。
		String outFileDefName = JBSbatAplConst.getAplConstValue("OTD") + outDef;
		
		// 出力定義ファイルオブジェクトを生成する
		JBSbatDefFileUtil outFileDef = new JBSbatDefFileUtil(outFileDefName, fileUtil);
		// 退避したエンコード形式を戻す（出力定義ファイルオブジェクト生成時に上書きが発生しているため）
		fileUtil.setEncode(enc);

		fileUtil.print(outUsePrcMap, outFileDef);
		
		finalOutCnt += 1;
	}
	/**▲▲▲▲▲▲メソッド追加 終了▲▲▲▲▲▲*/
}
