package mcframe.serverMSBC.MSBCZL010;

import mcframe.commonCore.lang.*;
import mcframe.commonCore.container.*;
import mcframe.commonCore.container.MCList.SortType;
import mcframe.commonCore.notice.*;
import mcframe.serverCore.logic.*;
import mcframe.serverCore.notice.MCMessagePool;
import mcframe.serverCore.queryapi.MCDBContainer;
import mcframe.serverCore.queryapi.MCQueryApiBuilder;
import static mcframe.serverCore.queryapi.IFMCSQL.*;
import mcframe.commonCore.annotation.EI;
import mcframe.commonCore.annotation.Rev;
import mcframe.commonCore.annotation.Rev.Pj;
import mcframe.commonCore.annotation.Rev.Cl;
import mcframe.commonMA.constant.*;
import mcframe.commonMAUC.MAUCC2010.MAUCC_RowMapperWith;
import mcframe.serverMA.dbc.*;
import mcframe.serverMB.dbc.*;
import mcframe.serverMS.dbc.*;
import mcframe.serverMAUC.MAUCL0060.ElmArgsR;
import static mcframe.commonMA.notice.MA_Msg.*;
import static mcframe.serverMAUC.MAUCL0010.MAUCL_MCDataUtil.*;
import static mcframe.serverMAUC.MAUCL0020.MAUCL_AppSys.*;
import static mcframe.serverMAUC.MAUCL7080.MAUCL_DbUtil.*;
import static mcframe.serverMAUC.MAUCL0030.MAUCL_Dac.*;
import static mcframe.serverMAUC.MAUCL0060.MAUCL_Num.*;
import mcframe.commonMB.constant.*;
import static mcframe.commonMB.notice.MB_Msg.*;
import static mcframe.serverMBUC.MBUCL0010.MBUCL_MCDataUtil.*;
import mcframe.commonMS.constant.*;
import static mcframe.commonMS.notice.MS_Msg.*;

import static mcframe.serverFXUC.FXUCL0160.FXUCL_DateUtil.*;
import static mcframe.serverFXUC.FXUCL0170.FXUCL_ValidaterUtil.*;
import mcframe.serverCore.queryapi.MCQueryExecution.MCQueryPlan;
import static mcframe.serverMA.dbc.MAFunction.*;
import static mcframe.serverMS.dbc.MSFunction.*;
import static mcframe.serverMA.dbc.MABCFunction.*;
import static mcframe.serverMA.dbc.MABGFunction.*;
import static mcframe.serverMA.dbc.MABSFunction.*;
import static mcframe.serverMB.dbc.MBBAFunction.*;
import static mcframe.serverMB.dbc.MBBBFunction.*;
import static mcframe.serverMB.dbc.MBBCFunction.*;
import static mcframe.serverMB.dbc.MBBEFunction.*;
import static mcframe.serverMS.dbc.MSBAFunction.*;
import static mcframe.serverMS.dbc.MSBBFunction.*;
import static mcframe.serverMS.dbc.MSBCFunction.*;
import static mcframe.serverMS.dbc.MSBDFunction.*;
import static mcframe.serverMS.dbc.MSBEFunction.*;
import static mcframe.serverMS.dbc.MSBFFunction.*;
import static mcframe.serverMS.dbc.MSBGFunction.*;
import static mcframe.serverMS.dbc.MSBHFunction.*;
import static mcframe.serverMS.dbc.MSBIFunction.*;

//FMCB IMPORT START
import java.util.HashMap;
import java.util.Map;
import mcframe.serverMSBC.MSBCZL010.*;	// このimportはFrameManagerの自動生成で追加されました。
import mcframe.serverMSBE.MSBEL5060.*;
import mcframe.serverFXUC.FXUCL0030.FXUCL_MCDbcCache;
import mcframe.serverFXUC.FXUCL0160.FXUCL_DateUtil;
import static mcframe.serverMAUC.MAUCL0140.MAUCL_DateUtil.*;
import mcframe.serverMSBC.MSBCL0010.*;
//FMCB IMPORT END

/**
 * "MSBCL_ProdPlnReg"ロジッククラスです。<p>
 *
 * 実装仕様書から自動生成されるクラスです。
 */
@EI
public class MSBCL_ProdPlnReg extends MSBCL_ProdPlnReg_MC {

//FMCB CUSTOM START
	/* 改　版　履　歴
	 * 
	 * DATE             Seq         Editor          Description
	 * =============    ========    ============    ============================
	 * 2025-06-30       r1.00       XB.ZHAO         PJ_TKN-350 【詳細・開発・単体】MSBCZP010_生産計画登録
	 * 
	 */
	
	public static String OPE_M = "1";				// 生産
	public static String OPE_P = "2";				// 購買
	
	protected static String[] rqmt_keys = {
			ChkZ01_Rslt2R.$itm_cd
			,ChkZ01_Rslt2R.$itm_sub1
			,ChkZ01_Rslt2R.$itm_sub2
			,ChkZ01_Rslt2R.$itm_sub3
			,ChkZ01_Rslt2R.$strg_loc_cd
			,ChkZ01_Rslt2R.$dt
		};
	
	protected static String[] mst_rqmt_keys = {
			MST_RQMT_R.$itm_cd
			,MST_RQMT_R.$itm_sub1
			,MST_RQMT_R.$itm_sub2
			,MST_RQMT_R.$itm_sub3
			,MST_RQMT_R.$strg_loc_cd
			,MST_RQMT_R.$due_dt
		};
	
	/**
	 * ChkZ01オペレーション.<p>
	 *
	 * 在庫推移を資産発生基準の観点で照会をする<br>
	 */
	public class ChkZ01 extends MSBCL_ProdPlnReg_MC_A.ChkZ01 {
		@Override
		protected void call() {
			super.call();
		}

