/*********************************************************************
*   All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JCHejbCH0101KRCK
*   ソースファイル名：JCHejbCH0101KRCK.java
*   作成者          ：富士通
*   日付            ：2011年09月14日
*＜機能概要＞
*   割引サービス対象契約の関連制約部品クラス
*＜修正履歴＞
*   バージョン  修正日      修正者      修正内容
*   v1.00.00    2011/09/14  富士通      新規作成
*	v5.00.00    2013/08/27  FJ) 林     【IT1-2013-0001612】請求取消仕様変更。料金変更登録時の債権存在チェックを変更。
*	v5.00.01    2013/09/17  FJ) 林     【随時-13-5005】料金変更一括変更時、請求存在チェックでステータスエラー判定を実施しないよう変更。
*	v5.00.02    2013/10/21  FJ) 林     【OM-2013-0003447】債権存在チェック時に債権ステータスを保持するよう修正。
*	v5.00.03    2013/10/23  FJ) 林     【OM-2013-0002749】請求存在チェック時に請求依頼年月日を保持するよう修正。
*	v5.00.04    2013/10/25  FJ) 林     【OM-2013-0003660】料金変更で債権ステータスがリアル収納/仮収納の時もエラーとする。
*	v5.00.05    2013/11/01  FJ)小野    【OM-2013-0003539】請求内訳の存在チェックを追加。
*	v8.00.00    2014/02/19  FJ)小野    【ANK-1589-00-00】 消費税に伴う料金施策（増税対応）。
*	v8.00.01	2014/04/25	FJ) 林     【OM-2014-0001671】会社別合計内訳マイナス金額チェック削除対応
*	v8.00.02	2014/06/09	FJ) 中井   【OM-2014-0001815】前受金取り消したら料金再調整でABEND
*	v9.00.00	2014/05/08	FJ) 林     【ANK-2054-00-00】スマートリンク端末補償対応
*	v10.00.00	2014/09/24	FJ) 古田   【OM-2014-0002987】料金変更時の債権ステータスチェック対応
*	v12.00.00	2015/02/13	FJ) 川島   【OM-2015-0000053】工事遅延分存在チェック追加
**********************************************************************/

package eo.ejb.common.entity;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.fujitsu.futurity.model.base.CAANConnectionMgr;
import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.JSYejbConnection;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.constant.JACStrConst;
import eo.common.util.JPCDateUtil;
import eo.ejb.cbm.entity.CH0101ETMsg;
import eo.ejb.cbm.entity.CH0101LE;
import eo.ejb.cbm.entity.CH0501ETMsg;
import eo.ejb.cbs.cbsmsg.ECH0051D011CBSMsg;
import eo.ejb.cbs.cbsmsg.ECH0051D012CBSMsg;
import eo.ejb.cbs.cbsmsg.ECH0051D012CBSMsg1List;
import eo.ejb.common.JCHModelCommon;
import eo.ejb.common.JCHSeikyUtil;
import eo.ejb.common.JPCModelCommon;
import eo.ejb.common.db.JCHejbCH0101DBABase;
import eo.ejb.common.db.JCHejbCH0101SecProc;

/**
 * <p>
 * 請求内訳の関連制約部品クラスです。
 * </p>
 * @author 富士通
 */
public class JCHejbCH0101KRCK extends JCHejbCH0101DBABase
{
	/**
	 * <p>
	 * 新しいJCHejbCH0101KRCKを作成します。
	 * </p>
	 */
	public JCHejbCH0101KRCK()
	{
		super();
	}

	/**
	 * <p>
	 * 請求契約（カレント）存在チェック。
	 * 存在すればtrue、存在しなければfalseを返す。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param inList 処理対象のリスト
	 * @return 存在すればtrue、存在しなければfalseを返す。
	 */
	public static boolean isPrcAdjCheck001(CAANMsg inCBSMsg, AgentDispatchContext inContext, String seikyKeiNo){

		CAANMsg retMsg = JCHModelCommon.getSeikyKeiCurrent(inCBSMsg, inContext, seikyKeiNo);

		if (retMsg == null)
		{
			return false;
		}
		return true;
	}

