/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatCHSeikyOutPutFileErrChk
*	ソースファイル名	：JBSbatCHSeikyOutPutFileErrChk.java
*	作成者				：富士通　
*	作成日				：2015年02月24日
*＜機能概要＞
*　請求書印刷チェック部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v13.00.00	2015/02/24  FJ）福岡	新規作成 ANK-2416-00-00
*	v13.00.01	2015/03/31  FJ）寺園	ST4-2015-0000001　性能改善対応
*********************************************************************/
package eo.business.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import eo.business.common.JACbatParamUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.common.JKKBatConst;
import eo.business.util.file.JBSbatCHIFM242;
import eo.business.util.file.JBSbatCHIFM243;
import eo.business.util.file.JBSbatCHIFM244;
import eo.business.util.table.JBSbatZM_M_CD_NM_KANRI;
import eo.common.constant.JACStrConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.common.util.JKKStringUtil;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.file.JBSbatDefFileUtil;
import eo.framework.file.JBSbatInputFileUtil;
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.JBSbatCheckUtil;
import eo.framework.util.JBSbatDateUtil;

/**
* KSSOLより受信した「お客様情報連携」ファイルのチェックを行う。<p>
* <BR>
* @author 富士通
*/
public class JBSbatCHSeikyOutPutFileErrChk extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	
	/** テーブル(コード名称管理)*/
	private static final String D_TBL_NAME_ZM_M_CD_NM_KANRI = "ZM_M_CD_NM_KANRI";
	
	/** SQL定義キー(CH_SELECT_005)*/
	private static final String ZM_M_CD_NM_KANRI_CH_SELECT_008 = "CH_SELECT_008";
	
	/** テーブルアクセスクラス(コード名称管理)*/
	private JBSbatSQLAccess db_ZM_M_CD_NM_KANRI = null;
	
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/
	
	/** フリーパラメタ（入力ファイル） */
	ArrayList<HashMap<String, String>> chifm243List = null;
		
	/** エラー内容 */
	private HashMap<String, String> errMap = null;
	
	/** コード名称マスタ：支払区分 */
	private Map<String, String> payKbnMap = null;
	
	/** コード名称マスタ：領収のみフラグ */
	private Map<String, String> rOnlyMap = null;
	
	/** コード名称マスタ：発送区分 */
	private Map<String, String> hassoKbnMap = null;
	
	/** エラー定数：該当keyにて業パラ管理. */
	final private String ERR_01 = "CH_ERR_CHPRC08401_01";		// 請求先番号エラー
	final private String ERR_02 = "CH_ERR_CHPRC08401_02";		// 請求年月エラー
	final private String ERR_03 = "CH_ERR_CHPRC08401_03";		// 支払区分エラー
	final private String ERR_04 = "CH_ERR_CHPRC08401_04";		// 領収のみフラグエラー
	final private String ERR_05 = "CH_ERR_CHPRC08401_05";		// 発送年月日エラー
	final private String ERR_06 = "CH_ERR_CHPRC08401_06";		// 発送区分エラー
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		
		// DBアクセスクラスを生成します
		db_ZM_M_CD_NM_KANRI = new JBSbatSQLAccess(commonItem, D_TBL_NAME_ZM_M_CD_NM_KANRI);
		
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
		
		// freeパラメタ取得
		this.chifm243List 	= new ArrayList<HashMap<String,String>>();
		String infPass   	= super.freeItem.split(JKKBatConst.S_PARAM_DELIM)[0];
		String infdef   	= super.freeItem.split(JKKBatConst.S_PARAM_DELIM)[1];
		
		// freeパラメタのパスを元に,ファイル取得
		setCHIFM241List(infPass, infdef);
		
		// 業パラ取得（エラー内容）
		this.errMap = getErrMap();
		
		// コード名称マスタ取得
		this.payKbnMap   = makeCdNmMap("CD00166");				// 支払区分
		this.rOnlyMap    = makeCdNmMap("CD00002");				// 領収のみフラグ
		this.hassoKbnMap = makeCdNmMap("CD01668");				// 発送区分
		
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * 主処理
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute() throws Exception {
		
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		super.logPrint.printDebugLog("execute() start");
		
		// 共通電文
		JBSbatOutputItem oBean = new JBSbatOutputItem();
		
		// お客様情報連携ファイル妥当性チェック.
		singleErrChk(oBean);
		
		// エラー情報が存在する場合は,warning設定して処理終了.
		if (isErr(oBean)) return oBean;
		
		/** ↓以降は,正常処理とする */
		
		// お客様情報チェック済ファイル生成
		outOkFile(oBean);
		
		super.logPrint.printDebugLog("execute() end");
		return oBean;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		super.logPrint.printDebugLog("terminal() start");
		
		db_ZM_M_CD_NM_KANRI.close();
		
		super.logPrint.printDebugLog("terminal() end");
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * 
	 * freeパラメタに定義されているファイルを取得する.
	 * 
	 * @param  path ファイルパス
	 */
	private void setCHIFM241List(String path, String def) throws Exception {
		
		JBSbatServiceInterfaceMap rowMap = null;
		
		/** CHIFM241.defを使用.固定長をカンマ区切りで取得. */
		
		JBSbatInputFileUtil readObj      = new JBSbatInputFileUtil(path);
		JBSbatDefFileUtil   fileDef      = new JBSbatDefFileUtil(JBSbatAplConst.getAplConstValue("IND") + def, readObj);
		
		readObj.createReader();
		
		String line = "";
		while(readObj.ready()) {
			
			line   = readObj.readLine();
			rowMap = fileDef.lineToObject(line, readObj, 0);
			
			// CHIFM241 => CHIFM243 へ変換.
			this.chifm243List.add(retCHIFM243Map(rowMap));
		}
		
		// 閉じる
		if (readObj != null)
			readObj.close();
		
		// 初期化
		readObj = null;
	}
	
	/**
	 * 
	 * CHIFM243へ変換したMapを返却する.
	 * 
	 * @param  adRowMap
	 * @return 
	 * @throws Exception
	 */
	private HashMap<String, String> retCHIFM243Map(JBSbatServiceInterfaceMap adRowMap) throws Exception {
		
		HashMap<String, String> ret = new HashMap<String, String>();
		
		// 請求年月編集用
		String y  = adRowMap.getString(JBSbatCHIFM244.SEIKY_Y);												// 請求年
		String m  = adRowMap.getString(JBSbatCHIFM244.SEIKY_M);												// 請求月
		
		//請求年が空白の場合空文字を設定する
		if(JKKStringUtil.isNullBlank(y)){
			y = "";
		}
		//請求月が空白の場合空文字を設定する
		if(JKKStringUtil.isNullBlank(m)){
			m = "";
		}
		
		// 設定処理
		ret.put(JBSbatCHIFM243.SEIKY_KEI_NO,   adRowMap.getString(JBSbatCHIFM244.SEIKY_KEI_NO));			// 請求契約番号
		ret.put(JBSbatCHIFM243.SEIKY_YM,       new StringBuffer(y).append(m).toString());					// 請求年月
		ret.put(JBSbatCHIFM243.PAY_KBN,        adRowMap.getString(JBSbatCHIFM244.PAY_KBN));					// 支払区分
		ret.put(JBSbatCHIFM243.R_FLG,          adRowMap.getString(JBSbatCHIFM244.R_FLG));					// 領収のみフラグ
		ret.put(JBSbatCHIFM243.HASSO_YMD,      adRowMap.getString(JBSbatCHIFM244.HASSO_YMD));				// 発送年月日
		ret.put(JBSbatCHIFM243.HASSO_KBN,      adRowMap.getString(JBSbatCHIFM244.HASSO_KBN));				// 発送区分
		
		return ret;
	}
	
	/** 
	 * 
	 * 妥当性チェックを実施する.
	 * 
	 * @param tg
	 * @return
	 */
	private String chk(HashMap<String, String> tg) {
		
		super.logPrint.printDebugLog("chk() start");
		
		String chkTg = "";
		
		// 1.請求先番号：必須、数値チェック
		chkTg = tg.get(JBSbatCHIFM243.SEIKY_KEI_NO);
		
		super.logPrint.printDebugLog("請求先番号=" + chkTg );
		
		boolean isChkOK1 = JBSbatCheckUtil.invoke(chkTg, new String[]{JACStrConst.MOJI_HNKK_SUJI_ONE});
		boolean isChkOK2 = !JKKStringUtil.isNullSpace(chkTg);
		if (!isChkOK1 || !isChkOK2) {
			super.logPrint.printDebugLog("請求先番号：必須、数値チェックエラー=" + chkTg);
			super.logPrint.printDebugLog("chk() end");
			return this.ERR_01;
		}
		
		// 2.請求年月：年月妥当性チェック
		chkTg = tg.get(JBSbatCHIFM243.SEIKY_YM);
		if (!JBSbatDateUtil.checkDate(chkTg, 6)) {
			super.logPrint.printDebugLog("請求年月：年月妥当性チェックエラー=" + chkTg);
			super.logPrint.printDebugLog("chk() end");
			return this.ERR_02;
		}
		
		// 3.支払区分：マスタ存在チェック
		chkTg = tg.get(JBSbatCHIFM243.PAY_KBN);
		if (!this.payKbnMap.containsKey(chkTg)) {
			super.logPrint.printDebugLog("支払区分：マスタ存在チェックエラー=" + chkTg);
			super.logPrint.printDebugLog("chk() end");
			return this.ERR_03;
		}
		
		// 4.領収のみフラグ：マスタ存在チェック
		chkTg = tg.get(JBSbatCHIFM243.R_FLG);
		if (!this.rOnlyMap.containsKey(chkTg)) {
			super.logPrint.printDebugLog("領収のみフラグ：マスタ存在チェックエラー=" + chkTg);
			super.logPrint.printDebugLog("chk() end");
			return this.ERR_04;
		}
		
		// 5.発送年月日：年月日妥当性チェック
		chkTg = tg.get(JBSbatCHIFM243.HASSO_YMD);
		if (!JBSbatDateUtil.checkDate(chkTg, 8)) {
			super.logPrint.printDebugLog("発送年月日：年月日妥当性チェックエラー=" + chkTg);
			super.logPrint.printDebugLog("chk() end");
			return this.ERR_05;
		}
		
		// 6.発送区分：マスタ存在チェック
		chkTg = tg.get(JBSbatCHIFM243.HASSO_KBN);
		if (!this.hassoKbnMap.containsKey(chkTg)) {
			super.logPrint.printDebugLog("発送区分：マスタ存在チェックエラー=" + chkTg);
			super.logPrint.printDebugLog("chk() end");
			return this.ERR_06;
		}
		
		super.logPrint.printDebugLog("チェックエラー無");
		super.logPrint.printDebugLog("chk() end");
		
		return "";
	}
	
	/** 
	 * 
	 * お客様情報チェック済ファイルを作成.
	 * 
	 * @param  tg
	 * @return 
	 */
	private JBSbatServiceInterfaceMap retOkMap(HashMap<String, String> tg) {
		
		JBSbatServiceInterfaceMap ret = new JBSbatServiceInterfaceMap();
		
		// 初期設定値がそのまま[チェック済]リストとなる.
		ret.setMap(tg);
		ret.setOutFlg(true);
		
		return ret;
	}
	
	/** 
	 * 
	 * お客様情報エラーリストを作成.
	 * 
	 * @param  tg
	 * @param  errCd
	 * @return
	 */
	private JBSbatServiceInterfaceMap retNgMap(HashMap<String, String> tg, String errCd) {
		
		JBSbatServiceInterfaceMap ret = new JBSbatServiceInterfaceMap();
		
		// エラーリスト生成
		ret.set(JBSbatCHIFM242.SEIKY_KEI_NO,   tg.get(JBSbatCHIFM243.SEIKY_KEI_NO));			// 請求契約番号
		ret.set(JBSbatCHIFM242.SEIKY_YM,       tg.get(JBSbatCHIFM243.SEIKY_YM));				// 請求年月
		ret.set(JBSbatCHIFM242.PAY_KBN,        tg.get(JBSbatCHIFM243.PAY_KBN));					// 支払区分
		ret.set(JBSbatCHIFM242.R_FLG,          tg.get(JBSbatCHIFM243.R_FLG));					// 領収のみフラグ
		ret.set(JBSbatCHIFM242.HASSO_YMD,      tg.get(JBSbatCHIFM243.HASSO_YMD));				// 発送年月日
		ret.set(JBSbatCHIFM242.HASSO_KBN,      tg.get(JBSbatCHIFM243.HASSO_KBN));				// 発送区分
		ret.set(JBSbatCHIFM242.ERR_CD,         errCd);											// エラーコード
		ret.set(JBSbatCHIFM242.ERR_NAIYO,      this.errMap.get(errCd));							// エラー内容
		
		ret.setOutFlg(true);
		
		return ret;
	}
	
	/** 
	 * 
	 * チェックOKとなった件数分,お客様情報チェック済ファイルを作成.
	 * 
	 * @param oBean
	 */
	private void outOkFile(JBSbatOutputItem oBean) {
		
		// 無条件にOKリストへ格納する.
		for (HashMap<String, String> tg : this.chifm243List) {
			oBean.addOutMapList(retOkMap(tg));
		}
	}
	
	/** 
	 * 
	 * 妥当性チェックを実施し,
	 * チェックNGとなった件数分,お客様情報エラーリストを作成.
	 * 
	 * @param oBean
	 */
	private void singleErrChk(JBSbatOutputItem oBean) {
		
		// お客様情報連携ファイルの妥当性チェック開始
		for (HashMap<String, String> tg : this.chifm243List) {
			
			// 単体エラーチェック
			String errCd = chk(tg);
			
			// エラー有の場合,エラー情報設定.
			if (!JKKStringUtil.isNullBlank(errCd))
				oBean.addOutMapList_2(retNgMap(tg, errCd));
		}
	}
	
	/** 
	 * 
	 * お客様情報エラーリスト（エラー有無）を判定する.
	 * エラー有の場合,ワーニングメッセージも同時に設定する.
	 * 
	 * @param  oBean
	 * @return エラー有：true、エラー無：false
	 */
	private boolean isErr(JBSbatOutputItem oBean) {
		
		super.logPrint.printDebugLog("isErr() start");
		// エラー有：true、エラー無：false
		boolean isErr = oBean.isOutMapList_2() ? true : false;
		
		if (isErr) {
			
			super.logPrint.printDebugLog("お客様情報エラーリスト エラー有=" + isErr);
			// ワーニング
			String msg = "お客様情報連携ファイルが、不整合です。";
			super.logPrint.printBusinessErrorLog(JPCBatchMessageConstant.ECHB1500KW, new String[] { msg });
		}
		super.logPrint.printDebugLog("お客様情報エラーリスト エラー無=" + isErr);
		super.logPrint.printDebugLog("isErr() end");
		return isErr;
	}
	
	/** 
	 * 
	 * エラー情報を業パラより取得し,返却する.
	 * 
	 * @return 
	 * @throws Exception
	 */
	private HashMap<String, String> getErrMap() throws Exception {
		
		JACbatParamUtil paramUtil   = new JACbatParamUtil(super.commonItem);
		HashMap<String, String> ret = new HashMap<String, String>();
		
		ret.put(this.ERR_01, paramUtil.getGyoumuParameter(this.ERR_01));				// 請求先番号エラー
		ret.put(this.ERR_02, paramUtil.getGyoumuParameter(this.ERR_02));				// 請求年月エラー
		ret.put(this.ERR_03, paramUtil.getGyoumuParameter(this.ERR_03));				// 支払区分エラー
		ret.put(this.ERR_04, paramUtil.getGyoumuParameter(this.ERR_04));				// 領収のみフラグエラー
		ret.put(this.ERR_05, paramUtil.getGyoumuParameter(this.ERR_05));				// 発送年月日エラー
		ret.put(this.ERR_06, paramUtil.getGyoumuParameter(this.ERR_06));				// 発送区分エラー

		// v13.00.01 ADD START
		paramUtil.close();
		// v13.00.01 ADD END
		
		return ret;
	}
	
	/** 
	 * 
	 * コード名称を取得し,Map化する.
	 * 
	 * @param  key
	 * @return 
	 * @throws Exception
	 */
	private Map<String, String> makeCdNmMap(String key) throws Exception {
		
		// コード名称管理情報取得
		JBSbatCommonDBInterface cdNmInfo = selectCdNmInfo(key);
		// 取得情報をマップ化する
		Map<String, String> ret = new HashMap<String, String>();
		
		while(cdNmInfo != null) {
			
			String cdDiv   = cdNmInfo.getString(JBSbatZM_M_CD_NM_KANRI.CD_DIV);			// コード区分
			String cdDivNm = cdNmInfo.getString(JBSbatZM_M_CD_NM_KANRI.CD_DIV_NM);		// コード区分名
			
			ret.put(cdDiv, cdDivNm);
			
			cdNmInfo = this.db_ZM_M_CD_NM_KANRI.selectNext();
		}
		
		return ret;
	}
	
	/** 
	 * 
	 * コード名称管理マスタより,コード区分とコード区分名を取得する.
	 * 
	 * @param  key
	 * @return 
	 * @throws Exception
	 */
	private JBSbatCommonDBInterface selectCdNmInfo(String key) throws Exception {
		
		// SQL実行
		executeZM_M_CD_NM_KANRI_CH_SELECT_008(new String[] {key, super.opeDate, super.opeDate});
		JBSbatCommonDBInterface ret = this.db_ZM_M_CD_NM_KANRI.selectNext();
		
		// 取得不可の場合,Throw
		if (ret == null) {
			
			String[] msgParam = new String[]
			{ JBSbatZM_M_CD_NM_KANRI.TABLE_NAME, new String[] {key, super.opeDate, super.opeDate}.toString() };
			
			throw new JBSbatBusinessException(JPCBatchMessageConstant.ECHB0270CH, msgParam);
		}
		
		return ret;
	}
	
	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**
	 * SQLKEY(CH_SELECT_008)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 * 
	 * 3.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 *		 	コード種別コード
	 *		 	適用開始年月日
	 *		 	適用終了年月日
	 * </pre>
	 * <p>
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeZM_M_CD_NM_KANRI_CH_SELECT_008(Object[] param) throws Exception
	{
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());
		paramList.setValue(param[2].toString());

		// DBアクセスを実行します
		this.db_ZM_M_CD_NM_KANRI.selectBySqlDefine(paramList, ZM_M_CD_NM_KANRI_CH_SELECT_008);
	}
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
}