		@Override
		protected MCMessageList doServerCheckBase() {
			MCMessageList msgL = super.doServerCheckBase();
		 
			return msgL;
		}
		
		protected Map<ChkZ01_Rslt2R, MCList<MST_RQMT_R>> vRqmtMap = new HashMap<>();
		
		public Map<ChkZ01_Rslt2R, MCList<MST_RQMT_R>> getRqmtMap(){
			return vRqmtMap;
		}
		
		@Override
		protected MCMessageList doServerCheckSub() {
			MCMessageList msgL = super.doServerCheckSub();
		 
			MCList<ChkZ01_Rslt1R> notErr1L = getChkList(up0());
		 
			MCList<ChkZ01_Rslt2R> notErr2L = getChkList(up1());
		 
			// 未確定分の日次生産依頼情報 取得ロック
			MCList<MST_RQMT_R> rqmtL = MCList.create(MST_RQMT_R.class);
			executeQuery(rqmtL, Query.MSBCZL010_MST_RQMT_SZ05(), notErr2L);
			
			// ChkZ01_Rslt2Rの行毎にチェックを行う
			for (ChkZ01_Rslt2R up1R : notErr2L) {
				MCList<MST_RQMT_R> rqmtTmpL = rqmtL.subList(rqmt_keys, up1R);
				vRqmtMap.put(up1R, rqmtTmpL);
				
				// 未確定の所要数量の合計
				MCNumber rqmt_qty = MCNumber.ZERO;
				
				if(rqmtTmpL.isEmpty() == false) {
					rqmt_qty = rqmtTmpL.sum(MST_RQMT_R.$rqmt_qty);
				}
				
				if(isSame(rqmt_qty, nvl(up1R.rqmt_qty(), MCNumber.ZERO))==false) {
					MCMessage msg = new MCMessage(MSBCZL027, up1R.itm_cd(), up1R.strg_loc_cd(), up1R.dt().toString("yyyy/MM/dd"));
					
					ChkZ01_Rslt1R up0R = up0().getFirst(ChkZ01_Rslt1R.$grp_peg_no, up1R.grp_peg_no());
					msg.setCauseRow(up0R, null);
					msgL.add(msg);
					
					up0R.err_flg(true);
					up1R.err_flg(true);
				}
			}
		 
			return msgL;
		}
	}
	/**
	 * UpdZ01オペレーション.<p>
	 *
	 * 在庫推移を資産発生基準の観点で照会をする<br>
	 */
	public class UpdZ01 extends MSBCL_ProdPlnReg_MC_A.UpdZ01 {
		@Override
		protected void call() {
			super.call();
		}
		
		protected void up() {
			editUp();	// SubOpesの上り電文設定するため、super.up()の前に実行
		}

		/**
		 * 上り電文を編集する。
		 */
		protected void editUp() {
			/// pegNo 設定
			setPegNo(ChkZ01_Rslt1R.$peg_no, up0());
			setPegNo(ChkZ01_Rslt2R.$peg_no, up1());
		}
		
		protected Map<ChkZ01_Rslt2R, MCList<MST_RQMT_R>> vRqmtMap = new HashMap<>();
		
		/**
		 * 指定所要ＮＯの該当上り電文2を取得
		 * @param rqmt_no
		 * @return
		 */
		protected ChkZ01_Rslt2R getChkZ01_Rslt2R_By_RqmtNo(String rqmt_no) {
			for (Map.Entry<ChkZ01_Rslt2R, MCList<MST_RQMT_R>> entry : vRqmtMap.entrySet()) {
				if(entry.getValue().getFirst(MST_RQMT_R.$rqmt_no, rqmt_no) != null) {
					return entry.getKey();
				}
			}
			return null;
		}
		
		@Override
		protected void doIt() {
			up();
			
			// 登録・訂正処理前チェックを呼び出す
			callThisChkZ01();
			
			MCList<ChkZ01_Rslt2R> notErr2L = getChkList(up1());
			MCList<mcframe.serverMSBC.MSBCL0010.Chk01_RsltR> up0L_MSBCL0010 = MCList.create(mcframe.serverMSBC.MSBCL0010.Chk01_RsltR.class);
			MCList<mcframe.serverMSBC.MSBCL0010.Chk02_RsltR> up0L_MSBCL0010_del = MCList.create(mcframe.serverMSBC.MSBCL0010.Chk02_RsltR.class);
			
			for (ChkZ01_Rslt2R up1R : notErr2L) {
				MCList<MST_RQMT_R> rqmtTmpL = vRqmtMap.get(up1R);
				
				if(up1R.inpt_gr_qty().gt(up1R.gr_qty())){
					MCNumber diff = up1R.inpt_gr_qty().subtract(up1R.gr_qty());
					
					// 更新後の入庫数量 > 更新前の入庫数量
					if(rqmtTmpL.isEmpty()) {
						// 新規
						mcframe.serverMSBC.MSBCL0010.Chk01_RsltR up0R = crtMSBCL0010_RqmtRegUpd01Up0R(up1R);
						up0L_MSBCL0010.add(up0R);
					}else {
						// 更新
						mcframe.serverMSBC.MSBCL0010.Chk01_RsltR up0R = 
								crtMSBCL0010_RqmtRegUpd01Up0R(up1R, rqmtTmpL.get(rqmtTmpL.size()-1), diff);
						up0L_MSBCL0010.add(up0R);
					}
				}
				else if(up1R.inpt_gr_qty().lt(up1R.gr_qty())){
					// 更新後の入庫数量 < 更新前の入庫数量
					MCNumber diff = up1R.gr_qty().subtract(up1R.inpt_gr_qty());
					
					for (MST_RQMT_R rqmtR : rqmtTmpL) {
						if(rqmtR.rqmt_qty().gt(diff)) {
							// 更新
							mcframe.serverMSBC.MSBCL0010.Chk01_RsltR up0R = 
									crtMSBCL0010_RqmtRegUpd01Up0R(up1R, rqmtTmpL.get(rqmtTmpL.size()-1), diff.multiply(MCNumber.valueOf(-1)));
							up0L_MSBCL0010.add(up0R);
							
							diff = MCNumber.ZERO;
						}else {
							// 削除
							mcframe.serverMSBC.MSBCL0010.Chk02_RsltR up0R = crtMSBCL0010_RqmtRegDel01Up0R(rqmtR);
							up0L_MSBCL0010_del.add(up0R);
							
							diff = diff.subtract(rqmtR.rqmt_qty());
						}
						
						if(diff.eq(MCNumber.ZERO)) {
							break;
						}
					}
					
					
				}
			}
			
			// 更新
			callMSBCL0010_RqmtRegUpd01(up0L_MSBCL0010);
			
			// 削除
			callMSBCL0010_RqmtRegDel01(up0L_MSBCL0010_del);
			
			// 下り電文セット
			setDown();
		}
		