	/**
	 * <p>
	 * 請求存在チェック。
	 * 存在すればtrue、存在しなければfalseを返す。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param seikyYm 請求年月
	 * @param seikyNo 請求番号
	 * @return 配列の1番目の要素にエラーコード、配列の2番目の要素に更新年月日時分秒を設定し返す。
	 */
	public static String[] isPrcAdjCheck002(CAANMsg inCBSMsg, AgentDispatchContext inContext, String seikyYm, String seikyNo)
	{
		CAANMsg[] retMsg = JCHModelCommon.getSeikyUnique(inCBSMsg, inContext, seikyYm, seikyNo);

		// 返却用配列
		String[] retCode = new String[2];

		// 請求が存在しない場合
		if (retMsg.length < 1)
		{
			retCode[0] = "EB";
			return retCode;
		}

		String sSeikyStat = retMsg[0].getString("SEIKY_STAT");
		if ("ECH0101D011".equals(inCBSMsg.getString("templateID")))
		{
			if (!JACStrConst.SEIKY_STAT_KR_CALC.equals(sSeikyStat) && !JACStrConst.SEIKY_STAT_KR_FIX.equals(sSeikyStat))
			{
				// 料金調整の場合、請求ステータスが「仮計算中」「仮確定」以外であればエラー
				retCode[0] = "EJ";
				return retCode;
			}
		}
		else
		{
			if (!"4".equals(inCBSMsg.getObject("func_code").toString()))
			{
				if(JACStrConst.SEIKY_STAT_KR_CALC.equals(sSeikyStat)|| JACStrConst.SEIKY_STAT_KR_FIX.equals(sSeikyStat))
				{
					// 料金変更の場合、請求ステータスが「仮計算中」「仮確定」であればエラー
					retCode[0] = "EJ";
					return retCode;
				}
			}
		}
		
		// 請求依頼年月日を保持
		inCBSMsg.setPrivate("SEIKY_REQ_YMD", retMsg[0].getString("SEIKY_REQ_YMD"));
		
		// 更新年月日時分秒を設定
		retCode[0] = null;
		retCode[1] = retMsg[0].getString("UPD_DTM");
		return retCode;
	}

	/**
	 * <p>
	 * 債権存在チェック。
	 * 存在すればtrue、存在しなければfalseを返す。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param seikyYm 請求年月
	 * @param saikenNo 債権番号
	 * @return 配列の1番目の要素にエラーコード、配列の2番目の要素に更新年月日時分秒を設定し返す。
	 */
	public static String[] isPrcAdjCheck003(CAANMsg inCBSMsg, AgentDispatchContext inContext, String seikyYm, String saikenNo)
	{
		CAANMsg[] retMsg = JCHModelCommon.getSaikenUnique(inCBSMsg, inContext, seikyYm, saikenNo);

		// 返却用配列
		String[] retCode = new String[2];

		// 債権が存在しない場合
		if (retMsg.length < 1)
		{
			retCode[0] = "EC";
			return retCode;
		}

		String saikenStat = retMsg[0].getString("SAIKEN_STAT");
		String jutoFinYmd = retMsg[0].getString("JUTO_FIN_YMD");
		
		if ("ECH0101D012".equals(inCBSMsg.getString("templateID")))
		{
			// 料金変更では以下の場合エラー
			/* ++++++++++ v10.00.00 変更開始 ++++++++++ */
			//  ・債権ステータスがリアル収納(030)
			//  ・債権ステータスが仮収納(040)
			//  ・債権ステータスが収納済(050)かつ充当完了年月日が空でない、
			//  ・債権ステータスが一部収納(060)
//			if (JACStrConst.SAIKEN_STAT_REAL_KAKNO.equals(saikenStat)
//					|| JACStrConst.SAIKEN_STAT_KARI_KAKNO.equals(saikenStat)
//					||(JACStrConst.SAIKEN_STAT_KAKNO_ZUMI.equals(saikenStat) && jutoFinYmd!= null) 
//					|| JACStrConst.SAIKEN_STAT_ICHIBU_KAKNO.equals(saikenStat))
//			{
			//  ・債権ステータスがリアル収納(030)
			//  ・債権ステータスが仮収納(040)
			//  ・債権ステータスが収納済(050)かつ充当完了年月日が空でない、
			//  ・債権ステータスが一部収納(060)
			//  ・債権ステータスが貸倒登録済(080)
			//  ・債権ステータスが債権取消(090)
			if (JACStrConst.SAIKEN_STAT_REAL_KAKNO.equals(saikenStat)
					|| JACStrConst.SAIKEN_STAT_KARI_KAKNO.equals(saikenStat)
					||(JACStrConst.SAIKEN_STAT_KAKNO_ZUMI.equals(saikenStat) && jutoFinYmd!= null) 
					|| JACStrConst.SAIKEN_STAT_ICHIBU_KAKNO.equals(saikenStat)
					|| JACStrConst.SAIKEN_STAT_KASHID_ADD.equals(saikenStat)
					|| JACStrConst.SAIKEN_STAT_CL.equals(saikenStat))
			{
			/* ++++++++++ v10.00.00 変更完了 ++++++++++ */

				retCode[0] = "EK";
				return retCode;
			}
		}

		// 債権ステータスを保持
		inCBSMsg.setPrivate("SAIKEN_STAT", saikenStat);
		
		// 更新年月日時分秒を設定
		retCode[0] = null;
		retCode[1] = retMsg[0].getString("UPD_DTM");
		return retCode;
	}

