/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatCHDelKhoSknCst
*	ソースファイル名	：JBSbatCHDelKhoSknCst.java
*	作成者				：富士通　
*	作成日				：2013年07月08日
*＜機能概要＞
*　削除候補債権抽出部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v5.00.00	2013/07/08  富士通		新規作成
*	v6.00.00	2013/11/18  FJ)伊藤		【】入力変更に伴い処理変更
*	v8.00.00	2014/05/19  FJ)狭間		【OM-2014-0001868】累積データ削除で貸倒登録済を削除対象から除外
*********************************************************************/
package eo.business.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JACbatParamUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatCHIFM191;
import eo.business.util.file.JBSbatCHIFM193;
import eo.business.util.file.JBSbatCHIFM203;
import eo.framework.file.JBSbatDefFileUtil;
import eo.framework.file.JBSbatInputFileUtil;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.util.JBSbatAplConst;
import eo.framework.util.JBSbatDateUtil;
import eo.common.constant.JACStrConst;
import eo.common.util.JPCDateChecker;
import eo.common.util.JPCDateUtil;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/

public class JBSbatCHDelKhoSknCst extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/
	
	/** 退避用請求契約番号 */
	private String taihiSeiky = JACStrConst.KARA_MOJI;
	
	/** 削除対象となったレコードをカウント */
	private BigDecimal deleteRecCount = null;
	
	/** APLConstのプロパティ名：入力ファイル定義 */
	private final String IND = "IND";
	
	/** 削除条件年月日*/
	private String judgeYmd = JACStrConst.KARA_MOJI;
	
	/** 請求契約番号債権数マップ */
	private HashMap<String, BigDecimal> seikyKeiNoSknCntMap = new HashMap<String, BigDecimal>();
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][initial]");
		
		//条件判定年月日を設定。
		setJudgeDate(commonItem);
		
		//フリーより請求契約番号債権数ファイルのパスとDEFを取得
		String[] freeItems = super.freeItem.split(JACStrConst.SEMI_COLON);
		
		deleteRecCount = BigDecimal.ZERO;
		
		//ファイルを全て読み込み、全レコードをマップに代入
		for (JBSbatServiceInterfaceMap inMap : getMaps(freeItems[0],freeItems[1]))
		{
			String seikyKeiNo = inMap.getString(JBSbatCHIFM203.SEIKY_KEI_NO);
			
			BigDecimal saikenCount = new BigDecimal(inMap.getString(JBSbatCHIFM203.SAIKEN_COUNT));
			
			seikyKeiNoSknCntMap.put(seikyKeiNo, saikenCount);
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][initial]");
		
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * 条件判定日時を設定
	 * @param commonItem バッチ共通パラメータ電文
	 * @throws Exception スローされる例外
	 */
	private void setJudgeDate(JBSbatCommonItem commonItem) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][setJudgeDate]");
		
		//バッチ共通パラメータを取得
		JACbatParamUtil paramUtil = new JACbatParamUtil(commonItem);
		
		//何ヶ月戻るかを設定する変数
		int revValue = 0;
		
		try
		{
			//設定された業務パラメータを取得
			revValue = -1 * Integer.parseInt(paramUtil.getGyoumuParameter(JACStrConst.WKPARA_CH_DEL_CRITERIA_01));
		}
		finally
		{
			//パラメータクローズ
			paramUtil.close();
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setJudgeDate][revValue=" + revValue + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setJudgeDate][opeDate=" + super.opeDate + "]");
		
		//走行日（バッチ運用日）から業務パラメータ分の月を戻し（製造時は25ヶ月）、末日取得のために年月までにトリミングして取得。
		String judgeYm = JPCDateUtil.addMonth(super.opeDate, revValue).substring(0, 6);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setJudgeDate][judgeYm=" + judgeYm + "]");
		
		//末日を取得し、条件日にセット
		judgeYmd = judgeYm + JBSbatDateUtil.getEndOfMonth(judgeYm);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setJudgeDate][judgeYmd=" + judgeYmd + "]");
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][setJudgeDate]");
	}
	
	/**
	 * ファイルから全レコードを取得
	 * 
	 * @param id 定義ファイルID
	 * @return 全レコードマップ
	 * @throws Exception スローされる例外
	 */
	private ArrayList<JBSbatServiceInterfaceMap> getMaps(String id,String filePath) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getMaps]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMaps][id=" + id + "]");
		
		//全レコードマップを格納するリスト配列を用意
		ArrayList<JBSbatServiceInterfaceMap> inMaps = new ArrayList<JBSbatServiceInterfaceMap>();
		
		//レコードの文字列を保管する変数
		String record = JACStrConst.KARA_MOJI;
		
		//各ファイルを取得
		JBSbatInputFileUtil readFile = new JBSbatInputFileUtil(filePath);
		readFile.setLine(JACStrConst.LINE_LF);
		readFile.setEncode(JACStrConst.ENCODE_SJIS);
		readFile.createReader();
		
		JBSbatDefFileUtil fileDef = getFileDefUtil(id,readFile);
		
		//ファイルのレコードを全て読む
		while (readFile.ready())
		{
			//一行読んで
			record = readFile.readLine();
			

			//マップとして配列に挿入
			inMaps.add(getRecMap(readFile,record,fileDef));
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getMaps]");
		
		return inMaps;
	}
	
	/**
	 * 定義ファイルIDから定義ファイルを取得
	 * 
	 * @param id 定義ファイルID
	 * @return 定義ファイル
	 * @throws Exception スローされる例外
	 */
	private JBSbatDefFileUtil getFileDefUtil(String fileId, JBSbatInputFileUtil inFileObj) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getFileDefUtil]");
		
		//定義ファイルフォルダ＋ID＋.defにする
		String filePath = JBSbatAplConst.getAplConstValue(IND) + fileId;
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getFileDefUtil][filePath=" + filePath + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getFileDefUtil]");
		
		//ファイル取得しながらリターン
		return new JBSbatDefFileUtil(filePath, inFileObj);
	}

	/**
	 * ファイルからレコードを取得
	 * 
	 * @param inFileObj 入力ファイルオブジェクト
	 * @param sLine 行文字列
	 * @param fileDef ファイル定義名
	 * @return レコードマップ
	 * @throws Exception スローされる例外
	 */
	private JBSbatServiceInterfaceMap getRecMap(JBSbatInputFileUtil inFileObj, String sLine, JBSbatDefFileUtil fileDefObj) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getRecMap][record=" + sLine + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getRecMap]");
		
		//レコードを取得
		return fileDefObj.lineToObject(sLine, inFileObj, 0);
	}

	/**
	 * 主処理
	 * @param inMap　入力電文
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute]");
		
		//出力アイテムの設定
		JBSbatOutputItem outputItem = new JBSbatOutputItem();

		//レコードの請求契約番号取得
		String inSeikyNumber = inMap.getString(JBSbatCHIFM193.SEIKY_KEI_NO);
		
		//請求契約番号の持つ債権カウントを取得
		BigDecimal recSaikenCount = seikyKeiNoSknCntMap.get(inSeikyNumber);

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][inMap.SAIKEN_NO=" + inMap.getString(JBSbatCHIFM193.SAIKEN_NO) + "]");
		
		if(judgeDeleteRec(inMap))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][recSeikyNumber=" + inSeikyNumber + "]");
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][taihiSeiky=" + taihiSeiky + "]");
			
			//退避している請求契約番号と同じかどうか（一個前に削除対象に選ばれた請求番号と比較）
			if(inSeikyNumber.equals(taihiSeiky))
			{
				//カウントを追加
				deleteRecCount = deleteRecCount.add(BigDecimal.ONE);
				
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][deleteRecCount=" + deleteRecCount + "]");
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][recSaikenCount=" + recSaikenCount + "]");
				
				//請求契約番号の持つ債権数と、削除レコードカウントが一致しないかどうか
				if(deleteRecCount != recSaikenCount)
				{
					//一致しなければ最終債権ではないので、出力アイテム情報の設定
					outputItem.addOutMapList(this.outPutDelSaikenInfo(inMap));
				}
			}
			//請求番号が一致しない（請求番号の中で最初の削除債権レコード）
			else
			{
				//カウントを1にして
				deleteRecCount = BigDecimal.ONE;
				
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][deleteRecCount=" + deleteRecCount + "]");
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][recSaikenCount=" + recSaikenCount + "]");
				
				//請求契約番号を退避
				taihiSeiky = inSeikyNumber;
				
				//請求契約番号の持つ債権数と、削除レコードカウントが一致しないかどうか
				if(deleteRecCount != recSaikenCount)
				{
					//一致しなければ最終債権ではないので、出力アイテム情報の設定
					outputItem.addOutMapList(this.outPutDelSaikenInfo(inMap));
				}
			}
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][execute]");

		return outputItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][terminal]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][terminal]");
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
	
	/**
	 * 入力されたレコードが削除対象かどうかを判定します。
	 */
	private boolean judgeDeleteRec(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][judgeDeleteRec]");
		
		//債権ステータスを取得
		String saikenStat = inMap.getString(JBSbatCHIFM193.SAIKEN_STAT);
		
		//最大年月日を取得
		String compareYmd = JACStrConst.KARA_MOJI;
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][judgeDeleteRec][saikenStat=" + saikenStat + "]");
		
		//請求取消の場合
		if(saikenStat.equals(JACStrConst.SAIKEN_STAT_CL))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][judgeDeleteRec][SET:SAIKEN_SHOKYAKU_YMD]");
			//債権償却日を設定
			compareYmd = inMap.getString(JBSbatCHIFM193.SAIKEN_SHOKYAKU_YMD);
		}
		//収納済の場合
		else if (saikenStat.equals(JACStrConst.SAIKEN_STAT_KAKNO_ZUMI))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][judgeDeleteRec][SET:JUTO_FIN_YMD]");
			
			//充当完了年月日を設定
			compareYmd = inMap.getString(JBSbatCHIFM193.JUTO_FIN_YMD);
			
			//充当完了日が未設定か空文字の場合
			if(compareYmd == null || compareYmd.equals(JACStrConst.KARA_MOJI))
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][judgeDeleteRec][SET:SAIKEN_FIX_YMD]");
				
				//債権確定年月日を取得
				compareYmd = inMap.getString(JBSbatCHIFM193.SAIKEN_FIX_YMD);
			}
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][judgeDeleteRec][compareYmd=" + compareYmd + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][judgeDeleteRec]");
		
		//日付取得できない場合は強制的にfalse（削除対象外）
		if(compareYmd == null || compareYmd.equals(JACStrConst.KARA_MOJI))
		{
			return false;
		}
		//日付を取得したら比較処理へ
		else
		{
			//比較年月日が条件年月日よりも過去（同日含む）ならばtrueを返す。
			return JPCDateChecker.isPastDate(compareYmd, judgeYmd, "1");
		}
	}
	
	/**
	 * 削除候補債権情報ファイル出力処理
	 * @param  inMap    入力電文
	 * @return outInfoMap 削除候補債権情報
	 * @throws Exception  業務サービス内で発生した例外全般。
	 */
	private JBSbatServiceInterfaceMap outPutDelSaikenInfo(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][outPutDelSaikenInfo]");

		JBSbatServiceInterfaceMap outInfoMap = new JBSbatServiceInterfaceMap();

		// 請求契約番号
		outInfoMap.set(JBSbatCHIFM191.SEIKY_KEI_NO,			inMap.getString(JBSbatCHIFM191.SEIKY_KEI_NO));

		// 債権年月
		outInfoMap.set(JBSbatCHIFM191.SAIKEN_YM,			inMap.getString(JBSbatCHIFM191.SAIKEN_YM));
		
		// 債権番号
		outInfoMap.set(JBSbatCHIFM191.SAIKEN_NO,			inMap.getString(JBSbatCHIFM191.SAIKEN_NO));
		
		outInfoMap.set(JBSbatCHIFM191.SAIKEN_STAT,			inMap.getString(JBSbatCHIFM191.SAIKEN_STAT));			// 債権ステータス
		outInfoMap.set(JBSbatCHIFM191.JUTO_FIN_YMD,			inMap.getString(JBSbatCHIFM191.JUTO_FIN_YMD));			// 充当完了年月日
		outInfoMap.set(JBSbatCHIFM191.SAIKEN_SHOKYAKU_YMD,	inMap.getString(JBSbatCHIFM191.SAIKEN_SHOKYAKU_YMD));	// 債権償却年月日

		outInfoMap.setOutFlg(true);

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][outPutDelSaikenInfo]");

		return outInfoMap;
	}
}