		/**
		 * 登録・訂正処理前チェックを呼び出す
		 */
		protected void callThisChkZ01() {
			ChkZ01 ope = crtChkZ01();
		 
			// 上電文設定
			ope.up0().addAll(up0());	// ChkZ01_Rslt1の設定
			ope.up1().addAll(up1());	// ChkZ01_Rslt2の設定
		 
			// オペレション実行
			ope.exec();
			
			vRqmtMap = ope.getRqmtMap();
		}
		
		protected mcframe.serverMSBC.MSBCL0010.Chk01_RsltR crtMSBCL0010_RqmtRegUpd01Up0R(ChkZ01_Rslt2R inptR) {
			mcframe.serverMSBC.MSBCL0010.Chk01_RsltR up0R = mcframe.serverMSBC.MSBCL0010.Chk01_RsltR.create();
			
			up0R.setStatus(MCRow.Status.CREATE);
			
			up0R.mrp_typ( MSC_MRP_TYP.MRP.value() ); // ＭＲＰ区分
			up0R.rqmt_no( null ); // 所要ＮＯ
			up0R.due_dt( inptR.dt() ); // 納期
			up0R.itm_cd( inptR.itm_cd() ); // 品目ＣＤ
			up0R.itm_sub1( inptR.itm_sub1() ); // 枝番１
			up0R.itm_sub2( inptR.itm_sub2() ); // 枝番２
			up0R.itm_sub3( inptR.itm_sub3() ); // 枝番３
			
			up0R.strg_loc_cd( inptR.strg_loc_cd() ); // 格納場所ＣＤ
			
			up0R.rqmt_qty( inptR.inpt_gr_qty().subtract(inptR.gr_qty()) ); // 所要数量
			up0R.mfg_loc_cd( inptR.mfg_loc_cd() ); // 製造場所ＣＤ
			up0R.sppl_cd( inptR.sppl_cd() ); // 発注先ＣＤ
			up0R.rqst_loc_cd( null ); // 依頼先場所ＣＤ
			up0R.sno1( null ); // 手配ＮＯ１
			up0R.sno2( null ); // 手配ＮＯ２
			up0R.sno3( null ); // 手配ＮＯ３
			up0R.sno4( null ); // 手配ＮＯ４
			up0R.rqmt_typ( null ); // 所要区分
			up0R.intr_rmrks( null ); // 内部備考
			up0R.sub_char1( null ); // 予備１
			up0R.sub_char2( null ); // 予備２
			up0R.sub_char3( null ); // 予備３
			
			return up0R;
		}
		
		protected mcframe.serverMSBC.MSBCL0010.Chk01_RsltR crtMSBCL0010_RqmtRegUpd01Up0R(ChkZ01_Rslt2R inptR, MST_RQMT_R rqmtR, MCNumber diff) {
			mcframe.serverMSBC.MSBCL0010.Chk01_RsltR up0R = mcframe.serverMSBC.MSBCL0010.Chk01_RsltR.create();
			
			up0R.setStatus(MCRow.Status.MODIFY);
			
			up0R.mrp_typ( MSC_MRP_TYP.MRP.value() ); // ＭＲＰ区分
			up0R.rqmt_no( rqmtR.rqmt_no() ); // 所要ＮＯ
			up0R.due_dt( rqmtR.due_dt() ); // 納期
			up0R.itm_cd( rqmtR.itm_cd() ); // 品目ＣＤ
			up0R.itm_sub1( rqmtR.itm_sub1() ); // 枝番１
			up0R.itm_sub2( rqmtR.itm_sub2() ); // 枝番２
			up0R.itm_sub3( rqmtR.itm_sub3() ); // 枝番３
			up0R.strg_loc_cd( rqmtR.strg_loc_cd() ); // 格納場所ＣＤ
			
			up0R.rqmt_qty( rqmtR.rqmt_qty().add(diff)); // 所要数量＝既存＋更新後の入庫数量ー更新前の入庫数量
			
			up0R.mfg_loc_cd( rqmtR.mfg_loc_cd() ); // 製造場所ＣＤ
			up0R.sppl_cd( rqmtR.sppl_cd() ); // 発注先ＣＤ
			up0R.rqst_loc_cd( rqmtR.rqst_loc_cd() ); // 依頼先場所ＣＤ
			up0R.sno1( rqmtR.sno1() ); // 手配ＮＯ１
			up0R.sno2( rqmtR.sno2() ); // 手配ＮＯ２
			up0R.sno3( rqmtR.sno3() ); // 手配ＮＯ３
			up0R.sno4( rqmtR.sno4() ); // 手配ＮＯ４
			up0R.rqmt_typ( rqmtR.rqmt_typ() ); // 所要区分
			up0R.intr_rmrks( rqmtR.intr_rmrks() ); // 内部備考
			up0R.sub_char1( rqmtR.sub_char1() ); // 予備１
			up0R.sub_char2( rqmtR.sub_char2() ); // 予備２
			up0R.sub_char3( rqmtR.sub_char3() ); // 予備３
			up0R.upd_cntr( rqmtR.upd_cntr() ); // 更新カウンタ
			
			return up0R;
		}
		