	/**
	 * <p>
	 * サービス契約（カレント）存在チェック。
	 * 未入居明細用サービス契約番号の場合はチェック対象外とする。
	 * チェック対象のリストのうち、全て存在すればtrue、1件でも存在しなければfalseを返す。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param inList 処理対象のリスト
	 * @return チェック対象のリストのうち、全て存在すればtrue、1件でも存在しなければfalseを返す。
	 */
	public static boolean isPrcAdjCheck004(CAANMsg inCBSMsg, AgentDispatchContext inContext, CAANMsg[] inList)
	{
		return JCHModelCommon.isExistsSvcKeiCurrent2(inCBSMsg, inContext, inList);
	}

	/**
	 * <p>
	 * 請求先単位合計額マイナス額チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param alPrcShukResltList 料金集計結果
	 * @return 請求先単位合計額が1以上の場合、true、0以下の場合、falseを返す。
	 */
	public static boolean isPrcAdjCheck005(CAANMsg inCBSMsg, AgentDispatchContext inContext, ArrayList<CAANMsg> alPrcShukResltList){

		// 料金項目抽出変換を取得（単一）
		CAANMsg[] prcKmkCsChge = JCHModelCommon.getPrcKmkCsChge(inCBSMsg, inContext, false, JACStrConst.WKPARA_CH_WKS_SEIKY_TANI_GK);

		String sPrcKmkCd = prcKmkCsChge[0].getString("PRC_KMK_CD");

		// 一覧から請求先単位の前受金充当額を取得する。
		for (CAANMsg iDMsg : alPrcShukResltList){

			// 料金項目コードの判定
			String sPrcKmkCd_Seiky = iDMsg.getString(JACStrConst.KEY_PRC_SHUK_PRC_KMK_CD);

			// 料金項目コードが同値の明細の調整後金額を判定する。
			if (sPrcKmkCd_Seiky.equals(sPrcKmkCd))
			{
				// 調整後金額を取得する。
				String sAjstAfAmnt = iDMsg.getString(JACStrConst.KEY_PRC_SHUK_AMNT);

				if (sAjstAfAmnt == null || sAjstAfAmnt.length() == 0)
				{
					// 調整後料金が設定されていない場合次明細の処理を行う。
					continue;
				}

				// マイナス金額か判定する。
				BigDecimal bdAjstAfAmnt = new BigDecimal(sAjstAfAmnt);
				BigDecimal Zero = new BigDecimal(0);
				if (bdAjstAfAmnt.compareTo(Zero) < 0)
				{
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * <p>
	 * 請求取消チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param inList 処理対象のリスト
	 * @return 前受金充当の明細が存在する場合、falseを返す。
	 */
	public static boolean isPrcAdjCheck009(CAANMsg inCBSMsg, AgentDispatchContext inContext, CAANMsg[] inList){

		for (CAANMsg msg : inList)
		{
			// すべての明細が削除か判定する。
			if (msg.getString(JACStrConst.ECH0101CBSMSG1LIST_AJST_DIV) != null) {
				if (!"03".equals(msg.getString(JACStrConst.ECH0101CBSMSG1LIST_AJST_DIV)))
				{
					// 削除以外が存在した場合、処理終了
					return true;
				}
			}
		}

		// 料金項目抽出変換を取得（単一）
		CAANMsg[] prcKmkCsChge = JCHModelCommon.getPrcKmkCsChge(inCBSMsg, inContext, false, JACStrConst.WKPRA_CH_WKS_MAEUK_JT_SIKY);

		// 前受金充当の明細が存在するか判定する。
		for (CAANMsg msg : inList)
		{
			// 明細の料金項目コードを取得する。
			String sPrcKmkCd_Meisai = msg.getString(JACStrConst.ECH0101CBSMSG1LIST_PRC_KMK_CD);

			if (sPrcKmkCd_Meisai.equals(prcKmkCsChge[0].getString("prc_kmk_cd")))
			{
				// 料金項目コードが同一の場合エラー
				return false;
			}
		}

		return true;
	}

	/**
	 * <p>
	 * 請求情報排他チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param lastUpdtime チェック時点で取得した更新年月日時分秒
	 * @return 更新年月日時分秒が異なる場合、falseを返す。
	 */
	public static boolean isPrcAdjCheck010(CAANMsg inCBSMsg, AgentDispatchContext inContext, String lastUpdtime){

		// 更新前請求更新年月日時分秒
		String sSeikyUpdDTMAF = inCBSMsg.getString(JACStrConst.ECH0101CBSMSG_SEIKY_UPD_DTM_AF);

		if (!sSeikyUpdDTMAF.equals(lastUpdtime))
		{
			return false;
		}
		return true;
	}

	/**
	 * <p>
	 * 債権情報排他チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param lastUpdtime チェック時点で取得した更新年月日時分秒
	 * @return 更新年月日時分秒が異なる場合、falseを返す。
	 */
	public static boolean isPrcAdjCheck011(CAANMsg inCBSMsg, AgentDispatchContext inContext, String lastUpdtime){

		// 更新前債権更新年月日時分秒
		String sSaikenUpdDTMAF = inCBSMsg.getString(JACStrConst.ECH0101CBSMSG_SAIKEN_UPD_DTM_AF);

		if (!sSaikenUpdDTMAF.equals(lastUpdtime))
		{
			return false;
		}
		return true;
	}

	/**
	 * <p>
	 * 機器製造番号チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param listName リスト名
	 * @param targetDay 処理対象日付
	 * @return チェック対象のリストのうち、全てOKであればtrue、1件でもNGであればfalseを返す。
	 */
	public static boolean isPrcAdjCheck012(CAANMsg inCBSMsg, AgentDispatchContext inContext, String listName, String targetDay)
	{
		return JCHModelCommon.isExistsKikiTkSvcKei(inCBSMsg, inContext, listName, targetDay);
	}

	/**
	 * <p>
	 * 前受金充当額訂正期間チェック。
	 * </p>
	 * @param inCBSMsg  処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param sSeikyYm  請求年月
	 * @param inList1   料金明細リスト
	 * @return 前受金充当額訂正可能な期間でなければfalseを返します。
	 */
	public static boolean isPrcAdjCheck013(CAANMsg inCBSMsg, AgentDispatchContext inContext, String sSeikyYm, CAANMsg[] inList1){
		return JCHModelCommon.isPrcAdjKikan(inCBSMsg, inContext, sSeikyYm, inList1);
	}

	/**
	 * <p>
	 * サービス契約（カレント）存在チェック。
	 * チェック対象のリストのうち、全て存在すればtrue、1件でも存在しなければfalseを返す。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param inList 処理対象のリスト
	 * @return チェック対象のリストのうち、全て存在すればtrue、1件でも存在しなければfalseを返す。
	 */
	public static boolean isZuijiSeiCheck000(CAANMsg inCBSMsg, AgentDispatchContext inContext, ArrayList<CAANMsg> inList)
	{
		return JCHModelCommon.isExistsSvcKeiCurrent(inCBSMsg, inContext, inList);
	}

	/**
	 * <p>
	 * 請求先単位合計額マイナス額チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param sAmnt 請求先単位合計額
	 * @return 請求先単位合計額が1以上の場合、true、0以下の場合、falseを返す。
	 */
	public static boolean isZuijiSeiCheck001(CAANMsg inCBSMsg, AgentDispatchContext inContext, String sAmnt)
	{
		if (sAmnt == null
				|| sAmnt.trim().length() == 0){
			return false;
		}

		BigDecimal bdAmnt = new BigDecimal(sAmnt);

		// 金額がマイナスの場合はエラー
		if (bdAmnt.compareTo(new BigDecimal(0)) <= 0)
		{
			return false;
		}

		return true;
	}

	/**
	 * <p>
	 * 請求先単位合計額、入金額同値チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param sAmnt 請求先単位合計額
	 * @param sNyukinAmnt 入金額
	 * @return 請求先単位合計額と入金額が同値の場合、true、異なる場合、falseを返す。
	 */
	public static boolean isZuijiSeiCheck003(CAANMsg inCBSMsg, AgentDispatchContext inContext, String sAmnt, String sNyukinAmnt)
	{
		BigDecimal bdSeikyAmnt = new BigDecimal(sAmnt);
		BigDecimal bdNyukinAmnt = new BigDecimal(sNyukinAmnt);

		if (bdSeikyAmnt.compareTo(bdNyukinAmnt) == 0){
			// 同値の場合、チェックＯＫ
			return true;
		}

		return false;
	}

	/**
	 * <p>
	 * 随時請求登録時に入金額が預り金を超えているかチェックを行う。
	 * </p>
	 * @param inNyuKinAmnt 入金額
	 * @param inAzukariAmnt 預り金
	 * @return 入金額が預り金より小さい場合：true
	 * 			入金額が預り金より大き場合：false
	 */
	public static boolean isZuijiSeiCheck004(String inNyuKinAmnt, String inAzukariAmnt)
	{
		// 入金額が預り金を超えているかチェックを行う。
		BigDecimal bdNyuKinAmnt = new BigDecimal(inNyuKinAmnt);
		BigDecimal bdAzukariAmnt = new BigDecimal(inAzukariAmnt);
		
		if(bdNyuKinAmnt.compareTo(bdAzukariAmnt) > 0){
			// 入金額が預り金より大きい場合、チェックＮＧ
			return false;
		}
		return true;
	}

	/**
	 * <p>
	 * 機器製造番号チェック。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param targetDay 処理対象日付
	 * @return チェック対象のリストのうち、全てOKであればtrue、1件でもNGであればfalseを返す。
	 */
	public static boolean isZuijiSeiCheck005(CAANMsg inCBSMsg, AgentDispatchContext inContext, String targetDay)
	{
		return JCHModelCommon.isExistsKikiTkSvcKei(inCBSMsg, inContext, ECH0051D011CBSMsg.ECH0051D011CBSMSG1LIST, targetDay);
	}

	/**
	 * <p>
	 * 請求先単位合計額取得処理。
	 * 処理対象リストの中から請求先単位合計額を取得し文字列で返す。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param inList 処理対象のリスト
	 * @param itemNm 金額キー項目名
	 * @return 請求先単位合計額
	 */
	public static String getSeikyGokei(CAANMsg inCBSMsg, AgentDispatchContext inContext, ArrayList<CAANMsg> inList, String itemNm)
	{
		// 料金項目抽出変換を取得（単一）
		CAANMsg[] prcKmkCsChge = JCHModelCommon.getPrcKmkCsChge(inCBSMsg, inContext, false, JACStrConst.WKPARA_CH_WKS_SEIKY_TANI_GK);

		// 金額
		String sAmnt = null;

		String sPrcGrpCd = prcKmkCsChge[0].getString("PRC_GRP_CD");
		String sPcrsCd = prcKmkCsChge[0].getString("PCRS_CD");
		String sPrcSvcCd = prcKmkCsChge[0].getString("PRC_SVC_CD");
		String sPrcKmkCd = prcKmkCsChge[0].getString("PRC_KMK_CD");

		// 処理対象リストの中からチェック対象の料金項目コードに該当するものを取得
		for (CAANMsg inMsg : inList){

			if (sPrcGrpCd.equals(inMsg.getString("prc_grp_cd"))
					&& sPcrsCd.equals(inMsg.getString("pcrs_cd"))
					&& sPrcSvcCd.equals(inMsg.getString("prc_svc_cd"))
					&& sPrcKmkCd.equals(inMsg.getString("prc_kmk_cd")))
			{
				sAmnt = inMsg.getString(itemNm);
				return sAmnt;
			}
		}

		return sAmnt;

	}

	/**
	 * <p>
	 * 請求内訳存在チェック処理
	 * </p>
	 * 指定された請求内訳が存在するかチェックを行う。
	 * <br>
	 * @param inMsg 処理対象のメッセージ
	 * @param inContext エージェントディスパッチコンテキスト
	 * @return 存在有無 true：存在する、false：存在しない
	 * @throws CAANException 
	 */
	public static boolean isExistSeikyUcwk(CAANMsg inMsg, AgentDispatchContext inContext)
	{
		// 作成する請求に必要な料金項目コードを取得する（取得件数が1件であると業務的に保障される場合のみ）
		// 請求額合計				[00900900601]
		// 請求額					[00900940601]
		String[] workParamId1 = {
								JACStrConst.WKPARA_CH_WKS_SEIKY_TANI_GK,
								JACStrConst.WKPRA_CH_WKS_GSN_SKY_TG_MI
								};

		// 作成する請求に必要な料金項目コードを取得する（取得件数が複数件になる場合）
		// 債権額うち消費税			[00900910201][10900910201]
		String[] workParamId2 = {
								JACStrConst.WKPRA_CH_WKS_SAIKEN_U_STAX
								};

		try
		{
			JCHejbCH0101SecProc ch101SecPrc = new JCHejbCH0101SecProc();
			List<HashMap<String, String>> prcKmkList1 = ch101SecPrc.getPrcKmkCsChge(inMsg, inContext, workParamId1, false);

			List<HashMap<String, String>> prcKmkList2 = ch101SecPrc.getPrcKmkCsChge(inMsg, inContext, workParamId2, true);

			// すべての請求内訳リストの中に以下のどちらも必ず存在しなければならない
			// 請求額合計				[00900900601]
			// 請求額					[00900940601]
			for (int i = 0; i < prcKmkList1.size(); i++)
			{
				HashMap<String, String> prcKmk = prcKmkList1.get(i);

				CAANMsg[] msgCH0051List = inMsg.getCAANMsgList(ECH0051D012CBSMsg.ECH0051D012CBSMSG1LIST);
				for (int j = 0; msgCH0051List.length > j; j++)
				{
					String inSeikyYm = msgCH0051List[j].getString(ECH0051D012CBSMsg1List.SEIKY_YM);
					String inSeikyNo = msgCH0051List[j].getString(ECH0051D012CBSMsg1List.SEIKY_NO);

					// 検索条件設定
					CAANMsg seikyUcwkKey = new CAANMsg(CH0101ETMsg.class.getName());
					seikyUcwkKey.set(CH0101ETMsg.SEIKY_YM, inSeikyYm);
					seikyUcwkKey.set(CH0101ETMsg.SEIKY_NO, inSeikyNo);
					seikyUcwkKey.set(CH0101ETMsg.PRC_KMK_CD, prcKmk.get("PRC_KMK_CD"));
					seikyUcwkKey.set(CH0101ETMsg.MK_FLG, JACStrConst.MK_FLG_YK);

					// 請求内訳取得
					CH0101LE le = new CH0101LE();

					CAANMsg[] ret = le.findByCondition(seikyUcwkKey);

					// 請求内訳が存在しない場合、falseを返す。
					if (ret.length == 0)
					{
						return false;
					}
				}
			}

			// すべての請求内訳リストの中で以下のどちらかが存在すればよい
			// 債権額うち消費税			[00900910201][10900910201]
			CAANMsg[] msgCH0051List = inMsg.getCAANMsgList(ECH0051D012CBSMsg.ECH0051D012CBSMSG1LIST);
			for (int j = 0; msgCH0051List.length > j; j++)
			{
				String inSeikyYm = msgCH0051List[j].getString(ECH0051D012CBSMsg1List.SEIKY_YM);
				String inSeikyNo = msgCH0051List[j].getString(ECH0051D012CBSMsg1List.SEIKY_NO);

				boolean existsFlg = false;

				// 検索条件設定
				for (int i = 0; i < prcKmkList2.size(); i++)
				{
					HashMap<String, String> prcKmk = prcKmkList2.get(i);

					CAANMsg seikyUcwkKey = new CAANMsg(CH0101ETMsg.class.getName());
					seikyUcwkKey.set(CH0101ETMsg.SEIKY_YM, inSeikyYm);
					seikyUcwkKey.set(CH0101ETMsg.SEIKY_NO, inSeikyNo);
					seikyUcwkKey.set(CH0101ETMsg.PRC_KMK_CD, prcKmk.get("PRC_KMK_CD"));
					seikyUcwkKey.set(CH0101ETMsg.MK_FLG, JACStrConst.MK_FLG_YK);

					// 請求内訳取得
					CH0101LE le = new CH0101LE();

					CAANMsg[] ret = le.findByCondition(seikyUcwkKey);

					// 請求内訳が存在する場合、trueをセット。
					if (ret.length > 0)
					{
						existsFlg = true;
						break;
					}
				}

				if (!existsFlg)
				{
					return false;
				}
			}

			return true;

		} catch (CAANException e) {
			return false;
		}

	}
	
	/**
	 * 工事遅延分存在チェック処理
	 * @param inMsg 処理メッセージ
	 * @param inContext ディスパッチコンテキスト
	 * @param seikyNo 請求番号
	 * @param seikyKeiNo 請求契約番号
	 * @param seikyYm 請求年月
	 * @return 正常：true、異常：false
	 */
	public static boolean isExistKojiDly(CAANMsg inMsg, AgentDispatchContext inContext, String seikyNo, String seikyKeiNo, String seikyYm)
	{
		// 運用日付
		String opeDate = String.valueOf(JPCModelCommon.getOpeDate(inMsg, inContext, null));
		
		// 料金計算日翌日
		CAANMsg ch0501 = JCHModelCommon.getEventYmd(inMsg, seikyYm, JACStrConst.EVENT_CD_PRC_CALC_DAY);
		String prcCalcDay = ch0501.getString(CH0501ETMsg.EVENT_YMD);
		String prcCalcNextDay = JPCDateUtil.addDay(prcCalcDay, 1);
		
		// 請求処理日
		ch0501 = JCHModelCommon.getEventYmd(inMsg, seikyYm, JACStrConst.EVENT_CD_SIKY_TRN_DAY);
		String sikyTrnDay = ch0501.getString(CH0501ETMsg.EVENT_YMD);
		
		// 料金計算日翌日 ≦ 運用日付 ≦ 請求処理日の場合、正常を返却
		if(opeDate.compareTo(prcCalcNextDay) >= 0 && opeDate.compareTo(sikyTrnDay) <= 0)
		{
			return true;
		}
		
		// 工事遅延分の請求を取得
		// コネクション
		Connection con1 = null;
		// プリペアステートメント
		PreparedStatement pstmt = null;
		// リザルトセット
		ResultSet rsltQuery = null;
		// 検索結果リスト
		ArrayList<String> resultList = new ArrayList<String>();
		
		try{
			
			//コネクション取得
			con1 = JSYejbConnection.getConnection(CH0101ETMsg.getTableName());
			
			// SQL文_基本部1
			StringBuffer sql_Buff = new StringBuffer();
			sql_Buff.append("SELECT CH0101.PRC_KMK_CD")						// 料金項目コード
					.append(" FROM CH_T_SEIKY_UCWK CH0101")					// 請求内訳
					.append(" WHERE CH0101.SEIKY_NO = ?")					// 請求番号 ... (1)
					.append(" AND CH0101.SEIKY_KEI_NO = ?")					// 請求契約番号 ... (2)
					.append(" AND CH0101.SEIKY_YM = ?")						// 請求年月 ... (3)
					.append(" AND CH0101.SEIKY_YM <> CH0101.GSAN_SEIKY_YM")	// 工事遅延分判定
					.append(" AND CH0101.MK_FLG = '0'")
					.append(" AND EXISTS (")
					.append("  SELECT 1")
					.append("  FROM CH_M_PRC_KMK_CS_CHGE CH0401")			// 料金項目抽出変換
					.append("  WHERE CH0401.PRC_GRP_CD = CH0101.PRC_GRP_CD")
					.append("  AND CH0401.PCRS_CD = CH0101.PCRS_CD")
					.append("  AND CH0401.PRC_SVC_CD = CH0101.PRC_SVC_CD")
					.append("  AND CH0401.PRC_KMK_CD = CH0101.PRC_KMK_CD")
					.append("  AND CH0401.SYS_CD = 'CH'")					// 請求収納
					.append("  AND CH0401.WORK_KINO_SKBT_CD = 'ADJ_U_DSP'")	// 料金変更・調整可能
					.append("  AND CH0401.CHSHT_CHG_CD = '1'")				// 抽出のみ
					.append("  AND CH0401.PRC_KMK_CS_CHGE_TSTAYMD <= ?")	// 運用日付 ... (4)
					.append("  AND CH0401.PRC_KMK_CS_CHGE_TENDYMD >= ?")	// 運用日付 ... (5)
					.append("  AND CH0401.MK_FLG = '0'")
					.append(" )")
					.append(" AND EXISTS (")
					.append("  SELECT 1")
					.append("  FROM CH_M_PRC_KMK_CS_CHGE CH0401")			// 料金項目抽出変換
					.append("  WHERE CH0401.PRC_GRP_CD = CH0101.PRC_GRP_CD")
					.append("  AND CH0401.PCRS_CD = CH0101.PCRS_CD")
					.append("  AND CH0401.PRC_SVC_CD = CH0101.PRC_SVC_CD")
					.append("  AND CH0401.PRC_KMK_CD = CH0101.PRC_KMK_CD")
					.append("  AND CH0401.SYS_CD = 'CH'")					// 請求収納
					.append("  AND CH0401.WORK_KINO_SKBT_CD = 'TEISE_PSB'")	// 訂正可能
					.append("  AND CH0401.CHSHT_CHG_CD = '1'")				// 抽出のみ
					.append("  AND CH0401.PRC_KMK_CS_CHGE_TSTAYMD <= ?")	// 運用日付 ... (6)
					.append("  AND CH0401.PRC_KMK_CS_CHGE_TENDYMD >= ?")	// 運用日付 ... (7)
					.append("  AND CH0401.MK_FLG = '0'")
					.append(" )");
			
			pstmt = con1.prepareStatement(sql_Buff.toString());
			
			//ログ出力(SQL文の出力)
			JSYejbLog.outlog(inContext, JSYejbLog.DBACCESS, JCHSeikyUtil.class, sql_Buff);
			
			// パラメータの設定
			int i = 0;
			CAANJDBCUtil.setParam(pstmt, ++i, seikyNo);		// (1)
			CAANJDBCUtil.setParam(pstmt, ++i, seikyKeiNo);	// (2)
			CAANJDBCUtil.setParam(pstmt, ++i, seikyYm);		// (3)
			CAANJDBCUtil.setParam(pstmt, ++i, opeDate);		// (4)
			CAANJDBCUtil.setParam(pstmt, ++i, opeDate);		// (5)
			CAANJDBCUtil.setParam(pstmt, ++i, opeDate);		// (6)
			CAANJDBCUtil.setParam(pstmt, ++i, opeDate);		// (7)
			
			// ResultSetの取得
			rsltQuery = pstmt.executeQuery();
			
			String prcKmkCd = null;
			while (rsltQuery.next())
			{
				prcKmkCd = rsltQuery.getString(CH0101ETMsg.PRC_KMK_CD);
				
				// 値が未設定の場合は設定しない
				if(null == prcKmkCd || 0 == prcKmkCd.length())
				{
					continue;
				}
				
				resultList.add(prcKmkCd);
			}
			
		} catch(SQLException e) {
			inMsg.set(CH0101ETMsg.STATUS, StatusCodes.FIND_DB_ERR);
			throw new CAANRuntimeException(e);
		} finally {
			// 資源の解放
			try{
				if(rsltQuery != null){
					rsltQuery.close();
				}
				if(pstmt != null){
					pstmt.close();
				}
				if(con1 != null){
					CAANConnectionMgr.getInstance().close(con1);
				}
			}catch(SQLException e){
				inMsg.set(CH0101ETMsg.STATUS, StatusCodes.FIND_DB_ERR);
				throw new CAANRuntimeException(e);
			}
		}
		
		for(String prckmkCd : resultList)
		{
			// ３桁目から５桁目が900(請求収納)以外は工事遅延分なので異常を返却
			if(!JACStrConst.PRC_KMK_CD_BUNRUI_SIKY_SHUNO.equals(prckmkCd.substring(2, 5)))
			{
				return false;
			}
		}
		
		// 工事遅延分が存在しないため、正常を返却
		return true;
	}

}
