/*********************************************************************
 *  All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *	システム名			：eo顧客基幹システム
 *	モジュール名		：JBSbatCHKsdTrgtsUcwkKshkm
 *	ソースファイル名	：JBSbatCHKsdTrgtsUcwkKshkm.java
 *	作成者				：富士通　
 *	作成日				：2023年10月25日
 *＜機能概要＞
 *　貸倒れ対象者内訳消込部品です。
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	v68.00.00   2023/10/25  FJ)森脇		【ANK-4475-00-00】インボイス対応 STEP2
 *********************************************************************/
package eo.business.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.common.JBSbatMatchServiceInterface;
import eo.business.util.file.JBSbatCHIFM441;
import eo.common.constant.JACStrConst;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatServiceInterfaceMap;

/**
 * (クラスの機能概要)
 * <p>
 *<BR>
 * 
 * @author 富士通
 */
public class JBSbatCHKsdTrgtsUcwkKshkm extends JBSbatBusinessService implements JBSbatMatchServiceInterface
{
	/** ▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼ */
	/** キーマッチ処理フラグ */
	private boolean matchProcFlg;

	/** マスタファイル処理フラグ */
	private boolean mastProcFlg;

	/** トランファイル処理フラグ */
	private boolean tranProcFlg;
	/** ▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲ */

	/** free項目 */
	private String[] freeItems = null;

	/** 料金項目情報制御フラグ */
	private String prcKmkInfCtrlFlg = JACStrConst.KARA_MOJI;

	/** 減額残 **/
	private BigDecimal mastAmntZan = BigDecimal.ZERO;

	/** 減額残初期化フラグ **/
	private boolean mastAmntZanInitFlg = false;

	/** 引代残 **/
	private BigDecimal tranAmntZan = BigDecimal.ZERO;

	/** 引代残初期化フラグ **/
	private boolean tranAmntZanInitFlg = false;

	/** マスタレコード保持用 **/
	private JBSbatServiceInterfaceMap mastMapTemp = new JBSbatServiceInterfaceMap();
	
	/** トランレコード保持用 **/
	private JBSbatServiceInterfaceMap tranMapTemp = new JBSbatServiceInterfaceMap();