		protected mcframe.serverMSBC.MSBCL0010.Chk02_RsltR crtMSBCL0010_RqmtRegDel01Up0R(MST_RQMT_R rqmtR) {
			mcframe.serverMSBC.MSBCL0010.Chk02_RsltR up0R = mcframe.serverMSBC.MSBCL0010.Chk02_RsltR.create();
			
			up0R.mrp_typ( MSC_MRP_TYP.MRP.value() ); // ＭＲＰ区分
			up0R.rqmt_no( rqmtR.rqmt_no() ); // 所要ＮＯ
			up0R.upd_cntr( rqmtR.upd_cntr() ); // 更新カウンタ
			
			return up0R;
		}
		
		/**
		 * [MSBCL0010：日次生産依頼登録] MSBCL_RqmtReg.Upd01 更新オペレーションを呼び出す
		 */
		protected void callMSBCL0010_RqmtRegUpd01(MCList<mcframe.serverMSBC.MSBCL0010.Chk01_RsltR> up0L) {
			MSBCL_RqmtReg.Upd01 ope = MSBCL_RqmtReg.crtUpd01();
			
			// 上電文設定
			ope.up0().addAll(up0L);
			
			// オペレション実行前のMCMessageListの待機
			MCMessageList msgTmpL = new MCMessageList();
			msgTmpL.addAll(MCMessagePool.getMessageList());
			MCMessagePool.clear();
			
			// オペレション実行
			ope.exec();
			
			// オペレション実行後のMCMessageList復旧
			MCMessageList msgCurL = new MCMessageList();
			if(MCMessagePool.isEmpty()==false) {
				msgCurL.addAll(MCMessagePool.getMessageList());
				MCMessagePool.clear();
			}
			
			if(msgTmpL.isEmpty() == false) {
				MCMessagePool.addAll(msgTmpL);
			}
			
			for (MCMessage innerMsg : msgCurL) {
				if(innerMsg.getCauseRow() != null) {
					MCMessage msg = getOuterMsg(innerMsg);
					MCMessagePool.add(msg);
				}else {
					MCMessagePool.add(innerMsg);
				}
				
			}
		}
		
		/**
		 * [MSBCL0010：日次生産依頼登録] MSBCL_RqmtReg.Del01 取消オペレーションを呼び出す
		 */
		protected void callMSBCL0010_RqmtRegDel01(MCList<mcframe.serverMSBC.MSBCL0010.Chk02_RsltR> up0L) {
			MSBCL_RqmtReg.Del01 ope = MSBCL_RqmtReg.crtDel01();
		 
			// 上電文設定
			ope.up0().addAll(up0L);
		 
			// オペレション実行前のMCMessageListの待機
			MCMessageList msgTmpL = new MCMessageList();
			msgTmpL.addAll(MCMessagePool.getMessageList());
			MCMessagePool.clear();
			
			// オペレション実行
			ope.exec();

			// オペレション実行後のMCMessageList復旧
			MCMessageList msgCurL = new MCMessageList();
			if(MCMessagePool.isEmpty()==false) {
				msgCurL.addAll(MCMessagePool.getMessageList());
				MCMessagePool.clear();
			}
			
			if(msgTmpL.isEmpty() == false) {
				MCMessagePool.addAll(msgTmpL);
			}
			
			for (MCMessage innerMsg : msgCurL) {
				if(innerMsg.getCauseRow() != null) {
					MCMessage msg = getOuterMsg(innerMsg);
					MCMessagePool.add(msg);
				}else {
					MCMessagePool.add(innerMsg);
				}
				
			}
		}
		
		/**
		 * 外部メッセージ作成
		 * ※内部メッセージが発生箇所を含めていないため、発行箇所情報を追加する
		 * @param innerMsg
		 * @return
		 */
		protected MCMessage getOuterMsg(MCMessage innerMsg){
			String rqmt_no = innerMsg.getCauseRow().getString(mcframe.serverMSBC.MSBCL0010.Chk02_RsltR.$rqmt_no);
			
			ChkZ01_Rslt2R up1R;
			
			if(isNull(rqmt_no)) {
				up1R = up1().getFirst(rqmt_keys, innerMsg.getCauseRow().toArray(mst_rqmt_keys));
			}else {
				up1R = getChkZ01_Rslt2R_By_RqmtNo(rqmt_no);
			}
			
			ChkZ01_Rslt1R up0R = up0().getFirst(ChkZ01_Rslt1R.$grp_peg_no, up1R.grp_peg_no());
			
			MCMessage msg = new MCMessage(MSBCZL028, innerMsg.toString(), innerMsg.getID(),
					up0R.itm_cd(), up0R.strg_loc_cd(), up1R.dt().toString("yyyy/MM/dd"));
			
			msg.setCauseRow(up0R, null);
			
			up0R.err_flg(true);
			up1R.err_flg(true);
			
			return msg;
		}
		
		/**
		 * 下り電文セット
		 */
		protected void setDown() {
			// 下り電文設定
			down0().setAll(up0());	// UpdZ01_Rslt1の設定
			down1().setAll(up1());	// UpdZ01_Rslt2の設定
			
			//処理結果状況区分
			setRtnStsTyp();
		}
		
		//処理結果状況区分:MAC_RTN_STS_TYP
		//NOT_EXE,OK,WRN,ERR
		protected void setRtnStsTyp() {
			for (ChkZ01_Rslt1R r : down0()) {
				if (r.err_flg()==false) {
					r.rtn_sts_typ(MAC_RTN_STS_TYP.OK.value());
				}
				else{
					r.rtn_sts_typ(MAC_RTN_STS_TYP.ERR.value());
				}
			}
			
			for (ChkZ01_Rslt2R r : down1()) {
				if (r.err_flg()==false) {
					r.rtn_sts_typ(MAC_RTN_STS_TYP.OK.value());
				}
				else{
					r.rtn_sts_typ(MAC_RTN_STS_TYP.ERR.value());
				}
			}
		}
	}
	/**
	 * SrchZ01オペレーション.<p>
	 *
	 * 在庫推移を在庫発生基準の観点で照会をする<br>
	 */
	public class SrchZ01 extends MSBCL_ProdPlnReg_MC_A.SrchZ01 {
		@Override
		protected void call() {
			super.call();
		}
		
		/**
		 * 論理削除フラグ制御のオン・オフを取得します。<p>
		 * デフォルトではfalseを返します。
		 */
		@Override
		protected boolean isDelFlgCtl() {
			return true;
		}
		
		@Override
		protected void doSearchMain() {
			super.doSearchMain();
		 
			// 品目詳細マスタ 情報取得SQL文を実行
			MCList<SrchZ01_RsltR> frameItmDtlL = MCList.create(SrchZ01_RsltR.class);
			executeQuery(frameItmDtlL, Query.MSBCZL010_MAM_ITM_DTL_SZ01(), up0());
			
			// 前提条件チェック：品目毎で品目格納場所１つのみ
			String[] frameGrpKey = {
					SrchZ01_RsltR.$itm_cd
					,SrchZ01_RsltR.$itm_sub1
					,SrchZ01_RsltR.$itm_sub2
					,SrchZ01_RsltR.$itm_sub3
				};
			
			MCList<SrchZ01_RsltR>[] frameLArr  = frameItmDtlL.groupList(frameGrpKey);
			
			// 表示枠を作成
			MCList<SrchZ01_RsltR> frameL = MCList.create(SrchZ01_RsltR.class);
			
			for(MCList<SrchZ01_RsltR> frameTmpL : frameLArr) {
				if(frameTmpL.size() > 1) {
					frameTmpL.sort(MAM_ITM_STRG_R.$prio);
					frameL.add(frameTmpL.get(0));
				}else {
					SrchZ01_RsltR tmp = frameTmpL.get(0);
					if(isNull(tmp.strg_loc_cd())) {
						MCMessage msg = new MCMessage(MSBCZL029, tmp.itm_cd());
						MCMessagePool.add(msg);
					}else {
						frameL.add(tmp);
					}
				}
			}
			
			frameL.addDateColumn(SrchZ01_CndR.$dt_fr, up0().dt_fr());
			frameL.addDateColumn(SrchZ01_CndR.$dt_to, up0().dt_to());
			
			// 直近の在庫締め日を取得
			MST_CLOSE_R closeR = getCloseR();
			MCDate last_ac_dt = new MCDate();
					
			if( closeR != null){
				last_ac_dt = getYmEndDt(closeR.ym());
			}
			frameL.addDateColumn("last_ac_dt", last_ac_dt);
			down1().last_ac_dt(last_ac_dt);
			
			// オーダ情報が未確定分の日次生産依頼情報 取得
			MCList<SrchZ01_RsltR> rqmtAllL = MCList.create(SrchZ01_RsltR.class);
			executeQuery(rqmtAllL, Query.MSBCZL010_MST_RQMT_SZ02(), frameL);
			updateDt(rqmtAllL);
			
			// 未確定分の品目オーダ情報 取得
			MCList<SrchZ01_RsltR> odrAllL = MCList.create(SrchZ01_RsltR.class);
			executeQuery(odrAllL, Query.MSBCZL010_MST_ITM_ORDER_SZ03(), frameL);
			updateDt(odrAllL);
			
			// 日次需要 情報取得
			// 検索期間：今日（6/13）だと、検索時で　8/1～から検索対象
			MCDate dt_fr_cst = FXUCL_DateUtil.getToday().startOfMonth().addMonth(2);
			//MCDate dt_fr_cst = FXUCL_DateUtil.getToday().startOfMonth().addMonth(0);
			
			frameL.addDateColumn("dt_fr_cst", dt_fr_cst);
			
			MCList<SrchZ01_RsltR> cstAllL = MCList.create(SrchZ01_RsltR.class);
			executeQuery(cstAllL, Query.MSBCZL010_MST_DLY_DMND_SZ04(), frameL);
			updateDt(cstAllL);
			
			// 遷移計算用クラス作成
			CalTransTtl oCalTransTtl = new CalTransTtl();
			oCalTransTtl.transKey = new String[] {SrchZ01_RsltR.$dt	};	// 遷移キー
			oCalTransTtl.sumCols = 				// 合計項目
					new String[] {					
					SrchZ01_RsltR.$gr_qty,
					SrchZ01_RsltR.$gi_qty,
					SrchZ01_RsltR.$rqmt_qty};
			
			oCalTransTtl.transCols = 		// 遷移項目
					new TransCol[] {
						new TransCol(
								SrchZ01_RsltR.$stk_qty,
								new String[] {SrchZ01_RsltR.$gr_qty},
								new String[] {SrchZ01_RsltR.$gi_qty}
								)
							};	
			
			// 品目-製造場所ＣＤ（格納場所ＣＤ）毎にループ
			for(SrchZ01_RsltR frameR : frameL) {
				// [MSBEL5060：在庫推移検索サービス] MSBEL_InvTransService.InvTrans_Srch01 在庫発生基準検索オペレーションを呼び出す
				MCList<SrchZ01_RsltR> ioL = callMSBEL5060_InvTrans_Srch01(frameR);
				
				// オーダ情報が未確定分の日次生産依頼情報 取得
				MCList<SrchZ01_RsltR> rqmtL = rqmtAllL.subList(frameGrpKey, frameR.toArray(frameGrpKey));
				copyFrameVal(rqmtL, frameR);
				
				// 品目オーダ情報 取得
				MCList<SrchZ01_RsltR> odrL = odrAllL.subList(frameGrpKey, frameR.toArray(frameGrpKey));
				copyFrameVal(odrL, frameR);
				
				// 日次需要 情報取得
				MCList<SrchZ01_RsltR> cstL = cstAllL.subList(frameGrpKey, frameR.toArray(frameGrpKey));
				copyFrameVal(cstL, frameR);
				
				// 在庫遷移を算出
				MCList<SrchZ01_RsltR> grpL = MCList.create(SrchZ01_RsltR.class);
				grpL.add(frameR);
				grpL.addAll(rqmtL);
				grpL.addAll(odrL);
				grpL.addAll(cstL);
				grpL.addAll(ioL);
			
				if(up0().no_io_flg() == true) {
					// 空データ
					MCList<SrchZ01_RsltR> emptyL = makeEmptyL();
					copyFrameVal(emptyL, frameR);
					grpL.addAll(emptyL);
				}
				
				// 日付順
				MCSortPolicy policy = new MCSortPolicy();
				policy.add(SortType.ASC_NULL_AHEAD, SrchZ01_RsltR.$dt);
				grpL.sort(policy);
				
				// 同一日付の場合、後ろの行を合算して、リストから削除
				oCalTransTtl.cal(grpL);
				
				// 出力判定
				boolean matchedFlg = true;
				
				// マイナス在庫のみ
				if(up0().minus_only_flg()==true) {
					if(hasMinusStk(grpL)== false) {
						matchedFlg = false;
					}
				}
				
				// 入出庫予定なしを含む
				if(up0().no_io_flg() == false) {
					if(hasIo(grpL)== false) {
						matchedFlg = false;
					}
				}
				
				if(matchedFlg) {
					down0().addAll(grpL);
				}
			}
		}
		