	/**
	 * 初期処理
	 * 
	 * @param JBSbatCommonItem commonItem バッチ共通パラメータ電文
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
		/** ▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼ */
		/** ▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼ */
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][initial]");
		/** ▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲ */

		// free項目を取得
		String freeItem = commonItem.getFreeItem();
		freeItems = freeItem.split(JACStrConst.FREE_DIV);
		
		// 料金項目情報制御フラグを取得
		prcKmkInfCtrlFlg = freeItems[0];

		// 減額残初期化フラグに true を設定
		mastAmntZanInitFlg = true;

		// 引代残初期化フラグに true を設定
		tranAmntZanInitFlg = true;

		/** ▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲ */
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][initial][opeDate=" + super.opeDate + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][initial][freeItem=" + super.freeItem + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][initial]");
	}

	/**
	 * 主処理
	 * 
	 * @param mastMap 入力電文
	 * @param tranMap 入力電文
	 * @param outputInItem 入力情報
	 * @return JBSbatOutputItem 出力情報
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap mastMap, JBSbatServiceInterfaceMap tranMap, JBSbatOutputItem outputInItem) throws Exception
	{
		/** ▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼ */
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute]");
		assert mastMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][mastMap=" + mastMap.getMap().toString() + "]") : true;
		assert tranMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][tranMap=" + tranMap.getMap().toString() + "]") : true;

		if (mastMap != null && tranMap == null)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍのみ存在する]");
			// 入力Ｍのみ存在する場合
			this.setMastProcFlg(true);

			// 減額残を初期化
			resetMastAmntZan(mastMap);

			// 出力情報生成
			makeOutPutMap(mastMap, outputInItem);
		}
		else if (mastMap == null && tranMap != null)
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｔのみ存在する]");
			// 入力Ｔのみ存在する場合
			this.setTranProcFlg(true);

			// 引代残を初期化
			resetTranAmntZan(tranMap);

			// 出力情報生成
			makeOutPutMap(tranMap, outputInItem);
		}
		else
		{
			// 入力Ｍ、入力Ｔともに存在する

			// 減額残を初期化
			resetMastAmntZan(mastMap);

			// 引代残を初期化
			resetTranAmntZan(tranMap);

			// マッチングキー（マスタ）を作成
			String mastKey = getMatchingKey(mastMap);

			// マッチングキー（トラン）を作成
			String tranKey = getMatchingKey(tranMap);

			mastMapTemp = mastMap;

			tranMapTemp = tranMap;

			if (mastKey.toString().compareTo(tranKey.toString()) == 0)
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍ、入力Ｔともに存在する][入力Ｍ＝入力Ｔ]");
				// 入力Ｍ = 入力Ｔ

				if (mastAmntZan.compareTo(BigDecimal.ZERO) > 0)
				{
					// 減額残がマイナスでない場合
					this.setMastProcFlg(true);

					// 出力情報生成
					makeOutPutMap(mastMapTemp, outputInItem);
				}
				else if (tranAmntZan.abs().compareTo(mastAmntZan.abs()) >= 0)
				{
					// 引き代が減額残より大きい場合
					this.setMastProcFlg(true);

					// 引代残に 引代残 - 減額残 を設定
					tranAmntZan = tranAmntZan.add(mastAmntZan);
					// 減額残に 0 を設定
					mastAmntZan = BigDecimal.ZERO;

					// 減額残初期化フラグに true を設定
					mastAmntZanInitFlg = true;
				}
				else
				{
					// 減額残が引き代より大きい場合
					this.setTranProcFlg(true);

					// 減額残に 減額残 - 引き代金額 を設定
					mastAmntZan = mastAmntZan.add(tranAmntZan);
					// 引代残に 0 を設定
					tranAmntZan = BigDecimal.ZERO;

					// 引代残初期化フラグに true を設定
					tranAmntZanInitFlg = true;
				}
			}
			else if (mastKey.toString().compareTo(tranKey.toString()) < 0)
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍ、入力Ｔともに存在する][入力Ｍ＜入力Ｔ]");
				// 入力Ｍ < 入力Ｔ
				this.setMastProcFlg(true);

				// 出力情報生成
				makeOutPutMap(mastMapTemp, outputInItem);
			}
			else
			{
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力Ｍ、入力Ｔともに存在する][入力Ｍ＞入力Ｔ]");
				// 入力Ｍ > 入力Ｔ
				this.setTranProcFlg(true);

				// 出力情報生成
				makeOutPutMap(tranMapTemp, outputInItem);
			}
		}
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][execute]");
		return outputInItem;
		/** ▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲ */
	}

	/**
	 * 業務サービス終了処理
	 * 
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	public void terminal() throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][terminal]");
		/** ▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼ */
		/** ▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼ */
		/** ▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲ */

		/** ▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲ */
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][terminal]");
	}

	/** ▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼ */
	/**
	 * @return mastProcFlg を戻します。
	 */
	public boolean isMastProcFlg()
	{
		return mastProcFlg;
	}

	/**
	 * @return matchProcFlg を戻します。
	 */
	public boolean isMatchProcFlg()
	{
		return matchProcFlg;
	}

	/**
	 * @return tranProcFlg を戻します。
	 */
	public boolean isTranProcFlg()
	{
		return tranProcFlg;
	}

	/**
	 * @param mast_ProcFlg 設定する mastProcFlg。
	 */
	public void setMastProcFlg(boolean mast_ProcFlg)
	{
		this.mastProcFlg = mast_ProcFlg;
	}

	/**
	 * @param match_ProcFlg 設定する matchProcFlg。
	 */
	public void setMatchProcFlg(boolean match_ProcFlg)
	{
		this.matchProcFlg = match_ProcFlg;
	}

	/**
	 * @param tran_ProcFlg 設定する tranProcFlg。
	 */
	public void setTranProcFlg(boolean tran_ProcFlg)
	{
		this.tranProcFlg = tran_ProcFlg;
	}

	/** ▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲ */

	/**
	 * 引数で渡された情報をもとにマッチング用のキーを作成し、返却します。
	 * 
	 * @param trgMap 対象情報
	 * @return String マッチングキー
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private String getMatchingKey(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		StringBuffer buf = new StringBuffer();

		// 請求契約番号
		buf.append(inMap.getString(JBSbatCHIFM441.SEIKY_KEI_NO));

		// 債権番号
		buf.append(inMap.getString(JBSbatCHIFM441.SAIKEN_NO));

		// 処理順
		String trnJun =String.format("%03d", new Integer(inMap.getInt(JBSbatCHIFM441.TRN_JUN)));
		buf.append(trnJun);

		// 不課税識別
		buf.append(inMap.getString(JBSbatCHIFM441.FUKAZEI_TAX_RT_SKBT));

		if ("1".equals(prcKmkInfCtrlFlg))
		{
			// 料金項目コード
			buf.append(inMap.getString(JBSbatCHIFM441.PRC_KMK_CD).substring(0, 8));
		}

		return buf.toString();
	}

	/**
	 * 出力データ編集
	 * 
	 * @param inMap 入力電文
	 * @param outputInItem 入力情報
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void makeOutPutMap(JBSbatServiceInterfaceMap inMap, JBSbatOutputItem outputInItem) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeOutPutMap]");

		JBSbatServiceInterfaceMap outputMap = new JBSbatServiceInterfaceMap();

		// 入力電文コピー
		outputMap.setMap(inMap.getMap());

		// 債権額
		if (isMastProcFlg())
		{
			// 入力Ｍ の場合
			outputMap.setBigDecimal(JBSbatCHIFM441.SAIKEN_AMNT, mastAmntZan);

			// 減額残初期化フラグに true を設定
			mastAmntZanInitFlg = true;
		}
		else if (isTranProcFlg())
		{
			// 入力Ｔ の場合
			outputMap.setBigDecimal(JBSbatCHIFM441.SAIKEN_AMNT, tranAmntZan);

			// 引代残初期化フラグに true を設定
			tranAmntZanInitFlg = true;
		}

		if (outputMap.getBigDecimal(JBSbatCHIFM441.SAIKEN_AMNT).compareTo(BigDecimal.ZERO) == 0)
		{
			// 金額が 0 の場合は出力対象外
			return;
		}

		// 出力フラグを設定
		outputMap.setOutFlg(true);

		// 出力共通電文に設定
		outputInItem.addOutMapList(outputMap);

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeOutPutMap]");
	}

	/**
	 * 減額残初期化
	 * 
	 * @param mastMap 入力電文
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void resetMastAmntZan(JBSbatServiceInterfaceMap mastMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][resetMastAmntZan]");

		if (mastAmntZanInitFlg)
		{
			// 減額残初期化フラグが true の場合

			// 減額残を初期化
			mastAmntZan = mastMap.getBigDecimal(JBSbatCHIFM441.SAIKEN_AMNT);
			// 減額残初期化フラグに false を設定
			mastAmntZanInitFlg = false;
		}

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][resetMastAmntZan]");
	}

	/**
	 * 引代残初期化
	 * 
	 * @param mastMap 入力電文
	 * @throws Exception 業務サービス内で発生した例外全般
	 */
	private void resetTranAmntZan(JBSbatServiceInterfaceMap tranMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][resetTranAmntZan]");

		if (tranAmntZanInitFlg)
		{
			// 引代残初期化フラグが true の場合

			// 引代残を初期化
			tranAmntZan = tranMap.getBigDecimal(JBSbatCHIFM441.SAIKEN_AMNT);
			// 引代残初期化フラグに false を設定
			tranAmntZanInitFlg = false;
		}

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][resetTranAmntZan]");
	}

}