		/**
		 * 締処理情報 情報取得
		 * @param 検索条件。Where句に使用される
		 * @return : MCRow 
		 */
		protected MST_CLOSE_R getCloseR()
		{
			MCList<MST_CLOSE_R> closeL = MCList.create(MST_CLOSE_R.class);
		 
			MST_CLOSE_R t = MST_CLOSE_R.create("T");
			MCQueryApiBuilder close_bldr = MCQueryApiBuilder.create(t); 
			// 検索項目設定
			close_bldr.setSelectAll();
		 
			// 検索条件設定
			// 必須条件時：addWhereWithAnd を使用
			close_bldr.addWhereWithAnd(t.stk_cl_flg.eq(value(true)));  // 在庫締ＦＬＧ
			
			// データ順設定
			close_bldr.addOrderBy(t.ym.desc().nullsLast());  // 年月度
		 
			// 検索実行、結果をMCList:closeLに格納
			// close_bldr.setDistinct();	// 検索結果をDistinct
			// int cnt = dbSelect(createSqlId(LOGIC_ID, close_bldr.getBaseDbc(), "S01"), closeL, close_bldr);	// no binding
			int cnt = dbSelect(createSqlId(LOGIC_ID, close_bldr.getBaseDbc(), "S01"), closeL, close_bldr);
			if( closeL.isEmpty()==false ) return closeL.get(0);
			return null;
		}
		
		/**
		 * 開始日以前の日付を全て開始日の先日と設定
		 * @param rsltL
		 */
		protected void updateDt(MCList<SrchZ01_RsltR> rsltL) {
			for(SrchZ01_RsltR r : rsltL) {
				if(r.dt().lt(up0().dt_fr())) {
					r.dt(up0().dt_fr().addDay(-1));
				}
			}
		}
		
		/**
		 * 初期データ
		 * @return
		 */
		protected MCList<SrchZ01_RsltR> makeEmptyL() {
			MCList<SrchZ01_RsltR> rsltL =  MCList.create(SrchZ01_RsltR.class);
			MCDate dt = up0().dt_fr().addDay(-1);
			
			// 締在庫
			SrchZ01_RsltR closeR = rsltL.createRow();
			rsltL.add(closeR);
			
			closeR.dt(null);
			closeR.gi_qty(MCNumber.ZERO);
			closeR.gr_qty(MCNumber.ZERO);
			
			// 前日～dt_to
			while(dt.lte(up0().dt_to())) {
				SrchZ01_RsltR r = rsltL.createRow();
				rsltL.add(r);
				
				r.dt(dt);
				r.gi_qty(MCNumber.ZERO);
				r.gr_qty(MCNumber.ZERO);
				
				dt = dt.addDay(1);		// 次の日
			}

			return rsltL;
		}
		
		/**
		 * マイナス在庫の有無をチェック
		 * @param dataL
		 * @return
		 */
		public boolean hasMinusStk(MCList<SrchZ01_RsltR> dataL) {
			for(SrchZ01_RsltR dataR : dataL) {
				if(MCNumber.ZERO.gt( dataR.stk_qty())) {
					return true;
				}
			}
			return false;
		}
		
		/**
		 * 入出庫予定なしをチェック
		 * @return
		 */
		public boolean hasIo(MCList<SrchZ01_RsltR> dataL) {
			for(SrchZ01_RsltR dataR : dataL) {
				if(up0().dt_fr().lte(dataR.dt())) {
					if(isNull(dataR.gr_qty())==false && MCNumber.ZERO.neq( dataR.gr_qty())) {
						return true;
					}
					
					if(isNull(dataR.gi_qty())==false && MCNumber.ZERO.neq( dataR.gi_qty())) {
						return true;
					}
				}
			}
			return false;
		}
		
		/**
		 * キー比較
		 * @return
		 */
		protected boolean isSameRow(MCRow r1, MCRow r2, String[] keys) {
			
			for(String key : keys) {
				if(isSame(r1.getValue(key), r2.getValue(key)) 
						|| (isNull(r1.getValue(key)) && isNull(r2.getValue(key)) )) {
					continue;
				}else {
					return false;
				}
			}
			
			return true;
		}
		
		/**
		 * 遷移項目定義
		 */
		public class TransCol{
			public String colNm;					// 遷移項目
			public String[] plusColNms;				// 合算項目
			public String[] substractColNms;		// 減算項目
			
			public TransCol(String colNm, String[] plusColNms, String[] substractColNms) {
				this.colNm = colNm;
				this.plusColNms = plusColNms;
				this.substractColNms = substractColNms;
			}
		}
		
		/**
		 * 遷移計算
		 */
		public class CalTransTtl{
			public String[] transKey;						// 遷移キー
			public String[] sumCols;						// 合計項目
			public TransCol[] transCols;					// 遷移項目
			
			protected void calTransCol(TransCol transCol, MCRow curR, MCRow priorR) {
				// 遷移計算
				MCNumber val =  priorR.getNumber(transCol.colNm);
				
				for(String colNm : transCol.plusColNms) {
					val = MCNumber.sum(val, curR.getNumber(colNm));
				}
				
				for(String colNm : transCol.substractColNms) {
					val = MCNumber.sum(val, MCNumber.valueOf(-1).multiply(curR.getNumber(colNm)));
				}
				
				curR.setNumber(transCol.colNm,val);
			}
			
			/**
			 * 遷移合計計算
			 */
			public void cal(MCList<?> dataL) {
				MCRow curR = null;
				MCRow priorR = null;
				MCRow prior2R = null;
				
				for(int i=0; i<dataL.size(); i++) {
					curR = dataL.get(i);
									
					if(priorR == null) {
						// 次の行へ
						priorR = curR;
					}else {
						// 前の行、現在行のグループ項目配列が一致する時
						if(isSameRow(priorR, curR, transKey )){
							// 合計
							for(String sumCol : sumCols) {
								priorR.setNumber(sumCol, (MCNumber.sum(curR.getNumber(sumCol), priorR.getNumber(sumCol))));	
							}
							
							if(prior2R == null) {
								// 遷移項目の初期値
								for(TransCol transCol : transCols) {
									priorR.setNumber(transCol.colNm, (MCNumber.sum(curR.getNumber(transCol.colNm), priorR.getNumber(transCol.colNm))));	
								}
							}
							else {
								// 遷移計算
								for(TransCol transCol : transCols) {
									calTransCol(transCol, priorR, prior2R);
								}	
							}
							
							dataL.remove(i);
							i--;
						}else
						{
							// 遷移計算
							for(TransCol transCol : transCols) {
								calTransCol(transCol, curR, priorR);
							}
							
							// 次の行へ
							prior2R = priorR;
							priorR = curR;
						}						
					}
				}
			}
		}
		
		protected MCList<SrchZ01_RsltR> callMSBEL5060_InvTrans_Srch01(SrchZ01_RsltR frameR) {
			MSBEL_InvTransService.InvTrans_Srch01 ope = MSBEL_InvTransService.crtInvTrans_Srch01();
		 
			// 上電文設定
			// Cnd MCRowの設定
			mcframe.serverMSBE.MSBEL5060.CndR up0R = ope.up0();
		 
			up0R.gr_prcd_flg( true ); 								// 入庫ステータス・先行手配
			up0R.gr_sts_opn_grp_flg( true ); 						// 未確定
			up0R.gr_sts_ordsav_grp_flg(true ); 						// オーダ保存
			up0R.gr_sts_fix_grp_flg( true ); 						// 依頼
			up0R.gr_sts_schd_grp_flg( true ); 						// 予定
			up0R.gr_sts_ord_grp_flg( true ); 						// 指図済
			up0R.gr_act_flg( true ); 								// 実績
			up0R.gi_prcd_flg( true ); 								// 出庫ステータス・先行手配
			up0R.gi_sts_opn_grp_flg( true ); 						// 未確定
			up0R.gi_sts_ordsav_grp_flg( true ); 					// オーダ保存
			up0R.gi_sts_fix_grp_flg( true ); 						// 依頼
			up0R.gi_sts_schd_grp_flg( true ); 						// 予定
			up0R.gi_sts_ord_grp_flg( true ); 						// 指図済
			up0R.gi_act_flg( true ); 								// 実績
			
			up0R.dt_fr( up0().dt_fr() ); 							// 期間ＦＲＯＭ
			up0R.dt_to( up0().dt_to() ); 							// 期間ＴＯ
			
			up0R.missing_flg( false ); 								// 欠品ありのみ
			
			up0R.tgt_ver_flg(true);									// 版管理対象
			up0R.non_ver_flg(true);									// 版管理対象外
			
			up0R.loc_cd( frameR.strg_loc_cd() ); 					// 場所ＣＤ
			
			up0R.site_cd( null ); 									// 工場・物流倉庫ＣＤ
			up0R.site_nm( null ); 									// 工場・物流倉庫名
			up0R.wg_cd( null ); 									// ワーキンググループＣＤ
			up0R.wg_nm( null ); 									// ワーキンググループ名
			up0R.lg_grp_cd( null ); 								// 物流グループＣＤ
			up0R.lg_grp_nm( null ); 								// 物流グループ名
			up0R.alloc_grp_cd( null ); 								// 総量引当場所グループＣＤ
			up0R.alloc_grp_nm( null ); 								// 総量引当場所グループ名
			
			up0R.loc_grp_cd( null ); 								// 製造場所グループＣＤ
			up0R.loc_grp_nm( null ); 								// 製造場所グループ名
			
			up0R.quality_typ( MAC_QUALITY_TYP.GOOD.value() ); 		// 良品区分
			up0R.gd_cd( null ); 									// 格付ＣＤ
			up0R.gd_nm( null ); 									// 格付名
						
			up0R.itm_cd( frameR.itm_cd() ); 							// 品目ＣＤ
			up0R.itm_sub1( frameR.itm_sub1() ); 						// 枝番１
			up0R.itm_sub2( frameR.itm_sub2() ); 						// 枝番２
			up0R.itm_sub3( frameR.itm_sub3() ); 						// 枝番３

			up0R.master_dt( null ); 								// マスタ適用日
			up0R.alloc_gi_flg( false); 								// 引当済の投入・出庫予定のみ
				
			up0R.sum_unit_typ( MSC_SUM_UNIT_TYP.LOC.value() ); 		// 集計単位区分
			up0R.sno1_flg( false ); 								// 手配ＮＯ１
			up0R.sno2_flg( false ); 								// 手配ＮＯ２
			up0R.sno3_flg( false ); 								// 手配ＮＯ３
			up0R.sno4_flg( false ); 								// 手配ＮＯ４
			
			up0R.dtl_flg( false ); 									// 明細出力
			up0R.srch_flg( false );									// 検索のみ 
			up0R.amt_flg( false ); 									// 金額計算
			
			// オペレション実行
			ope.exec();
			
			// 下電文の戻すカラムへ反映
			down1().ac_dt(ope.down0().ac_dt());
			
			MCList<SrchZ01_RsltR> ioL = MCList.create(SrchZ01_RsltR.class); 
			
			for(mcframe.serverMSBE.MSBEL5060.RsltR r : ope.down1()) {
				SrchZ01_RsltR tmpR = down0().createRow();
				ioL.add(tmpR);
								
				tmpR.dt(r.dt());								// 入出庫日
				tmpR.gr_qty(MCNumber.sum(r.gr_schd_qty(),r.gr_act_qty()));		// 入庫数量
				tmpR.gi_qty(MCNumber.sum(r.gi_schd_qty(),r.gi_act_qty()));		// 出庫数量
				tmpR.stk_qty(r.stk_qty());						// 在庫数量
			}
			
			copyFrameVal(ioL, frameR);
			
			return ioL;
		}
		
		protected void copyFrameVal(MCList<SrchZ01_RsltR> destL, SrchZ01_RsltR frameR) {
			for(SrchZ01_RsltR tmpR : destL) {
				copyFrameVal(tmpR, frameR);
			}
		}
		
		protected void copyFrameVal(SrchZ01_RsltR destR, SrchZ01_RsltR frameR) {
			destR.itm_cd(frameR.itm_cd());						// 品目ＣＤ
			destR.itm_sub1(frameR.itm_sub1());					// 枝番１
			destR.itm_sub2(frameR.itm_sub2());					// 枝番２
			destR.itm_sub3(frameR.itm_sub3());					// 枝番３
			destR.itm_nm(frameR.itm_nm());						// 品名
			destR.itm_alt_nm1(frameR.itm_alt_nm1());				// 型式
			destR.itm_alt_nm2(frameR.itm_alt_nm2());				// 図番
			destR.itm_alt_nm3(frameR.itm_alt_nm3());				// 仕様
			destR.itm_alt_nm4(frameR.itm_alt_nm4());				// 材質

			destR.base_unit_cd(frameR.base_unit_cd());			// 基準単位ＣＤ
			destR.base_unit_nm(frameR.base_unit_nm());			// 基準単位名
			destR.base_unit_dec_place(frameR.base_unit_dec_place());	// 基準単位小数部有効桁数
			destR.loc_grp_cd(frameR.loc_grp_cd());				// 製造場所グループＣＤ

			destR.strg_loc_cd(frameR.strg_loc_cd());				// 格納場所ＣＤ
			destR.strg_loc_nm(frameR.strg_loc_nm());				// 格納場所名
			
			destR.daily_prd_cap(frameR.daily_prd_cap());			// 日産能力値
			destR.mfg_loc_cd(frameR.mfg_loc_cd());				// 製造場所ＣＤ
			destR.mfg_loc_nm(frameR.mfg_loc_nm());				// 製造場所名
		
			destR.sppl_cd(frameR.sppl_cd());					// 発注先ＣＤ
			destR.sppl_nm(frameR.sppl_nm());					// 発注先名
			
			destR.wg_cd(frameR.wg_cd());							// ワーキンググループＣＤ
			destR.wg_nm(frameR.wg_nm());							// ワーキンググループ名	
		}
	
	}
//FMCB CUSTOM END
}