using System;
using System.Data;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using static iMESCore.Base.iMESConst;
using static iMESCore.Base.iMESComXML;
using static iMESCore.Base.iMESComSubroutine;
using System.Collections.Generic;
using System.Collections;
using iMESCore.Settings;
using kcSYS;
using kcWIP;
using System.Data.Common;
using System.Linq;
using static iMESCore.DataBase.iMESSql;
using System.Xml;
using kcOP;
using kcUSR;
using Org.BouncyCastle.Asn1;
using static kcWIP.clsMaterialHandler;
using System.Net.NetworkInformation;
using System.IO;
using System.Reflection;
using System.Text;
using Newtonsoft.Json;
using iMESCIOC.Response.EAP;

namespace tcEAI_C
{

    public class clsEAP
    {

        public static string strDataBaseType;
        public static string strConnectionString;
        private kcWIP.clsLot objLot = new kcWIP.clsLot();


        private static System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();       // 用以讀取Xml字串12345611111

        public static iMESWIPReleaseLogHandler.clsLotReleaseLogHandle objLotLog;

        private static udReverse.clsReverse objReverse = new udReverse.clsReverse();

        private static clsDBCom objDBCom = new clsDBCom();

        public static string strSQL = "";

        #region 共用功能 ConbineXMLFunction
        public static void SaveLog1(string LogMsg, string LogPath = "", string Json = "")
        {
            DateTime datLogTime = DateTime.Now;
            string strLogFileName;
            try
            {
                if (LogPath.Equals(""))
                {
                    if (DriveExists("D"))
                    {
                        LogPath = @"D:\MESLOG";
                    }
                    else
                    {
                        LogPath = System.IO.Directory.GetCurrentDirectory();
                    }

                }
                else if (!LogPath.EndsWith(@"\"))
                    LogPath += @"\Log";
                else
                    LogPath += "Log";

                if (!Directory.Exists(LogPath))
                    Directory.CreateDirectory(LogPath);

                string head = datLogTime.ToString("yyyy/MM/dd HH:mm:ss fff");
                LogMsg = head + System.Environment.NewLine + Json + System.Environment.NewLine + LogMsg + System.Environment.NewLine;
                strLogFileName = LogPath + @"\" + "" + datLogTime.ToString("yyyyMMdd") + ".log";

                using (System.IO.StreamWriter SW = new System.IO.StreamWriter(strLogFileName, true))
                {
                    SW.WriteLine(LogMsg);  // 输出并换行  
                    SW.Flush();  // 刷新  
                    SW.Close();  // 关闭输出流  
                }
            }
            catch (Exception ex)
            {
            }
        }
        public static bool DriveExists(string driveLetter)
        {
            try
            {
                // 获取所有驱动器信息
                DriveInfo[] allDrives = DriveInfo.GetDrives();
                foreach (DriveInfo drive in allDrives)
                {
                    // 检查驱动器名称是否匹配
                    if (drive.Name.StartsWith(driveLetter + ":"))
                    {
                        return true; // 找到匹配的驱动器，返回true
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("发生错误：" + ex.Message);
            }
            return false; // 未找到匹配的驱动器，返回false
        }
        public static string CombineXMLRequest_AutoExecutionLot(string InXml, string functionid, string computername, DataTable dtLotInfo, string OPNo, string CurUserNo, string SendTime, bool blnRuleChk = true)
        {
            string CombineXMLRequest_AutoExecutionLotRet = default(string);

            string strLotXML = "<lotinfo>";
            string strLotNoColumnName = "";
            if (dtLotInfo.Columns.Contains("Lot_ID"))
            {
                strLotNoColumnName = "Lot_ID";
            }
            else if (dtLotInfo.Columns.Contains("LotNo"))
            {
                strLotNoColumnName = "LotNo";
            }

            string strrulecheckTag = "";
            if (!blnRuleChk)
            {
                strrulecheckTag = "<chkrule>false</chkrule>";
            }

            foreach (DataRow drTemp in dtLotInfo.Rows)
                strLotXML = Conversions.ToString(strLotXML + Operators.ConcatenateObject(Operators.ConcatenateObject("<value><lotno>", drTemp[strLotNoColumnName]), "</lotno></value>"));
            strLotXML += "</lotinfo>";
            CombineXMLRequest_AutoExecutionLotRet = "" + "<request><identity> " + "<transactionid>" + Strings.Format(DateTime.Now, "yyyyMMddHHmmssfff") + "</transactionid>" + "<functionid>" + functionid + "</functionid>" + strLotXML + "<computername>" + computername + "</computername>" + "<opno>" + OPNo + "</opno>" + "<curuserno>" + CurUserNo + "</curuserno>" + "<sendtime>" + SendTime + "</sendtime>" + strrulecheckTag + "</identity>" + "<datainfo>" + InXml + "</datainfo>" + "</request>";
            return CombineXMLRequest_AutoExecutionLotRet;
        }

        #endregion

        #region ReverseTriggerOP

        public static bool ExeReverseTriggerOP_NotUseUndo(string pUserNo, string pLotNo, string pLotSerial = defString, int pLotStamp = defInteger, string ComputreName = "EAI")
        {

            string InXml, OutXml, strIdentity, strParameter;
            bool blnExecResult = false;

            // 2020/3/17 Ning, Mantis: 0068960, WIP_Kit 增加ExeReverseTriggerOP_NotUseUndo共用函式
            try
            {
                // 檢查此 BR 是否此站第一次執行，若是第一次執行則以刪除Temp, Cont, LotLog...的方式取消Trigger OP的動作
                strIdentity = CombineXMLIdentity(ComputreName, pUserNo, DateTime.Now.ToString(defDateTimeFormat));

                strParameter = CombineXMLParameter("lotno", "LotNo", "String", CInput(pLotNo), "");
                // 因FormLoad不見得會成功取得Lot的資料,有可能失敗,故使用變數來決定是否傳出參數.
                if ((pLotSerial ?? "") != defString)
                {
                    strParameter += CombineXMLParameter("lotserial", "LotSerial", "String", CInput(pLotSerial), "");
                }
                if (pLotStamp != defInteger)
                {
                    strParameter += CombineXMLParameter("lotstamp", "LotStamp", "Long", pLotStamp.ToString(), "");
                }
                InXml = CombineXMLRequest(strIdentity, strParameter);
                // OutXml = InvokeSrv("wsWIP.ReverseTriggerOP_NotUseUndo", InXml)

                object[] aryPars = clsCom.funGetMethodParameters("wsSTD", "wsWIP", "ReverseTriggerOP_NotUseUndo");
                aryPars[0] = InXml;
                OutXml = clsCom.funExecuteMethod("wsSTD", "wsWIP", "ReverseTriggerOP_NotUseUndo", ref aryPars) as string;

                blnExecResult = true;
            }
            catch (Exception ex)
            {

            }

            return blnExecResult;
        }

        #endregion

        #region "测试工序进出站"
        public string Execute_CI_LOT(Dictionary<string, string> dicPars, Dictionary<string, DataTable> dicPars_DataTable, string UserNo, string LanguageMode, ref List<ArrayList> aryMessage)
        {
            string Execute_CI_LOTRet = default(string);

            var datSendTime = default(DateTime);
            string strComputerName = string.Empty;
            string strCurUserNo = UserNo;

            object blnRuleCheck = true;
            bool blnEXETriggerOP = false;
            string LotNo = "";
            DataSet dsTemp = new DataSet();
            IDbConnection cnnTemp = null;
            AppSettings objSetting = new AppSettings();
            var CollectionSQL = new Collection();
            string strSQL = "";
            string LotResult = "";
            string ComputerName = Environment.MachineName;
            DateTime sendTime = DateTime.Now;
            DbDataReader drTemp = null;
            DbDataReader drTemp1 = null;
            int Curqty = 0;
            string ProductNo = "";
            string ProductVersion = "";
            string MONO = "";
            long LotStamp = 0;
            string UnitNo = "";
            string OPNO = "";

            try
            {
                string strDataBaseType = objSetting.GetDataBaseType();
                string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
                cnnTemp = CreateConnection(strConnectionString);

                //首先根据unitid(子批批号)查出来当前批次
                strSQL = $@"SELECT * FROM TBLWIPPRDSTATE_LQ WHERE PRODUCTTYPE=1 AND PRODUCTID='{dicPars["unitid"]}' AND STATE=1";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    LotNo = drTemp["LOTNO"].ToString();
                }
                else
                {
                    throw new iMESException.MESException("0000-200002", "[%LOTNO%] [%NOT FOUND%]");
                }
                drTemp.Close();

                strSQL = $"SELECT A.*,B.MONO FROM TBLWIPLOTSTATE A LEFT JOIN TBLWIPLOTBASIS B ON A.LOTNO=B.BASELOTNO WHERE A.LOTNO='{LotNo}' ";
                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "TBLWIPLOTSTATE", cnnTemp);
                if (dsTemp.Tables["TBLWIPLOTSTATE"].Rows.Count > 0)
                {
                    Curqty = Convert.ToInt32(dsTemp.Tables["TBLWIPLOTSTATE"].Rows[0]["Curqty"].ToString());
                    if (!dsTemp.Tables["TBLWIPLOTSTATE"].Rows[0]["STATUS"].ToString().Equals("0"))
                    {
                        throw new iMESException.MESException("0000-12561", $"母批批次{LotNo}状态不为待进站！");
                    }
                    MONO = dsTemp.Tables["TBLWIPLOTSTATE"].Rows[0]["MONO"].ToString();
                    LotStamp = Convert.ToInt64(dsTemp.Tables["TBLWIPLOTSTATE"].Rows[0]["LotStamp"].ToString());
                    UnitNo = dsTemp.Tables["TBLWIPLOTSTATE"].Rows[0]["CURUNITNO"].ToString();
                    OPNO = dsTemp.Tables["TBLWIPLOTSTATE"].Rows[0]["OPNO"].ToString();
                }
                else
                {
                    throw new iMESException.MESException("0000-12561", $"批次{LotNo }找不到在制信息！");
                }

                strSQL = $"SELECT * FROM TBLOEMOBASIS WHERE MONO='{MONO }'";
                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "TBLOEMOBASIS", cnnTemp);
                if (dsTemp.Tables["TBLOEMOBASIS"].Rows.Count > 0)
                {
                    ProductNo = dsTemp.Tables["TBLOEMOBASIS"].Rows[0]["ProductNo"].ToString();
                    ProductVersion = dsTemp.Tables["TBLOEMOBASIS"].Rows[0]["ProductVersion"].ToString();
                }
                else
                {
                    throw new iMESException.MESException("0000-200001", $"工单{MONO}不存在！");
                }

                #region 分批逻辑，子批进出站
                if (Curqty > 1)
                {
                    string splitLotNo = "";
                    using (var objSYSEng = new kcSYS.clsSYSEng())
                    {
                        splitLotNo = objSYSEng.GetSplitLotNo(true, LotNo, "");
                    }

                    //新建分批表
                    DataTable dtSplitLot;
                    dtSplitLot = new DataTable("SplitLot");
                    dtSplitLot.Columns.Add("SplitLotNo", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("SplitLotQty", Type.GetType("System.Decimal"));
                    dtSplitLot.Columns.Add("SplitSysQty", Type.GetType("System.Decimal"));
                    dtSplitLot.Columns.Add("Action", Type.GetType("System.Int32"));
                    dtSplitLot.Columns.Add("NodeID", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("ReturnType", Type.GetType("System.Int32"));
                    dtSplitLot.Columns.Add("FromProductNo", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("FromProductVersion", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("ProductNo", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("ProductVersion", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("UnitNo", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("OPNo", Type.GetType("System.String"));
                    //加入母批
                    DataRow drData;
                    drData = dtSplitLot.NewRow();
                    drData["SplitLotNo"] = LotNo;
                    drData["SplitLotQty"] = Curqty - 1;
                    drData["SplitSysQty"] = Curqty - 1;
                    drData["Action"] = 0;
                    drData["NodeID"] = "";
                    drData["ReturnType"] = 0;
                    drData["FromProductNo"] = ProductNo;
                    drData["FromProductVersion"] = ProductVersion;
                    drData["ProductNo"] = ProductNo;
                    drData["ProductVersion"] = ProductVersion;
                    drData["UnitNo"] = UnitNo;
                    drData["OPNo"] = OPNO;
                    dtSplitLot.Rows.Add(drData);
                    //加入子批
                    DataRow drData2;
                    drData2 = dtSplitLot.NewRow();
                    drData2["SplitLotNo"] = splitLotNo;
                    drData2["SplitLotQty"] = 1;
                    drData2["SplitSysQty"] = 1;
                    drData2["Action"] = 0;
                    drData2["NodeID"] = "";
                    drData2["ReturnType"] = 0;
                    drData2["FromProductNo"] = ProductNo;
                    drData2["FromProductVersion"] = ProductVersion;
                    drData2["ProductNo"] = ProductNo;
                    drData2["ProductVersion"] = ProductVersion;
                    drData2["UnitNo"] = UnitNo;
                    drData2["OPNo"] = OPNO;
                    dtSplitLot.Rows.Add(drData2);
                    //获取返回结果
                    string returnSplitResult = "";
                    try
                    {
                        using (var objLot = new kcWIP.clsLot())
                        {
                            returnSplitResult = objLot.BR_Manual_LotSplit(LotStamp, LotNo, 0, UserNo, dtSplitLot);
                            //执行分批后查询分批的在制情况
                            //未查询到表示分批失败，返回，否则继续后续逻辑
                            strSQL = $"SELECT * FROM TBLWIPLOTSTATE WHERE LOTNO='{splitLotNo}' ";
                            ExecuteSQLQuery_Adapter(strSQL, dsTemp, "TBLWIPLOTSTATE2", cnnTemp);
                            if (dsTemp.Tables["TBLWIPLOTSTATE2"].Rows.Count > 0)
                            {
                                //执行子批自动进出站
                                dicPars.Add("lotno", splitLotNo);
                                Execute_CI_LOTRet = Convert.ToString(AutoexecutionLot_Lot_CS(ref blnEXETriggerOP, dicPars, dicPars_DataTable, "CI", datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck)));
                                if (Execute_CI_LOTRet.Contains("success"))
                                {
                                    strSQL = $@"UPDATE TBLWIPPRDSTATE_LQ SET STATE=0 WHERE PRODUCTTYPE=1 AND PRODUCTID='{dicPars["unitid"]}' AND STATE=1";
                                    CollectionSQL.Add(strSQL);

                                    strSQL = $@"INSERT INTO TBLWIPPRDSTATE_LQ(LOTNO,PRODUCTID,EQPID,STATE,OPNO,CARRIERID,PRODUCTTYPE,CREATEDATE) VALUES('{dicPars["lotno"]}','{dicPars["unitid"]}','',1,'{OPNO }','',1,To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'))";
                                    CollectionSQL.Add(strSQL);

                                    ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);
                                }
                            }
                            else
                            {
                                throw new iMESException.MESException("0000-12561", $"分批失败！");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        returnSplitResult = "执行分批失败--" + e.Message;
                        throw new iMESException.MESException("0000-12561", returnSplitResult);
                    }
                }
                #endregion
                #region 母批标准进出站逻辑
                else
                {
                    //只有确定批号后再传入
                    dicPars.Add("lotno", LotNo);
                    Execute_CI_LOTRet = Convert.ToString(AutoexecutionLot_Lot_CS(ref blnEXETriggerOP, dicPars, dicPars_DataTable, "CI", datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck)));
                }
                #endregion

                return Execute_CI_LOTRet;
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {

                CloseConnection(cnnTemp);
            }
        }

        public string Execute_CO_LOT(Dictionary<string, string> dicPars, Dictionary<string, DataTable> dicPars_DataTable, string UserNo, string LanguageMode, ref List<ArrayList> aryMessage)
        {
            string Execute_CO_LOTRet = default(string);

            var datSendTime = default(DateTime);       // 送達時間
            string strFunctionID = "CO";  // 執行類型  'CI(進站)、CO (出站) 、SPC(SPC資料
            string strComputerName = string.Empty;   // Request Client ComputerName 
            string strCurUserNo = UserNo;     // Request User -紀錄操作人員

            string strSQL = "";

            object blnRuleCheck = true;
            bool blnEXETriggerOP = false;
            string LotNo;
            DbDataReader drTemp = null;
            IDbConnection cnnTemp = null;
            AppSettings objSetting = new AppSettings();
            DataSet dsLotTemp;
            DataSet dsTemp = new DataSet();
            string LotSerial = "", OPNO = "", InventoryNo = "", MONo = "", CurUnitNo = "", ProductNo, ProductVersion, BaseLotNo = "", BRNo, LogGroupSerial = "";
            int intOPReference, intOPStatus; // OPReference參數要參考0:Product,1:Module.  OPStatus 0:站間,1:站中
            string ReferenceNo, ReferenceVersion, NodeVersion, ModProcessNo, ModProcessVersion, CurModuleNo, CurModuleVersion, CurNodeId, AreaNo, OPGroupNo, strGOLinkName;
            double CurQty;

            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            //首先根据unitid(子批批号)查出来当前批次
            strSQL = $@"SELECT * FROM TBLWIPPRDSTATE_LQ WHERE PRODUCTTYPE=1 AND PRODUCTID='{dicPars["unitid"]}' AND STATE=1";
            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
            if (drTemp.Read())
            {
                LotNo = drTemp["LOTNO"].ToString();
            }
            else
            {
                throw new iMESException.MESException("0000-200002", "[%LOTNO%] [%NOT FOUND%]");
            }
            drTemp.Close();

            using (var ds = new DataSet())
            {
                ExecuteSQLQuery_Adapter(
                          "Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " +
                          " From tblWIPTemp_Attrib A, tblSYSElementBasis B " +
                          " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " +
                          " and (AttribPhase = 99 or AttribPhase = 2) And B.AllowNull = 0 And A.LotNo ='" + LotNo + "'",
                          ds.Tables.Add("TempAttrib"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                dicPars_DataTable.Add("lotattrib", ds.Tables[0]);
            }

            // 2.2 取得所有傳入Lot的AttribPhase = PhaseNo並且為99 的Keyin TempCopmonentAttrib 
            using (var ds = new DataSet())
            {
                ExecuteSQLQuery_Adapter(
                              "Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " +
                              " From tblWIPTemp_ComponentAttrib A, tblSYSElementBasis B " +
                              " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " +
                              " and (AttribPhase = 99 or AttribPhase = 2) And B.AllowNull = 0 And A.LotNo ='" + LotNo + "'",
                              ds.Tables.Add("TempCopmonentAttrib"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                dicPars_DataTable.Add("lotcomponentattrib", ds.Tables[0]);
            }

            strSQL = "Select C.LotSerial, A.ProcessNo, A.OPNo, A.NodeId, A.AreaNo, A.HaveComponent, A.CurUnitNo, A.CurQty, A.GoStatus, A.HaveLevel, " + " A.OPReference, A.ModuleNo, A.ModuleVersion, A.LogGroupSerial, A.OPStatus,A.BRNo,A.GoLinkName, " + " B.BaseLotNo, B.ProductNo, B.ProductVersion,A.OPGroupNo,B.MONo,C.INVENTORYNO From tblWIPTemp_LotState C,tblWIPLotState A, tblWIPLotBasis B " + " Where A.LotNo ='" + LotNo + "'" + " And A.BaseLotNo = B.BaseLotNo AND C.LOTNO=A.LOTNO";
            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
            if (drTemp.Read())
            {
                intOPReference = Conversions.ToInteger(drTemp["OPReference"]);
                if (intOPReference == 0)      // 參考Product
                {
                    ReferenceNo = drTemp["ProductNo"].ToString();
                    ReferenceVersion = drTemp["ProductVersion"].ToString();
                }
                else if (intOPReference == 1)  // 參考Module
                {
                    ReferenceNo = drTemp["ModuleNo"].ToString();
                    ReferenceVersion = drTemp["ModuleVersion"].ToString();
                }
                else
                {
                    throw new iMESException.MESException("0000-202001", "[%LotNo%] : " + LotNo);
                }

                LotSerial = drTemp["LotSerial"].ToString();
                ProductNo = drTemp["ProductNo"].ToString();
                ProductVersion = drTemp["ProductVersion"].ToString();
                CurModuleNo = drTemp["ModuleNo"].ToString();
                CurModuleVersion = drTemp["ModuleVersion"].ToString();
                OPNO = drTemp["OPNo"].ToString();
                BaseLotNo = drTemp["BaseLotNo"].ToString();
                InventoryNo = Conversions.ToString(drTemp["InventoryNo"]);
                CurNodeId = drTemp["NodeID"].ToString();
                AreaNo = drTemp["AreaNo"].ToString();
                // HaveComponent = drTemp("HaveComponent")
                CurUnitNo = drTemp["CurUnitNo"].ToString();
                CurQty = Convert.ToDouble(drTemp["CurQty"]);
                // SetWait時會有資料,故不會Null
                LogGroupSerial = drTemp["LogGroupSerial"].ToString();
                intOPStatus = Conversions.ToInteger(drTemp["OPStatus"]);
                BRNo = drTemp["BRNo"].ToString();
                OPGroupNo = drTemp["OPGroupNo"].ToString();
                strGOLinkName = drTemp["GoLinkName"].ToString(); // 2012/02/22
                MONo = drTemp["MONo"].ToString(); // 2020/06/05 Elvis 0072943: 回填完工數量
                                                  // 2022/2/25 0104829: SDD211216_02-01 / HaveComponent、HaveLevel判斷抽換成共用function
            }
            else
            {
                throw new iMESException.MESException("0000-202002", "[%LotNo%] : " + LotNo);
            }
            drTemp.Close();

            dicPars.Add("lotno", LotNo);
            dicPars.Add("opno", OPNO);

            using (var objkcWIP_clsLot = new clsLot())
            {
                dsLotTemp = objkcWIP_clsLot.ShowLotBasisJoinState(LotNo);
            }
            if (dsLotTemp.Tables[0].Rows.Count < 1)
            {
                throw new iMESException.MESException("0000-200001", "[%LOTNO%][%NOT FOUND%]");
            }

            using (var obj = new kcEAP.clsWIP())
            {
                if (obj.ChkCO_UseMaterial(LotNo) == false)
                {
                    throw new iMESException.MESException("0000-200001", "ChkCO_UseMaterial Fail!");
                }
            }
            //(xg)检查请求报文是否增加了errorcode、errorvalue参数
            var errorcode = "";
            var errorvalue = "";
            if (dicPars.ContainsKey("errorcode"))
            {
                errorcode = dicPars["errorcode"].ToString();
                errorvalue = dicPars["errorvalue"].ToString();
            }

            // 1. 检查字典中是否存在这个key
            if (dicPars_DataTable.ContainsKey("lotattrib"))
            {
                if (dicPars_DataTable["lotattrib"] != null)
                {
                    if (dicPars_DataTable["lotattrib"].Select("ATTRIBNO='GoodQty'").Length > 0)
                    {
                        dicPars_DataTable["lotattrib"].Select("ATTRIBNO='GoodQty'")[0]["ATTRIBVALUE"] = CurQty;
                    }

                    if (dicPars_DataTable["lotattrib"].Select("ATTRIBNO='DefectQty'").Length > 0)
                    {
                        dicPars_DataTable["lotattrib"].Select("ATTRIBNO='DefectQty'")[0]["ATTRIBVALUE"] = 0;
                    }
                }
            }

            //查询当前的作业站的属性中是否有【测试工序】属性，若有的话，将socketid存到进站的参数中，执行进站逻辑。
            strSQL = "SELECT * FROM TBLOPPROPERTY WHERE ISSUESTATE=2 AND PROPERTYNO='测试工序' AND OPNO='" + OPNO + "'";
            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
            if (drTemp.Read())
            {
                if (dicPars["result"].ToString().ToUpper() == "NG")
                {
                    // 1. 检查字典中是否存在这个key
                    if (dicPars_DataTable.ContainsKey("lotattrib"))
                    {
                        if (dicPars_DataTable["lotattrib"] != null)
                        {
                            if (dicPars_DataTable["lotattrib"].Select("ATTRIBNO='GoodQty'").Length > 0)
                            {
                                dicPars_DataTable["lotattrib"].Select("ATTRIBNO='GoodQty'")[0]["ATTRIBVALUE"] = 0;
                            }

                            if (dicPars_DataTable["lotattrib"].Select("ATTRIBNO='DefectQty'").Length > 0)
                            {
                                dicPars_DataTable["lotattrib"].Select("ATTRIBNO='DefectQty'")[0]["ATTRIBVALUE"] = CurQty;
                            }
                        }
                    }

                    Collection CollectionSQL = new Collection();
                    //直接入不良品库
                    strSQL = "Insert into tblINVWIP_Scrap(LogGroupSerial,InventoryNo,LotSerial,LotNo,OPNo,UnitNo,ScrapQty,LossQty,BaseLotNo, InputDate)" + " Values ('" + LogGroupSerial + "','" + InventoryNo + "','" + LotSerial + "', '" + LotNo + "','" + OPNO + "','" + CurUnitNo + "'," + CurQty + ",0,'" + BaseLotNo + "'," + " To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')" + ")";
                    CollectionSQL.Add(strSQL);
                    // 加入ReverseUpdateContent
                    strSQL = "Delete From tblINVWIP_Scrap Where LotSerial='" + LotSerial + "'";
                    Collection argcolSQL_Rows9 = null;
                    objReverse.AddReverseUpdateContent(ref LotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows9);

                    // 變更LotSate
                    // 2012/02/22,新增GoLinkName
                    strSQL = "Update tblWIPLotState Set LotSerial = '" + LotSerial + "'," + " Status = 12 ," + " GoStatus = null , " + " GoLinkName = null , " + " EventTime =  To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')," + " EventUserNo='" + UserNo + "'," + " EventDescription='测试工序入不良品仓'," + " ArriveTime =  To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'),";
                    if (intOPStatus == 1) // 站中Wait才須給EndTime
                    {
                        strSQL = strSQL + " PreOPEndTime =  To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'),";
                    }
                    strSQL = strSQL + " OPStatus = 0 Where LotNo = '" + LotNo + "'";
                    CollectionSQL.Add(strSQL);

                    // 執行本站結束的相關處理,站中才須處理
                    decimal decGoodQty = default(decimal), decFailQty = default(decimal), decLossQty = default(decimal);
                    if (intOPStatus == 1)
                    {
                        // 檢查是否已有產出
                        string strGoodUnitNo = "";

                        objLot.SHR_CalOutput(ref cnnTemp, ref decGoodQty, ref decFailQty, ref decLossQty, ref strGoodUnitNo, LogGroupSerial, (decimal)CurQty, CurUnitNo);

                        // 結算工時.
                        decimal FinalGoodQtyTmp = defInteger, FinalFailQtyTmp = defInteger;
                        objLot.EndOP(ref FinalGoodQtyTmp, ref FinalFailQtyTmp, LotNo, LotSerial, DateTime.Now, CollectionSQL, UserNo, true, EventDescription: "测试工序入不良品仓", GoodQty: 0m, FailQty: decGoodQty + decFailQty, LossQty: decLossQty, UnitNo: strGoodUnitNo, CalculateEMP: true);
                    }
                    else
                    {
                        // 由EndModule內自行處理
                        decGoodQty = defInteger;
                        decFailQty = defInteger;
                    }

                    // 不正常結束,CompleteFlag=0.
                    if (intOPReference == 1)
                    {
                        if (decGoodQty == defInteger)
                        {
                            objLot.EndModule(LotNo, LotSerial, DateTime.Now, CollectionSQL, EventUserNo: UserNo, EventDescription: "测试工序入不良品仓", CompleteFlag: 0, UnUpdateFailQty: (decimal)CurQty, FinalGoodQty: 0m);
                        }
                        else
                        {
                            objLot.EndModule(LotNo, LotSerial, DateTime.Now, CollectionSQL, EventUserNo: UserNo, EventDescription: "测试工序入不良品仓", CompleteFlag: 0, UnUpdateFailQty: decGoodQty + decFailQty, FinalGoodQty: 0m);
                        }
                    }

                    // 2017/09/25 YF, 叫用工單達交率處理者，判斷是否回寫實際完工日
                    // 2020/03/17 OwenLiu, Mantis:0068929 工單實際開工日/工單實際完工日 調整還原機制的共用處理
                    new kcOE.WorkOrderRateHandler().ActualFinishDateProcess(pLotNo: LotNo, pLotSerial: LotSerial , pEventTime: DateTime .Now , pCollectionSQL: CollectionSQL, objReverse: objReverse);
                    //(xg)20260722
                    if (errorcode != "")
                    {
                        //更改表TBLPCSDIELOG_LQ
                        strSQL = $"update TBLPCSDIELOG_LQ set BADFLAG = 1,REASONNO = '{errorcode}' where unitid='{dicPars["unitid"].ToString()}'";
                        CollectionSQL.Add(strSQL);
                        //更改表TBLPCSDIELOG_LQ
                        strSQL = $"update tblwipprdstate_LQ set STATE=2 where LOTNO='{LotNo}' AND state= 1";
                        CollectionSQL.Add(strSQL);
                    }
                    ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);
                }
                else if (dicPars["result"].ToString().ToUpper() == "FAIL")
                {
                    strSQL = $@"select * from TBLCUSTESTOPRESULT where lotno ='{LotNo }' and opno ='{OPNO }' and eqpid='{dicPars["eqp_id"]}'";
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "TBLCUSTESTOPRESULT", cnnTemp);
                    if (dsTemp.Tables["TBLCUSTESTOPRESULT"].Rows.Count + 1 < int.Parse(drTemp["DefaultValue"].ToString()))
                    {
                        Collection CollectionSQL = new Collection();
                        //走cycle节点，回到原站点
                        strSQL = $@"INSERT INTO TBLCUSTESTOPRESULT(ErrorNo,ReasonName,LOTNO,OPNO,EQPID,RESULT,TESTTIME) VALUES('{errorcode}','{errorvalue}','{dicPars["lotno"]}','{dicPars["opno"]}','{dicPars["eqp_id"]}','{dicPars["result"]}',To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'))";
                        CollectionSQL.Add(strSQL);

                        ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);

                        Execute_CO_LOTRet = Convert.ToString(AutoexecutionLot_Lot_CS(ref blnEXETriggerOP, dicPars, dicPars_DataTable, strFunctionID, datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck), "CYCLE"));
                    }
                    else
                    {
                        // 1. 检查字典中是否存在这个key
                        if (dicPars_DataTable.ContainsKey("lotattrib"))
                        {
                            if (dicPars_DataTable["lotattrib"] != null)
                            {
                                if (dicPars_DataTable["lotattrib"].Select("ATTRIBNO='GoodQty'").Length > 0)
                                {
                                    dicPars_DataTable["lotattrib"].Select("ATTRIBNO='GoodQty'")[0]["ATTRIBVALUE"] = 0;
                                }

                                if (dicPars_DataTable["lotattrib"].Select("ATTRIBNO='DefectQty'").Length > 0)
                                {
                                    dicPars_DataTable["lotattrib"].Select("ATTRIBNO='DefectQty'")[0]["ATTRIBVALUE"] = CurQty;
                                }
                            }
                        }
                        //直接入不良品库
                        Collection CollectionSQL = new Collection();
                        //直接入不良品库
                        strSQL = "Insert into tblINVWIP_Scrap(LogGroupSerial,InventoryNo,LotSerial,LotNo,OPNo,UnitNo,ScrapQty,LossQty,BaseLotNo, InputDate)" + " Values ('" + LogGroupSerial + "','" + InventoryNo + "','" + LotSerial + "', '" + LotNo + "','" + OPNO + "','" + CurUnitNo + "'," + CurQty + ",0,'" + BaseLotNo + "'," + " To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')" + ")";
                        CollectionSQL.Add(strSQL);
                        // 加入ReverseUpdateContent
                        strSQL = "Delete From tblINVWIP_Scrap Where LotSerial='" + LotSerial + "'";
                        Collection argcolSQL_Rows9 = null;
                        objReverse.AddReverseUpdateContent(ref LotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows9);

                        // 變更LotSate
                        // 2012/02/22,新增GoLinkName
                        strSQL = "Update tblWIPLotState Set LotSerial = '" + LotSerial + "'," + " Status = 12 ," + " GoStatus = null , " + " GoLinkName = null , " + " EventTime =  To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')," + " EventUserNo='" + UserNo + "'," + " EventDescription='测试工序入不良品仓'," + " ArriveTime =  To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'),";
                        if (intOPStatus == 1) // 站中Wait才須給EndTime
                        {
                            strSQL = strSQL + " PreOPEndTime =  To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'),";
                        }
                        strSQL = strSQL + " OPStatus = 0 Where LotNo = '" + LotNo + "'";
                        CollectionSQL.Add(strSQL);

                        // 執行本站結束的相關處理,站中才須處理
                        decimal decGoodQty = default(decimal), decFailQty = default(decimal), decLossQty = default(decimal);
                        if (intOPStatus == 1)
                        {
                            // 檢查是否已有產出
                            string strGoodUnitNo = "";

                            objLot.SHR_CalOutput(ref cnnTemp, ref decGoodQty, ref decFailQty, ref decLossQty, ref strGoodUnitNo, LogGroupSerial, (decimal)CurQty, CurUnitNo);

                            // 結算工時.
                            decimal FinalGoodQtyTmp = defInteger, FinalFailQtyTmp = defInteger;
                            objLot.EndOP(ref FinalGoodQtyTmp, ref FinalFailQtyTmp, LotNo, LotSerial, DateTime.Now, CollectionSQL, UserNo, true, EventDescription: "测试工序入不良品仓", GoodQty: 0m, FailQty: decGoodQty + decFailQty, LossQty: decLossQty, UnitNo: strGoodUnitNo, CalculateEMP: true);
                        }
                        else
                        {
                            // 由EndModule內自行處理
                            decGoodQty = defInteger;
                            decFailQty = defInteger;
                        }

                        // 不正常結束,CompleteFlag=0.
                        if (intOPReference == 1)
                        {
                            if (decGoodQty == defInteger)
                            {
                                objLot.EndModule(LotNo, LotSerial, DateTime.Now, CollectionSQL, EventUserNo: UserNo, EventDescription: "测试工序入不良品仓", CompleteFlag: 0, UnUpdateFailQty: (decimal)CurQty, FinalGoodQty: 0m);
                            }
                            else
                            {
                                objLot.EndModule(LotNo, LotSerial, DateTime.Now, CollectionSQL, EventUserNo: UserNo, EventDescription: "测试工序入不良品仓", CompleteFlag: 0, UnUpdateFailQty: decGoodQty + decFailQty, FinalGoodQty: 0m);
                            }
                        }

                        // 2017/09/25 YF, 叫用工單達交率處理者，判斷是否回寫實際完工日
                        // 2020/03/17 OwenLiu, Mantis:0068929 工單實際開工日/工單實際完工日 調整還原機制的共用處理
                        new kcOE.WorkOrderRateHandler().ActualFinishDateProcess(pLotNo: LotNo, pLotSerial: LotSerial, pEventTime: DateTime.Now, pCollectionSQL: CollectionSQL, objReverse: objReverse);
                        //(xg)20260722
                        if (errorcode != "")
                        {
                            //更改表TBLPCSDIELOG_LQ
                            strSQL = $"update TBLPCSDIELOG_LQ set BADFLAG = 1,REASONNO = '{errorcode}' where unitid='{dicPars["unitid"].ToString()}'";
                            CollectionSQL.Add(strSQL);
                            //更改表TBLPCSDIELOG_LQ
                            strSQL = $"update tblwipprdstate_LQ set STATE=2 where LOTNO='{LotNo}' AND state= 1";
                            CollectionSQL.Add(strSQL);
                        }
                        ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);
                    }
                }
                else if (dicPars["result"].ToString().ToUpper() == "PASS")
                {
                    Collection CollectionSQL = new Collection();
                    strSQL = $@"INSERT INTO TBLCUSTESTOPRESULT(LOTNO,OPNO,EQPID,RESULT,TESTTIME) VALUES('{dicPars["lotno"]}','{dicPars["opno"]}','{dicPars["eqp_id"]}','{dicPars["result"]}',To_Date('" + Strings.Format(DateTime.Now, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'))";
                    CollectionSQL.Add(strSQL);

                    ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);

                    //正常出站
                    Execute_CO_LOTRet = Convert.ToString(AutoexecutionLot_Lot_CS(ref blnEXETriggerOP, dicPars, dicPars_DataTable, strFunctionID, datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck)));
                }
            }
            else
            {
                Execute_CO_LOTRet = Convert.ToString(AutoexecutionLot_Lot_CS(ref blnEXETriggerOP, dicPars, dicPars_DataTable, strFunctionID, datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck)));
            }
            drTemp.Close();

            return Execute_CO_LOTRet;
        }

        // 0102096: [6.0.5] EAP自動報工架構_SDD210906_05-01/ Execute_CI_LOT
        public object AutoexecutionLot_Lot_CS(ref bool blnEXETriggerOP, Dictionary<string, string> dicPars, Dictionary<string, DataTable> dicPars_DataTable, string FunctionID, DateTime ArriveTime, string UserNo, string ComputerName, bool blnRuleCheck = true, string LinkName = defString)
        {
            object AutoexecutionLot_LotRet = default(object);
            var dtLotState = new DataTable();                      // Load Afer TriggerOP
            var objLot = new clsLot();
            var objSYS = new clsSYSUserLog();
            var objWIP = new kcWIP.clsWIP();
            var objUSR = new iMESUserManager.clsUSRSecurity();
            var objclsWIP = new clsWIP();
            var objEMS = new kcEMS.clsEMSEquipment();
            var objReverse = new udReverse.clsReverse();
            DataRow drAdd;
            IDbConnection cnnTemp = null;
            var drTemp = default(DbDataReader);
            //OleDbCommand cmmTemp;
            AppSettings objSetting = new AppSettings();

            string strException;
            string strResult;
            int PhaseNo;
            string AreaNo = defString;
            string OPNo = defString;
            string PSNo = defString;
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString); // Create connection

            string strServiceName = "ExecuteLot";


            var dtLotNo = new DataTable();
            dtLotNo.Columns.Add("LotNo", System.Type.GetType("System.String"));
            var drLotAdd = dtLotNo.NewRow();
            drLotAdd["LotNo"] = dicPars["lotno"];
            dtLotNo.Rows.Add(drLotAdd);
            string LotNo = dtLotNo.Rows[0]["LotNo"].ToString();

            string InXML = "";
            string OutXML = "";

            string strRetrunMsg = "";

            var dtChkRuleLot2 = new DataTable("ChkRuleLot"); // minya 20200315
            string strEquipmentNo = defString;
            string strERFMsg = "";
            try
            {

                // 1.依InXml資料與Lot目前狀態比對是否符合
                DataRow drLotState = null;
                var strKernelModule = default(string);
                var strKernelFunctionName = default(string);

                // 檢查USER過帐权限
                DataRow drUser;
                if (!string.IsNullOrEmpty(UserNo))
                {
                    drUser = objUSR.GetUserSecurity(UserNo, 2);
                    if (string.IsNullOrEmpty(drUser["UserNo"].ToString()))
                    {
                        UserNo = "EAP_AGENT";
                        drUser = objUSR.GetUserSecurity(UserNo, 2);
                        if (string.IsNullOrEmpty(drUser["UserNo"].ToString()))
                        {
                            throw new iMESException.MESException("0000-200015", "[%Please provide curuser or set EAP_Agent correct, then execute Lot%] !");
                        }
                    }
                }
                else
                {
                    UserNo = "EAP_AGENT";
                    drUser = objUSR.GetUserSecurity(UserNo, 2);
                    if (string.IsNullOrEmpty(drUser["UserNo"].ToString()))
                    {
                        throw new iMESException.MESException("0000-200015", "[%Please provide curuser or set EAP_Agent correct, then execute Lot%] !");
                    }
                }

                strEquipmentNo = dicPars["eqp_id"];

                // 2.取得生產批現況資訊
                string refBRNO = defString;
                string refBRExecutionFile = defString;

                string strLots = "(";
                foreach (DataRow drTempLotNo in dtLotNo.Rows)
                    strLots += "'" + drTempLotNo["LotNo"].ToString() + "',";
                strLots = strLots.TrimEnd(',');
                strLots += ")";

                if (tcEAI.clsEAP.funLoadLotStatusJoinOPBusinessRule(strLots, ref dtLotNo) < 0)
                {
                    throw new iMESException.MESException("0000-200091", "[%funLoadLotStatusJoinOPBusinessRule fail%]!");
                }
                if (!(dtLotNo == null) && dtLotNo.Rows.Count > 0) // 取出區域與作業站
                {
                    OPNo = dtLotNo.Rows[0]["OPNo"].ToString();
                    AreaNo = dtLotNo.Rows[0]["AreaNo"].ToString();
                    PSNo = dtLotNo.Rows[0]["PSNo"].ToString();
                }

                // 檢查User是否有此OP的權限------------------------------------------------------------------------------------------------
                // Gary Lu 20121114:這個作業站不在群組內才要進行權限檢查
                if (objUSR.ChkUserOPPriv(UserNo, OPNo) == false)
                {
                    throw new iMESException.MESException("0000-202015", "[%UserNo%]:" + UserNo + "[%NOTHINGSTATE%][%OPPRIVILEGE%], [%OPNo%]:" + OPNo);
                }

                // 檢查User是否有產品區段設定權限------------------------------------------------------------------------------------------------
                if (objUSR.ChkUserPSPriv(UserNo, PSNo) == false)
                {
                    throw new iMESException.MESException("0000-200062", "[%EmployeeNo%]:" + UserNo + "[%has no PS Privilege%], [%PSNo%]:" + PSNo);
                }

                objUSR = null;

                // 6.取得班別
                string ShiftNo = "N/A";
                using (var obj = new clsUSRDepartment())
                {
                    ShiftNo = obj.GetShift(UserNo);
                }

                // 0  : Sucess
                // -1 : Program Error
                // -2 : LotInfo Error
                // -3 : Each Lot Has Different BR
                // -4 : RefLotNo Didn't Setting KERNELMODULE(tblOPBusinessRuleBasis)
                // -5 : RefLotNo Didn't Setting KERNELFUNCTIONNAME(tblOPBusinessRuleBasis)
                // -6 : LotStatus Error
                switch (tcEAI.clsEAP.ChkLotStateAndBRNo(strLots, FunctionID, OPNo))
                {
                    case -1:
                        {
                            throw new iMESException.MESException("0000-200091", "[%ChkLotStateAndBRNo fail%]!");
                        }
                    case -2:
                        {
                            throw new iMESException.MESException("0000-200091", "[%LotNo And OPNo fail!%]");
                        }
                    case -3:
                        {
                            throw new iMESException.MESException("0000-200091", "[%Each Lot Has Different BR%]");
                        }
                    case -4:
                        {
                            throw new iMESException.MESException("0000-200091", "[%RefLotNo%]  " + LotNo + "; [%Not Setting KERNELMODULE(tblOPBusinessRuleBasis)%]");
                        }
                    case -5:
                        {
                            throw new iMESException.MESException("0000-200091", "[%RefLotNo%]  " + LotNo + "; [%Not Setting KERNELFUNCTIONNAME(tblOPBusinessRuleBasis)%]");
                        }
                    case -6:
                        {
                            throw new iMESException.MESException("0000-200091", "[%LotStatus Error%]");
                        }
                }

                foreach (DataRow drTempLotNo in dtLotNo.Rows)
                {
                    if (dtLotNo.Rows.IndexOf(drTempLotNo) == 0)
                    {
                        refBRNO = drTempLotNo["BRNO"].ToString();
                        refBRExecutionFile = drTempLotNo["EXECUTIONFILE"].ToString();
                    }
                    else if (drTempLotNo["BRNO"].ToString() != refBRNO)
                    {
                        // LotBR 與首批不一致
                        throw new iMESException.MESException("0000-200091", "[%LotNo%]:" + drTempLotNo["LotNo"].ToString() + " [%BR%] [%Is Not THE SAME%]");
                    }

                    funCheckStateByLot(ref strKernelModule, ref strKernelFunctionName, drTempLotNo["LotNo"].ToString(), drTempLotNo, FunctionID, OPNo);
                }

                if (FunctionID == "CO")
                {
                    if (refBRExecutionFile.ToUpper() != "BR_L_CO_GEN.DLL" && refBRExecutionFile.ToUpper() != "BR_L_CO_GEN_M.DLL")
                    {
                        //0156845: [6.0.7]调整EAP接口查核支援BR逻辑,增加查核brno
                        if (!tcEAI.clsEAP.ExeBrnoIfSupport(refBRExecutionFile.ToUpper(), refBRNO))
                        {
                            throw new iMESException.MESException("0000-200091", "[%Only Support L_CO_GEN Now%] [%NOWUSE%]:" + refBRNO + "");
                        }

                    }
                }
                else if (refBRExecutionFile.ToUpper() != "BR_L_CI_GEN.DLL" && refBRExecutionFile.ToUpper() != "BR_L_CI_GEN_M.DLL")
                {
                    //0156845: [6.0.7]调整EAP接口查核支援BR逻辑,增加查核brno
                    if (!tcEAI.clsEAP.ExeBrnoIfSupport(refBRExecutionFile.ToUpper(), refBRNO))
                    {
                        throw new iMESException.MESException("0000-200091", "[%Only Support L_CI_GEN Now%] [%NOWUSE%]:" + refBRNO + "");
                    }
                }

                // 3.Execution Trigger OP
                if (!dtLotNo.Columns.Contains("blnEXETriggerOP"))
                {
                    using (var dcTemp = new DataColumn())
                    {
                        dcTemp.ColumnName = "blnEXETriggerOP";
                        dcTemp.DataType = Type.GetType("System.Boolean");
                        dcTemp.DefaultValue = false;
                        dtLotNo.Columns.Add(dcTemp);
                    }
                }

                foreach (DataRow drTempLot in dtLotNo.Rows)
                {
                    // If drTempLot("Status") = 0 Then
                    string DescriptionTmp = defString;
                    long NewLotStampTmp = defInteger;
                    switch (objLot.TriggerOP(ref DescriptionTmp, ref NewLotStampTmp, Convert.ToString(drTempLot["LotNo"]), UserNo: UserNo))
                    {

                        case "hold_exceedtime":
                            {
                                tcEAI.clsWIP.BRERFCreateExecute(pUserId: UserNo, pLotNo: Convert.ToString(drTempLot["LotNo"]), pERFType: 1, pHoldTime: 0, pRuleNo: "EXCEEDTIME");
                                throw new iMESException.MESException("0000-200091", "LotNO:" +
                                    drTempLot["LotNo"] + "[%VIOLATE TIME CONTROL,CREATE ERF%]!");
                            }
                        case "futurehold":
                            {
                                tcEAI.clsWIP.BRERFCreateExecute(pUserId: UserNo, pLotNo: Convert.ToString(drTempLot["LotNo"]), pERFType: 3, pHoldTime: 0);
                                throw new iMESException.MESException("0000-200091", "LotNO:" +
                                    drTempLot["LotNo"] + "[%FUTUREHOLD SET,CREATE ERF%]!");
                            }
                        case "futurewait":
                            {
                                throw new iMESException.MESException("0000-200091", "LotNO:" + drTempLot["LotNo"] + "[%FUTUREWAIT%]!");
                            }
                        case "futureos":
                            {
                                throw new iMESException.MESException("0000-200091", "LotNO:" + drTempLot["LotNo"] + "[%FUTURE OS%]!");
                            }

                        default:
                            {
                                // 2020/03/11 Shih Kai, 68676 :自动进出站BR检核-TriggerOP後增加補做TriggerPhase
                                // Trigger Phase
                                drLotState = objLot.GetLotBasisJoinState(LotNo: drTempLot["LotNo"].ToString());  // 取得最新的LotState

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 0, false))) // by Product
                                {
                                    PhaseNo = objLot.GetBusinessRulePhase(drLotState["ProductNo"].ToString(), drLotState["ProductVersion"].ToString(), drLotState["OPNo"].ToString(), drLotState["BRNo"].ToString());
                                }
                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 1, false))) // by Module
                                {
                                    PhaseNo = objLot.GetBusinessRulePhase(drLotState["ModuleNo"].ToString(), drLotState["ModuleVersion"].ToString(), drLotState["OPNo"].ToString(), drLotState["BRNo"].ToString());
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-200015", "LotNo:" +
                                        drTempLot["LotNo"] + ",[%OPREFERENCE ERROR%]!");
                                }

                                // 剛做完TriggerOP,不用再執行Attrib的變更
                                objLot.TriggerPhase_LotState(Convert.ToString(drTempLot["LotNo"]), PhaseNo, UserNo);

                                drTempLot["blnEXETriggerOP"] = true;
                                break;
                            }
                    }
                }

                var drLotRow = objLot.GetLotBasisJoinState(LotNo: LotNo);  // 取得最新的LotState

                string strLotStamp = drLotRow["LotStamp"].ToString();
                string strLotSerial = drLotRow["LotSerial"].ToString();
                string strLogGroupSerial = drLotRow["LogGroupSerial"].ToString();
                int intPhaseNo = Conversions.ToInteger(drLotRow["PhaseNo"]);

                blnEXETriggerOP = true;

                // 4.ReLoad Lotstate Afer Trigger OP In dtLotState
                tcEAI.clsEAP.funLoadLotStatusJoinOPBusinessRule(strLots, ref dtLotState);


                // 20200309 Edison Mantis : 68289: [SEMI WAFER]通用性CI/CO BR檢核
                // 區域設備檢核 Key in Lot Attrib檢核 Component Attrib檢核, Check Control Rule
                // =============================================== 68289 Start ===============================================

                // 5.Xml轉Table
                DataTable dtLotList = new DataTable(), dtLotAttrib = new DataTable(), dtLotError = new DataTable(), dtLotComponent = new DataTable(), dtLotCompAttrib = new DataTable(), dtEquipment = new DataTable(), dtTempAttrib = new DataTable(), dtComponentError = new DataTable();
                DataTable dtAccessory = null;

                // 將批號加入資料表以便檢查設備
                dtLotList.Columns.Add("LotNo");
                DataRow drLotNo;
                drLotNo = dtLotList.NewRow();
                drLotNo["LotNo"] = LotNo;
                dtLotList.Rows.Add(drLotNo);

                if (dicPars_DataTable.Keys.Contains("lotattrib"))
                {
                    //查询当前的作业站的属性中是否有【测试工序】属性，若有的话，将socketid存到进站的参数中，执行进站逻辑。
                    string strSQL = "SELECT * FROM TBLOPPROPERTY WHERE ISSUESTATE=2 AND PROPERTYNO='测试工序' AND OPNO='" + OPNo + "'";
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (drTemp.Read())
                    {
                        dtLotAttrib = dicPars_DataTable["lotattrib"];
                    }
                    drTemp.Close();
                }

                if (dicPars_DataTable.Keys.Contains("loterror"))
                {
                    dtLotError = dicPars_DataTable["loterror"];
                }

                if (dicPars_DataTable.Keys.Contains("lotcompoment"))
                {
                    dtLotComponent = dicPars_DataTable["lotcompoment"];
                }
                if (dicPars_DataTable.Keys.Contains("lotcomponentattrib"))
                {
                    dtLotCompAttrib = dicPars_DataTable["lotcomponentattrib"];
                }

                if (dicPars_DataTable.Keys.Contains("equipment"))
                {
                    dtEquipment = dicPars_DataTable["equipment"];
                }
                else
                {
                    dtEquipment.Columns.Add("EquipmentNo");
                    DataRow drEQP;
                    drEQP = dtEquipment.NewRow();
                    drEQP["EquipmentNo"] = strEquipmentNo;
                    dtEquipment.Rows.Add(drEQP);
                }

                if (dicPars_DataTable.Keys.Contains("tempattrib"))
                {
                    dtTempAttrib = dicPars_DataTable["tempattrib"];
                }
                if (dicPars_DataTable.Keys.Contains("componenterror"))
                {
                    dtComponentError = dicPars_DataTable["componenterror"];
                }
                if (dicPars_DataTable.Keys.Contains("accessorylist"))
                {
                    dtAccessory = dicPars_DataTable["accessorylist"];
                }

                if (dtAccessory == null)
                {
                    dtAccessory = objEMS.LoadEQPACCStateJoinAccState_EAP(EquipmentNo: strEquipmentNo);
                }

                string strCANodeName, strComponentNodeName;
                string strLinkName = "PASS";
                string strMailGroupNo = "";
                string strMsg = "";
                string strRuleNo = defString;
                int intERFType = 0;
                DataTable dtLotRuleData = default(DataTable);
                //DataTable dtLotRuleData = default(DataTable), dtCompRuleData = default(DataTable);

                var dtLotAttrib_Temp = new DataTable();
                //dtLotAttrib_Temp.Columns.Add("LotNo", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("AttribNo", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("AttribType", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribSequence", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribSource", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribPhase", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribValue", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("SaveToLotPropertyNo", Type.GetType("System.String"));
                // 2021/12/1 缺少QCItemNo,於標準BRcheckin會出錯
                dtLotAttrib_Temp.Columns.Add("TestValue", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("QCItemNo", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("Result", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("Result_INT", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("FactorSerial", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("SerialNo", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("MEMO", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("ComponentNo", Type.GetType("System.String"));
                // SPC
                dtLotAttrib_Temp.Columns["TestValue"].Expression = "AttribValue";

                var dtLotCompAttrib_Temp = new DataTable();
                dtLotCompAttrib_Temp.Columns.Add("LotNo", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("ComponentNo", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("AttribNo", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("AttribValue", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("AttribType", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("AttribSequence", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("AttribSource", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("AttribPhase", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("SaveToLotPropertyNo", Type.GetType("System.String"));

                if (blnRuleCheck)
                {

                    // 預設
                    strCANodeName = "componentattrib";
                    strComponentNodeName = "component";
                    // Call XmlToTable(InXML, dtEquipment, dtLotList, dtLotAttrib, dtLotError, dtLotComponent, dtLotCompAttrib, strLots, LotNo, strCANodeName, strComponentNodeName, refBRNO) 'refBRNO minya 20200312

                    // dtLotAttrib若不包含欄位:LotNo,會出錯誤
                    if (!(dtLotAttrib == null))
                    {
                        if (!dtLotAttrib.Columns.Contains("LotNo"))
                        {
                            dtLotAttrib.Columns.Add("LotNo");
                            if (!(dtLotNo == null) && dtLotNo.Rows.Count > 0)
                            {
                                foreach (DataRow dr in dtLotAttrib.Rows)
                                    dr["LotNo"] = dtLotNo.Rows[0]["LotNo"].ToString();
                            }
                        }
                    }
                    // 6. 基本檢查
                    funBasisCheck(CIorCO: FunctionID, dtLotNo: dtLotNo, dtEquipment: dtEquipment, dtLotList: dtLotList, dtLotAttrib: dtLotAttrib, dtLotError: dtLotError, dtLotComponent: dtLotComponent, dtLotCompAttrib: dtLotCompAttrib, dtTempAttrib: ref dtTempAttrib, strLots: strLots);

                    // 7.格式化Rule Check 資料 並進行ChkControlRule----------------------------------------------------------------------------------------------
                    string strBatchComponent = "";
                    string strAttrib = "";
                    string strCAttrib = "";
                    string strError = "";
                    string strTemp = "";

                    // 7.1 需要判 Rule 的生產批
                    var dtChkRuleLot = new DataTable("ChkRuleLot");
                    string strRuleLot = "";
                    dtChkRuleLot.Columns.Add("LotNo", Type.GetType("System.String"));

                    foreach (DataRow rL in dtLotNo.Rows)
                    {
                        strRuleLot += CombineXMLValueTag(
                                       CombineXMLValue("lotno", CInput(rL["LotNo"].ToString())));
                        dtChkRuleLot.Rows.Add(rL["LotNo"].ToString());
                    }

                    // 7.2 格式化資料Component
                    foreach (DataRow rC in dtLotComponent.Rows)
                    {
                        strBatchComponent += CombineXMLValueTag(
                                 CombineXMLValue("lotno", CInput(rC["LotNo"].ToString())) +
                                 CombineXMLValue("componentno", CInput(rC["ComponentNo"].ToString())));
                    }

                    // 7.3 格式化-Key In Attrib
                    // KeyIn Attrib
                    //20240102,13871,0155146: [6.0.7]EAP接口Execute_CO_LOT，出站输入特性参数时，EAP和产品作业站输入一致，但是会提示报错
                    DataTable attribtemp = null;
                    using (var obj = new clsLot())
                    {
                        attribtemp = obj.ShowTemp_Attrib(LotNo).Tables[0];
                    }
                    //foreach (DataRow rLA in dtLotAttrib.Rows)
                    //{
                    //    for (int x = 0, loopTo = attribtemp.Rows.Count - 1; x <= loopTo; x++)
                    //    {
                    //        if (rLA["AttribNo"].ToString() == attribtemp.Rows[x]["AttribNo"].ToString())
                    //        {
                    //            attribtemp.Rows[x]["AttribValue"] = rLA["AttribValue"].ToString();
                    //        }
                    //    }
                    //}
                    //20240102,13871,0155146,註解此
                    //for (var i = 0; i < dtLotAttrib_Temp.Rows.Count - 1; i++)
                    //{
                    //    for (var j = 0; j < attribtemp.Rows.Count - 1; j++)
                    //    {
                    //        if (Conversions.ToBoolean(Operators.ConditionalCompareObjectEqual(attribtemp.Rows[j]["AttribNo"], dtLotAttrib_Temp.Rows[i]["AttribNo"], false)))
                    //        {
                    //            attribtemp.Rows[j]["AttribValue"] = CInput(dtLotAttrib_Temp.Rows[i]["AttribValue"].ToString());
                    //        }
                    //    }
                    //}
                    //dtLotAttrib_Temp.Clear();
                    //for (var p = 0; p < attribtemp.Rows.Count; p++)
                    //{
                    //    strAttrib = strAttrib + CombineXMLValueTag(
                    //            CombineXMLValue("lotno", LotNo) +
                    //            CombineXMLValue("attribno", CInput(attribtemp.Rows[p]["AttribNo"].ToString())) +
                    //            CombineXMLValue("attribtype", attribtemp.Rows[p]["AttribType"].ToString()) +
                    //            CombineXMLValue("attribsequence", attribtemp.Rows[p]["AttribSequence"].ToString()) +
                    //            CombineXMLValue("attribsource", attribtemp.Rows[p]["AttribSource"].ToString()) +
                    //            CombineXMLValue("attribphase", attribtemp.Rows[p]["AttribPhase"].ToString()) +
                    //            CombineXMLValue("attribvalue", CInput(attribtemp.Rows[p]["AttribValue"].ToString())) +
                    //            CombineXMLValue("savetolotpropertyno", CInput(attribtemp.Rows[p]["SaveToLotPropertyNo"].ToString())) +
                    //            CombineXMLValue("qcitemno", CInput(attribtemp.Rows[p]["QCItemNo"].ToString())));
                    //    DataRow drTemp_Rows;
                    //    drTemp_Rows = dtLotAttrib_Temp.NewRow();
                    //    drTemp_Rows["LotNo"] = LotNo;
                    //    drTemp_Rows["AttribNo"] = attribtemp.Rows[p]["AttribNo"];
                    //    drTemp_Rows["AttribType"] = attribtemp.Rows[p]["AttribType"];
                    //    drTemp_Rows["AttribSequence"] = attribtemp.Rows[p]["AttribSequence"];
                    //    drTemp_Rows["AttribSource"] = attribtemp.Rows[p]["AttribSource"];
                    //    drTemp_Rows["AttribPhase"] = attribtemp.Rows[p]["AttribPhase"];
                    //    drTemp_Rows["AttribValue"] = attribtemp.Rows[p]["AttribValue"].ToString();
                    //    drTemp_Rows["SaveToLotPropertyNo"] = attribtemp.Rows[p]["SaveToLotPropertyNo"];
                    //    drTemp_Rows["QCItemNo"] = attribtemp.Rows[p]["QCItemNo"];
                    //    dtLotAttrib_Temp.Rows.Add(drTemp_Rows);
                    //}

                    if (!(attribtemp == null))
                    {
                        attribtemp.DefaultView.RowFilter = "(AttribPhase = " + intPhaseNo + " or AttribPhase = 99) And AttribSource <> 0";   // CurPhase & All的所有Attrib,除了KeyIn
                        for (int i = 0; i <= attribtemp.DefaultView.Count - 1; i++)
                        {
                            strTemp = CombineXMLValue("lotno", LotNo) +
                                      CombineXMLValue("attribno", CInput(attribtemp.DefaultView[i]["AttribNo"].ToString())) +
                                      CombineXMLValue("attribtype", attribtemp.DefaultView[i]["AttribType"].ToString()) +
                                      CombineXMLValue("attribsequence", attribtemp.DefaultView[i]["AttribSequence"].ToString()) +
                                      CombineXMLValue("attribsource", attribtemp.DefaultView[i]["AttribSource"].ToString()) +
                                      CombineXMLValue("attribphase", attribtemp.DefaultView[i]["AttribPhase"].ToString()) +
                                      CombineXMLValue("savetolotpropertyno", CInput(attribtemp.DefaultView[i]["SaveToLotPropertyNo"].ToString()));
                            if (attribtemp.DefaultView[i]["AttribValue"] is DBNull)
                                strTemp += CombineXMLValue("attribvalue", "");
                            else
                                strTemp += CombineXMLValue("attribvalue", CInput(attribtemp.DefaultView[i]["AttribValue"].ToString()));
                            strAttrib += CombineXMLValueTag(strTemp);
                        }
                        //還原顯示
                        attribtemp.DefaultView.RowFilter = "AttribSource <> 0 And AttribSource <> 1 And (AttribPhase = " + intPhaseNo + " or AttribPhase = 99)";    // Source = Not KeyIn, Not Calculate ,CurPhase and All

                        //Temp:Attrib_KeyIn
                        for (int i = 0; i <= dtLotAttrib.Rows.Count - 1; i++)
                        {
                            if (dtLotAttrib.Rows[i]["AttribValue"] is DBNull)
                                dtLotAttrib.Rows[i]["AttribValue"] = "";

                            DataRow[] drChk = attribtemp.Select("AttribNo='" + dtLotAttrib.Rows[i]["AttribNo"] + "'");
                            if (drChk.Length == 0)
                            {
                                throw new iMESException.MESException("0000-203010", "[%AttribNo%]:" + dtLotAttrib.Rows[i]["AttribNo"].ToString());
                            }
                            else
                            {
                                strTemp = CombineXMLValue("lotno", LotNo) +
                                          CombineXMLValue("attribno", CInput(dtLotAttrib.Rows[i]["AttribNo"].ToString())) +
                                          CombineXMLValue("attribtype", drChk[0]["AttribType"].ToString()) +
                                          CombineXMLValue("attribsequence", drChk[0]["AttribSequence"].ToString()) +
                                          CombineXMLValue("attribsource", drChk[0]["AttribSource"].ToString()) +
                                          CombineXMLValue("attribphase", drChk[0]["AttribPhase"].ToString()) +
                                          CombineXMLValue("attribvalue", CInput(dtLotAttrib.Rows[i]["AttribValue"].ToString())) +
                                          CombineXMLValue("savetolotpropertyno", CInput(drChk[0]["SaveToLotPropertyNo"].ToString()));
                                if (drChk[0]["QCItemNo"] is DBNull)
                                    strTemp += CombineXMLValue("qcitemno", "");
                                else
                                    strTemp += CombineXMLValue("qcitemno", CInput(drChk[0]["QCItemNo"].ToString()));

                                SaveLog1(strTemp, @"D:\MESLog\Execute_CO_LOT");

                                strAttrib += CombineXMLValueTag(strTemp);
                            }
                        }
                    }


                    // 7.4.格式化 Component Attrib
                    foreach (DataRow rCA in dtLotCompAttrib.Rows)
                    {
                        DataSet dsTemp;
                        using (var obj = new clsLot())
                        {
                            dsTemp = obj.ShowTemp_ComponentAttrib(LotNo);
                        }

                        for (int x = 0, loopTo1 = dsTemp.Tables[0].Rows.Count - 1; x <= loopTo1; x++)
                        {
                            if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(rCA["AttribNo"], dsTemp.Tables[0].Rows[x]["AttribNo"], false)))
                            {
                                strCAttrib = strCAttrib + CombineXMLValueTag(
                            CombineXMLValue("lotno", LotNo) +
                            CombineXMLValue("componentno", CInput(dsTemp.Tables[0].Rows[x]["ComponentNo"].ToString())) +
                            CombineXMLValue("attribno", CInput(rCA["AttribNo"].ToString())) +
                            CombineXMLValue("attribtype", dsTemp.Tables[0].Rows[x]["AttribType"].ToString()) +
                            CombineXMLValue("attribsequence", dsTemp.Tables[0].Rows[x]["AttribSequence"].ToString()) +
                            CombineXMLValue("attribsource", dsTemp.Tables[0].Rows[x]["AttribSource"].ToString()) +
                            CombineXMLValue("attribphase", dsTemp.Tables[0].Rows[x]["AttribPhase"].ToString()) +
                            CombineXMLValue("attribvalue", CInput(rCA["AttribValue"].ToString())) +
                            CombineXMLValue("savetolotpropertyno", CInput(dsTemp.Tables[0].Rows[x]["SaveToLotPropertyNo"].ToString())));

                                DataRow drTemp_Rows;
                                drTemp_Rows = dtLotCompAttrib_Temp.NewRow();
                                drTemp_Rows["LotNo"] = LotNo;
                                drTemp_Rows["ComponentNo"] = dsTemp.Tables[0].Rows[x]["ComponentNo"];
                                drTemp_Rows["AttribNo"] = rCA["AttribNo"];
                                drTemp_Rows["AttribType"] = dsTemp.Tables[0].Rows[x]["AttribType"];
                                drTemp_Rows["AttribSequence"] = dsTemp.Tables[0].Rows[x]["AttribSequence"];
                                drTemp_Rows["AttribSource"] = dsTemp.Tables[0].Rows[x]["AttribSource"];
                                drTemp_Rows["AttribPhase"] = dsTemp.Tables[0].Rows[x]["AttribPhase"];
                                drTemp_Rows["AttribValue"] = rCA["AttribValue"].ToString();
                                drTemp_Rows["SaveToLotPropertyNo"] = dsTemp.Tables[0].Rows[x]["SaveToLotPropertyNo"];
                                dtLotCompAttrib_Temp.Rows.Add(drTemp_Rows);
                            }
                        }
                    }

                    // 7.5 格式化不良原因
                    foreach (DataRow rE in dtLotError.Rows)
                    {
                        strError = strError + CombineXMLValueTag(
                     CombineXMLValue("lotno", CInput(rE["LotNo"].ToString())) +
                     CombineXMLValue("componentno", CInput(rE["ComponentNo"].ToString())) +
                     CombineXMLValue("errorno", CInput(rE["ErrorNo"].ToString())) +
                     CombineXMLValue("errorqty", rE["ErrorQty"].ToString()) +
                     CombineXMLValue("errorlevel", rE["ErrorLevel"].ToString()));
                    }

                    // 7.6 Control Rule Check-------------------------------------------------------------------------------------------------------------
                    DataSet dsTestValue = null;

                    //if (ChkControlRule_BatchComponent(dtChkRuleLot, true, UserNo, strRuleLot, strBatchComponent, ref strAttrib, ref strCAttrib, ref strLinkName, ref strMsg, ref strRuleNo, ref intERFType, ref dtLotRuleData, ref dtCompRuleData, ref strMailGroupNo, ref dsTestValue, strError) < 0)
                    if (tcEAI.clsEAP.ChkControlRule(ref dsTestValue, ref dtChkRuleLot, LotNo, UserNo, Conversions.ToLong(strLotStamp), ref strAttrib, ref strLinkName, ref strMsg, ref strRuleNo, ref intERFType, ref strMailGroupNo, strError) < 0)

                    {
                        throw new iMESException.MESException("0000-200091", "[%LotNo%]:" + LotNo + ",Check Control Rule [%FUNCTION%][%Fail%].");
                    }

                    // Check SPC Contorl
                    if (funChkSPCControl_Var(UserNo, LotNo, ref strAttrib, dsTestValue, ref strLinkName, ref intERFType, ref strERFMsg, dtEquipment) < 0)
                    {
                        throw new iMESException.MESException("0000-200091", "[%LotNo%]:" + LotNo + ",Check SPC Contorl [%FUNCTION%][%Fail%].");
                    }
                    strERFMsg = tcEAI.clsEAP.TranslateMsg(strERFMsg);

                    //strAttrib to dtLotAttrib_Temp
                    dtLotAttrib_Temp = ConvertXmlToDataTable(dtLotAttrib_Temp, strAttrib);

                    // 取得RuleNo
                    DataRow[] drSelHoldRule;
                    if (!(dtLotRuleData == null) && dtLotRuleData.Rows.Count > 0)
                    {
                        if (strLinkName == "HOLD")
                        {
                            drSelHoldRule = dtLotRuleData.Select("Linkname= 'HOLD'");
                            if (drSelHoldRule.Length > 0)
                            {
                                strRuleNo = drSelHoldRule[0]["RuleNo"].ToString();
                            }
                        }
                    }

                    // 2020/03/12 Lena, 將 InXml 中的 LiknName、Lot Attrib、Component Attrib 置換為 Control Rule Check 後的結果
                    string strLinkNameTagName = "linkname".ToLower();
                    string strLAttribTagName = "attrib".ToLower();
                    string strCAttribTagName = strCANodeName.ToLower();

                    int intStartIndex, intEndIndex;
                    string strHand, strLast, strChang;
                    string strInXml = InXML;
                    DataRow[] drSel;

                    // LinkName
                    if (!string.IsNullOrEmpty(strLinkName))
                    {
                        intStartIndex = Strings.InStr(strInXml, "<" + strLinkNameTagName + ">");
                        intEndIndex = Strings.InStr(strInXml, "</" + strLinkNameTagName + ">");
                        if (intStartIndex > 0 && intEndIndex > 0)
                        {
                            strHand = strInXml.Substring(0, intStartIndex - 1);
                            strLast = Strings.Mid(strInXml, intEndIndex + strLinkNameTagName.Length + 3);
                            string argname = "LinkName";
                            string argtype = "String";
                            string argdesc = "";
                            strChang = CombineXMLParameter(strLinkNameTagName, argname, argtype, strLinkName, argdesc);
                            strInXml = strHand + strChang + strLast;
                        }
                    }

                    // Lot Attrib
                    if (!string.IsNullOrEmpty(strAttrib))
                    {
                        intStartIndex = Strings.InStr(strInXml, "<" + strLAttribTagName + ">");
                        intEndIndex = Strings.InStr(strInXml, "</" + strLAttribTagName + ">");
                        if (intStartIndex > 0 && intEndIndex > 0)
                        {
                            strHand = strInXml.Substring(0, intStartIndex - 1);
                            strLast = Strings.Mid(strInXml, intEndIndex + strLAttribTagName.Length + 3); // strLAttribTagName.Length + 3 = </strLAttribTagName> 的長度
                            string argtype1 = "String";
                            string argdesc1 = "";
                            strChang = CombineXMLParameterMultiValue(strLAttribTagName, strLAttribTagName, argtype1, strAttrib, argdesc1);
                            strInXml = strHand + strChang + strLast;
                        }
                    }

                    // Component Attrib
                    if (!string.IsNullOrEmpty(strCAttrib))
                    {
                        intStartIndex = Strings.InStr(strInXml, "<" + strCAttribTagName + ">");
                        intEndIndex = Strings.InStr(strInXml, "</" + strCAttribTagName + ">");
                        if (intStartIndex > 0 && intEndIndex > 0)
                        {
                            strHand = strInXml.Substring(0, intStartIndex - 1);
                            strLast = Strings.Mid(strInXml, intEndIndex + strCAttribTagName.Length + 3); // strCAttribTagName.Length + 3 = </strCAttribTagName> 的長度
                            string argtype2 = "String";
                            string argdesc2 = "";
                            strChang = CombineXMLParameterMultiValue(strCAttribTagName, strCAttribTagName, argtype2, strCAttrib, argdesc2);
                            strInXml = strHand + strChang + strLast;
                        }
                    }

                    InXML = strInXml;

                    dtChkRuleLot2 = dtChkRuleLot.Copy();

                    //var drSelRule = default(DataRow[]);
                    //foreach (DataRow drTempComponent in dtCompRuleData.Rows)
                    //{
                    //    if (Strings.Right(drTempComponent["RuleAction"].ToString(), 4) == "HOLD")
                    //    {
                    //        drSelRule = dtLotRuleData.Select("LotNo = '" + drTempComponent["LotNo"].ToString() + "'");
                    //        if (drSelRule.Length > 0)
                    //        {
                    //            drSelRule[0]["LinkName"] = Strings.Right(drTempComponent["RuleAction"].ToString(), 4);
                    //            if (string.IsNullOrEmpty(drSelRule[0]["RuleNo"].ToString()))
                    //            {
                    //                drSelRule[0]["RuleNo"] = drTempComponent["RuleNo"].ToString();
                    //            }
                    //            else
                    //            {
                    //                drSelRule[0]["RuleNo"] = drSelRule[0]["RuleNo"] + "," + drTempComponent["RuleNo"].ToString();
                    //            }
                    //        }
                    //    }
                    //    else if (drTempComponent["RuleAction"].ToString() == "WAIT")
                    //    {
                    //        drSelRule = dtLotRuleData.Select("LotNo = '" + drTempComponent["LotNo"].ToString() + "'");
                    //        if (drSelRule.Length > 0)
                    //        {
                    //            if (drSelRule[0]["LinkName"].ToString() != "PASS")
                    //            {
                    //                drSelRule[0]["LinkName"] = "WAIT";
                    //                if (string.IsNullOrEmpty(drSelRule[0]["RuleNo"].ToString()))
                    //                {
                    //                    drSelRule[0]["RuleNo"] = drTempComponent["RuleNo"].ToString();
                    //                }
                    //                else
                    //                {
                    //                    drSelRule[0]["RuleNo"] = drSelRule[0]["RuleNo"] + "," + drTempComponent["RuleNo"].ToString();
                    //                }
                    //            }
                    //        }
                    //    }
                    //}

                    // ===============================================  68289 End  ===============================================
                }

                // 將LotStamp替換為TriggerOP後的LotStamp
                if (blnEXETriggerOP)
                {
                    string strLotStampTagName = "lotstamp".ToLower();

                    int intStartIndex, intEndIndex;
                    string strHand, strLast, strChang;
                    string strInXml = InXML;
                    DataRow[] drSel;

                    // 取得LotStamp 
                    intStartIndex = Strings.InStr(strInXml, "<" + strLotStampTagName + ">");
                    intEndIndex = Strings.InStr(strInXml, "</" + strLotStampTagName + ">");
                    if (intStartIndex > 0 && intEndIndex > 0)
                    {
                        strHand = strInXml.Substring(0, intStartIndex - 1);
                        strLast = Strings.Mid(strInXml, intEndIndex + strLotStampTagName.Length + 3);
                        string argname1 = "LotStamp";
                        string argtype3 = "Long";
                        string argvalue = Conversions.ToInteger(dtLotState.Rows[0]["LotStamp"]).ToString();
                        string argdesc3 = "";
                        strChang = CombineXMLParameter(strLotStampTagName, argname1, argtype3, argvalue, argdesc3);
                        strInXml = strHand + strChang + strLast;
                        InXML = strInXml;
                    }
                }

                if (LinkName != defString)
                {
                    strLinkName = LinkName;
                }

                string strcheckinresult = ""; // BR_CheckIn回傳success or fail
                using (var obj = new clsLot())
                {
                    if (FunctionID == "CO")
                    {
                        // 5.取出GoodQty,GoodUnitNo---------------------------------------------------------------------------------------------------
                        DataRow[] drSel;
                        double GoodQty = 0d;

                        drSel = dtLotAttrib_Temp.Select("AttribNo='GoodQty'");
                        if (drSel.Length == 0)
                        {
                            throw new iMESException.MESException("0000-200001", "[%CheckOut%] [%GoodQty%] [%not found%]");
                        }
                        else
                        {
                            GoodQty = Convert.ToDouble(drSel[0]["AttribValue"]);
                        }
                        // 進站之前已扣料過。
                        strcheckinresult = obj.BR_CheckOut(Conversions.ToLong(strLotStamp), LotNo, strLinkName, dtLotAttrib_Temp, dtEquipment, null, null, (decimal)GoodQty, UserNo);

                        strRetrunMsg = strcheckinresult;
                        // 9.Return Value
                        if (!string.IsNullOrEmpty(strRetrunMsg))
                        {
                            strResult = "fail";
                            throw new iMESException.MESException("0000-200011", "[%LotNo%] : " + LotNo + "[%Execute%] [%Fail%].");
                        }
                        else
                        {
                            strException = "";
                            strResult = "success";
                        }
                    }

                    else
                    {
                        strcheckinresult = obj.BR_CheckIn(Conversions.ToLong(strLotStamp), LotNo, strLinkName, dtLotAttrib_Temp, dtEquipment, UserNo, ShiftNo, dtAccessory: dtAccessory);
                        strRetrunMsg = strcheckinresult;

                        // 9.Return Value
                        if (strRetrunMsg == "success")
                        {
                            strException = "";
                            strResult = "success";
                        }
                        else
                        {
                            strResult = "fail";
                            throw new iMESException.MESException("0000-200011", "[%LotNo%] : " + LotNo + "[%Execute%] [%Fail%].");
                        }
                    }
                }



                objSYS.AddEventLog(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, "ExecuteLot", ComputerName: ComputerName);
                // Call BRTransferLot(LotNo, UserNo, strLinkName, 1)
                tcEAI.clsEAP.BRTransferLot_Bin(LotNo, UserNo, strLinkName, intERFType, strRuleNo, ComputerName: ComputerName, RuleMsg: strERFMsg);


                lblExitProcedure:
                ;
            }


            catch (iMESException.MESException ex)
            {

                if (FunctionID == "CI")
                {
                    if (dtLotNo.Columns.Contains("blnEXETriggerOP"))
                    {
                        // CheckIn失敗將狀態變更回Queue
                        foreach (DataRow drTempLotInfo in dtLotNo.Rows)
                        {
                            if (Convert.ToBoolean(drTempLotInfo["blnEXETriggerOP"]))
                            {
                                DataRow[] drSel = dtLotState.Select("LotNO='" + drTempLotInfo["LotNo"] + "'".ToString());
                                // Call objReverse.ExecuteReverse(drSel(0)("LotNo"), "AutoExe", Now, , , , , drSel(0)("LotStamp"))
                                // Call objLot.ExeReverseTriggerOP(drSel(0)("LotNo"), drSel(0)("LotSerial"), drSel(0)("LogGroupSerial"), drSel(0)("LotStamp"))
                                ExeReverseTriggerOP_NotUseUndo(UserNo, Convert.ToString(drSel[0]["LotNo"]), Convert.ToString(drSel[0]["LotSerial"]), Conversions.ToInteger(drSel[0]["LotStamp"]), ComputerName);
                            }
                        }
                    }
                }

                strResult = "fail";
                strRetrunMsg = ex.Message;

                objSYS.AddErrorLog_ErrorCode(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, ex.Message + " : " + ex.StackTrace, ComputerName: ComputerName, ErrorCode: Convert.ToString(ex.ErrorCode));

                throw ex;
            }

            catch (Exception ex)
            {

                if (FunctionID == "CI")
                {
                    // CheckIn失敗將狀態變更回Queue
                    if (dtLotNo.Columns.Contains("blnEXETriggerOP"))
                    {
                        foreach (DataRow drTempLotInfo in dtLotNo.Rows)
                        {
                            if (Convert.ToBoolean(drTempLotInfo["blnEXETriggerOP"]))
                            {
                                DataRow[] drSel = dtLotState.Select("LotNO='" + drTempLotInfo["LotNo"] + "'".ToString());
                                // Call objReverse.ExecuteReverse(drSel(0)("LotNo"), "AutoExe", Now, , , , , drSel(0)("LotStamp"))
                                // Call objLot.ExeReverseTriggerOP(drSel(0)("LotNo"), drSel(0)("LotSerial"), drSel(0)("LogGroupSerial"), drSel(0)("LotStamp"))
                                ExeReverseTriggerOP_NotUseUndo(UserNo, Convert.ToString(drSel[0]["LotNo"]), Convert.ToString(drSel[0]["LotSerial"]), Conversions.ToInteger(drSel[0]["LotStamp"]), ComputerName);
                            }
                        }
                    }
                }

                strResult = "fail";
                strRetrunMsg = ex.Message;
                objSYS.AddErrorLog_ErrorCode(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, ex.Message + " : " + ex.StackTrace, ComputerName: ComputerName);

                throw ex;
            }

            finally
            {
                if (!(drTemp == null))
                    drTemp.Close();
                if (!(objLot == null))
                {
                    objLot.Dispose();
                    objLot = null;
                }
                if (!(objSYS == null))
                {
                    objSYS.Dispose();
                    objSYS = null;
                }
                AutoexecutionLot_LotRet = strRetrunMsg;
                CloseConnection(cnnTemp);
            }

            return AutoexecutionLot_LotRet;
        }

        private static short funCheckStateByLot(ref string strKernelModule, ref string strKernelFunctionName, string strLotNo, DataRow drLotState, string strFunctionId = defString, string strOPNo = defString)
        {

            try
            {
                // C1:檢查狀態是否符合
                if (strFunctionId == "CI")
                {
                    // CI,狀態必須是0.
                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drLotState["Status"], 0, false)))
                    {
                        // 生產批狀態不可執行此動作!
                        throw new iMESException.MESException("0000-217001", "[%LotNo%]:" + strLotNo + ",[%Status%] [%is not%] [%Queue%]!");
                    }
                    // ElseIf strFunctionId = "CO" Then
                    // 'CO,狀態必須是1.
                    // If drLotState("Status") <> 1 Then
                    // Throw New iMESException.MESException("0000-217001", "[%LotNo%]:" & strLotNo & ",[%Status%] [%is not%] [%Running%]!")
                    // End If
                }

                // C2:檢查作業站是否符合
                if (strOPNo != defString)
                {
                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(strOPNo, drLotState["OPNo"], false)))
                    {
                        throw new iMESException.MESException("0000-203029", "[%LotNo%]:" + strLotNo + ",[%CurOPNo%] [%is not%] " + strOPNo + "!");
                    }
                }

                // 取得BR設定之KernelModule,KernelFunctionName 
                using (var objOP = new clsOpBasis())
                {
                    DataRow drBR;
                    drBR = objOP.GetBusinessRule(drLotState["BRNo"].ToString());
                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drBR["BRNo"], "", false)))
                    {
                        throw new iMESException.MESException("0000-200003", "[%BRNo%]:" + drLotState["BRNo"]);
                    }
                }
            }


            catch (Exception ex)
            {
                throw;
            }

            return default(short);


        }
        private static int funChkSPCControl_Var(string UserNo, string LotNo, ref string strAttrib, DataSet dsTestValue, ref string strLinkName, ref int intERFType, ref string strERFMsg, DataTable Equipment = default(DataTable))
        {
            int funChkSPCControl_VarRet = default(int);

            funChkSPCControl_VarRet = -1;

            string InXml, OutXml, strIdentity, strParameter;
            XmlDocument XmlDoc = new XmlDocument();
            string strTemp;

            string strEquipmentNo = defString;
            string strQCItemNo = defString;

            try
            {
                // 檢查設備是不是1台
                if (!(Equipment == null))
                {
                    if (Equipment.Rows.Count == 1)
                        strEquipmentNo = Equipment.Rows[0]["EquipmentNo"].ToString();
                    else
                        throw new iMESException.MESException("0000-103010", "[%SAVETOQCITEM%],[%ONLY SINGLE EQUIPMENT%]");
                }

                // 檢查有無需要拋SPC
                if (dsTestValue == null || dsTestValue.Tables[0].Select(" QCItemNo <> '' ").Length <= 0)
                {
                    funChkSPCControl_VarRet = 0;
                    return funChkSPCControl_VarRet;
                }

                // 新增check spc拋回的資料欄
                dsTestValue.Tables[0].Columns.Add("Result", System.Type.GetType("System.String"));
                dsTestValue.Tables[0].Columns.Add("Result_INT", System.Type.GetType("System.Int32"));
                dsTestValue.Tables[0].Columns.Add("FactorSerial", System.Type.GetType("System.String"));
                dsTestValue.Tables[0].Columns.Add("ERFMsg", System.Type.GetType("System.String"));

                // 檢查SPC管制規格
                strIdentity = CombineXMLIdentity("EAI", UserNo, Convert.ToString(DateTime.Now));
                strParameter = CombineXMLParameter("lotno", "LotNo", "String", CInput(LotNo), "");
                if (strEquipmentNo != defString)
                {
                    strParameter += CombineXMLParameter("equipmentno", "EquipmentNo", "String", CInput(strEquipmentNo), "");
                }
                InXml = CombineXMLRequest(strIdentity, strParameter);

                object[] aryPars = clsCom.funGetMethodParameters("wsSTD", "wsSPC", "CheckSPCContorl_Var");
                aryPars[0] = InXml;
                aryPars[1] = dsTestValue;
                OutXml = clsCom.funExecuteMethod("wsSTD", "wsSPC", "CheckSPCContorl_Var", ref aryPars) as string;

                XmlDoc.LoadXml(OutXml);
                if (chkExecutionSuccess(XmlDoc))
                {
                    strLinkName = funGetFinalLinkName(strLinkName, dsTestValue.Tables[0], intERFType);
                    dsTestValue.Tables[0].DefaultView.Sort = "QCItemNo";
                    if (!(dsTestValue.Tables[0] == null) && dsTestValue.Tables[0].DefaultView.ToTable().Rows.Count > 0)
                    {
                        strERFMsg = "";
                        strAttrib = "";
                        foreach (DataRow dr in dsTestValue.Tables[0].Rows)
                        {
                            strTemp = CombineXMLValue("attribno", CInput(dr["AttribNo"].ToString())) +
                                      CombineXMLValue("attribtype", dr["AttribType"].ToString()) +
                                      CombineXMLValue("attribsequence", dr["AttribSequence"].ToString()) +
                                      CombineXMLValue("attribsource", dr["AttribSource"].ToString()) +
                                      CombineXMLValue("attribphase", dr["AttribPhase"].ToString()) +
                                      CombineXMLValue("attribvalue", CInput(dr["AttribValue"].ToString())) +
                                      CombineXMLValue("savetolotpropertyno", CInput(dr["SaveToLotPropertyNo"].ToString()));

                            if (!(dr["QCItemNo"] is DBNull))
                            {
                                strTemp += CombineXMLValue("qcitemno", CInput(dr["QCItemNo"].ToString()));

                                if ((strQCItemNo == defString || strQCItemNo != dr["QCItemNo"].ToString()) && !(dr["ERFMsg"] is DBNull))
                                {
                                    strQCItemNo = dr["QCItemNo"].ToString();
                                    strERFMsg += dr["ERFMsg"].ToString() + ControlChars.Lf;
                                }
                            }
                            else
                            {
                                strTemp += CombineXMLValue("qcitemno", "");
                            }
                            if (!(dr["Result"] is DBNull))
                                strTemp += CombineXMLValue("result", CInput(dr["Result"].ToString()));
                            else
                                strTemp += CombineXMLValue("result", "");
                            if (!(dr["Result_INT"] is DBNull))
                                strTemp += CombineXMLValue("result_int", CInput(dr["Result_INT"].ToString()));
                            else
                                strTemp += CombineXMLValue("result_int", "");
                            if (!(dr["FactorSerial"] is DBNull))
                                strTemp += CombineXMLValue("factorserial", CInput(dr["FactorSerial"].ToString()));
                            else
                                strTemp += CombineXMLValue("factorserial", "");
                            if (!(dr["SerialNo"] is DBNull))
                                strTemp += CombineXMLValue("serialno", CInput(dr["SerialNo"].ToString()));
                            else
                                strTemp += CombineXMLValue("serialno", "");

                            strAttrib += CombineXMLValueTag(strTemp);
                        }
                    }

                    funChkSPCControl_VarRet = 0;
                }
            }
            catch (Exception ex)
            {
                throw;
            }
            return funChkSPCControl_VarRet;
        }
        private static string funGetFinalLinkName(string strLinkName, DataTable dtKeyIn, int intERFType = defInteger)
        {
            string funGetFinalLinkNameRet = default(string);

            try
            {
                // =====  整理生產批品管項目結果 =========
                string strSPCLinkName = "";
                if (dtKeyIn.Select(" Result = 'HOLD' ").Length > 0)
                    strSPCLinkName = "HOLD";
                else if (dtKeyIn.Select(" Result = 'WAIT' ").Length > 0)
                    strSPCLinkName = "WAIT";
                else if (dtKeyIn.Select(" Result = 'WARNING' ").Length > 0)
                    strSPCLinkName = "WARNING";
                else if (dtKeyIn.Select(" Result = 'ALARM' ").Length > 0)
                    strSPCLinkName = "ALARM";
                else if (dtKeyIn.Select(" Result = 'ALERT' ").Length > 0)
                    strSPCLinkName = "ALERT";
                if (funGetLinkNamePriority(strLinkName) < funGetLinkNamePriority(strSPCLinkName))
                {
                    strLinkName = strSPCLinkName;
                    if (strLinkName == "HOLD")
                        intERFType = 1;
                }

                funGetFinalLinkNameRet = strLinkName;
            }
            catch (Exception ex)
            {
                throw;
            }
            return funGetFinalLinkNameRet;
        }

        // 取得Link Name權重
        private static int funGetLinkNamePriority(string strLinkName)
        {
            int funGetLinkNamePriorityRet = default(int);

            try
            {
                int intResult = -1;
                // =====  整理生產批(各品管項目綜合)結果,並存入資料庫 =========
                if (Strings.InStr(strLinkName, "HOLD") > 0)
                    intResult = 5;
                else if (Strings.InStr(strLinkName, "WAIT") > 0)
                    intResult = 4;
                else if (Strings.InStr(strLinkName, "ALARM") > 0)
                    intResult = 0;
                else if (Strings.InStr(strLinkName, "ALERT") > 0)
                    intResult = 0;
                else
                    intResult = 0;

                funGetLinkNamePriorityRet = intResult;
            }
            catch (Exception ex)
            {
                throw;
            }
            return funGetLinkNamePriorityRet;
        }
        public static DataTable ConvertXmlToDataTable(DataTable dataTable, string xmlString)
        {
            XmlDocument XmlDoc = new XmlDocument();

            if (!(xmlString.Contains("<root>") && xmlString.Contains("</root>")))
            {
                xmlString = "<root>" + xmlString + "</root>";
            }

            XmlDoc.LoadXml(xmlString);

            foreach (XmlNode node in XmlDoc.DocumentElement.ChildNodes)
            {
                DataRow row = dataTable.NewRow();
                foreach (XmlNode childNode in node.ChildNodes)
                {
                    if (dataTable.Columns.Contains(childNode.Name))
                    {
                        switch (dataTable.Columns[childNode.Name].DataType.ToString())
                        {
                            case "System.Int32":
                                {
                                    row[childNode.Name] = Conversions.ToInteger(childNode.InnerText);
                                    break;
                                }
                            default:
                                {
                                    row[childNode.Name] = childNode.InnerText;
                                    break;
                                }
                        }
                    }
                }
                dataTable.Rows.Add(row);
            }

            return dataTable;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="CIorCO"></param>
        /// <param name="dtLotNo"></param>
        /// <param name="dtEquipment"></param>
        /// <param name="dtLotList"></param>
        /// <param name="dtLotAttrib"></param>
        /// <param name="dtLotError"></param>
        /// <param name="dtLotComponent"></param>
        /// <param name="dtLotCompAttrib"></param>
        /// <param name="dtTempAttrib"></param>
        /// <param name="strLots"></param>
        /// <param name="Type"></param>
        /// <param name="pRunningMdoe">0:預設檢察區域設備，非0不檢察區域設備</param>
        private static void funBasisCheck(string CIorCO, DataTable dtLotNo, DataTable dtEquipment, DataTable dtLotList, DataTable dtLotAttrib, DataTable dtLotError, DataTable dtLotComponent, DataTable dtLotCompAttrib, ref DataTable dtTempAttrib, string strLots, string Type = defString, short pRunningMdoe = 0)
        {

            DataRow[] drSel;
            DataTable dtTempCopmonentAttrib;
            try
            {

                // 判斷PhaseNo
                int PhaseNo = 99;
                if (CIorCO == "CI")
                {
                    PhaseNo = 1;
                }
                else if (CIorCO == "CO")
                {
                    PhaseNo = 2;
                }

                // 1.設備檢查
                if (pRunningMdoe == 0 && CIorCO == "CI")
                {

                    // 1.1 載入區域設備可用設備
                    foreach (DataRow r in dtLotNo.Rows)
                    {
                        DataTable dtAvailableEquipment_All;
                        DataTable dtAvailableEquipment_Chamber;
                        using (var objLot = new clsLot())
                        {
                            dtAvailableEquipment_All = objLot.ShowAvailableEquipment_All(r["LotNo"].ToString()).Tables[0];
                            dtAvailableEquipment_Chamber = objLot.ShowAvailableEquipment_All(r["LotNo"].ToString()).Tables["Chamber"];
                        }

                        drSel = dtAvailableEquipment_All.Select(" AllowExecute=1 ");

                        // 1.2 若區域內無可用設備,但卻傳入設備編號則拋出錯誤訊息
                        if (drSel.Length == 0)
                        {
                            if (dtEquipment.Rows.Count > 0)
                            {
                                throw new iMESException.MESException("0000-003000", "[%Area has none Available Equipment%]");
                            }
                        }
                        else
                        {

                            // 1.3 若傳入設備編號不在區域可用設備中則拋出錯誤訊息
                            foreach (DataRow rE in dtEquipment.Rows)
                            {
                                drSel = dtAvailableEquipment_All.Select(" AllowExecute=1 And EquipmentNo = '" + rE["EquipmentNo"] + "' ".ToString());
                                if (drSel.Length == 0)
                                {
                                    //判断子设备是否存在
                                    if (!(dtAvailableEquipment_Chamber is null) && dtAvailableEquipment_Chamber.Rows.Count > 0)
                                    {
                                        drSel = dtAvailableEquipment_Chamber.Select(" AllowExecute=1 And EquipmentNo = '" + rE["EquipmentNo"] + "' ".ToString());
                                        if (drSel.Length == 0)
                                        {
                                            throw new iMESException.MESException("0000-003000", "[%EquipmentNo%]: " + rE["EquipmentNo"] + " [%Not In Available Equipment%]");
                                        }
                                    }
                                    else
                                    {
                                        throw new iMESException.MESException("0000-003000", "[%EquipmentNo%]: " + rE["EquipmentNo"] + " [%Not In Available Equipment%]");
                                    }
                                }
                            }
                        }

                    }

                }

                // 2.檢查KeyInAttrib
                // 2.1 取得所有傳入Lot的AttribPhase = PhaseNo並且為99 的Keyin TempAttrib 
                using (var ds = new DataSet())
                {
                    AppSettings objSetting = new AppSettings();
                    //string argstrDataBaseType = "Null";
                    //using (var cn = new OleDbConnection(objSetting.GetConnectionString(strDataBaseType: ref argstrDataBaseType)))
                    //{
                    //    using (var da = new OleDbDataAdapter("Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " + " From tblWIPTemp_Attrib A, tblSYSElementBasis B " + " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " + " and (AttribPhase = 99 or AttribPhase = " + PhaseNo + ") And B.AllowNull = 0 And A.LotNo In " + strLots, cn))
                    //    {
                    //        da.Fill(ds.Tables.Add("TempAttrib"));
                    //    }
                    //}
                    ExecuteSQLQuery_Adapter(
                              "Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " +
                              " From tblWIPTemp_Attrib A, tblSYSElementBasis B " +
                              " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " +
                              " and (AttribPhase = 99 or AttribPhase = " + PhaseNo + ") And B.AllowNull = 0 And A.LotNo In " + strLots,
                              ds.Tables.Add("TempAttrib"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                    dtTempAttrib = ds.Tables[0];
                }

                // 2.2 取得所有傳入Lot的AttribPhase = PhaseNo並且為99 的Keyin TempCopmonentAttrib 
                using (var ds = new DataSet())
                {
                    AppSettings objSetting = new AppSettings();
                    //string argstrDataBaseType1 = "Null";
                    //using (var cn = new OleDbConnection(objSetting.GetConnectionString(strDataBaseType: ref argstrDataBaseType1)))
                    //{
                    //    using (var da = new OleDbDataAdapter("Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " + " From tblWIPTemp_ComponentAttrib A, tblSYSElementBasis B " + " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " + " and (AttribPhase = 99 or AttribPhase = " + PhaseNo + ") And B.AllowNull = 0 And A.LotNo In " + strLots, cn))
                    //    {
                    //        da.Fill(ds.Tables.Add("TempCopmonentAttrib"));
                    //    }
                    //}
                    ExecuteSQLQuery_Adapter(
                                  "Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " +
                                  " From tblWIPTemp_ComponentAttrib A, tblSYSElementBasis B " +
                                  " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " +
                                  " and (AttribPhase = 99 or AttribPhase = " + PhaseNo + ") And B.AllowNull = 0 And A.LotNo In " + strLots,
                                  ds.Tables.Add("TempCopmonentAttrib"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                    dtTempCopmonentAttrib = ds.Tables[0];
                }

                foreach (DataRow rL in dtLotNo.Rows)
                {

                    switch (Type)
                    {
                        case "ASM":  // //因為欄位大小寫問題,且以XML檢查為主
                            {

                                foreach (DataRow rLA in dtLotAttrib.Rows)
                                {
                                    drSel = dtTempAttrib.Select(" AttribNo = '" + rLA["attribno"] + "' ".ToString());
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rLA["attribno"] + " ,[%AttribNo%]: " + rLA["attribno"] + " [%NOT PASS ARGUMENTS%]");
                                    }
                                }


                                foreach (DataRow rCA in dtLotCompAttrib.Rows)
                                {
                                    drSel = dtTempCopmonentAttrib.Select(" AttribNo = '" + rCA["attribno"] + "' ".ToString());
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rCA["attribno"] + " ,[%AttribNo%]: " + rCA["attribno"] + " [%NOT PASS ARGUMENTS%]");
                                    }

                                    // 2.3 若為CPASS，並且傳入值為1時，必須存在相對應的Error
                                    else if (drSel[0]["AttribNo"].ToString().ToUpper() == "CPASS" && Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drSel[0]["AttribValue"], 1, false)))
                                    {
                                        drSel = dtLotError.Select(" LotNo = '" +
                                            rCA["LotNo"] + "' And ComponentNo = '" + rCA["ComponentNo"] + "' ");
                                        if (drSel.Length == 0)
                                        {
                                            throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                                rCA["LotNo"] + " ,[%AttribNo%]: " + rCA["AttribNo"] + " Error Data ");
                                        }
                                    }
                                }

                                break;
                            }

                        case "LotAttrib": //只檢查 LotAttrib
                            {
                                // 2.3 LotAttrib 若為not null Attrib未傳入則拋出錯誤訊息
                                foreach (DataRow rLA in dtTempAttrib.Select("LotNo = '" + rL["LotNo"] + "' And AttribType = 0 ".ToString()))
                                {
                                    drSel = dtLotAttrib.Select(" LotNo = '" + rLA["LotNo"] + "' And AttribNo = '" + rLA["AttribNo"] + "' ".ToString());
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rLA["LotNo"] + " ,[%AttribNo%]: " + rLA["AttribNo"] + " [%NOT PASS ARGUMENTS%]");
                                    }
                                }
                                break;
                            }

                        default:
                            {

                                // 2.3 LotAttrib 若為not null Attrib未傳入則拋出錯誤訊息
                                foreach (DataRow rLA in dtTempAttrib.Select("LotNo = '" + rL["LotNo"] + "' And AttribType = 0 ".ToString()))
                                {
                                    drSel = dtLotAttrib.Select(" LotNo = '" + rLA["LotNo"] + "' And AttribNo = '" + rLA["AttribNo"] + "' ".ToString());
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rLA["LotNo"] + " ,[%AttribNo%]: " + rLA["AttribNo"] + " [%NOT PASS ARGUMENTS%]");
                                    }
                                }

                                // 2.4 ComponentAttrib 若為not null Attrib未傳入則報錯
                                foreach (DataRow rCA in dtTempCopmonentAttrib.Select("LotNo = '" + rL["LotNo"] + "' And AttribType = 1 ".ToString()))
                                {
                                    drSel = dtLotCompAttrib.Select(" LotNo = '" +
                                        rCA["LotNo"] + "' And AttribNo = '" + rCA["AttribNo"] + "' ");
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rCA["LotNo"] + " ,[%AttribNo%]: " + rCA["AttribNo"] + " [%NOT PASS ARGUMENTS%]");
                                    }

                                    // 2.3 若為CPASS，並且傳入值為1時，必須存在相對應的Error
                                    else if (drSel[0]["AttribNo"].ToString().ToUpper() == "CPASS" && Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drSel[0]["AttribValue"], 1, false)))
                                    {
                                        drSel = dtLotError.Select(" LotNo = '" +
                                            rCA["LotNo"] + "' And ComponentNo = '" + rCA["ComponentNo"] + "' ");
                                        if (drSel.Length == 0)
                                        {
                                            throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                                rCA["LotNo"] + " ,[%AttribNo%]: " + rCA["AttribNo"] + " Error Data ");
                                        }
                                    }
                                }

                                break;
                            }
                    }

                }
            }

            catch (iMESException.MESException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
            }

        }

        private void funBasisCheck(string CIorCO, DataTable dtLotNo, DataTable dtEquipment, DataTable dtLotList, DataTable dtLotAttrib, DataTable dtLotError, ref DataTable dtTempAttrib, string strLots, string Type = defString, short pRunningMdoe = 0)
        {

            DataRow[] drSel;
            DataTable dtTempCopmonentAttrib;
            try
            {
                // 判斷PhaseNo
                int PhaseNo = 99;
                if (CIorCO == "CI")
                {
                    PhaseNo = 1;
                }
                else if (CIorCO == "CO")
                {
                    PhaseNo = 2;
                }

                // 1.設備檢查
                if (pRunningMdoe == 0 && CIorCO == "CI")
                {
                    // 1.1 載入區域設備可用設備
                    foreach (DataRow r in dtLotNo.Rows)
                    {
                        DataTable dtAvailableEquipment_All;
                        using (var objLot = new clsLot())
                        {
                            dtAvailableEquipment_All = objLot.ShowAvailableEquipment_All(r["LotNo"].ToString()).Tables[0];
                        }

                        drSel = dtAvailableEquipment_All.Select(" AllowExecute=1 ");

                        // 1.2 若區域內無可用設備,但卻傳入設備編號則拋出錯誤訊息
                        if (drSel.Length == 0)
                        {
                            if (dtEquipment.Rows.Count > 0)
                                throw new iMESException.MESException("0000-003000", "[%Area has none Available Equipment%]");

                        }
                        else
                        {
                            // 1.3 若傳入設備編號不在區域可用設備中則拋出錯誤訊息
                            foreach (DataRow rE in dtEquipment.Rows)
                            {
                                drSel = dtAvailableEquipment_All.Select(" AllowExecute=1 And EquipmentNo = '" + rE["EquipmentNo"] + "' ".ToString());
                                if (drSel.Length == 0)
                                {
                                    throw new iMESException.MESException("0000-003000", "[%EquipmentNo%]: " +
                                        rE["EquipmentNo"] + " [%Not In Available Equipment%]");
                                }
                            }
                        }
                    }
                }

                // 2.檢查KeyInAttrib
                // 2.1 取得所有傳入Lot的AttribPhase = PhaseNo並且為99 的Keyin TempAttrib 
                using (var ds = new DataSet())
                {
                    AppSettings objSetting = new AppSettings();

                    ExecuteSQLQuery_Adapter(
                              "Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " +
                              " From tblWIPTemp_Attrib A, tblSYSElementBasis B " +
                              " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " +
                              " and (AttribPhase = 99 or AttribPhase = " + PhaseNo + ") And B.AllowNull = 0 And A.LotNo In " + strLots,
                              ds.Tables.Add("TempAttrib"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                    dtTempAttrib = ds.Tables[0];
                }

                // 2.2 取得所有傳入Lot的AttribPhase = PhaseNo並且為99 的Keyin TempCopmonentAttrib 
                using (var ds = new DataSet())
                {
                    AppSettings objSetting = new AppSettings();
                    ExecuteSQLQuery_Adapter(
                                  "Select A.*,B.ElementName As AttribName, B.InputType, B.DataType, B. ValueType " +
                                  " From tblWIPTemp_ComponentAttrib A, tblSYSElementBasis B " +
                                  " Where A.AttribNo=B.ElementNo And A.AttribSource = 0 " +
                                  " and (AttribPhase = 99 or AttribPhase = " + PhaseNo + ") And B.AllowNull = 0 And A.LotNo In " + strLots,
                                  ds.Tables.Add("TempCopmonentAttrib"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                    dtTempCopmonentAttrib = ds.Tables[0];
                }

                foreach (DataRow rL in dtLotNo.Rows)
                {
                    switch (Type)
                    {
                        case "ASM":  // //因為欄位大小寫問題,且以XML檢查為主
                            {
                                foreach (DataRow rLA in dtLotAttrib.Rows)
                                {
                                    drSel = dtTempAttrib.Select(" AttribNo = '" + rLA["attribno"] + "' ".ToString());
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rLA["attribno"] + " ,[%AttribNo%]: " + rLA["attribno"] + " [%NOT PASS ARGUMENTS%]");
                                    }
                                }

                                break;
                            }

                        case "LotAttrib": //只檢查 LotAttrib
                            {
                                // 2.3 LotAttrib 若為not null Attrib未傳入則拋出錯誤訊息
                                foreach (DataRow rLA in dtTempAttrib.Select("LotNo = '" + rL["LotNo"] + "' And AttribType = 0 ".ToString()))
                                {
                                    drSel = dtLotAttrib.Select(" LotNo = '" + rLA["LotNo"] + "' And AttribNo = '" + rLA["AttribNo"] + "' ".ToString());
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rLA["LotNo"] + " ,[%AttribNo%]: " + rLA["AttribNo"] + " [%NOT PASS ARGUMENTS%]");
                                    }
                                }
                                break;
                            }

                        default:
                            {
                                // 2.3 LotAttrib 若為not null Attrib未傳入則拋出錯誤訊息
                                foreach (DataRow rLA in dtTempAttrib.Select("LotNo = '" + rL["LotNo"] + "' And AttribType = 0 ".ToString()))
                                {
                                    drSel = dtLotAttrib.Select(" LotNo = '" + rLA["LotNo"] + "' And AttribNo = '" + rLA["AttribNo"] + "' ".ToString());
                                    if (drSel.Length == 0)
                                    {
                                        throw new iMESException.MESException("0000-200002", "[%LotNo%]:" +
                                            rLA["LotNo"] + " ,[%AttribNo%]: " + rLA["AttribNo"] + " [%NOT PASS ARGUMENTS%]");
                                    }
                                }

                                break;
                            }
                    }
                }

            }
            catch (iMESException.MESException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
            }

        }
        #endregion



        #region EAP 客制接口
        /// <summary>
        /// 首站进站
        /// </summary>
        /// <param name="aryMessage"></param>
        /// <param name="aryException"></param>
        /// <param name="MONO"></param>
        /// <param name="EQPID"></param>
        /// <returns></returns>
        public static bool funTrackIn_Inquiry(ref List<ArrayList> aryMessage, ref List<ArrayList> aryException, string MONO, string EQPID)
        {
            bool funTrackIn_Inquiry = default(bool);
            //bool r = false;
            string strSQL = default(string);
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();

            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            DataSet dsData = new DataSet();



            string strReturn = "";






            int EQPSTATE = 0; //设备管控闲置状态

            int nowEQPSTATE = 0; //现在设备管控闲置状态

            string strLotNo = "";//生产批号

            try
            {
                //先检查 设备状态是否是闲置

                //检查设备是否存在
                strSQL = "SELECT 1 FROM TBLEQPEQUIPMENTBASIS WHERE EQUIPMENTNO='" + EQPID + "' AND ISSUESTATE = 2";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    //throw new iMESException.MESException("0000-202001", +" ：设备不存在！");
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备不存在！%]");
                    return false;
                }
                drTemp.Close();

                //获取设备管控闲置状态是多少
                strSQL = "Select EQUIPMENTSTATE From TBLEQPSTATECONTROL Where CONTROLNO Is Not Null AND CONTROLTYPE ='EQP Break Down' AND CONTROLNO='Idle'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    EQPSTATE = Conversions.ToInteger(drTemp["EQUIPMENTSTATE"]);
                }
                else
                {
                    //throw new iMESException.MESException("0000-202001", "闲置状态未设定！");
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%设备闲置状态未设定!%]");
                    return false;
                }
                drTemp.Close();


                //获取现在设备的状态
                strSQL = "Select EQUIPMENTSTATE From tblEMSEquipmentState WHERE EQUIPMENTNO='" + EQPID + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    nowEQPSTATE = Conversions.ToInteger(drTemp["EQUIPMENTSTATE"]);
                }
                else
                {
                    //throw new iMESException.MESException("0000-202001", "闲置状态未设定！");

                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：状态未设定!%]");
                    return false;
                }
                drTemp.Close();

                //比较现在的状态和闲置状态是否一致
                if (nowEQPSTATE != EQPSTATE)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备非闲置状态,不能进站!%]");
                    return false;
                }


                //根据工单获取生产批
                strSQL = $"SELECT A.BASELOTNO,B.STATUS,B.LotStamp FROM TBLWIPLOTBASIS A INNER JOIN  TBLWIPLOTSTATE B ON A.BASELOTNO = B.LOTNO WHERE A.MONO='{MONO}' AND B.STATUS IN (0,1,2,3,4,5) AND A.LotState = '1'";
                ExecuteSQLQuery_Adapter(strSQL, dsData, "TBLWIPLOTBASIS", cnnTemp);

                if (dsData.Tables["TBLWIPLOTBASIS"].Rows.Count == 0)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: MONO + "[%：无在制生产批！%]");
                    return false;
                }

                if (dsData.Tables["TBLWIPLOTBASIS"].Rows.Count > 1)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: MONO + "[%：该工单有多个批次存在，请检查是否已上料！%]");
                    return false;
                }


                strLotNo = Conversions.ToString(dsData.Tables["TBLWIPLOTBASIS"].Rows[0]["BASELOTNO"]);

                //调用标准进站
                var datSendTime = default(DateTime);       // 送達時間
                object blnRuleCheck = true;
                bool blnEXETriggerOP = false;
                string strComputerName = string.Empty;   // Request Client ComputerName 
                string strCurUserNo = string.Empty;     // Request User -紀錄操作人員
                Dictionary<string, string> dicPars = new Dictionary<string, string>(); //固定引數,Request傳入的一般參數
                Dictionary<string, DataTable> dicPars_DataTable = new Dictionary<string, DataTable>(); //固定引數,Request傳入的DataTable參數

                //添加批号
                dicPars.Add("lotno", strLotNo);
                dicPars.Add("equipmentno", EQPID);


                AutoexecutionLot_Lot(ref blnEXETriggerOP, dicPars, dicPars_DataTable, "CI", datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck));

                funTrackIn_Inquiry = true;
                exitfun:
                ;
            }
            catch (Exception ex)
            {
                // 一行调用，拿到完整异常字符串
                string errorMsg = clsERP.GetExceptionFullMessage(ex);
                throw new Exception(errorMsg);
            }
            finally
            {



                drTemp?.Close();

                dsData?.Dispose();
                CloseConnection(cnnTemp);
            }
            return funTrackIn_Inquiry;

        }

        public static bool funTrackIn_InquirybyLot(ref List<ArrayList> aryMessage, ref List<ArrayList> aryException, string Lotid, string EQPID)
        {
            bool funTrackIn_Inquiry = default(bool);
            //bool r = false;
            string strSQL = default(string);
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();

            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            DataSet dsData = new DataSet();



            string strReturn = "";






            int EQPSTATE = 0; //设备管控闲置状态

            int nowEQPSTATE = 0; //现在设备管控闲置状态

            string strLotNo = "";//生产批号

            try
            {
                //先检查 设备状态是否是闲置

                //检查设备是否存在
                strSQL = "SELECT 1 FROM TBLEQPEQUIPMENTBASIS WHERE EQUIPMENTNO='" + EQPID + "' AND ISSUESTATE = 2";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    //throw new iMESException.MESException("0000-202001", +" ：设备不存在！");
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备不存在！%]");
                    return false;
                }
                drTemp.Close();

                //获取设备管控闲置状态是多少
                strSQL = "Select EQUIPMENTSTATE From TBLEQPSTATECONTROL Where CONTROLNO Is Not Null AND CONTROLTYPE ='EQP Break Down' AND CONTROLNO='Idle'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    EQPSTATE = Conversions.ToInteger(drTemp["EQUIPMENTSTATE"]);
                }
                else
                {
                    //throw new iMESException.MESException("0000-202001", "闲置状态未设定！");
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%设备闲置状态未设定!%]");
                    return false;
                }
                drTemp.Close();


                //获取现在设备的状态
                strSQL = "Select EQUIPMENTSTATE From tblEMSEquipmentState WHERE EQUIPMENTNO='" + EQPID + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    nowEQPSTATE = Conversions.ToInteger(drTemp["EQUIPMENTSTATE"]);
                }
                else
                {
                    //throw new iMESException.MESException("0000-202001", "闲置状态未设定！");

                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：状态未设定!%]");
                    return false;
                }
                drTemp.Close();

                //比较现在的状态和闲置状态是否一致
                if (nowEQPSTATE != EQPSTATE)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备非闲置状态,不能进站!%]");
                    return false;
                }


                //根据工单获取生产批
                strSQL = $"SELECT A.BASELOTNO,B.STATUS,B.LotStamp FROM TBLWIPLOTBASIS A INNER JOIN  TBLWIPLOTSTATE B ON A.BASELOTNO = B.LOTNO WHERE A.BASELOTNO='{Lotid}' AND B.STATUS IN (0,1,2,3,4,5) AND A.LotState = '1'";
                ExecuteSQLQuery_Adapter(strSQL, dsData, "TBLWIPLOTBASIS", cnnTemp);

                if (dsData.Tables["TBLWIPLOTBASIS"].Rows.Count == 0)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: Lotid + "[%：无在制生产批！%]");
                    return false;
                }

                if (dsData.Tables["TBLWIPLOTBASIS"].Rows.Count > 1)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: Lotid + "[%：请检查是否已上料！%]");
                    return false;
                }


                strLotNo = Conversions.ToString(dsData.Tables["TBLWIPLOTBASIS"].Rows[0]["BASELOTNO"]);

                //调用标准进站
                var datSendTime = default(DateTime);       // 送達時間
                object blnRuleCheck = true;
                bool blnEXETriggerOP = false;
                string strComputerName = string.Empty;   // Request Client ComputerName 
                string strCurUserNo = string.Empty;     // Request User -紀錄操作人員
                Dictionary<string, string> dicPars = new Dictionary<string, string>(); //固定引數,Request傳入的一般參數
                Dictionary<string, DataTable> dicPars_DataTable = new Dictionary<string, DataTable>(); //固定引數,Request傳入的DataTable參數

                //添加批号
                dicPars.Add("lotno", strLotNo);
                dicPars.Add("equipmentno", EQPID);


                AutoexecutionLot_Lot(ref blnEXETriggerOP, dicPars, dicPars_DataTable, "CI", datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck));
                funTrackIn_Inquiry = true;
                exitfun:
                ;
            }
            catch (Exception ex)
            {
                // 一行调用，拿到完整异常字符串
                string errorMsg = clsERP.GetExceptionFullMessage(ex);
                throw new Exception(errorMsg);
            }
            finally
            {



                drTemp?.Close();

                dsData?.Dispose();
                CloseConnection(cnnTemp);
            }
            return funTrackIn_Inquiry;

        }
        /// <summary>
        /// 首站出站
        /// </summary>
        /// <param name="aryMessage"></param>
        /// <param name="aryException"></param>
        /// <param name="MONO"></param>
        /// <param name="EQPID"></param>
        /// <param name="PanleId"></param>
        /// <param name="Column"></param>
        /// <param name="Line"></param>
        /// <param name="carrierId"></param>
        /// <param name="Qty"></param>
        /// <param name="MapData">来料不良图谱，第 k 位为 '0' 表示该位置不良；不传则不打不良</param>
        /// <returns></returns>
        public static bool funTrackOut_Inquiry(ref List<ArrayList> aryMessage, ref List<ArrayList> aryException, string MONO, string EQPID, string PanleId, string Column, string Line, string carrierId, decimal Qty, string MapData = "")
        {
            bool funTrackOut_Inquiry = default(bool);
            //bool r = false;
            string strSQL = default(string);
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();


            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            DataSet dsData = new DataSet();



            string strReturn = "";


            string strMLotNo = "";//母生产批号
            string strNLotNo = "";//子生产批号
            string strProductNo = "";//产品号
            string strProductVersion = "";//产品版本
            string strSeqNoRule = "";//序号规则
            string strSeqNoType = "";//序号类别
            string strSeqNoSize = "";//起始位置
            string strDirection = "";//走向
            string strOPNO = "";

            string strUnitIdOrPannid = "";//UnitId或者Pannid

            bool bolLastLot = false;//是否是最后一笔

            DataSet dataSetLotNo = new DataSet();

            kcWIP.clsLot objLot = new kcWIP.clsLot();

            Collection CollectionSQL = new Collection();

            bool bolInsertMONoProperty = false; //插入工单属性

            decimal decMQTY = 0; //母批数量

            try
            {
                //先检查 设备状态是否是闲置

                //检查设备是否存在
                strSQL = "SELECT 1 FROM TBLEQPEQUIPMENTBASIS WHERE EQUIPMENTNO='" + EQPID + "' AND ISSUESTATE = 2";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备不存在！%]");
                    return false;
                }
                drTemp.Close();




                //根据工单获取生产批
                strSQL = $"SELECT A.BASELOTNO,B.STATUS FROM TBLWIPLOTBASIS A INNER JOIN  TBLWIPLOTSTATE B ON A.BASELOTNO = B.LOTNO WHERE A.MONO='{MONO}' AND B.STATUS IN (0,1,2,3,4,5) AND A.LotState = '1'";
                ExecuteSQLQuery_Adapter(strSQL, dsData, "TBLWIPLOTBASIS", cnnTemp);

                if (dsData.Tables["TBLWIPLOTBASIS"].Rows.Count == 0)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: MONO + "[%：无在制生产批！%]");
                    return false;
                }



                if (dsData.Tables["TBLWIPLOTBASIS"].Rows.Count > 1)
                {
                    //存在多个生产批，如果查出来多个批次，则查找工单属性中的批次进行分批
                    strSQL = "SELECT PROPERTYVALUE FROM TBLOEMOPROPERTY WHERE MONO='" + MONO + "' AND  LOWER(PROPERTYNO) = LOWER('firstlotno')";
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (!drTemp.Read())
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: MONO + "[%：不能存在firstlotno工单属性！%]");
                        return false;
                    }
                    else
                    {
                        strMLotNo = Conversions.ToString(drTemp["PROPERTYVALUE"]);
                    }
                    drTemp.Close();
                }
                else
                {
                    //只有一笔
                    strMLotNo = Conversions.ToString(dsData.Tables["TBLWIPLOTBASIS"].Rows[0]["BASELOTNO"]);

                    //只有一笔则插入工单属性
                    bolInsertMONoProperty = true;
                }


                if (string.IsNullOrEmpty(strMLotNo))
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: MONO + "[%：无在制母生产批！%]");
                    return false;
                }


                //获取母批的基本信息
                strSQL = $"SELECT A.PRODUCTNO,A.PRODUCTVERSION,B.STATUS,B.CURQTY,B.OPNO,B.LOTSTAMP FROM TBLWIPLOTBASIS A LEFT JOIN TBLWIPLOTSTATE  B ON A.BASELOTNO = B.LOTNO WHERE A.BASELOTNO ='{strMLotNo}'";
                ExecuteSQLQuery_Adapter(strSQL, dsData, "TBLWIPLOTBASIS_MLOT", cnnTemp);

                if (dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows.Count == 0)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: strMLotNo + "[%：批次状态不是执行中，不允许出站！%]");
                    return false;
                }

                //检查母批状态是否是执行中 STATUS 是否为 1
                if (Conversions.ToInteger(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["STATUS"]) != 1)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: strMLotNo + "[%：母生产批状态不是执行中！%]");
                    return false;
                }


                //判断母批是否够分
                if (Convert.ToDecimal(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["CURQTY"]) <= Qty)
                {
                    //不够分或者刚好
                    bolLastLot = true; //母批则作为最后一批出站，保留母批分批

                    decMQTY = Convert.ToDecimal(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["CURQTY"]);
                }


                //判断产品是否绑定了panleid&unit序号规则

                strProductNo = Conversions.ToString(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["PRODUCTNO"]);
                strProductVersion = Conversions.ToString(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["PRODUCTVERSION"]);
                strOPNO = Conversions.ToString(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["OPNO"]);

                strSQL = "SELECT PANLEID,UNITID,STARTPOINT,DIRECTION FROM TBLPRDPRODUCTBASIS WHERE PRODUCTNO='" + strProductNo + "' AND PRODUCTVERSION='" + strProductVersion + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    if (drTemp["PANLEID"].ToString().Trim() != "")
                    {
                        strSeqNoRule = drTemp["PANLEID"].ToString().Trim();
                        strSeqNoType = "PANLEID";
                        strSeqNoSize = drTemp["STARTPOINT"].ToString().Trim();
                        strDirection = drTemp["DIRECTION"].ToString().Trim();
                    }

                    //优先选择UNITID规则
                    if (drTemp["UNITID"].ToString().Trim() != "")
                    {
                        strSeqNoRule = drTemp["UNITID"].ToString().Trim();
                        strSeqNoType = "UNITID";
                        strSeqNoSize = drTemp["STARTPOINT"].ToString().Trim();
                        strDirection = drTemp["DIRECTION"].ToString().Trim();
                    }
                }
                else
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%产品编号%] :" + strProductNo + " [%产品版本%] :" + strProductVersion + "[%未panleid&unit序号规则%]");
                    return false;
                }
                drTemp.Close();

                if (strSeqNoRule == "")
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%产品编号%] :" + strProductNo + " [%产品版本%] :" + strProductVersion + "[%未panleid&unit序号规则%]");
                    return false;
                }
                if (strSeqNoSize == "" || strDirection == "")
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%产品编号%] :" + strProductNo + " [%产品版本%] :" + strProductVersion + "[%未维护初始位置和走向%]");
                    return false;
                }





                //检查母批是否可以分批
                objLot.ChkLotStamp(strMLotNo, Convert.ToInt32(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["LOTSTAMP"]), pOPNo: Convert.ToString(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["OPNO"]), pStatus: Convert.ToInt32(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["STATUS"]));



                //先生成序号
                int intColumn = int.Parse(Column);
                int intLine = int.Parse(Line);

                string[,] unitIdOrPannids = new string[intLine, intColumn];
                string[,] locations = new string[intLine, intColumn];

                //产生位置号与序号（原地逐字抽出为公共方法，行为不变）
                if (!funInitDieSerial(ref aryMessage, ref aryException, PanleId, strMLotNo, strProductNo, strProductVersion, strSeqNoRule, strSeqNoType, strSeqNoSize, strDirection, intColumn, intLine, unitIdOrPannids, locations, cnnTemp))
                {
                    return false;
                }
                
                //(xg)根据 mapdata 字段中为1的数量作为子批数量进行分批（只分良品，不分不良品）-- 龙旗定制
                //(xg)原逻辑: 直接使用报文 Qty 作为子批数量进行分批
                decimal intGoodCount = Qty;
                if (!string.IsNullOrEmpty(MapData) && MapData.Length == intColumn * intLine)
                {
                    //(xg)统计 mapdata 中良品(值为1)的数量
                    intGoodCount = 0;
                    foreach (char c in MapData)
                    {
                        if (c == '1')
                            intGoodCount++;
                    }
                    //(xg)重新判断母批是否够分，使用良品数量；无良品时不分批
                    if (Convert.ToDecimal(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["CURQTY"]) <= intGoodCount || intGoodCount == 0)
                    {
                        bolLastLot = true;
                        decMQTY = Convert.ToDecimal(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["CURQTY"]);
                    }
                    else
                    {
                        bolLastLot = false;
                        decMQTY = Convert.ToDecimal(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["CURQTY"]);
                    }
                }
                //如果够分批，则执行分批
                if (!bolLastLot)
                {
                    string newSplitLot = string.Empty; //子批
                    string newSplitLotXml = string.Empty; //子批
                    long LotStamp;
                    DataTable dtSplitLot;
                    decimal MCurQty = 0;
                    string ProductNo = string.Empty;
                    string ProductVersion = string.Empty;
                    string oldCarrierNo = string.Empty;
                    string OPNo = defString;
                    string ShiftNo = "N/A";
                    string userNo = "EAP_AGENT";

                    //开始分批
                    //******************************start 开始拆批****************************
                    //刷新生产批信息
                    LoadLotBasisJoinState_M1001(ref dataSetLotNo, BaseLotNo: strMLotNo);

                    //1.先检查拆批的生产批资料是否存在
                    if (dataSetLotNo.Tables["BasisJoinState"].Rows.Count == 0)
                    {
                        throw new Exception($" 未找{strMLotNo}对应生产批资料!");
                    }

                    //获取拆批前所需要的资料
                    //母批的LotStamp
                    object lotStampValue = dataSetLotNo.Tables["BasisJoinState"].Rows[0]["LotStamp"];
                    LotStamp = lotStampValue == DBNull.Value ? 0 : Convert.ToInt64(lotStampValue);

                    dtSplitLot = new DataTable("SplitLot");
                    dtSplitLot.Columns.Add("SplitLotNo", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("SplitLotQty", Type.GetType("System.Double"));
                    dtSplitLot.Columns.Add("Action", Type.GetType("System.Int32"));
                    dtSplitLot.Columns.Add("NodeID", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("ReturnType", Type.GetType("System.Int32"));
                    // 2005/08/15
                    dtSplitLot.Columns.Add("ProductNo", Type.GetType("System.String"));
                    dtSplitLot.Columns.Add("ProductVersion", Type.GetType("System.String"));
                    // 2008/05/22
                    dtSplitLot.Columns.Add("CarrierNo", Type.GetType("System.String"));
                    // 2021/10/14 生產批歷程欄位新增
                    dtSplitLot.Columns.Add("OPNo", Type.GetType("System.String"));


                    //取新批号
                    //依数量分批
                    MCurQty = Convert.ToDecimal(dataSetLotNo.Tables["BasisJoinState"].Rows[0]["CURQTY"].ToString());
                    ProductNo = dataSetLotNo.Tables["BasisJoinState"].Rows[0]["ProductNo"].ToString();
                    ProductVersion = dataSetLotNo.Tables["BasisJoinState"].Rows[0]["ProductVersion"].ToString();
                    OPNo = dataSetLotNo.Tables["BasisJoinState"].Rows[0]["ProductVersion"].ToString();





                    //放母批
                    DataRow newSplitLotData = dtSplitLot.NewRow();
                    newSplitLotData["SplitLotNo"] = strMLotNo;
                    //(xg)原: newSplitLotData["SplitLotQty"] = MCurQty - Qty;
                    newSplitLotData["SplitLotQty"] = MCurQty - intGoodCount;
                    newSplitLotData["Action"] = 0;
                    newSplitLotData["NodeID"] = "";
                    newSplitLotData["ReturnType"] = 0;
                    newSplitLotData["ProductNo"] = ProductNo;
                    newSplitLotData["ProductVersion"] = ProductVersion;
                    newSplitLotData["OPNo"] = OPNo;
                    dtSplitLot.Rows.Add(newSplitLotData);

                    //直接取新批号 [直接回写数据库]
                    using (kcSYS.clsSYSEng objSYSEng = new kcSYS.clsSYSEng())
                    {
                        newSplitLotXml = objSYSEng.GetSplitLotNo_Multiple(true, 1, strMLotNo);
                    }

                    //获取到xml之后解析
                    xmlDoc.LoadXml(newSplitLotXml);

                    //获取子批
                    newSplitLot = xmlDoc.GetElementsByTagName("InitSplitLotNo").Item(0)
                                                .SelectNodes("LotNo").Item(0).InnerXml;


                    strNLotNo = newSplitLot;

                    //放子批
                    DataRow newSplitLotData2 = dtSplitLot.NewRow();
                    newSplitLotData2["SplitLotNo"] = newSplitLot;
                    //(xg)原: newSplitLotData2["SplitLotQty"] = Qty;
                    newSplitLotData2["SplitLotQty"] = intGoodCount;
                    newSplitLotData2["Action"] = 0;
                    newSplitLotData2["NodeID"] = "";
                    newSplitLotData2["ReturnType"] = 0;
                    newSplitLotData2["ProductNo"] = ProductNo;
                    newSplitLotData2["ProductVersion"] = ProductVersion;
                    newSplitLotData2["OPNo"] = OPNo;
                    dtSplitLot.Rows.Add(newSplitLotData2);

                    //做BR分批
                    //objLot.BR_Manual_LotSplit(LotStamp, strMLotNo, 1, userNo, dtSplitLot, ShiftNo: ShiftNo);

                    //母批不出站
                    BR_Manual_LotSplit_M(LotStamp, strMLotNo, 1, userNo, dtSplitLot, ShiftNo: ShiftNo);

                    //******************************end 开始拆批****************************

                    ////开始生产批转移,生产批转移需要走隐藏站规则，因为有客制，所以调用MEStc的功能，防止后续改动导致EAP出错
                    string strLinkName = "PASS";
                    string strMailGroupNo = "";
                    string strMsg = "";
                    string strRuleNo = defString;
                    int intERFType = 0;
                    string strERFMsg = "";
                    string ComputerName = System.Net.Dns.GetHostName();
                    BRTransferLot_Bin_M(newSplitLot, "EAP", strLinkName, intERFType, strRuleNo, ComputerName: ComputerName, RuleMsg: strERFMsg);

                }
                else
                {
                    //母批作为最后一批直接出站

                    //调用标准进站
                    var datSendTime = default(DateTime);       // 送達時間
                    object blnRuleCheck = true;
                    bool blnEXETriggerOP = false;
                    string strComputerName = string.Empty;   // Request Client ComputerName 
                    string strCurUserNo = string.Empty;     // Request User -紀錄操作人員
                    Dictionary<string, string> dicPars = new Dictionary<string, string>(); //固定引數,Request傳入的一般參數
                    Dictionary<string, DataTable> dicPars_DataTable = new Dictionary<string, DataTable>(); //固定引數,Request傳入的DataTable參數

                    //添加批号
                    dicPars.Add("lotno", strMLotNo);
                    dicPars.Add("equipmentno", EQPID);

                    //出站明细
                    DataTable dtLotAttrib = new DataTable(); //特性
                    //添加LotNo列
                    dtLotAttrib.Columns.Add("LotNo", typeof(string));
                    dtLotAttrib.Columns.Add("AttribNo", typeof(string));
                    dtLotAttrib.Columns.Add("AttribValue", typeof(string));



                    //查询生产批的绑定特性，这里是出站，所以使用TEMP表
                    strSQL = $"SELECT  ATTRIBNO,ATTRIBVALUE FROM TBLWIPTEMP_ATTRIB WHERE LOTNO='{strMLotNo}'";
                    ExecuteSQLQuery_Adapter(strSQL, dsData, "TBLWIPTEMP_ATTRIB", cnnTemp);
                    if (dsData.Tables["TBLWIPTEMP_ATTRIB"].Rows.Count > 0)
                    {
                        foreach (DataRow dr in dsData.Tables["TBLWIPTEMP_ATTRIB"].Rows)
                        {
                            DataRow drLotAttrib = dtLotAttrib.NewRow();
                            drLotAttrib["LotNo"] = strMLotNo;
                            drLotAttrib["AttribNo"] = dr["ATTRIBNO"].ToString();
                            if (dr["AttribNo"].ToString() == "GoodQty")
                            {
                                drLotAttrib["AttribValue"] = decMQTY;

                            }
                            else if (dr["AttribNo"].ToString() == "ScrapQty")
                            {
                                drLotAttrib["AttribValue"] = 0;
                            }
                            else if (dr["AttribNo"].ToString() == "DefectQty")
                            {
                                drLotAttrib["AttribValue"] = 0;
                            }
                            else
                            {
                                drLotAttrib["AttribValue"] = dr["ATTRIBVALUE"].ToString();
                            }

                            dtLotAttrib.Rows.Add(drLotAttrib);
                        }
                    }


                    dicPars_DataTable.Add("lotattrib", dtLotAttrib);



                    AutoexecutionLot_Lot(ref blnEXETriggerOP, dicPars, dicPars_DataTable, "CO", datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck));



                }





                //个案表开始处理

                //要对那个批次做个案表处理
                string inLotNo = strMLotNo;
                if (strNLotNo != "")
                {
                    //若有子批，则传子批
                    inLotNo = strNLotNo;
                }

                //查询新批次的MNewLotSerial
                string strMNewLotSerial = "";

                strSQL = $"SELECT A.BASELOTNO,B.LOTSERIAL FROM TBLWIPLOTBASIS A LEFT JOIN TBLWIPLOTSTATE B ON A.BASELOTNO=B.LOTNO WHERE A.BASELOTNO='{inLotNo}'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: inLotNo + "[%：生产批无 LOTSERIAL！%]");
                    return false;
                }
                else
                {
                    strMNewLotSerial = Conversions.ToString(drTemp["LOTSERIAL"]);
                }
                drTemp.Close();




                //如果报文中传了carrierid，则子批进行上载具操作，存TBLWIPCARRIERSTATE/TBLWIPCARRIERSTATElLOG表。若没有传carrierid，则不进行上载具操作。
                if (!string.IsNullOrEmpty(carrierId))
                {
                    //上载具

                    string strCarrierType = ""; //载具类别

                    int CurCarrierPosition = 1;     // 当前位置

                    //载具基础资料检查
                    strSQL = "Select CarrierNo,CarrierState,CarrierType From tblWIPCarrierState Where CarrierNo Is Not Null  And CarrierNo = '" + carrierId + "'";
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (drTemp.Read())
                    {
                        if (drTemp["CarrierState"].ToString().Trim() != "1" && drTemp["CarrierState"].ToString().Trim() != "0")
                        {
                            clsERP.combineMessage(ref aryMessage, mmsg: "[%载具编号%] :" + carrierId + "[% 只有待使用和使用中状态的载具才可以上载具!%] ");
                            return false;
                        }

                        strCarrierType = drTemp["CarrierType"].ToString().Trim();
                    }
                    else
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%载具编号%] :" + carrierId + "[%不存在!%] ");
                        return false;
                    }
                    drTemp.Close();

                    //载具寿命检查
                    bool isCheckResult = CheckCarrierLife_M(carrierId, strCarrierType, UserNo: "EAP");
                    if (!isCheckResult)
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%载具编号%] :" + carrierId + "[%当前载具已经达到预警寿命!%] ");
                        return false;
                    }

                    //获取现在最大的位置
                    strSQL = "Select Count(CarrierPosition) CountPosition From tblWIPCarrierStateDetail Where CarrierNo = '" + carrierId + "'";
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (drTemp.Read())
                    {
                        CurCarrierPosition = Conversions.ToInteger(drTemp["CountPosition"]);
                    }
                    drTemp.Close();

                    if (CurCarrierPosition == 0)
                    {
                        CurCarrierPosition = 1;
                    }

                    using (kcEQP.clsCarrierBasis objCarrierBasis = new kcEQP.clsCarrierBasis())
                    {
                        //检查容量
                        objCarrierBasis.CheckPutsOnUnitID(carrierId, inLotNo, CurCarrierPosition);


                    }

                    //检查无问题，则上载具，这里支持回复处理
                    AddCarrierStateDetail_M(carrierId, "EAP", inLotNo, CurCarrierPosition, UserNo: "EAP", LotSerial: strMNewLotSerial, colSQL: CollectionSQL);

                }

                //记录 　然后将对应数据存到客制表TBLWIPPRDSTATE_LQ&TBLWIPPRDLOG_LQ,具体取值参考1.4中的数据库表的明细。


                SaveWIPPrdStateLog_M(LotNo: inLotNo, ProductID: PanleId, EQPID: EQPID, OPNo: strOPNO, State: 1, ProductType: "0", CarrierID: carrierId, LotSerial: strMNewLotSerial, colSQL: CollectionSQL);


                //for (int i = 0; i < intLine; i++)
                //{
                //    for (int j = 0; j < intColumn; j++)
                //    {
                //        WriteLog(unitIdOrPannids[i, j]);
                //    }
                //}

                //写入客制表 TBLPCSDIELOG_LQ（原地逐字抽出为公共方法，行为不变）
                funSaveDieLog(PanleId, inLotNo, EQPID, strOPNO, intColumn, intLine, carrierId, strMNewLotSerial, unitIdOrPannids, locations, CollectionSQL);

                //(xg)原: if (!funMarkBadByMapData(ref aryMessage, PanleId, inLotNo, MapData, strSeqNoSize, strDirection, intColumn, intLine, CollectionSQL))
                //(xg)改: 新增 unitIdOrPannids, strMLotNo 参数 — 不良品归属母批 + 同步更新客制状态表
                //解析 mapdata 打不良（来料异常）；走位设定与产生 LOCATIONNO 时同源；不良品归属母批，同步更新客制状态表
                if (!funMarkBadByMapData(ref aryMessage, PanleId, inLotNo, MapData, strSeqNoSize, strDirection, intColumn, intLine, CollectionSQL, unitIdOrPannids, strMLotNo))
                {
                    return false;
                }




                if (bolInsertMONoProperty)
                {
                    //这里查询一遍是为了并非调用时防止INSERT失败
                    strSQL = "SELECT PROPERTYVALUE FROM TBLOEMOPROPERTY WHERE MONO='" + MONO + "' AND  LOWER(PROPERTYNO) = LOWER('firstlotno')";
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (!drTemp.Read())
                    {
                        //不存在则插入
                        strSQL = $"INSERT INTO TBLOEMOPROPERTY (MONO, PROPERTYNO, PROPERTYVALUE, LOTSERIAL) VALUES ('{MONO}', 'firstlotno', '{strMLotNo}', null)";
                        CollectionSQL.Add(strSQL);

                        strSQL = $"DELETE FROM TBLOEMOPROPERTY WHERE MONO='{MONO}' AND PROPERTYNO='firstlotno'";

                        objReverse.AddReverseUpdateContent(ref strMNewLotSerial, ref strSQL, CollectionSQL);
                    }
                    else
                    {
                        //若是存在，则不是需要再更新

                        ////存在则更新
                        //strSQL = $"UPDATE TBLOEMOPROPERTY SET PROPERTYVALUE = '{strMLotNo}' WHERE MONO = '{MONO}' AND LOWER(PROPERTYNO) = LOWER('firstlotno')";
                        //CollectionSQL.Add(strSQL);
                    }
                    drTemp.Close();
                }

                if (CollectionSQL.Count > 0)
                {
                    ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);
                }


                funTrackOut_Inquiry = true;
                exitfun:
                ;
            }
            catch (Exception ex)
            {
                // 一行调用，拿到完整异常字符串
                string errorMsg = clsERP.GetExceptionFullMessage(ex);
                throw new Exception(errorMsg);
            }
            finally
            {

                if (objLot != null)
                {
                    objLot = null;
                }

                drTemp?.Close();

                dsData?.Dispose();
                CloseConnection(cnnTemp);
            }
            return funTrackOut_Inquiry;

        }

        private static void funInitlocation(string[,] location, string strSeqNoSize, string strDirection, int intColumn, int intLine)
        {
            // intColumn = 行数 (row)
            // intLine = 列数 (col)
            int totalPoints = intColumn * intLine;
            int maxNumberLength = totalPoints.ToString().Length;
            int index = 1;

            switch (strSeqNoSize)  // 起始角
            {
                case "左上":  // 起始点 (0, 0)
                    {
                        if (strDirection == "横向")  // S型横向
                        {
                            for (int row = 0; row < intColumn; row++)
                            {
                                if (row % 2 == 0)  // 偶数行从左到右
                                {
                                    for (int col = 0; col < intLine; col++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数行从右到左
                                {
                                    for (int col = intLine - 1; col >= 0; col--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "竖向")  // S型竖向
                        {
                            for (int col = 0; col < intLine; col++)
                            {
                                if (col % 2 == 0)  // 偶数列从上到下
                                {
                                    for (int row = 0; row < intColumn; row++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数列从下到上
                                {
                                    for (int row = intColumn - 1; row >= 0; row--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "全部横向")  // 单一方向横向：始终从左到右
                        {
                            for (int row = 0; row < intColumn; row++)
                            {
                                for (int col = 0; col < intLine; col++)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        else if (strDirection == "全部竖向")  // 单一方向竖向：始终从上到下
                        {
                            for (int col = 0; col < intLine; col++)
                            {
                                for (int row = 0; row < intColumn; row++)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        break;
                    }
                case "左下":  // 起始点 (0, intColumn-1)
                    {
                        if (strDirection == "横向")  // S型横向
                        {
                            for (int row = intColumn - 1; row >= 0; row--)
                            {
                                if ((intColumn - 1 - row) % 2 == 0)  // 偶数行（从底部数）从左到右
                                {
                                    for (int col = 0; col < intLine; col++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数行（从底部数）从右到左
                                {
                                    for (int col = intLine - 1; col >= 0; col--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "竖向")  // S型竖向
                        {
                            for (int col = 0; col < intLine; col++)
                            {
                                if (col % 2 == 0)  // 偶数列从下到上
                                {
                                    for (int row = intColumn - 1; row >= 0; row--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数列从上到下
                                {
                                    for (int row = 0; row < intColumn; row++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "全部横向")  // 单一方向横向：始终从左到右
                        {
                            for (int row = intColumn - 1; row >= 0; row--)
                            {
                                for (int col = 0; col < intLine; col++)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        else if (strDirection == "全部竖向")  // 单一方向纵向：始终从下到上
                        {
                            for (int col = 0; col < intLine; col++)
                            {
                                for (int row = intColumn - 1; row >= 0; row--)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        break;
                    }
                case "右上":  // 起始点 (intLine-1, 0)
                    {
                        if (strDirection == "横向")  // S型横向
                        {
                            for (int row = 0; row < intColumn; row++)
                            {
                                if (row % 2 == 0)  // 偶数行从右到左
                                {
                                    for (int col = intLine - 1; col >= 0; col--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数行从左到右
                                {
                                    for (int col = 0; col < intLine; col++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "竖向")  // S型竖向
                        {
                            for (int col = intLine - 1; col >= 0; col--)
                            {
                                if ((intLine - 1 - col) % 2 == 0)  // 偶数列（从右数）从上到下
                                {
                                    for (int row = 0; row < intColumn; row++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数列（从右数）从下到上
                                {
                                    for (int row = intColumn - 1; row >= 0; row--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "全部横向")  // 单一方向横向：始终从右到左
                        {
                            for (int row = 0; row < intColumn; row++)
                            {
                                for (int col = intLine - 1; col >= 0; col--)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        else if (strDirection == "全部竖向")  // 单一方向竖向：始终从上到下
                        {
                            for (int col = intLine - 1; col >= 0; col--)
                            {
                                for (int row = 0; row < intColumn; row++)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        break;
                    }
                case "右下":  // 起始点 (intLine-1, intColumn-1)
                    {
                        if (strDirection == "横向")  // S型横向
                        {
                            for (int row = intColumn - 1; row >= 0; row--)
                            {
                                if ((intColumn - 1 - row) % 2 == 0)  // 偶数行（从底部数）从右到左
                                {
                                    for (int col = intLine - 1; col >= 0; col--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数行（从底部数）从左到右
                                {
                                    for (int col = 0; col < intLine; col++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "竖向")  // S型竖向
                        {
                            for (int col = intLine - 1; col >= 0; col--)
                            {
                                if ((intLine - 1 - col) % 2 == 0)  // 偶数列（从右数）从下到上
                                {
                                    for (int row = intColumn - 1; row >= 0; row--)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                                else  // 奇数列（从右数）从上到下
                                {
                                    for (int row = 0; row < intColumn; row++)
                                    {
                                        location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                        index++;
                                    }
                                }
                            }
                        }
                        else if (strDirection == "全部横向")  // 单一方向横向：始终从右到左
                        {
                            for (int row = intColumn - 1; row >= 0; row--)
                            {
                                for (int col = intLine - 1; col >= 0; col--)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        else if (strDirection == "全部竖向")  // 单一方向竖向：始终从下到上
                        {
                            for (int col = intLine - 1; col >= 0; col--)
                            {
                                for (int row = intColumn - 1; row >= 0; row--)
                                {
                                    location[col, row] = index.ToString().PadLeft(maxNumberLength, '0');
                                    index++;
                                }
                            }
                        }
                        break;
                    }
            }
        }


        /// <summary>
        /// copy标准，支持回复处理
        /// </summary>
        /// <param name="CarrierNo"></param>
        /// <param name="BCIP"></param>
        /// <param name="ContentID"></param>
        /// <param name="CarrierPosition"></param>
        /// <param name="ContentFlag"></param>
        /// <param name="AdditionalXml"></param>
        /// <param name="ComponentNo"></param>
        /// <param name="UserNo"></param>
        /// <returns></returns>
        // 新增載具內容
        // 傳入值: 各欄位新增值
        // 傳回值: success(成功), fail(失敗)
        public static string AddCarrierStateDetail_M(string CarrierNo, string BCIP, string ContentID, int CarrierPosition = 1, int ContentFlag = 0, string AdditionalXml = "", string ComponentNo = "N/A", string UserNo = defString, string LotSerial = defString, Collection colSQL = null)
        {
            string AddCarrierStateDetailRet = default(string);
            // CarrierPosition：預設放置為第1個位置
            // ContentFlag：0:Tray 1:Stocker
            // 200612/15 Ben 新增ComponentNo

            var CollectionSQL = new Collection();
            string strSQLAddField = "";
            string strSQLAddValue = "";
            string strSQL = "";
            kcEQP.clsCarrierBasis objCarrierBasis = new kcEQP.clsCarrierBasis();

            try
            {
                // //Combine SQL
                strSQLAddField = "Insert Into tblWIPCarrierStateDetail (CarrierNo,CarrierPosition,BCIP,ContentID,Flag,LotNo,ComponentNo";
                strSQLAddValue = " Values ('" + CarrierNo + "'," + CarrierPosition + ",'" + BCIP + "','" + ContentID + "'," + ContentFlag + ",'" + ContentID + "','" + ComponentNo + "'";

                if (string.IsNullOrEmpty(AdditionalXml))
                {
                    // 當沒有額外的欄位時,直接給定strSQL
                    strSQL = strSQLAddField + ")" + strSQLAddValue + ")";
                }
                else
                {
                    // 加上additional的field & value 後傳回
                    strSQL = SeparateAddXML_Add(ref strSQLAddField, ref strSQLAddValue, AdditionalXml);
                }
                CollectionSQL.Add(strSQL);


                strSQL = $"DELETE FROM tblWIPCarrierStateDetail WHERE  CarrierNo='{CarrierNo}' AND LotNo ='{ContentID}'";
                //回复处理
                objReverse.AddReverseUpdateContent(ref LotSerial, ref strSQL, CollectionSQL);



                strSQL = " Update tblWIPLotState Set CarrierNo = '" + CarrierNo + "' Where LotNo = '" + ContentID + "' ";
                CollectionSQL.Add(strSQL);



                strSQL = " Update tblWIPLotState Set CarrierNo = '' Where LotNo = '" + ContentID + "' ";
                //回复处理
                objReverse.AddReverseUpdateContent(ref LotSerial, ref strSQL, CollectionSQL);


                //xuyan 2023/5/31 上载具更改载具状态，载具上有批号 CarrierState=1
                objCarrierBasis.UpdateCarrierState(ref CollectionSQL, CarrierNo, UserNo, 1);

                //收集
                if (colSQL != null)
                {
                    foreach (var item in CollectionSQL)
                    {
                        colSQL.Add(item);
                    }
                }

                //執行SQL指令
                //ExecuteSQLNoneQuery_UPD(Convert.ToString(DataBaseType), strConnectionString, CollectionSQL);

                //Return success
                AddCarrierStateDetailRet = "success";
            }
            catch (Exception e1)
            {
                // 回傳失敗
                AddCarrierStateDetailRet = "fail";

                // 發生錯誤時丟回本身的Function Name及系統錯誤訊息
                throw;

            } // New Exception("kcEQP.AddCarrierStateDetail: " & e1.Message)
            finally
            {
                if (objCarrierBasis != null)
                {
                    objCarrierBasis.Dispose();
                }
            }

            return AddCarrierStateDetailRet;


        }




        /// <summary>
        /// copy 标准，刷生产批信息
        /// </summary>
        /// <param name="dsTemp"></param>
        /// <param name="BaseLotNo"></param>
        /// <param name="OPNo"></param>
        /// <param name="Status"></param>
        /// <param name="OrgLotNo"></param>
        /// <param name="BatchNo"></param>
        /// <param name="BoxNo"></param>
        /// <param name="BatchSerial"></param>
        /// <param name="LotState"></param>
        /// <param name="RONo"></param>
        /// <param name="ItemNo"></param>
        /// <param name="MONo"></param>
        /// <param name="ProductNo"></param>
        /// <param name="ProductVersion"></param>
        /// <param name="CustomerNo"></param>
        /// <param name="HotLot"></param>
        /// <param name="EndWIPDate"></param>
        /// <param name="FromWIPDate"></param>
        /// <param name="LotNo"></param>
        /// <param name="LotSerial"></param>
        /// <param name="ProcessNo"></param>
        /// <param name="NodeId"></param>
        /// <param name="BRNo"></param>
        /// <param name="PSNo"></param>
        /// <param name="PhaseNo"></param>
        /// <param name="HaveComponent"></param>
        /// <param name="HaveLevel"></param>
        /// <param name="LinkName"></param>
        /// <param name="ERFStatus"></param>
        /// <param name="AreaNo"></param>
        /// <param name="ProcessVersion"></param>
        /// <param name="SORGLotNo"></param>
        /// <param name="AdditionalXml"></param>
        /// <param name="CustomerLotNo"></param>
        /// <param name="ComponentNo"></param>
        /// <param name="FactoryNo"></param>
        /// <param name="CurQTY"></param>
        /// <param name="blnShowPartialLot"></param>
        /// <param name="PartialType"></param>
        /// <returns></returns>
        public static string LoadLotBasisJoinState_M1001(ref DataSet dsTemp, string BaseLotNo = defString, string OPNo = defString, string Status = defString, string OrgLotNo = defString, string BatchNo = defString, string BoxNo = defString, string BatchSerial = defString, string LotState = defString, string RONo = defString, int ItemNo = defInteger, string MONo = defString, string ProductNo = defString, string ProductVersion = defString, string CustomerNo = defString, int HotLot = defInteger,
          DateTime EndWIPDate = default(DateTime), DateTime FromWIPDate = default(DateTime), string LotNo = defString, string LotSerial = defString, string ProcessNo = defString, string NodeId = defString, string BRNo = defString, string PSNo = defString, string PhaseNo = defString, int HaveComponent = defInteger, int HaveLevel = defInteger, string LinkName = defString, string ERFStatus = defString, string AreaNo = defString, string ProcessVersion = defString, string SORGLotNo = defString, string AdditionalXml = "", string CustomerLotNo = defString, string ComponentNo = defString, string FactoryNo = defString, int CurQTY = defInteger, bool blnShowPartialLot = true, int PartialType = defInteger)
        {
            string LoadLotBasisJoinState = default(string);
            // 此 Function 將資料以XML方式取出
            // 傳入值: 索引值

            IDbConnection cnnTemp = null;
            AppSettings objSetting = new AppSettings();
            var drTemp = default(DbDataReader);
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            string strSQL = "";
            try
            {
                // 2013/03/13, Hank, 開啟Report Mode
                cnnTemp = CreateConnection(strConnectionString);



                // 2016/12/26 YF, 取出作業站多人加工模式MultiOperatorMode
                // 2016/10/19 YF, 取出作業站用料選項取MaterialOption
                // 2016-08-11, Joe, Add PartialMode
                // PS.要優先使用tblWIPLotState的資料,故tblWIPLotState的欄位要放在Select前面
                // 2017/10/27 OwenLiu, 因應部份報工，同時取出流程主檔 PartialType


                strSQL = "SELECT A.*, B.*, C.OPName, C.OPShortName, C.PartialMode, C.MaterialOption, C.MultiOperatorMode, D.PartialType,E.PRODUCTNAME";
                strSQL += " FROM tblWIPLotState A  join tblWIPLotBasis B  ON A.BaseLotNo = B.BaseLotNo";
                strSQL += "   left join tblOPBasis C  ON A.OPNo = C.OPNo";
                strSQL += "   left join tblPRSProcessBasis D  ON A.ProcessNo = D.ProcessNo AND A.ProcessVersion = D.ProcessVersion";
                strSQL += "   INNER JOIN TBLPRDPRODUCTBASIS E  ON B.ProductNo=E.PRODUCTNO and B.ProductVersion=E.ProductVersion"; // 20180808
                strSQL += " WHERE A.LotNo IS NOT NULL ";

                // LotBasis condition
                if (BaseLotNo != defString)
                    strSQL = strSQL + " And B.BaseLotNo = '" + BaseLotNo + "'";
                if (OrgLotNo != defString)
                    strSQL = strSQL + " And B.OrgLotNo like '" + OrgLotNo + "'";
                if (LotState != defString)
                {
                    int i;
                    string[] aLotState = Strings.Split(LotState, "|"); // 各狀態值用|分隔
                    strSQL = strSQL + " And B.LotState In(" + aLotState[0];
                    for (i = 1; i <= Information.UBound(aLotState); i++)  // 其餘的

                        strSQL = strSQL + "," + aLotState[i];
                    strSQL = strSQL + ")";
                }
                if (RONo != defString)
                    strSQL = strSQL + " And B.RONo like '" + RONo + "'";
                if (ItemNo != defInteger)
                    strSQL = strSQL + " And B.ItemNo = " + ItemNo;
                if (MONo != defString)
                    strSQL = strSQL + " And B.MONo like '" + MONo + "'";
                if (ProductNo != defString)
                    strSQL = strSQL + " And B.ProductNo like '" + ProductNo + "'";
                if (ProductVersion != defString)
                {
                    int i;
                    string[] aVersion = Strings.Split(ProductVersion, "|");   // 各狀態值用|分隔
                    strSQL = strSQL + " And B.ProductVersion In('" + aVersion[0] + "'";
                    for (i = 1; i <= Information.UBound(aVersion); i++)  // 其餘的
                        strSQL = strSQL + ",'" + aVersion[i] + "'";
                    strSQL = strSQL + ")";
                }
                if (CustomerNo != defString)
                    strSQL = strSQL + " And B.CustomerNo = '" + CustomerNo + "'";
                if (HotLot != defInteger)
                    strSQL = strSQL + " And B.HotLot = " + HotLot;
                if (FromWIPDate != defDateTime)
                    strSQL = strSQL + " And B.WIPDate >= '" + Strings.Format((DateTime)FromWIPDate, "yyyy-MM-dd HH:mm:ss") + "'";
                if (EndWIPDate != defDateTime)
                {
                    // 如果傳入值不包含時間則加上23:59:59
                    if (EndWIPDate == EndWIPDate.Date)
                        strSQL = strSQL + " And B.WIPDate <='" + Strings.Format((DateTime)EndWIPDate, "yyyy-MM-dd") + " 23:59:59" + "'";
                    else
                        strSQL = strSQL + " And B.WIPDate <='" + Strings.Format((DateTime)EndWIPDate, "yyyy/MM/dd HH:mm:ss") + "'";
                }
                if (CustomerLotNo != defString)
                    strSQL += " And B.CustomerLotNo = '" + CustomerLotNo + "'";

                // LotState condition
                // cQueue = 0
                // cRunning = 1
                // cWait = 2
                // cHold = 3
                // cINV = 11
                if (Status != defString)
                {
                    int i;
                    string[] aStatus = Strings.Split(Status, "|"); // 各狀態值用|分隔
                    strSQL = strSQL + " And A.Status In(" + aStatus[0];
                    for (i = 1; i <= Information.UBound(aStatus); i++)  // 其餘的

                        strSQL = strSQL + "," + aStatus[i];
                    strSQL = strSQL + ")";
                }

                if (LotNo != defString)
                {
                    // strSQL = strSQL & " And A.LotNo = '" & LotNo & "'"
                    int i;
                    string[] aLotNo = Strings.Split(LotNo, "|"); // 各批號用|分隔
                    strSQL = strSQL + " And A.LotNo In('" + aLotNo[0] + "'";
                    for (i = 1; i <= Information.UBound(aLotNo); i++)  // 其餘的

                        strSQL = strSQL + ",'" + aLotNo[i] + "'";
                    strSQL = strSQL + ")";
                }

                if (LotSerial != defString)
                    strSQL = strSQL + " And A.LotSerial = '" + LotSerial + "'";

                if (ProcessNo != defString)
                {
                    strSQL = strSQL + " And A.ProcessNo = '" + ProcessNo + "'";
                    if (ProcessVersion != defString)
                    {
                        int i;
                        string[] aVersion = Strings.Split(ProcessVersion, "|");   // 各狀態值用|分隔
                        strSQL = strSQL + " And A.ProcessVersion In('" + aVersion[0] + "'";
                        for (i = 1; i <= Information.UBound(aVersion); i++)  // 其餘的
                            strSQL = strSQL + ",'" + aVersion[i] + "'";
                        strSQL = strSQL + ")";
                    }
                }
                if (OPNo != defString)
                    strSQL = strSQL + " And A.OPNo = '" + OPNo + "'";
                if (NodeId != defString)
                    strSQL = strSQL + " And A.NodeId = '" + NodeId + "'";
                if (BRNo != defString)
                    strSQL = strSQL + " And A.BRNo = '" + BRNo + "'";
                if (PSNo != defString)
                    strSQL = strSQL + " And A.PSNo = '" + PSNo + "'";
                if (HaveComponent != defInteger)
                    strSQL = strSQL + " And A.HaveComponent = " + HaveComponent;
                if (HaveLevel != defInteger)
                    strSQL = strSQL + " And A.HaveLevel = " + HaveLevel;
                if (LinkName != defString)
                    strSQL = strSQL + " And A.LinkName = '" + LinkName + "'";
                if (PhaseNo != defString)
                {
                    int i;
                    string[] aPhase = Strings.Split(PhaseNo, "|"); // 各狀態值用|分隔
                    strSQL = strSQL + " And A.PhaseNo In(" + aPhase[0];
                    for (i = 1; i <= Information.UBound(aPhase); i++)  // 其餘的
                        strSQL = strSQL + "," + aPhase[i];
                    strSQL = strSQL + ")";
                }
                if (SORGLotNo != defString)
                    strSQL += " And A.ORGLotNo = '" + SORGLotNo + "'";

                // 2016-08-09, Joe, 不顯示Partial站的Lot
                if (blnShowPartialLot == false)
                    strSQL += " And (PartialMode is null OR PartialMode = 0) ";

                // 2017/10/27 OwenLiu, 增加 PartialType 參數處理
                if (!PartialType.Equals(defInteger))
                    strSQL += " AND D.PartialType = " + PartialType;

                // ERF Status
                // Status
                // 0:Create
                // 1:Department
                // 2:Customer
                // 11:Final
                // 12:Abort
                // 21:Release

                if (ERFStatus != defString)
                {
                    int i;
                    string[] aERF = Strings.Split(ERFStatus, "|"); // 各狀態值用|分隔
                    strSQL = strSQL + " And A.LotNo In (Select LotNo From tblWIPERFBasis Where Status In (" + aERF[0];
                    for (i = 1; i <= Information.UBound(aERF); i++)  // 其餘的
                        strSQL = strSQL + "," + aERF[i];
                    strSQL = strSQL + "))";
                }
                if (AreaNo != defString)
                    strSQL = strSQL + " And A.AreaNo = '" + AreaNo + "'";

                if (BatchNo != defString)
                    strSQL = strSQL + " And A.BatchNo = '" + BatchNo + "'";

                if (BoxNo != defString)
                    strSQL = strSQL + " And A.BoxNo = '" + BoxNo + "'";

                if (BatchSerial != defString)
                    strSQL = strSQL + " And A.BatchSerial = '" + BatchSerial + "'";

                if (ComponentNo != defString)
                {
                    int i;
                    string[] aryComp = Strings.Split(ComponentNo, "|"); // 各狀態值用|分隔
                    strSQL += " And A.LotNo In (Select Distinct LotNo From tblWIPComponentState Where (ComponentNo='" + aryComp[0] + "'";
                    for (i = 1; i <= Information.UBound(aryComp); i++)  // 其餘的
                        strSQL += " Or ComponentNo='" + aryComp[i] + "'";
                    strSQL += "))";
                }

                if (FactoryNo != defString)
                    strSQL = strSQL + " And A.FactoryNo = '" + FactoryNo + "'";

                if (CurQTY != defInteger)
                    strSQL += " And A.CurQTY = " + CurQTY;

                if (AdditionalXml != "")
                    // 加上additional的condition
                    strSQL = strSQL + SeparateAddXML_Condition(AdditionalXml);

                // //Select data
                strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);

                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "BasisJoinState", cnnTemp);
                // //Combine return value
                LoadLotBasisJoinState = CombineXMLReturnValue("loadlotbasisjoinstate", "BasisJoinState", "DataSet", FormatXMLSchema(dsTemp.GetXmlSchema()), dsTemp.GetXml(), "");
            }
            catch (Exception e1)
            {
                LoadLotBasisJoinState = "fail";
                throw;
            } // (New Exception("kcWIP.LoadLotBasisJoinState: " & e1.Message))

            finally
            {
                CloseConnection(cnnTemp);
                //if (!daTemp == null)
                //    daTemp.Dispose();
                if (dsTemp != null)
                    dsTemp.Dispose();
            }
            return LoadLotBasisJoinState;
        }


        /// <summary>
        /// COPY 标准
        /// </summary>
        /// <param name="CarrierNo"></param>
        /// <param name="AdditionalXml"></param>
        /// <param name="CarrierState"></param>
        /// <returns></returns>
        // 將資料以XML方式取出tblWIPCarrierState
        // 傳入值: 索引值
        // 傳回值: XML(成功), fail(失敗)
        public string LoadCarrierState_M(string CarrierNo = defString, string AdditionalXml = "", int CarrierState = defInteger)
        {
            string LoadCarrierStateRet = default(string);

            string strSQL = "";
            IDbConnection cnnTemp = null;

            var dsCarrier = default(DataSet);

            try
            {
                // //Create connection
                cnnTemp = CreateConnection(strConnectionString);

                // //SQL Command
                strSQL = "Select * From tblWIPCarrierState Where CarrierNo Is Not Null ";

                if (CarrierNo != defString)
                {
                    strSQL = strSQL + "And CarrierNo = '" + CarrierNo + "'";
                }

                if (CarrierState != defInteger)
                {
                    strSQL = strSQL + "And CarrierState = '" + CarrierState + "'";
                }

                // Additional Condition
                if (!string.IsNullOrEmpty(AdditionalXml))
                {
                    strSQL = strSQL + SeparateAddXML_Condition(AdditionalXml);
                }

                // //Select data
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                // daCarrier = New OleDb.OleDbDataAdapter(cmmTemp) 
                dsCarrier = new DataSet();
                ExecuteSQLQuery_Adapter(strSQL, dsCarrier, "CarrierState", cnnTemp);

                // //Combine return value
                //LoadCarrierStateRet = CombineXMLReturnValue("LoadCarrierState".ToLower(), "CarrierState", "DataSet", FormatXMLSchema(dsCarrier.GetXmlSchema()), dsCarrier.GetXml(), "");
            }

            catch (Exception e1)
            {
                // 回傳失敗
                LoadCarrierStateRet = "fail";

                // 發生錯誤時丟回本身的Function Name及系統錯誤訊息
                throw;
            } // New Exception("kcEQP.LoadCarrierState: " & e1.Message)

            finally
            {
                CloseConnection(cnnTemp);
                if (dsCarrier != null)
                {
                    dsCarrier.Dispose();
                }

            }

            return LoadCarrierStateRet;

        }


        /// <summary>
        /// COPY tc 载具寿命检查
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static bool CheckCarrierLife_M(string CarrierNo, string CarrierType, string UserNo)
        {
            bool bolCheckCarrierLife_M = true;

            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            IDbConnection cnnTemp = null;
            Collection CollectionSQL = new Collection();
            string strSQL;

            try
            {

                cnnTemp = CreateConnection(strConnectionString);

                //载具寿命
                DataTable dt01 = new DataTable();
                strSQL = $" select * from TBLCUSCARRIERLIFE where CARRIERNO = '{CarrierNo}' ";
                ExecuteSQLQuery_Adapter(strSQL, dt01, cnnTemp);

                //载具类别寿命设定
                DataTable dt = new DataTable();
                strSQL = $" select * from TBLCUSCARRIERLIFESET where CARRIERTYPE = '{CarrierType}' ";
                ExecuteSQLQuery_Adapter(strSQL, dt, cnnTemp);
                if (dt.Rows.Count > 0)
                {
                    if (dt01.Rows.Count > 0)
                    {
                        string ACCUMULATEQTY = dt01.Rows[0]["ACCUMULATEQTY"].ToString(); //累计数量

                        string ALERTCOUNT = dt.Rows[0]["ALERTCOUNT"].ToString(); //预警次数
                        string LIMITCOUNT = dt.Rows[0]["LIMITCOUNT"].ToString(); //单次上限

                        //累计数量达到预警次数
                        if (decimal.Parse(ACCUMULATEQTY) >= decimal.Parse(ALERTCOUNT))
                        {
                            bolCheckCarrierLife_M = false;
                        }

                    }
                    else
                    {
                        strSQL = $@" insert into TBLCUSCARRIERLIFE (CARRIERNO,ACCUMULATEQTY,ACCTOTALUSEDQTY,CREATOR,CREATEDATE) 
                                     values ('{CarrierNo}',0,0,'{UserNo}',sysdate)";
                        CollectionSQL.Add(strSQL);
                        ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);

                    }

                }
            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                CloseConnection(cnnTemp);
            }

            return bolCheckCarrierLife_M;
        }



        // 写入客制表 TBLWIPPRDSTATE_LQ（现况）与 TBLWIPPRDLOG_LQ（履历）
        // 入参说明：
        //   LotNo       - 子批批号（分批后新批号）
        //   ProductID   - PanelID
        //   EQPID       - 设备编号（可为空）
        //   OPNo        - 作业站编号
        //   CarrierID   - 载具编号（可为空）
        //   State       - 状态（固定传 1）
        //   ProductType - 产品类别（固定传 "0"）
        public static void SaveWIPPrdStateLog_M(string LotNo, string ProductID, string EQPID,
                                           string OPNo, string CarrierID, int State, string ProductType, string LotSerial, Collection colSQL = null)
        {
            var CollectionSQL = new Collection();
            string strSQL;

            // 空值保护，LOG 表 EQPID/CARRIERID 为 NOT NULL
            string strEQPID = string.IsNullOrEmpty(EQPID) ? "" : EQPID.Replace("'", "''");
            string strCarrierID = string.IsNullOrEmpty(CarrierID) ? "" : CarrierID.Replace("'", "''");
            string strLotNo = LotNo.Replace("'", "''");
            string strProductID = ProductID.Replace("'", "''");
            string strOPNo = OPNo.Replace("'", "''");
            string strProdType = ProductType.Replace("'", "''");

            try
            {
                //查询有没有进站



                // 插入 TBLWIPPRDSTATE_LQ（现况表，EQPID/CARRIERID 允许空）
                strSQL = "INSERT INTO TBLWIPPRDSTATE_LQ " +
                         "(LOTNO, PRODUCTID, EQPID, STATE, OPNO, CARRIERID, PRODUCTTYPE, CREATEDATE) " +
                         "VALUES " +
                         "('" + strLotNo + "', '" + strProductID + "', '" + strEQPID + "', " +
                         State + ", '" + strOPNo + "', '" + strCarrierID + "', '" + strProdType + "', SYSDATE)";
                CollectionSQL.Add(strSQL);


                strSQL = $"DELETE FROM TBLWIPPRDSTATE_LQ WHERE  LOTNO='{strLotNo}'";
                //回复处理
                objReverse.AddReverseUpdateContent(ref LotSerial, ref strSQL, CollectionSQL);

                // 插入 TBLWIPPRDLOG_LQ（履历表）
                strSQL = "INSERT INTO TBLWIPPRDLOG_LQ " +
                         "(LOTNO, PRODUCTID, EQPID, OPNO, CARRIERID, PRODUCTTYPE, CREATEDATE) " +
                         "VALUES " +
                         "('" + strLotNo + "', '" + strProductID + "', '" + strEQPID + "', " +
                         "'" + strOPNo + "', '" + strCarrierID + "', '" + strProdType + "', SYSDATE)";
                CollectionSQL.Add(strSQL);


                strSQL = $"DELETE FROM TBLWIPPRDLOG_LQ WHERE  LOTNO='{strLotNo}'";
                //回复处理
                objReverse.AddReverseUpdateContent(ref LotSerial, ref strSQL, CollectionSQL);

                if (colSQL != null)
                {
                    foreach (string str in CollectionSQL)
                    {
                        colSQL.Add(str);
                    }
                }
                else
                {
                    // 提交至数据库（两条 INSERT 在同一事务内执行）
                    //ExecuteSQLNoneQuery_UPD(Convert.ToString(DataBaseType), strConnectionString, CollectionSQL);
                }


            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                    throw ex.InnerException;
                else
                    throw;
            }
        }

        /// <summary>
        /// 进站
        /// </summary>
        /// <param name="aryMessage"></param>
        /// <param name="aryException"></param>
        /// <param name="MONO"></param>
        /// <param name="EQPID"></param>
        /// <param name="ID"></param>
        /// <param name="remark"></param>
        /// <returns></returns>
        public static bool funTrackIn_Inquiry_LQ(ref List<ArrayList> aryMessage, ref List<ArrayList> aryException, string EQPID, string ID, string remark)
        {
            bool funTrackIn_Inquiry = default(bool);
            //bool r = false;
            string strSQL = default(string);
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();

            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);
            var CollectionSQL = new Collection();
            DataSet dsData = new DataSet();



            string strReturn = "";
            string OPNO = "";






            int EQPSTATE = 0; //设备管控闲置状态

            int nowEQPSTATE = 0; //现在设备管控闲置状态

            string strLotNo = "";//生产批号

            try
            {
                //先检查 设备状态是否是闲置

                //检查设备是否存在
                strSQL = "SELECT 1 FROM TBLEQPEQUIPMENTBASIS WHERE EQUIPMENTNO='" + EQPID + "' AND ISSUESTATE = 2";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    //throw new iMESException.MESException("0000-202001", +" ：设备不存在！");
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备不存在！%]");
                    return false;
                }
                drTemp.Close();

                //获取设备管控闲置状态是多少
                strSQL = "Select EQUIPMENTSTATE From TBLEQPSTATECONTROL Where CONTROLNO Is Not Null AND CONTROLTYPE ='EQP Break Down' AND CONTROLNO='Idle'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    EQPSTATE = Conversions.ToInteger(drTemp["EQUIPMENTSTATE"]);
                }
                else
                {
                    //throw new iMESException.MESException("0000-202001", "闲置状态未设定！");
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%设备闲置状态未设定!%]");
                    return false;
                }
                drTemp.Close();


                // ============================
                // 自动判断ID类型（通过序号规则）
                // LCSIP开头 → CarrierID（通用载具）
                // X1088开头 → CarrierID（专用载具）
                // 其他 → ProductID（PanelID或UnitID）
                // ============================
                string strIDValue = ID;
                string strProductID_Auto = "";
                string strCarrierID_Auto = "";
                string strAutoType = "";
                string Type;


                if (!string.IsNullOrEmpty(strIDValue))
                {
                    // 自动判断ID类型
                    if (strIDValue.StartsWith("LCSIP") || strIDValue.StartsWith("X1088"))
                    {
                        // 载具ID
                        strAutoType = "2";  // CarrierID
                        strCarrierID_Auto = strIDValue;
                    }
                    else
                    {
                        // 产品ID（PanelID或UnitID）
                        strAutoType = "1";  // ProductID
                        strProductID_Auto = strIDValue;
                    }
                }

                // 根据自动判断结果或手动指定的Type决定处理逻辑
                string strFinalType;

                strFinalType = strAutoType;
                //获取生产批批号
                if (strFinalType == "1")
                {
                    if (string.IsNullOrEmpty(strProductID_Auto))
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%Product_id 没有传值%]");
                        return false;
                    }
                    DataTable dt = new DataTable();
                    strSQL = $"select * from TBLWIPPRDSTATE_LQ where PRODUCTID = '{strProductID_Auto}' and state = 1";
                    ExecuteSQLQuery_Adapter(strSQL, dt, cnnTemp);
                    if (dt.Rows.Count != 1)
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: $"[%产品ID({strProductID_Auto})对应多个批次，请检查数据来源。%]");
                        return false;
                    }
                    strLotNo = dt.Rows[0]["LotNo"].ToString();
                }
                else if (strFinalType == "2")
                {
                    if (string.IsNullOrEmpty(strCarrierID_Auto))
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%Carrier_id 没有传值%]");
                        return false;
                    }
                    DataTable dt = new DataTable();
                    strSQL = $"select * from TBLWIPPRDSTATE_LQ where carrierid = '{strCarrierID_Auto}' and state = 1";
                    ExecuteSQLQuery_Adapter(strSQL, dt, cnnTemp);
                    if (dt.Rows.Count > 0)
                    {

                        strLotNo = dt.Rows[0]["LotNo"].ToString();
                    }
                    else
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%找不到对应的生产批%]");
                        return false;
                    }
                }
                strSQL = $"select * from tblwiplotstate where lotno = '{strLotNo}'";

                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    OPNO = drTemp["OPNO"].ToString();
                    string STATUS = drTemp["STATUS"].ToString();
                    string LotSerial = drTemp["LOGGROUPSERIAL"].ToString();
                    if (STATUS == "4")
                    {
                        var colNextNode = GetNextNode(strLotNo, "Null", defString, AdditionalXml: "");
                        using (kcWIP.clsLot objLot = new kcWIP.clsLot())
                        {
                            var drLotState = objLot.GetLotBasisJoinState(LotNo: strLotNo);   // 取得最新的LotState
                            objLot.SetLotStateToNextOP(Conversions.ToLong(drLotState["LotStamp"]), strLotNo, Convert.ToString(colNextNode["NodeID"]));
                            //objLot.SetLotStateToWait(Conversions.ToLong(drLotState["LotStamp"]), strLotNo, 2, UserNo: "EAP", WaitDescription: "ExeOSReturn finish then GetNextNode failed,can not find next node,linkname:" + strLinkName + ".");

                        }

                    }
                    else if (STATUS == "1")
                    {
                        funReentryUpdateTime(LotSerial, strLotNo, OPNO, ref CollectionSQL);
                        goto Reentry;
                    }
                    else if (STATUS == "0")
                    {
                        funReentryUpdateTime(LotSerial, strLotNo, OPNO, ref CollectionSQL);
                    }
                }
                drTemp.Close();
                Check_CIRequest_LOTMaterial(ref aryMessage, EQPID, strLotNo, OPNO);
                if (aryMessage.Count > 0)
                {
                    return false;
                }
                //调用标准进站
                var datSendTime = default(DateTime);       // 送達時間
                object blnRuleCheck = true;
                bool blnEXETriggerOP = false;
                string strComputerName = string.Empty;   // Request Client ComputerName
                string strCurUserNo = string.Empty;     // Request User -紀錄操作人員
                Dictionary<string, string> dicPars = new Dictionary<string, string>(); //固定引數,Request傳入的一般參數
                Dictionary<string, DataTable> dicPars_DataTable = new Dictionary<string, DataTable>(); //固定引數,Request傳入的DataTable參數

                //添加批号
                dicPars.Add("lotno", strLotNo);
                dicPars.Add("equipmentno", EQPID);


                AutoexecutionLot_Lot(ref blnEXETriggerOP, dicPars, dicPars_DataTable, "CI", datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck));
                strSQL = $"update TBLWIPPRDSTATE_LQ set eqpid = '{EQPID}',opno = '{OPNO}' where PRODUCTID = '{strProductID_Auto}' and state = 1";
                CollectionSQL.Add(strSQL);
                strSQL = $"update TBLWIPLOTLOG_REPORT set CIREMARK = '{remark}' where LoggroupSerial =(select LoggroupSerial from TBLWIPLOTSTATE where LOTNO='{strLotNo}')";
                CollectionSQL.Add(strSQL);

                Reentry:
                ;
                ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);
                //strLotNo = Conversions.ToString(dsData.Tables["TBLWIPLOTBASIS"].Rows[0]["BASELOTNO"]);


                funTrackIn_Inquiry = true;
                exitfun:
                ;
            }
            catch (Exception ex)
            {
                // 一行调用，拿到完整异常字符串
                string errorMsg = clsERP.GetExceptionFullMessage(ex);
                throw new Exception(errorMsg);
            }
            finally
            {

                drTemp?.Close();

                dsData?.Dispose();
                CloseConnection(cnnTemp);
            }
            return funTrackIn_Inquiry;

        }
        /// <summary>
        /// 出站
        /// </summary>
        /// <param name="aryMessage"></param>
        /// <param name="aryException"></param>
        /// <param name="MONO"></param>
        /// <param name="EQPID"></param>
        /// <param name="PanleId"></param>
        /// <param name="Column"></param>
        /// <param name="Line"></param>
        /// <param name="carrierId"></param>
        /// <param name="Qty"></param>
        /// <returns></returns>
        public static bool funTrackOut_Inquiry_LQ(ref List<ArrayList> aryMessage, ref List<ArrayList> aryException, string EQPID, string ID, string remark)
        {
            bool funTrackOut_Inquiry = default(bool);
            //bool r = false;
            string strSQL = default(string);
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();


            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            DataSet dsData = new DataSet();



            string strReturn = "";


            string strMLotNo = "";//母生产批号
            string strNLotNo = "";//子生产批号
            string strProductNo = "";//产品号
            string strProductVersion = "";//产品版本
            string strSeqNoRule = "";//序号规则
            string strSeqNoType = "";//序号类别
            string strSeqNoSize = "";//起始位置
            string strDirection = "";//走向
            string strOPNO = "";

            string strUnitIdOrPannid = "";//UnitId或者Pannid

            bool bolLastLot = false;//是否是最后一笔

            DataSet dataSetLotNo = new DataSet();

            kcWIP.clsLot objLot = new kcWIP.clsLot();

            Collection CollectionSQL = new Collection();

            bool bolInsertMONoProperty = false; //插入工单属性

            decimal decMQTY = 0; //母批数量

            try
            {
                //先检查 设备状态是否是闲置

                //检查设备是否存在
                strSQL = "SELECT 1 FROM TBLEQPEQUIPMENTBASIS WHERE EQUIPMENTNO='" + EQPID + "' AND ISSUESTATE = 2";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备不存在！%]");
                    return false;
                }
                drTemp.Close();


                // ============================
                // 自动判断ID类型（通过序号规则）
                // LCSIP开头 → CarrierID（通用载具）
                // X1088开头 → CarrierID（专用载具）
                // 其他 → ProductID（PanelID或UnitID）
                // ============================
                string strIDValue = ID;
                string strProductID_Auto = "";
                string strCarrierID_Auto = "";
                string strAutoType = "";
                string Type = "";


                if (!string.IsNullOrEmpty(strIDValue))
                {
                    // 自动判断ID类型
                    if (strIDValue.StartsWith("LCSIP") || strIDValue.StartsWith("X1088"))
                    {
                        // 载具ID
                        Type = "2";  // CarrierID
                        strCarrierID_Auto = strIDValue;
                    }
                    else
                    {
                        // 产品ID（PanelID或UnitID）
                        Type = "1";  // ProductID
                        strProductID_Auto = strIDValue;
                    }
                }

                // 根据自动判断结果或手动指定的Type决定处理逻辑

                // 17单 需求二/三:依作业站属性自动解绑(TRAY/小载具)+分批出站,在标准判型出站之前
                bool bolAutoUnbindHandled = false;
                if (!funAutoUnbindCheckOut_LQ(ref aryMessage, Type, strProductID_Auto, strCarrierID_Auto, EQPID, out bolAutoUnbindHandled))
                {
                    return false;
                }
                if (bolAutoUnbindHandled)
                {
                    return true;
                }



                if (Type == "1")
                {
                    if (strProductID_Auto is null && strProductID_Auto == "")
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%Product_id 没有传值%]");
                        return false;
                    }
                    DataTable dt = new DataTable();
                    strSQL = $"select * from TBLWIPPRDSTATE_LQ where PRODUCTID = '{strProductID_Auto}' and state = 1";
                    ExecuteSQLQuery_Adapter(strSQL, dt, cnnTemp);
                    if (dt.Rows.Count != 1)
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: $"[%产品ID({strProductID_Auto})对应多个批次，请检查数据来源。%]");
                        return false;
                    }
                    strMLotNo = dt.Rows[0]["LotNo"].ToString();
                }
                else if (Type == "2")
                {
                    //if (strCarrierID_Auto is null && strCarrierID_Auto == "")
                    //{
                    //    clsERP.combineMessage(ref aryMessage, mmsg: "[%Carrier_id 没有传值%]");
                    //    return false;
                    //}
                    if (strCarrierID_Auto is null || strCarrierID_Auto == "")   //17单 M3:原 && 恒不成立,检核形同虚设,应为 ||
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%Carrier_id 没有传值%]");
                        return false;
                    }

                    DataTable dt = new DataTable();
                    strSQL = $"select * from TBLWIPPRDSTATE_LQ where (carrierid = '{strCarrierID_Auto}' or TrayID = '{strCarrierID_Auto}') and state = 1";
                    ExecuteSQLQuery_Adapter(strSQL, dt, cnnTemp);
                    //foreach (DataRow row in dt.Rows)
                    //{
                    if (dt.Rows.Count == 0)
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%找不到对应的生产批%]");
                        return false;
                    }
                    strMLotNo = dt.Rows[0]["LotNo"].ToString();
                }

                //获取母批的基本信息
                strSQL = $"SELECT A.PRODUCTNO,A.PRODUCTVERSION,B.STATUS,B.CURQTY,B.OPNO,B.LOTSTAMP FROM TBLWIPLOTBASIS A LEFT JOIN TBLWIPLOTSTATE  B ON A.BASELOTNO = B.LOTNO WHERE A.BASELOTNO ='{strMLotNo}'";
                ExecuteSQLQuery_Adapter(strSQL, dsData, "TBLWIPLOTBASIS_MLOT", cnnTemp);


                if (dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows.Count == 0)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: strMLotNo + "[%：批次状态不是执行中，不允许出站！%]");
                    return false;
                }

                //检查母批状态是否是执行中 STATUS 是否为 1
                if (Conversions.ToInteger(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["STATUS"]) != 1)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: strMLotNo + "[%：母生产批状态不是执行中！%]");
                    return false;
                }

                //检查是否是用当前设备进站
                strSQL = "SELECT EQUIPMENTNO FROM TBLWIPTEMP_EQUIPMENT WHERE LotNo='" + strMLotNo + "' ";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    if (EQPID != drTemp["EQUIPMENTNO"].ToString())
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：当前设备不是进站设备，不允许出站！%]");
                        return false;
                    }
                }
                drTemp.Close();
                //调用标准出站
                var datSendTime = default(DateTime);       // 送達時間
                object blnRuleCheck = true;
                bool blnEXETriggerOP = false;
                string strComputerName = string.Empty;   // Request Client ComputerName 
                string strCurUserNo = string.Empty;     // Request User -紀錄操作人員
                Dictionary<string, string> dicPars = new Dictionary<string, string>(); //固定引數,Request傳入的一般參數
                Dictionary<string, DataTable> dicPars_DataTable = new Dictionary<string, DataTable>(); //固定引數,Request傳入的DataTable參數

                //添加批号
                dicPars.Add("lotno", strMLotNo);
                dicPars.Add("equipmentno", EQPID);

                //出站明细
                DataTable dtLotAttrib = new DataTable(); //特性
                                                         //添加LotNo列
                dtLotAttrib.Columns.Add("LotNo", typeof(string));
                dtLotAttrib.Columns.Add("AttribNo", typeof(string));
                dtLotAttrib.Columns.Add("AttribValue", typeof(string));

                decMQTY = decimal.Parse(dsData.Tables["TBLWIPLOTBASIS_MLOT"].Rows[0]["CURQTY"].ToString());

                //查询生产批的绑定特性，这里是出站，所以使用TEMP表
                strSQL = $"SELECT  ATTRIBNO,ATTRIBVALUE FROM TBLWIPTEMP_ATTRIB WHERE LOTNO='{strMLotNo}'";
                ExecuteSQLQuery_Adapter(strSQL, dsData, "TBLWIPTEMP_ATTRIB", cnnTemp);
                if (dsData.Tables["TBLWIPTEMP_ATTRIB"].Rows.Count > 0)
                {
                    foreach (DataRow dr in dsData.Tables["TBLWIPTEMP_ATTRIB"].Rows)
                    {
                        DataRow drLotAttrib = dtLotAttrib.NewRow();
                        drLotAttrib["LotNo"] = strMLotNo;
                        drLotAttrib["AttribNo"] = dr["ATTRIBNO"].ToString();
                        if (dr["AttribNo"].ToString() == "GoodQty")
                        {
                            drLotAttrib["AttribValue"] = decMQTY;

                        }
                        else if (dr["AttribNo"].ToString() == "ScrapQty")
                        {
                            drLotAttrib["AttribValue"] = 0;
                        }
                        else if (dr["AttribNo"].ToString() == "DefectQty")
                        {
                            drLotAttrib["AttribValue"] = 0;
                        }
                        else
                        {
                            drLotAttrib["AttribValue"] = dr["ATTRIBVALUE"].ToString();
                        }

                        dtLotAttrib.Rows.Add(drLotAttrib);
                    }
                }


                dicPars_DataTable.Add("lotattrib", dtLotAttrib);

                // ============================
                // 出站成功后，插入TBLWIPCONT_LOTRECORD记录（remark生产数据）
                // ============================
                if (!string.IsNullOrEmpty(strMLotNo) && !string.IsNullOrEmpty(remark))
                {
                    string strLotSerial = "";
                    string strBaseLotNo = "";
                    string strOPNos = "";
                    string strLogGroupSerial = "";
                    string strEventUserNo = "";

                    strSQL = $"SELECT LOTSERIAL, BASELOTNO, OPNO, LOGGROUPSERIAL, EVENTUSERNO FROM TBLWIPLOTSTATE WHERE LOTNO = '{strMLotNo}'";
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (drTemp.Read())
                    {
                        strLotSerial = drTemp["LOTSERIAL"] is DBNull ? "" : drTemp["LOTSERIAL"].ToString();
                        strBaseLotNo = drTemp["BASELOTNO"] is DBNull ? "" : drTemp["BASELOTNO"].ToString();
                        strOPNos = drTemp["OPNO"] is DBNull ? "" : drTemp["OPNO"].ToString();
                        strLogGroupSerial = drTemp["LOGGROUPSERIAL"] is DBNull ? "" : drTemp["LOGGROUPSERIAL"].ToString();
                        strEventUserNo = drTemp["EVENTUSERNO"] is DBNull ? "" : drTemp["EVENTUSERNO"].ToString();
                    }
                    drTemp.Close();

                    string strEventTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
                    strSQL = $"INSERT INTO TBLWIPCONT_LOTRECORD (BASELOTNO, LOTNO, LOTSERIAL, OPNO, LOTRECORD, USERNO, EVENTTIME, LOGGROUPSERIAL) " +
                             $"VALUES ('{strBaseLotNo}', '{strMLotNo}', '{strLotSerial}', '{strOPNos}', '{remark}', '{strEventUserNo}', " +
                             $"TO_DATE('{strEventTime}', 'SYYYY-MM-DD HH24:MI:SS'), '{strLogGroupSerial}')";
                    CollectionSQL.Add(strSQL);
                }
                AutoexecutionLot_Lot(ref blnEXETriggerOP, dicPars, dicPars_DataTable, "CO", datSendTime, strCurUserNo, strComputerName, Convert.ToBoolean(blnRuleCheck));
                #region 出站扣料逻辑
                // 字符串类型
                string LotSerial = "";
                string OPNo = "";
                string InventoryNo = "";
                string MONo = "";
                string CurUnitNo = "";
                string ProductNo = "";
                string ProductVersion = "";
                string BaseLotNo = "";
                string BRNo = "";
                string LogGroupSerial = "";
                long lngLotStamp = 0;
                decimal decCurQty = 0;
                int intMaterialOption = 0;
                int PhaseNo = 0;
                DataTable dtMaterial = new DataTable();
                DataTable dtMaterialLot = new DataTable();
                DateTime datEventTime = DateTime.Now;
                // 2016/10/26 YF, 取出作業站的用料選項
                // 2018/2/9, Ning, CurUnitNo改取自tblWIPLotState
                // 1.取出Temp LotState的資料
                if (strDataBaseType.ToUpper() == "ORACLE")
                {
                    strSQL = "Select A.LotSerial, A.OPNo, A.InventoryNo, A.MONo, B.CurUnitNo, A.ProductNo, A.ProductVersion, A.BaseLotNo, " + "       B.BRNo, B.LogGroupSerial, B.LotStamp, B.CurQty, B.PhaseNo, C.MaterialOption " + " From  tblWIPTemp_LotState A, tblWIPLotState B, tblOPBasis C " + " Where A.LotNo = '" + strMLotNo + "'" + " And   A.LotNo = B.LotNo " + " And   B.OPNo = C.OPNo ";
                }
                else
                {
                    strSQL = "Select A.LotSerial, A.OPNo, A.InventoryNo, A.MONo, B.CurUnitNo, A.ProductNo, A.ProductVersion, A.BaseLotNo, " + "       B.BRNo, B.LogGroupSerial, B.LotStamp, B.CurQty, B.PhaseNo, C.MaterialOption " + " From  tblWIPTemp_LotState A With (NoLock), tblWIPLotState B With (NoLock), tblOPBasis C With (NoLock) " + " Where A.LotNo = '" + strMLotNo + "'" + " And   A.LotNo = B.LotNo " + " And   B.OPNo = C.OPNo ";
                }
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    LotSerial = drTemp["LotSerial"].ToString();
                    OPNo = drTemp["OPNo"].ToString();
                    InventoryNo = drTemp["InventoryNo"].ToString();
                    MONo = drTemp["MONo"].ToString();
                    CurUnitNo = drTemp["CurUnitNo"].ToString();
                    ProductNo = drTemp["ProductNo"].ToString();
                    ProductVersion = drTemp["ProductVersion"].ToString();
                    BaseLotNo = drTemp["BaseLotNo"].ToString();
                    BRNo = drTemp["BRNo"].ToString();
                    LogGroupSerial = drTemp["LogGroupSerial"].ToString();
                    lngLotStamp = Conversions.ToLong(drTemp["LotStamp"]);
                    decCurQty = Convert.ToDecimal(drTemp["CurQty"]);
                    intMaterialOption = Conversions.ToInteger(drTemp["MaterialOption"]);
                    PhaseNo = Conversions.ToInteger(drTemp["PhaseNo"]); // 2020/11/26 Steven Mantis:0082084 [PAD]eRunCard_調整 BR 生產記錄
                }
                else
                {
                    throw new iMESException.MESException("0000-202003", "[%LotNo%] : " + strMLotNo);
                }
                drTemp.Close();
                using (var obj = new clsLot())
                {


                    // 4.Material
                    // 2016/10/26 YF, 依用料選項來執行扣料的方式
                    switch (intMaterialOption)
                    {
                        case 0:
                            {
                                // 發料點(線邊倉或工單)
                                obj.SHR_COMaterial(strMLotNo, LogGroupSerial, LotSerial, LotSerial, "EAP", datEventTime, InventoryNo, MONo, OPNo, ref cnnTemp, ref CollectionSQL, dicPars_DataTable["equipment"], dtMaterial, dtMaterialLot);
                                break;
                            }

                        case 1:
                            {
                                // 設備
                                var objHandler = new clsMaterialHandler();

                                if (false)
                                {
                                    // 採先進先出扣料
                                    objHandler.SHR_COMaterialByEQP_FIFO(strMLotNo, LogGroupSerial, LotSerial, ref CollectionSQL, ref dtMaterial, ref dtMaterialLot, dicPars_DataTable["equipment"], datEventTime);
                                }
                                else
                                {
                                    // 採輸入料批扣料
                                    objHandler.SHR_COMaterialByEQP(strMLotNo, LogGroupSerial, LotSerial, ref CollectionSQL, ref dtMaterial, ref dtMaterialLot, dicPars_DataTable["equipment"], datEventTime);
                                }



                                // Case 2
                                // 生產線, 待組裝版再實作

                                // Case 3
                                // 工位, 待組裝版再實作

                                objHandler = null;
                                break;
                            }

                        default:
                            {
                                throw new iMESException.MESException("0000-003000", "[%MaterialOption%]：" + intMaterialOption + " [%NOT DEFINE%]!");
                            }
                    }
                }
                #endregion



                if (CollectionSQL.Count > 0)
                {
                    ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);
                }


                funTrackOut_Inquiry = true;
                exitfun:
                ;
            }
            catch (Exception ex)
            {
                // 一行调用，拿到完整异常字符串
                string errorMsg = clsERP.GetExceptionFullMessage(ex);
                throw new Exception(errorMsg);
            }
            finally
            {

                if (objLot != null)
                {
                    objLot = null;
                }

                drTemp?.Close();

                dsData?.Dispose();
                CloseConnection(cnnTemp);
            }
            return funTrackOut_Inquiry;

        }

        public static void funReentryUpdateTime(string LotSerial, string LotNo, string OPNO, ref Collection CollectionSQL)
        {
            try
            {
                strSQL = $"update TBLWIPLOTLOG_REPORT set STARTTIME = SYSDATE,CHECKINTIME = SYSDATE where LOGGROUPSERIAL = '{LotSerial}'";
                CollectionSQL.Add(strSQL);
                //strSQL = $"update TBLWIPLOTLOG set STARTTIME = SYSDATE where LOGGROUPSERIAL = '{LotSerial}'";
                //CollectionSQL.Add(strSQL);
                strSQL = $"insert into tblcusentry(LOTSERIAL,LotNO,STARTTIME，OPNO) Values('{LotSerial}','{LotNo}',SYSDATE,'{OPNO}')";
                CollectionSQL.Add(strSQL);
                //回复处理
                strSQL = $"DELETE FROM tblcusentry WHERE LOTSERIAL='{LotSerial}'";
                Collection argcolSQL_Rows = null;
                objReverse.AddReverseUpdateContent(ref LotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows);
            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {

            }
        }

        #endregion

        #region 进出站对物料的管控
        public static DataSet Check_CIRequest_LOTMaterial(ref List<ArrayList> aryMessage, string EquipmentNo, string LotNo, string OPNo)
        {
            DataSet Check_CIRequest_LOTMaterialRet = default(DataSet);
            // Dim result As Boolean = False
            var result = new DataSet();

            var All_result = new DataSet();
            var dsTemp = default(DataSet);
            string InXML, OutXML;
            string MONO;
            string Materialoption = "";
            string LotQty = defString;
            string strMessage = "";
            string strError = "";
            try
            {
                object[] aryPars;

                aryPars = clsCom.funGetMethodParameters("kcEQP", "clsEQPBasis", "ShowEquipmentBasis");
                aryPars[0] = EquipmentNo;
                dsTemp = clsCom.funExecuteMethod("kcEQP", "clsEQPBasis", "ShowEquipmentBasis", ref aryPars) as DataSet;

                foreach (DataTable item in dsTemp.Tables)
                    All_result.Tables.Add(item.Copy());

                // 檢查設備是否存在
                if (All_result.Tables["EQPEquipmentBasis"] == null || All_result.Tables["EQPEquipmentBasis"].Rows.Count <= 0)
                {
                    throw new iMESException.MESException("0000-200003", "[%EQPNO%]:" + EquipmentNo + " [%IS NOT EXIST%]");
                }
                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(All_result.Tables["EQPEquipmentBasis"].Rows[0]["IssueState"], 2, false)))
                {
                    throw new iMESException.MESException("0000-200015", "[%EQPNO%]:" + EquipmentNo + " [%PLEASE CHECK ISSUE STATE%]");
                }

                aryPars = clsCom.funGetMethodParameters("kcWIP", "clsLot", "ShowLotBasisJoinState");
                aryPars[0] = LotNo;
                dsTemp = clsCom.funExecuteMethod("kcWIP", "clsLot", "ShowLotBasisJoinState", ref aryPars) as DataSet;

                foreach (DataTable item in dsTemp.Tables)
                    All_result.Tables.Add(item.Copy());

                // 檢查生產批是否存在
                if (All_result.Tables["BasisJoinState"] == null || All_result.Tables["BasisJoinState"].Rows.Count <= 0)
                {
                    throw new iMESException.MESException("0000-200003", "[%LOTNO%]:" + LotNo + " [%IS NOT EXIST%]");
                }
                if (All_result.Tables["BasisJoinState"].Rows[0]["CURQTY"] == null || Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(All_result.Tables["BasisJoinState"].Rows[0]["CURQTY"], 0, false)))
                {
                    throw new iMESException.MESException("0000-200017", "[%LOTNO%]:" + LotNo + " [%LOTCURQTY%] [%CANT BE%] 0");
                }
                else if (All_result.Tables["BasisJoinState"].Rows[0]["CURQTY"] == null || Convert.ToBoolean(Operators.ConditionalCompareObjectLess(All_result.Tables["BasisJoinState"].Rows[0]["CURQTY"], 0, false)))
                {
                    throw new iMESException.MESException("0000-200017", "[%LOTNO%]:" + LotNo + " [%LOTCURQTY%] [%MUST BE GREATER THAN%] 0 ");
                }
                else
                {
                    LotQty = All_result.Tables["BasisJoinState"].Rows[0]["CURQTY"].ToString();
                    MONO = All_result.Tables["BasisJoinState"].Rows[0]["MONO"].ToString();
                }


                aryPars = clsCom.funGetMethodParameters("kcOP", "clsOPBasis", "ShowOPBasis");
                aryPars[0] = OPNo;
                dsTemp = clsCom.funExecuteMethod("kcOP", "clsOPBasis", "ShowOPBasis", ref aryPars) as DataSet;

                foreach (DataTable item in dsTemp.Tables)
                    All_result.Tables.Add(item.Copy());

                // 檢查作業站編號是否存在
                if (All_result.Tables["OPBasis"] == null || All_result.Tables["OPBasis"].Rows.Count <= 0)
                {
                    throw new iMESException.MESException("0000-200003", "[%OPNO%]:" + OPNo + " [%IS NOT EXIST%]");
                }
                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(All_result.Tables["OPBasis"].Rows[0]["IssueState"], 2, false)))
                {
                    throw new iMESException.MESException("0000-200015", "[%OPNO%]:" + OPNo + " [%PLEASE CHECK ISSUE STATE%]");
                }
                else
                {
                    Materialoption = All_result.Tables["OPBasis"].Rows[0]["Materialoption"].ToString();
                }

                aryPars = clsCom.funGetMethodParameters("kcOE", "clsOEBasis", "ShowMOMaterialList");
                aryPars[0] = MONO;
                aryPars[2] = OPNo;
                dsTemp = clsCom.funExecuteMethod("kcOE", "clsOEBasis", "ShowMOMaterialList", ref aryPars) as DataSet;

                foreach (DataTable item in dsTemp.Tables)
                    All_result.Tables.Add(item.Copy());

                DataTable dtMOMaterialList;
                dtMOMaterialList = new DataTable("materiallist");
                dtMOMaterialList.Columns.Add("materialno", Type.GetType("System.String"));
                dtMOMaterialList.Columns.Add("materiallotno", Type.GetType("System.String"));
                dtMOMaterialList.Columns.Add("materiallevel", Type.GetType("System.String"));
                dtMOMaterialList.Columns.Add("checklotno", Type.GetType("System.String"));
                dtMOMaterialList.Columns.Add("checkmtlpass", Type.GetType("System.String"));
                dtMOMaterialList.Columns.Add("useqty", Type.GetType("System.String"));
                dtMOMaterialList.Columns.Add("unitno", Type.GetType("System.String"));


                aryPars = clsCom.funGetMethodParameters("kcWIP", "clsLot", "ShowChkLotCI_Material");
                aryPars[0] = LotNo;
                aryPars[1] = OPNo;
                aryPars[2] = EquipmentNo;
                aryPars[3] = true;
                dsTemp = clsCom.funExecuteMethod("kcWIP", "clsLot", "ShowChkLotCI_Material", ref aryPars) as DataSet;
                foreach (DataTable item in dsTemp.Tables)
                    All_result.Tables.Add(item.Copy());

                DataRow drData;
                foreach (DataRow r in All_result.Tables["all_materiallist"].Rows)
                {
                    drData = dtMOMaterialList.NewRow();
                    // drData("materialno") = r("materialno").ToString
                    drData["materialno"] = r["inputmaterialno"].ToString();
                    drData["materiallotno"] = r["materiallotno"].ToString();                                // 沒有物料批號資料時請填N/A
                    drData["materiallevel"] = r["materiallevel"].ToString();     // 0：Material(物料)。1：Product(半成品)。
                    drData["unitno"] = r["unitno"].ToString();
                    drData["checklotno"] = r["checklotno"].ToString();           // 0：False 1：True
                    drData["checkmtlpass"] = r["checkmtlpass"].ToString();                                 // -1: 不用查核 0：fail查核失敗, 上料數不足 1：pass查核成功, 上料數足夠
                    dtMOMaterialList.Rows.Add(drData);

                    // 若有傳出的DataTable中有錯誤訊息已 ;分號 做分隔
                    if (!string.IsNullOrEmpty(r["errorcode"].ToString()) | !string.IsNullOrEmpty(r["errormessage"].ToString()))
                    {
                        if (string.IsNullOrEmpty(strError))
                        {
                            strError = r["errorcode"].ToString();
                        }
                        else
                        {
                            strError = strError + ";" + r["errorcode"].ToString();
                        }

                        if (string.IsNullOrEmpty(strMessage))
                        {
                            strMessage = "[%materialno%]:" + r["materialno"].ToString() + " " + r["errormessage"].ToString();
                        }
                        else
                        {
                            strMessage = strMessage + ";" + "[%materialno%]:" + r["materialno"].ToString() + " " + r["errormessage"].ToString();
                        }

                    }

                }

                if (!string.IsNullOrEmpty(strMessage))
                {
                    throw new iMESException.MESException(strError, strMessage);
                }

                result.Tables.Add(dtMOMaterialList);
            }

            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                Check_CIRequest_LOTMaterialRet = result;

                if (dsTemp != null)
                    dsTemp.Dispose();
                if (result != null)
                    result.Dispose();
                if (All_result != null)
                    All_result.Dispose();
            }

            return Check_CIRequest_LOTMaterialRet;

        }



        #endregion


        #region "MakingCode明码查询"
        /// <summary>
        /// 明码查询接口：根据PanelSN查MAKINGCODE和UNITSN，并校验设备可用性
        /// </summary>
        public static bool funMakingCode(ref List<ArrayList> aryMessage, ref List<ArrayList> aryException, string PanelSN, string EQPID, ref string strMAKINGCODE, ref string strUNITSN)
        {
            bool funMakingCode = default(bool);
            string strSQL = default(string);
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();

            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            string strLotNo = "";

            try
            {
                // ============================
                // 1. 校验设备是否存在
                // ============================
                strSQL = "SELECT 1 FROM TBLEQPEQUIPMENTBASIS WHERE EQUIPMENTNO='" + EQPID + "' AND ISSUESTATE = 2";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: EQPID + "[%：设备不存在！%]");
                    return false;
                }
                drTemp.Close();

                // ============================
                // 2. 根据PanelSN（作为ProductID）查询LotNo
                // ============================
                strSQL = "SELECT LOTNO FROM TBLWIPPRDSTATE_LQ WHERE PRODUCTID = '" + PanelSN + "' AND STATE = '1'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%PanelSN(" + PanelSN + ")未找到对应批次!%]");
                    return false;
                }
                strLotNo = drTemp["LOTNO"].ToString();
                drTemp.Close();

                // ============================
                // 3. 校验设备：根据Lot状态决定校验逻辑
                //    STATUS=0(待进站)：检查设备是否可用（参考frmBR_L_CI_GEN加载可用设备逻辑）
                //    STATUS=1(已进站)：检查所选设备是否是当前批次进站设备
                // ============================
                strSQL = "SELECT STATUS FROM TBLWIPLOTSTATE WHERE LOTNO = '" + strLotNo + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%批次(" + strLotNo + ")状态未知，不允许查询!%]");
                    return false;
                }
                int lotStatus = Convert.ToInt32(drTemp["STATUS"]);
                drTemp.Close();

                if (lotStatus == 0)
                {
                    // STATUS=0 待进站：参考frmBR_L_CI_GEN带出所有可用设备，检查设备是否在可用设备列表中
                    DataTable dtAvailableEquipment_All;
                    DataTable dtAvailableEquipment_Chamber;
                    using (var objLot = new clsLot())
                    {
                        var dsAvailable = ShowAvailableEquipment_All(strLotNo);
                        dtAvailableEquipment_All = dsAvailable.Tables[0];

                    }

                    // 检查设备是否在可用设备列表中（AllowExecute=1）
                    DataRow[] drAvailable = dtAvailableEquipment_All.Select("AllowExecute=1 And EquipmentNo = '" + EQPID + "'");
                    if (drAvailable.Length == 0)
                    {

                        clsERP.combineMessage(ref aryMessage, mmsg: "[%设备(" + EQPID + ")不在批次(" + strLotNo + ")的可用设备列表中，不允许查询!%]");
                        return false;

                    }
                }
                else if (lotStatus == 1)
                {
                    // STATUS=1 已进站：检查所选设备是否是当前批次进站设备
                    strSQL = "SELECT A.LOTNO FROM TBLWIPLOTSTATE A " +
                             "LEFT JOIN TBLWIPTEMP_EQUIPMENT B ON A.LOTNO = B.LOTNO " +
                             "WHERE A.LOTNO = '" + strLotNo + "' AND A.STATUS = 1 AND B.EQUIPMENTNO = '" + EQPID + "'";
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (!drTemp.Read())
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%批次(" + strLotNo + ")未在设备(" + EQPID + ")上进站，不允许查询!%]");
                        return false;
                    }
                    drTemp.Close();
                }
                else
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%批次(" + strLotNo + ")状态为(" + lotStatus + ")，不支持该状态的明码查询!%]");
                    return false;
                }

                // ============================
                // 4. 查询 TBLPRDPRODUCTBASIS 获取 MAKINGCODE
                // ============================
                strSQL = "SELECT A.MAKINGCODE FROM TBLPRDPRODUCTBASIS A " +
                         "INNER JOIN TBLWIPLOTBASIS B ON A.PRODUCTNO = B.PRODUCTNO AND A.PRODUCTVERSION = B.PRODUCTVERSION " +
                         "WHERE B.BASELOTNO = '" + strLotNo + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    strMAKINGCODE = drTemp["MAKINGCODE"].ToString();
                }
                else
                {
                    strMAKINGCODE = "";
                }
                drTemp.Close();

                // ============================
                // 5. 查询 TBLPCSDIELOG_LQ 获取 Panel 对应的 Unit 信息
                // ============================
                strSQL = "SELECT UNITID,BadFlag FROM TBLPCSDIELOG_LQ WHERE PANLEID = '" + PanelSN + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                var listUnitSN = new List<string>();
                int location = 1;
                while (drTemp.Read())
                {
                    string unitId = drTemp["UNITID"].ToString();
                    int badFlag = 0;
                    if (Convert.ToInt16(drTemp["BadFlag"].ToString()) == 0)
                    {
                        badFlag = 1;

                    }
                    else
                    {
                        badFlag = 0;
                    }
                    if (!string.IsNullOrEmpty(unitId))
                    {
                        listUnitSN.Add("SN" + location.ToString() + ":" + unitId + ":" + badFlag);
                        location++;
                    }
                }
                drTemp.Close();
                strUNITSN = string.Join(";", listUnitSN);

                funMakingCode = true;
                exitfun:
                ;
            }
            catch (Exception ex)
            {
                string errorMsg = clsERP.GetExceptionFullMessage(ex);
                throw new Exception(errorMsg);
            }
            finally
            {
                drTemp?.Close();
                CloseConnection(cnnTemp);
            }
            return funMakingCode;
        }
        public static DataSet ShowAvailableEquipment_All(string LotNo, bool GetAccessory = false, bool GetMaterial = false, bool GetRecipe = false, string AdditionalXml = "", bool ChkCapacity = true, bool MultiQCList = false)
        {
            DataSet ShowAvailableEquipment_AllRet = default(DataSet);

            // PS1.Lot已被派工至非指定機台或非Area上的機台(未處理)
            // PS2.派工的部份先不加入,因派工機制尚待加強,故先不納入考量.

            IDbConnection cnnTemp = null;
            // Dim daTemp As New OleDb.OleDbDataAdapter
            var dsTemp = new DataSet();
            DbDataReader drTemp = null;

            DataRow[] drSel;
            string strAreaNo, strSerialNo, EquipmentNo, strDesc;
            string strEquipmentState = "";
            bool blnAllowExecute;
            bool blnAssign = false;    // 是否有指定機台
            bool blnDispatch = false;  // 是否有派工
            int i, j;

            string strEQPCapability = string.Empty;   // 設備能力
            int intOPReference; // 參數要參考0:Product,1:Module
            string strOPNo, strReferenceNo, strReferenceVersion;
            string strProductNo, strProductVersion;

            strDesc = "";
            strProductNo = "";
            strProductVersion = "";
            AppSettings objSetting = new AppSettings();
            try
            {
                string strDataBaseType = objSetting.GetDataBaseType();
                string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
                // //Create connection
                cnnTemp = CreateConnection(strConnectionString);

                // 1.取出Lot相關資料.
                strSQL = "Select A.AreaNo,A.OPReference, A.LotSerial,A.OPNo,B.ProductNo,B.ProductVersion,A.ModuleNo,A.ModuleVersion  From tblWIPLotState A,TBLWIPLOTBASIS B  Where A.LotNo=B.BASELotNo And A.LotNo='" + LotNo + "'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    strAreaNo = drTemp["AreaNo"].ToString();
                    strSerialNo = drTemp["LotSerial"].ToString();
                    strOPNo = drTemp["OPNo"].ToString();
                    intOPReference = Conversions.ToInteger(drTemp["OPReference"]);

                    // 0122190: 【美迪凯】配件管控失效
                    // 製程模塊(Module)不支援禁用設備設定、指定配件，
                    // 若生產批進到模組製程中， 設備與配件需取得產品上的設定。
                    strReferenceNo = drTemp["ProductNo"].ToString();
                    strReferenceVersion = drTemp["ProductVersion"].ToString();
                    strProductNo = drTemp["ProductNo"].ToString();
                    strProductVersion = drTemp["ProductVersion"].ToString();
                }
                else
                {
                    throw new iMESException.MESException("0000-200003", "[%Get temp data fail%]: [%LotState%]" + Constants.vbCrLf + "[%LotNo%]: " + LotNo);
                    // Throw New iMESException.MESException("0000-200003", "[Get LotNo:" & LotNo & " Lot State join Temp Lot State,is not exist.]")
                }
                drTemp.Close();


                // 1.1 設系統參數SelectAllAreaEQP (0:否, 1:是),判斷是否要選擇該作業站的所有機台,2010/01/06,by yumei
                // 2010/11/24,sammi.加上Module.
                string strParameterValue;

                strSQL = "Select ParameterValue From tblSYSParameter Where Upper(ParameterNo)='SELECTALLAREAEQP'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    strParameterValue = drTemp["ParameterValue"].ToString();
                }
                else
                {
                    strParameterValue = "";
                }
                drTemp.Close();


                if (strParameterValue == "1")
                {
                    // 取出產品或Module作業站的所有區域
                    string strAreaNo_All = "";
                    strSQL = "Select AreaNo From tblPRDOPArea" + " Where ProductNo='" + strReferenceNo + "'" + " And ProductVersion='" + strReferenceVersion + "'" + " And OPNo='" + strOPNo + "'";
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    while (drTemp.Read())
                    {
                        // 配合後面sql in語法使用,要加單引號
                        if (string.IsNullOrEmpty(strAreaNo_All))
                        {
                            strAreaNo_All = "'" + drTemp["AreaNo"] + "'".ToString();
                        }
                        else
                        {
                            strAreaNo_All = strAreaNo_All + "," + "'" + drTemp["AreaNo"] + "'".ToString();
                        }
                    }
                    drTemp.Close();


                    if (string.IsNullOrEmpty(strAreaNo_All))
                    {
                        strAreaNo = "'" + strAreaNo + "'";
                    }
                    else
                    {
                        strAreaNo = strAreaNo_All;
                    }
                }
                else
                {
                    strAreaNo = "'" + strAreaNo + "'";
                }

                // 2.取出CheckIn Confirm不可使用的機台狀態
                // {生產}允許使用,不過必須檢查Capacity
                strSQL = "Select EquipmentState From tblEMSViolateStatusChange " + " Where ViolativeState In (Select EquipmentState From tblEQPStateControl " + " Where Upper(ControlType) ='WIP TRACKING' And Upper(ControlNo) = 'CHECKINCONFIRM')" + " And EquipmentState <> 1";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    strEquipmentState = strEquipmentState + "," + drTemp["EquipmentState"].ToString();
                    while (drTemp.Read())
                        strEquipmentState = strEquipmentState + "," + drTemp["EquipmentState"].ToString();
                    // 去除第一個逗號
                    strEquipmentState = Strings.Mid(strEquipmentState, 2, Strings.Len(strEquipmentState) - 1);
                }
                drTemp.Close();


                // 2.5 檢查是否有設定產品作業站的設備能力 (Equipment Capability)  Larry 2007/12/21
                // 2010/11/23,sammi.改寫
                strSQL = "Select POA.AttribValue" + " From tblPRDOP PO,tblPRDOPAttrib POA " + " Where PO.SerialNo = POA.SerialNo " + " And PO.ProductNo='" + strReferenceNo + "'" + " And PO.ProductVersion='" + strReferenceVersion + "'" + " And PO.OPNo='" + strOPNo + "'" + " And UPPER (POA.AttribNo) = UPPER ('EQPCapability') ";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    strEQPCapability = drTemp["AttribValue"].ToString();
                }
                else
                {
                    strEQPCapability = string.Empty;
                }
                drTemp.Close();


                // 3.以AreaNo取出所有機台.
                // 有設定Equipment Capability的話 要過濾掉OFF狀態的設備
                if (!string.IsNullOrEmpty(strEQPCapability))
                {
                    // EQPSwitch 0:OFF 1:ON
                    // 當有設定PRDOPAttrib.EQPCapability時就只取 EQPSwitch=1(ON)的狀態

                    strSQL = " SELECT * ";
                    strSQL += "  FROM (SELECT AreaEQP.*, EQPCapability.Capability, EQPCapability.EQPSwitch ";
                    strSQL += "          FROM (SELECT EquipmentType, EquipmentNo, EquipmentName, ";
                    if (strDataBaseType != "oracle")
                    {
                        strSQL += "                       IsNull(EquipmentClass, '') AS EquipmentClass, ";
                        strSQL += "                       IsNull(Capacity, -1) AS Capacity, ";
                        strSQL += "                       IsNull(LoadPort, 0) AS EQPLoadPort, QCListNo ";
                    }
                    else
                    {
                        strSQL += "                       Nvl(EquipmentClass, '') AS EquipmentClass, ";
                        strSQL += "                       Nvl(Capacity, -1) AS Capacity, ";
                        strSQL += "                       Nvl(LoadPort, 0) AS EQPLoadPort, QCListNo ";
                    }
                    strSQL += "                  FROM tblEQPEquipmentBasis ";
                    strSQL += "                 WHERE IssueState = 2 And EquipmentNo IN ( ";
                    strSQL += "                            SELECT ObjectNo ";
                    strSQL += "                              FROM tblSMDAreaRelation ";
                    strSQL += "                             WHERE ContainAreaNo in (" + strAreaNo + ") ";
                    strSQL += "                                   AND ObjectType = 2) ";
                    strSQL += "                    OR EquipmentNo IN ( ";
                    strSQL += "                          SELECT EquipmentNo ";
                    strSQL += "                            FROM tblEQPGroupDetail ";
                    strSQL += "                           WHERE EquipmentGroup IN ( ";
                    strSQL += "                                    SELECT ObjectNo ";
                    strSQL += "                                      FROM tblSMDAreaRelation ";
                    strSQL += "                                     WHERE ContainAreaNo in (" + strAreaNo + ") ";
                    strSQL += "                                       AND ObjectType = 4))) AreaEQP ";
                    strSQL += "               LEFT OUTER JOIN ";
                    strSQL += "               (SELECT * ";
                    strSQL += "                  FROM tblEMSEQPCapabilityStatus ";
                    strSQL += "                 WHERE UPPER(Capability) = '" + strEQPCapability.ToUpper() + "') EQPCapability ";
                    strSQL += "               ON AreaEQP.EquipmentNo = EQPCapability.EquipmentNo ";
                    strSQL += "               ) A ";
                    strSQL += " WHERE A.EQPSwitch = 1 ";


                    strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    // daTemp.SelectCommand = cmmTemp
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "AreaEquipment_A", cnnTemp);
                }

                else
                {
                    strSQL = "Select EquipmentType,EquipmentNo, EquipmentName, ";
                    if (strDataBaseType != "oracle")
                    {
                        strSQL += " IsNull(EquipmentClass,'') as EquipmentClass , IsNull(Capacity,-1) as Capacity , IsNull(LoadPort,0) as EQPLoadPort, QCListNo ";
                    }
                    else
                    {
                        strSQL += " Nvl(EquipmentClass,'') as EquipmentClass , Nvl(Capacity,-1) as Capacity , Nvl(LoadPort,0) as EQPLoadPort, QCListNo ";
                    }
                    strSQL += " From tblEQPEquipmentBasis" + " Where IssueState = 2 And (EquipmentNo In (Select ObjectNo From tblSMDAreaRelation " + " Where ContainAreaNo in (" + strAreaNo + ") And ObjectType = 2)" + " Or EquipmentNo In (Select EquipmentNo From tblEQPGroupDetail " + " Where EquipmentGroup In (Select ObjectNo From tblSMDAreaRelation " + " Where ContainAreaNo in (" + strAreaNo + ") And ObjectType = 4)))";

                    strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    // daTemp.SelectCommand = cmmTemp
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "AreaEquipment_A", cnnTemp);

                }

                //子设备禁用
                strSQL = "select equipmentno from  tblPRDEQPConstraint WHERE PRODUCTNO='" + strReferenceNo + "' AND OPNO='" + strOPNo + "'";
                strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "PRDEQPConstraint_SubEquipment", cnnTemp);

                // 使用主設備查詢子設備
                // 2021/06/08 TsungYu =====================================================================================
                string strEQP = string.Empty;
                string strChamber = string.Empty;
                string strParameterChamber = string.Empty;

                strSQL = "Select ParameterValue From tblSYSParameter Where Upper(ParameterNo) = 'CHAMBERMANAGE'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    strParameterChamber = drTemp["ParameterValue"].ToString();
                }
                else
                {
                    strParameterChamber = "";
                }
                drTemp.Close();


                // 2021/8/26,Ning, 98778: 客户：浏阳泰科; 系统MESSeries 6.0.5.15; 问题：生产执行进站报错。
                if (strParameterChamber == "1" && dsTemp.Tables["AreaEquipment_A"].Rows.Count > 0)
                {
                    foreach (DataRow dr in dsTemp.Tables["AreaEquipment_A"].Rows)
                        strEQP += string.Format("'{0}',", dr["EquipmentNo"].ToString());
                    // If strEQP = String.Empty Then
                    // Throw New iMESException.MESException("0000-200015", "[%AreaNo%]: " & strAreaNo & " [%Can not find equipmentno data%]")
                    // End If
                    strEQP = strEQP.TrimEnd(',');

                    strSQL = "select EquipmentType,EquipmentNo,EquipmentName,BelongEquipmentNo, ";
                    if (strDataBaseType != "oracle")
                    {
                        strSQL += "                       IsNull(EquipmentClass, '') AS EquipmentClass, ";
                        strSQL += "                       IsNull(Capacity, -1) AS Capacity, ";
                        strSQL += "                       IsNull(LoadPort, 0) AS EQPLoadPort, QCListNo ";
                    }
                    else
                    {
                        strSQL += "                       Nvl(EquipmentClass, '') AS EquipmentClass, ";
                        strSQL += "                       Nvl(Capacity, -1) AS Capacity, ";
                        strSQL += "                       Nvl(LoadPort, 0) AS EQPLoadPort, QCListNo ";
                    }
                    strSQL += "  from tblEQPEquipmentBasis where BelongEquipmentNo  in (" + strEQP + ") And  IssueState = 2 order by EquipmentNo";
                    strSQL += "   ";
                    strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    // daTemp.SelectCommand = cmmTemp
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "Chamber", cnnTemp);

                    string strChamberEquipmentNo = string.Empty;


                    foreach (DataRow dr in dsTemp.Tables["Chamber"].Rows)
                    {
                        // clsAE不存在新增欄位
                        if (dsTemp.Tables["Chamber"].Columns.Contains("AllowExecute") == false)
                        {
                            var colChamberAE = new DataColumn("AllowExecute", Type.GetType("System.Int16"));
                            colChamberAE.DefaultValue = 0;
                            dsTemp.Tables["Chamber"].Columns.Add(colChamberAE);
                        }
                        // clsDescription不存在新增欄位
                        if (dsTemp.Tables["Chamber"].Columns.Contains("Description") == false)
                        {
                            // Description,不可執行的說明,Default="".
                            var colChamberDE = new DataColumn("Description", Type.GetType("System.String"));
                            colChamberDE.DefaultValue = "";
                            dsTemp.Tables["Chamber"].Columns.Add(colChamberDE);
                        }

                        EquipmentNo = dr["EquipmentNo"].ToString();
                        blnAllowExecute = true;
                        // 檢查子機台
                        // 檢查是否為可用狀態
                        if (!string.IsNullOrEmpty(strEquipmentState))
                        {
                            strSQL = "Select EquipmentNo From tblEMSEquipmentState " + " Where EquipmentNo = '" + EquipmentNo + "' And EquipmentState In (" + strEquipmentState + ")";
                            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                            if (drTemp.Read()) // 不可使用
                            {
                                blnAllowExecute = false;
                                strDesc += "EquipmentState is not available.";
                            }
                            drTemp.Close();

                        }
                        // 检查禁用设备
                        if (dsTemp.Tables["PRDEQPConstraint_SubEquipment"].Rows.Count > 0)
                        {
                            DataRow[] drTemp_SubEQP;
                            drTemp_SubEQP = dsTemp.Tables["PRDEQPConstraint_SubEquipment"].Select("EquipmentNo='" + dr["EquipmentNo"] + "'");
                            if (drTemp_SubEQP.Length > 0)
                            {
                                blnAllowExecute = false;
                                strDesc = "[%Equipment Is Constraint%]";
                            }
                        }
                        if (ChkCapacity)
                        {
                            // 可使用的情況下,檢查Capacity(-1不限制Capacity).已在機台上的量+目前此批的量.
                            if (blnAllowExecute && Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dr["Capacity"], -1, false)))
                            {
                                strSQL = "Select Nvl(Sum(CurQty),0) As SumCurQty From tblWIPLotState " + " Where LotNo In (Select LotNo From tblWIPTemp_Equipment " + " Where EquipmentNo='" + EquipmentNo + "')" + " Or LotNo = '" + LotNo + "'";
                                strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectGreater(drTemp["SumCurQty"], dr["Capacity"], false)))
                                    {
                                        blnAllowExecute = false;
                                        strDesc += "[%Capacity is full%]";
                                    }
                                }
                                drTemp.Close();

                            }
                        }

                        // 2007/10/24 Lena  
                        // 可使用的情況下,檢查 LoadPort(上貨區數量)(<=0 不限制LoadPort)
                        if (blnAllowExecute && Convert.ToBoolean(Operators.ConditionalCompareObjectGreater(dr["EQPLoadPort"], 0, false)))
                        {
                            strSQL = "Select Count(*) as LotQty From tblWIPTemp_Equipment " + " Where EquipmentNo = '" + EquipmentNo + "'";
                            strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                            if (drTemp.Read())
                            {
                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectGreaterEqual(drTemp["LotQty"], dr["EQPLoadPort"], false)))
                                {
                                    blnAllowExecute = false; // 不可使用, 已超過 LoadPort 設定的數量
                                    strDesc += "[%LoadPort is full.%]";
                                }
                            }
                            drTemp.Close();

                        }
                        // 變更狀態.
                        dr.BeginEdit();
                        if (blnAllowExecute)
                        {
                            dr["AllowExecute"] = 1;      // 可用
                                                         // 組合予後面使用,可使用的,才加入.
                            strChamberEquipmentNo += ",'" + EquipmentNo + "'";
                        }
                        else
                        {
                            dr["Description"] = strDesc;

                        } // 不可用說明
                        dr.EndEdit();
                    }
                }



                // ==========================================================================================================


                // 4.Add Column
                // RecipeGroup
                var colRG = new DataColumn("RecipeGroup", Type.GetType("System.String"));
                colRG.DefaultValue = "N/A";
                dsTemp.Tables["AreaEquipment_A"].Columns.Add(colRG);
                // RecipeVersion,Default=0.
                var colRV = new DataColumn("RecipeVersion", Type.GetType("System.String"));
                colRV.DefaultValue = 0;
                dsTemp.Tables["AreaEquipment_A"].Columns.Add(colRV);
                // EquipmentSource,1:參數指定機台,2:Area上的機台,Default=2.
                var colES = new DataColumn("EquipmentSource", Type.GetType("System.Int32"));
                colES.DefaultValue = 2;
                dsTemp.Tables["AreaEquipment_A"].Columns.Add(colES);
                // DispatchOrder,-1:沒有被派工,其他:派工順序,Default=-1.
                var colDO = new DataColumn("DispatchOrder", Type.GetType("System.Int32"));
                colDO.DefaultValue = -1;
                dsTemp.Tables["AreaEquipment_A"].Columns.Add(colDO);
                // AllowExecute,0:No,1:Yes,Default=0.
                var colAE = new DataColumn("AllowExecute", Type.GetType("System.Int16"));
                colAE.DefaultValue = 0;
                dsTemp.Tables["AreaEquipment_A"].Columns.Add(colAE);
                // Description,不可執行的說明,Default="".
                var colDE = new DataColumn("Description", Type.GetType("System.String"));
                colDE.DefaultValue = "";
                dsTemp.Tables["AreaEquipment_A"].Columns.Add(colDE);

                // Kevin 2014/01/05,模治具處理
                // 取出產品設定的模治具
                strSQL = " Select * From tblPRDAccessory" + " Where  ProductNo ='" + strReferenceNo + "'" + " And    ProductVersion = '" + strReferenceVersion + "'" + " And    OPNo ='" + strOPNo + "'" + " Order By AccessoryType,AccessoryNo";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                // daTemp.SelectCommand = cmmTemp
                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "PRDAccessory", cnnTemp);


                // 5.指定機台,可能有多台,指定機台一定在Area的集合內.
                string strAssEQP = "";
                if (strDataBaseType != "oracle")
                {
                    strSQL = "Select A.EquipmentNo,IsNull(A.RecipeGroup,'N/A') As RecipeGroup,IsNull(B.RecipeVersion,0) As RecipeVersion " + " From tblPRDOPEQPRecipe A left outer join (Select RecipeGroup,RecipeVersion From tblEQPRecipeBasis Where CurVersion=1) B " + " On A.RecipeGroup=B.RecipeGroup " + " Where A.SerialNo='" + strSerialNo + "'";
                }
                else
                {
                    strSQL = "Select A.EquipmentNo,Nvl(A.RecipeGroup,'N/A') As RecipeGroup,Nvl(B.RecipeVersion,0) As RecipeVersion " + " From tblPRDOPEQPRecipe A,(Select RecipeGroup,RecipeVersion From tblEQPRecipeBasis Where CurVersion=1) B " + " Where A.RecipeGroup=B.RecipeGroup(+) " + " And A.SerialNo='" + strSerialNo + "'";
                }
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                while (drTemp.Read())
                {
                    blnAssign = true;
                    EquipmentNo = drTemp["EquipmentNo"].ToString();
                    drSel = dsTemp.Tables["AreaEquipment_A"].Select("EquipmentNo='" + EquipmentNo + "'");
                    if (drSel.Length > 0)
                    {
                        drSel[0].BeginEdit();
                        drSel[0]["RecipeGroup"] = drTemp["RecipeGroup"];
                        drSel[0]["RecipeVersion"] = drTemp["RecipeVersion"];
                        drSel[0]["EquipmentSource"] = 1; // 來自參數指定機台
                        drSel[0].EndEdit();
                        strAssEQP += "," + EquipmentNo;
                    }
                }
                drTemp.Close();


                // 有指定機台的情況下,紀錄其他非指定機台不可使用的原因.
                if (blnAssign)
                {
                    strDesc = "Have assigned equipment(" + Strings.Mid(strAssEQP, 2) + "),but current equipment is not assigned.";
                    drSel = dsTemp.Tables["AreaEquipment_A"].Select("EquipmentSource=2");
                    var loopTo = drSel.Length - 1;
                    for (j = 0; j <= loopTo; j++)
                    {
                        drSel[j].BeginEdit();
                        drSel[j]["Description"] = strDesc;
                        drSel[j].EndEdit();
                    }
                }

                // 6.檢查各機台的可用性.
                string strEquipmentNo = "";
                string strRecipe = "";
                string strSel = "";

                if (blnAssign)
                    strSel += " And EquipmentSource=1"; // 取出指定機台
                if (blnDispatch)
                    strSel += " And DispatchOrder<>-1"; // 取出派工機台

                if (string.IsNullOrEmpty(strSel))
                {
                    drSel = dsTemp.Tables["AreaEquipment_A"].Select();
                }
                else
                {
                    strSel = Strings.Replace(strSel, "And", "", 1, 1, CompareMethod.Text);
                    drSel = dsTemp.Tables["AreaEquipment_A"].Select(strSel);
                }

                var loopTo1 = drSel.Length - 1;
                for (i = 0; i <= loopTo1; i++)
                {
                    blnAllowExecute = true;
                    strDesc = "";
                    EquipmentNo = drSel[i]["EquipmentNo"].ToString();

                    // 檢查是否為可用狀態
                    if (!string.IsNullOrEmpty(strEquipmentState))
                    {
                        strSQL = "Select EquipmentNo From tblEMSEquipmentState " + " Where EquipmentNo = '" + EquipmentNo + "' And EquipmentState In (" + strEquipmentState + ")";
                        // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                        drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                        if (drTemp.Read()) // 不可使用
                        {
                            blnAllowExecute = false;
                            strDesc += "EquipmentState is not available.";
                        }
                        drTemp.Close();

                    }

                    if (ChkCapacity)
                    {
                        // 可使用的情況下,檢查Capacity(-1不限制Capacity).已在機台上的量+目前此批的量.
                        if (blnAllowExecute && Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drSel[i]["Capacity"], -1, false)))
                        {
                            strSQL = "Select Nvl(Sum(CurQty),0) As SumCurQty From tblWIPLotState " +
                                " Where LotNo In (Select LotNo From tblWIPTemp_Equipment " +
                                " Where EquipmentNo='" + EquipmentNo + "')" + " Or LotNo = '" + LotNo + "'";
                            strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                            if (drTemp.Read())
                            {
                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectGreater(drTemp["SumCurQty"], drSel[i]["Capacity"], false)))
                                {
                                    blnAllowExecute = false;
                                    strDesc += "[%Capacity is full%]";
                                }
                            }
                            drTemp.Close();

                        }
                    }

                    // 2007/10/24 Lena  
                    // 可使用的情況下,檢查 LoadPort(上貨區數量)(<=0 不限制LoadPort)
                    if (blnAllowExecute && Convert.ToBoolean(Operators.ConditionalCompareObjectGreater(drSel[i]["EQPLoadPort"], 0, false)))
                    {
                        strSQL = "Select Count(*) as LotQty From tblWIPTemp_Equipment " + " Where EquipmentNo = '" + EquipmentNo + "'";
                        strSQL = SQLCommandTuning(strDataBaseType, ref strSQL);
                        // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                        drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                        if (drTemp.Read())
                        {
                            if (Convert.ToBoolean(Operators.ConditionalCompareObjectGreaterEqual(drTemp["LotQty"], drSel[i]["EQPLoadPort"], false)))
                            {
                                blnAllowExecute = false; // 不可使用, 已超過 LoadPort 設定的數量
                                strDesc += "[%LoadPort is full.%]";
                            }
                        }
                        drTemp.Close();

                    }

                    // Kevin 2014/01/05,模治具處理
                    // 檢查設備可用性，依產品-作業站-模治具設定決定可用的設備，只要設備沒有掛上設定之模治具就不能使用，CI不開放選取
                    // 先判斷是否有設定資料，有的話才要檢查
                    if (blnAllowExecute && dsTemp.Tables["PRDAccessory"].Rows.Count > 0)
                    {

                        if (dsTemp.Tables["AccStateTemp"] != null)
                        {
                            dsTemp.Tables.Remove("AccStateTemp");
                        }

                        // 取出AccState
                        strSQL = "Select A.*,B.AccessoryState,B.AccumulateQty,B.AccSpareQty,C.ScrapLife,C.LifeManage,C.LifeScript,C.LifeTolerance,C.RepairCycle,D.StateName " + " From tblEMSEQPAccState A left join tblEMSAccessoryState B on A.AccessoryNo=B.AccessoryNo " + " And A.AccessoryVersion=B.AccessoryVersion left join tblEQPAccessoryLife C " + " on A.AccessoryType=C.Accessory " + " left join tblEQPAccStateBasis D On B.AccessoryState = D.AccessoryState " + " Where A.EquipmentNo = '" + EquipmentNo + "'" + " Order By A.AccessoryType,A.AccessoryNo";
                        // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                        // daTemp.SelectCommand = cmmTemp
                        ExecuteSQLQuery_Adapter(strSQL, dsTemp, "AccStateTemp", cnnTemp);


                        bool blnPRDAcc = false;  // 是否有產品設定的模治具
                        string strAccessoryType = "";
                        var aryShowAccType = new ArrayList();
                        var aryShowAccNo = new ArrayList();

                        if (dsTemp.Tables["AccStateTemp"].Rows.Count > 0)
                        {
                            // 檢查設備是否都有掛產品指定之模治具，相同類別允許掛多個，但至少要有一個
                            foreach (DataRow drPRD in dsTemp.Tables["PRDAccessory"].Rows)
                            {

                                // 檢查是否是同個模治具類別
                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(strAccessoryType, drPRD["AccessoryType"], false)))
                                {
                                    if (blnPRDAcc)
                                    {
                                        // 如果已有產品設定的模治具則跳至下一筆
                                        goto lblAccCheck;
                                    }
                                }
                                else
                                {
                                    // 第一個物料類別不判斷blnPRDAcc
                                    if (!string.IsNullOrEmpty(strAccessoryType))
                                    {
                                        // 不同模治具類別時，如果上個模治具類別沒有符合的資料，則此設備不可用
                                        if (blnPRDAcc == false)
                                        {
                                            // 只要有一種類別模治具不符合就是False
                                            blnAllowExecute = false;
                                        }
                                    }

                                    // 記錄此次模治具類別
                                    strAccessoryType = drPRD["AccessoryType"].ToString();
                                }

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drPRD["AccessoryNo"], "*", false)))
                                {
                                    // 如果模治具編號為*代表只有指定模治具類別
                                    foreach (DataRow drAcc in dsTemp.Tables["AccStateTemp"].Rows)
                                    {
                                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drAcc["AccessoryType"], drPRD["AccessoryType"], false)))
                                        {
                                            // 有符合的代表有掛指定的模治具類別
                                            blnPRDAcc = true;
                                            // 移除此次加入的類別
                                            aryShowAccType.Remove(drPRD["AccessoryType"]);
                                            // 有符合一筆即可
                                            goto lblAccCheck;
                                        }
                                        else
                                        {
                                            blnPRDAcc = false;
                                            if (!aryShowAccType.Contains(drPRD["AccessoryType"]))
                                            {
                                                aryShowAccType.Add(drPRD["AccessoryType"]);
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    // 如果模治具編號不為*代表有指定模治具
                                    foreach (DataRow drAcc in dsTemp.Tables["AccStateTemp"].Rows)
                                    {
                                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drAcc["AccessoryType"], drPRD["AccessoryType"], false)) && Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drAcc["AccessoryNo"], drPRD["AccessoryNo"], false)))
                                        {
                                            // 有符合的代表有掛指定的模治具類別
                                            blnPRDAcc = true;
                                            // 移除此次加入的編號
                                            aryShowAccNo.Remove(drPRD["AccessoryNo"]);
                                            // 有符合一筆即可
                                            break;
                                        }
                                        else
                                        {
                                            blnPRDAcc = false;
                                            if (!aryShowAccNo.Contains(drPRD["AccessoryNo"]))
                                            {
                                                aryShowAccNo.Add(drPRD["AccessoryNo"]);
                                            }
                                        }
                                    }
                                }
                                lblAccCheck:
                                ;

                            }

                            // 多判斷一次最後一個類別
                            if (blnPRDAcc == false)
                            {
                                // 只要有一種類別模治具不符合就是False
                                blnAllowExecute = false;
                            }

                            if (blnAllowExecute == false)
                            {
                                // 設備沒有掛載產品設定的模治具
                                // 不可用說明
                                strDesc += "Equipment don't use Product Setup's Accessorys";
                                if (aryShowAccType.Count > 0)
                                {
                                    strDesc += ", AccessoryType：";
                                    for (int k = 0, loopTo2 = aryShowAccType.Count - 1; k <= loopTo2; k++)
                                        strDesc = strDesc + aryShowAccType[k] + ",".ToString();
                                    strDesc = strDesc.TrimEnd(',');
                                }
                                if (aryShowAccNo.Count > 0)
                                {
                                    strDesc += ", AccessoryNo：";
                                    for (int k = 0, loopTo3 = aryShowAccNo.Count - 1; k <= loopTo3; k++)
                                        strDesc = strDesc + aryShowAccNo[k] + ",".ToString();
                                    strDesc = strDesc.TrimEnd(',');
                                }
                            }
                        }
                        else
                        {
                            // 設備沒掛模治具就一定沒有掛設定的必需模治具
                            // 不可用說明
                            blnAllowExecute = false;
                            strDesc += "There is Product Accessory Setup, Equipment don't use any Accessorys";
                        }
                    }

                    // 變更狀態.
                    drSel[i].BeginEdit();
                    if (blnAllowExecute)
                    {
                        drSel[i]["AllowExecute"] = 1;      // 可用
                                                           // 組合予後面使用,可使用的,才加入.
                        strEquipmentNo += ",'" + EquipmentNo + "'";
                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drSel[i]["RecipeGroup"], "N/A", false)))
                        {
                            strRecipe = strRecipe + ",('" + drSel[i]["RecipeGroup"] + "','" + drSel[i]["RecipeVersion"] + "')".ToString();
                        }
                    }
                    else
                    {
                        drSel[i]["Description"] = strDesc;

                    } // 不可用說明
                    drSel[i].EndEdit();
                }

                // ===================================
                // 子設備 TsungYu 2021/06/08
                if (strParameterChamber == "1" && dsTemp.Tables["AreaEquipment_A"].Rows.Count > 0)
                {
                    var parentColFIAcc = new DataColumn[1];
                    var childColChamber = new DataColumn[1];
                    parentColFIAcc[0] = dsTemp.Tables["AreaEquipment_A"].Columns["EquipmentNo"];
                    childColChamber[0] = dsTemp.Tables["Chamber"].Columns["BelongEquipmentNo"];

                    DataRelation tmpReAcc;
                    tmpReAcc = new DataRelation("Chamber", parentColFIAcc, childColChamber, false);
                    dsTemp.Relations.Add(tmpReAcc);
                }
                // ===================================

                if (!string.IsNullOrEmpty(strEquipmentNo))
                {
                    // 去除第一個逗號
                    strEquipmentNo = Strings.Mid(strEquipmentNo, 2, Strings.Len(strEquipmentNo) - 1);
                    string[] artEquipmentNo;
                    artEquipmentNo = strEquipmentNo.Split(',');

                    // '===================================
                    // '子設備 TsungYu 2021/06/08
                    // If strParameterChamber = "1" Then
                    // Dim parentColFIAcc(0) As DataColumn
                    // Dim childColChamber(0) As DataColumn
                    // parentColFIAcc(0) = dsTemp.Tables("AreaEquipment_A").Columns("EquipmentNo")
                    // childColChamber(0) = dsTemp.Tables("Chamber").Columns("BelongEquipmentNo")

                    // Dim tmpReAcc As DataRelation
                    // tmpReAcc = New DataRelation("Chamber", parentColFIAcc, childColChamber, False)
                    // dsTemp.Relations.Add(tmpReAcc)
                    // End If
                    // '===================================

                    // 取出模治具,GetAccessory是用來決定介面要不要看到EQP掛的模治具的變數
                    if (GetAccessory)
                    {
                        // Kevin 15/01/26,調整In的寫法
                        for (int m = 0, loopTo4 = artEquipmentNo.Length - 1; m <= loopTo4; m++)
                        {
                            // 取出AccState
                            strSQL = "Select A.*,B.AccessoryState,B.AccumulateQty,B.AccSpareQty,C.ScrapLife,C.LifeManage,C.LifeScript,C.LifeTolerance,C.RepairCycle,D.StateName " + " From tblEMSEQPAccState A left join tblEMSAccessoryState B on A.AccessoryNo=B.AccessoryNo " + " And A.AccessoryVersion=B.AccessoryVersion left join tblEQPAccessoryLife C " + " on A.AccessoryType=C.Accessory " + " left join tblEQPAccStateBasis D On B.AccessoryState = D.AccessoryState " + " Where A.EquipmentNo = " + artEquipmentNo[m] + " Order By A.AccessoryType,A.AccessoryNo";
                            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                            // daTemp.SelectCommand = cmmTemp
                            ExecuteSQLQuery_Adapter(strSQL, dsTemp, "AccState", cnnTemp);

                        }

                        // 建立Relation
                        var parentColFIAcc = new DataColumn[1];
                        var childColFIAcc = new DataColumn[1];
                        parentColFIAcc[0] = dsTemp.Tables["AreaEquipment_A"].Columns["EquipmentNo"];
                        childColFIAcc[0] = dsTemp.Tables["AccState"].Columns["EquipmentNo"];
                        // 建立主從關係(RelationName會影響WinForm資料的顯示)
                        DataRelation tmpReAcc;
                        tmpReAcc = new DataRelation("Accessory", parentColFIAcc, childColFIAcc, false);
                        dsTemp.Relations.Add(tmpReAcc);
                    }

                    // 取出物料
                    if (GetMaterial)
                    {
                        // Kevin 15/01/26,調整In的寫法
                        for (int m = 0, loopTo5 = artEquipmentNo.Length - 1; m <= loopTo5; m++)
                        {
                            // 取出MaterialState
                            strSQL = "Select EquipmentNo,MaterialNo,MaterialLotNo,Qty,UnitNo,InputDate From tblEMSEQPMaterialState " + " Where EquipmentNo = " + artEquipmentNo[m];
                            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                            // daTemp.SelectCommand = cmmTemp
                            ExecuteSQLQuery_Adapter(strSQL, dsTemp, "MaterialState", cnnTemp);

                        }

                        if (dsTemp.Tables["MaterialState"].Rows.Count == 0)
                        {
                            dsTemp.Tables.Remove("MaterialState");
                        }
                        else
                        {
                            // 建立Relation
                            var parentColFI = new DataColumn[1];
                            var childColFI = new DataColumn[1];

                            parentColFI[0] = dsTemp.Tables["AreaEquipment_A"].Columns["EquipmentNo"];
                            childColFI[0] = dsTemp.Tables["MaterialState"].Columns["EquipmentNo"];

                            // 建立主從關係(RelationName會影響WinForm資料的顯示)
                            DataRelation tmpRe1;
                            tmpRe1 = new DataRelation("Material", parentColFI, childColFI, false);
                            dsTemp.Relations.Add(tmpRe1);
                        }
                    }

                    // 取出Recipe
                    if (GetRecipe && !string.IsNullOrEmpty(strRecipe))
                    {
                        strRecipe = Strings.Mid(strRecipe, 2);  // 去除第一個逗號
                                                                // 取出RecipeDetail(因RecipeVersion要做為Key,故將Number轉為字串)
                        if (strDataBaseType != "oracle")
                        {
                            // strRecipe = Replace(strRecipe, "','", "+")
                            strRecipe = Strings.Replace(strRecipe, "','", "");
                            strSQL = "Select RecipeGroup,STR(RecipeVersion, 1) As RecipeVersion,RecipeNo,RecipeValue From tblEQPRecipeDetail " + " Where (RecipeGroup+Str(RecipeVersion,1)) In (" + strRecipe + ")";
                        }
                        else
                        {
                            strSQL = "Select RecipeGroup,Substr(RecipeVersion,1) As RecipeVersion,RecipeNo,RecipeValue From tblEQPRecipeDetail " + " Where (RecipeGroup,RecipeVersion) In (" + strRecipe + ")";
                        }
                        // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                        // daTemp.SelectCommand = cmmTemp
                        ExecuteSQLQuery_Adapter(strSQL, dsTemp, "RecipeDetail", cnnTemp);


                        if (dsTemp.Tables["RecipeDetail"].Rows.Count == 0)
                        {
                            dsTemp.Tables.Remove("RecipeDetail");
                        }
                        else
                        {
                            // 建立Relation
                            var parentColFI = new DataColumn[2];
                            var childColFI = new DataColumn[2];

                            parentColFI[0] = dsTemp.Tables["AreaEquipment_A"].Columns["RecipeGroup"];
                            childColFI[0] = dsTemp.Tables["RecipeDetail"].Columns["RecipeGroup"];
                            parentColFI[1] = dsTemp.Tables["AreaEquipment_A"].Columns["RecipeVersion"];
                            childColFI[1] = dsTemp.Tables["RecipeDetail"].Columns["RecipeVersion"];

                            // 建立主從關係(RelationName會影響WinForm資料的顯示)
                            DataRelation tmpRe1;
                            tmpRe1 = new DataRelation("Recipe", parentColFI, childColFI, false);
                            dsTemp.Relations.Add(tmpRe1);
                        }
                    }
                }

                // 2012/12/26 YF, 檢查產品所設定的設備能力
                var tmp = dsTemp.Tables;
                var argdtEquipment = tmp["AreaEquipment_A"];
                using (var objLot = new clsLot())
                {
                    objLot.funCheckEquipmentCapability(ref cnnTemp, ref argdtEquipment, strReferenceNo, strReferenceVersion, strOPNo);
                }


                // 2012/12/26 YF, 檢查產品所設定的禁用設備
                var tmp1 = dsTemp.Tables;
                var argdtEquipment1 = tmp1["AreaEquipment_A"];
                using (var objLot = new clsLot())
                {
                    objLot.funCheckEquipmentConstraint(ref cnnTemp, ref argdtEquipment1, strReferenceNo, strReferenceVersion, strOPNo);
                }
                // 現行製程模組不支持設備禁用設定，因此判斷設備禁用的設定應再統一查詢產品資料中的 禁用設備的設定
                if (intOPReference == 1)
                {
                    var tmp2 = dsTemp.Tables;
                    var argdtEquipment2 = tmp2["AreaEquipment_A"];
                    using (var objLot = new clsLot())
                    {
                        objLot.funCheckEquipmentConstraint(ref cnnTemp, ref argdtEquipment2, strProductNo, strProductVersion, strOPNo);
                    }
                }

                if (MultiQCList == true)
                {
                    // 2021/3/18,Ning,QCListNo:列出所有設定為CheckIn的點檢表編號, 若有多筆, 則以逗號串起
                    var tmp3 = dsTemp.Tables;
                    var argdtEquipment3 = tmp3["AreaEquipment_A"];
                    using (var objLot = new clsLot())
                    {
                        objLot.funFillEquipmentQCListNo(ref cnnTemp, ref argdtEquipment3);
                    }
                }

                // Return
                ShowAvailableEquipment_AllRet = dsTemp;
            }

            catch (Exception e1)
            {
                ShowAvailableEquipment_AllRet = null;
                throw;
            }

            finally
            {
                CloseConnection(cnnTemp);

                if (dsTemp != null)
                    dsTemp.Dispose();

            }
            return ShowAvailableEquipment_AllRet;

        }

        #endregion


        #region "LotMessage批次信息查询接口"
        /// <summary>
        /// 批次信息查询接口：根据PanelSN查LotNo，再查询批次相关的客户、产品、工艺、当前工序信息
        /// </summary>
        public static bool funLotMessage(ref List<ArrayList> aryMessage, ref List<ArrayList> aryException, string PanelSN, string EQPID,
            ref string strLOTNO, ref string strPROCESSNO, ref string strOPNO, ref string strPRODUCTNO, ref string strCUSTOMERNO)
        {
            bool funLotMessage = default(bool);
            string strSQL = default(string);
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();

            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            string strLotNo = "";

            try
            {
                // ============================
                // 1. 根据PanelSN（作为ProductID）查询LotNo
                // ============================
                strSQL = "SELECT LOTNO FROM TBLWIPPRDSTATE_LQ WHERE PRODUCTID = '" + PanelSN + "' AND STATE = '1'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%PanelSN(" + PanelSN + ")未找到对应批次!%]");
                    return false;
                }
                strLotNo = drTemp["LOTNO"].ToString();
                strLOTNO = strLotNo;
                drTemp.Close();

                // ============================
                // 2. 查询批次信息：产品、客户、流程编号、当前工序
                //    TBLWIPLOTBASIS: PRODUCTNO, CUSTOMERNO
                //    TBLWIPLOTSTATE: PROCESSNO (流程编号), OPNO (当前工序)
                // ============================
                strSQL = "SELECT A.PRODUCTNO, A.CUSTOMERNO, B.PROCESSNO, B.OPNO " +
                         "FROM TBLWIPLOTBASIS A " +
                         "LEFT JOIN TBLWIPLOTSTATE B ON A.BASELOTNO = B.LOTNO " +
                         "WHERE A.BASELOTNO = '" + strLotNo + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    strPRODUCTNO = drTemp["PRODUCTNO"].ToString();
                    strCUSTOMERNO = drTemp["CUSTOMERNO"].ToString();
                    strPROCESSNO = drTemp["PROCESSNO"].ToString();
                    strOPNO = drTemp["OPNO"].ToString();
                }
                else
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%批次(" + strLotNo + ")未找到批次基础信息!%]");
                    return false;
                }
                drTemp.Close();

                funLotMessage = true;
                exitfun:
                ;
            }
            catch (Exception ex)
            {
                string errorMsg = clsERP.GetExceptionFullMessage(ex);
                throw new Exception(errorMsg);
            }
            finally
            {
                drTemp?.Close();
                CloseConnection(cnnTemp);
            }
            return funLotMessage;
        }
        #endregion


        #region "MACBLUE MAC&蓝牙地址生成接口"
        /// <summary>
        /// MAC&蓝牙地址生成：根据UnitId查批次→产品→序号规则，按规则生成MAC和蓝牙地址
        /// </summary>
        public static string funMACBLUE(string request)
        {
            string strResult = "";
            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;

            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            string strUnitId = "";
            string strLotNo = "";
            string strProductNo = "";
            string strMACRuleNo = "";
            string strBlueToothRuleNo = "";
            string strGeneratedMACID = "";
            string strGeneratedBlueToothID = "";

            MACBLUEResponse response = new MACBLUEResponse();

            try
            {
                var Parameters = JsonConvert.DeserializeObject<Dictionary<string, string>>(request);
                strUnitId = Parameters.ContainsKey("unitid") ? Parameters["unitid"] : "";
                if (string.IsNullOrEmpty(strUnitId))
                    throw new Exception("[%unitid不能为空!%]");

                // 1. 根据unitid查LotNo
                string strSQL = "SELECT LOTNO FROM TBLWIPPRDSTATE_LQ WHERE PRODUCTID = '" + strUnitId + "' AND STATE = '1' AND PRODUCTTYPE = '1'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                    throw new Exception("[%未找到UnitId(" + strUnitId + ")对应的批次!%]");
                strLotNo = drTemp["LOTNO"].ToString();
                drTemp.Close();

                // 2. 根据LotNo查ProductNo
                strSQL = "SELECT PRODUCTNO FROM TBLWIPLOTBASIS WHERE BASELOTNO = '" + strLotNo + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                    throw new Exception("[%未找到批次(" + strLotNo + ")对应的产品!%]");
                strProductNo = drTemp["PRODUCTNO"].ToString();
                drTemp.Close();

                // 3. 查产品对应的MAC和蓝牙序号规则编号
                strSQL = "SELECT MACID, BLUETOOTH FROM TBLPRDPRODUCTBASIS WHERE PRODUCTNO = '" + strProductNo + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                    throw new Exception("[%未找到产品(" + strProductNo + ")的MAC/蓝牙规则!%]");
                strMACRuleNo = drTemp["MACID"].ToString();
                strBlueToothRuleNo = drTemp["BLUETOOTH"].ToString();
                drTemp.Close();

                // 4. 生成MAC序号
                if (!string.IsNullOrEmpty(strMACRuleNo))
                    strGeneratedMACID = funGenerateSerialWithRange(cnnTemp, strMACRuleNo, strUnitId, "MAC");
                else
                    strGeneratedMACID = "";

                // 5. 生成蓝牙序号
                if (!string.IsNullOrEmpty(strBlueToothRuleNo))
                    strGeneratedBlueToothID = funGenerateSerialWithRange(cnnTemp, strBlueToothRuleNo, strUnitId, "BLUETOOTH");
                else
                    strGeneratedBlueToothID = "";

                // 6. 存表：更新 TBLWIPPRDSTATE_LQ & TBLWIPPRDLOG_LQ
                if (!string.IsNullOrEmpty(strGeneratedMACID) || !string.IsNullOrEmpty(strGeneratedBlueToothID))
                {
                    strSQL = "UPDATE TBLWIPPRDSTATE_LQ SET MACID = '" + strGeneratedMACID + "', BLUETOOTHID = '" + strGeneratedBlueToothID + "' WHERE PRODUCTID = '" + strUnitId + "' AND STATE = '1'";
                    ExecuteSQLNoneQuery(strDataBaseType, strConnectionString, ref strSQL);

                    strSQL = "INSERT INTO TBLWIPPRDLOG_LQ (LOTNO, PRODUCTID, EQPID, OPNO, CARRIERID, PRODUCTTYPE, CREATEDATE, MACID, BLUETOOTHID) "
                           + "SELECT LOTNO, PRODUCTID, EQPID, OPNO, CARRIERID, PRODUCTTYPE, CREATEDATE, MACID, BLUETOOTHID "
                           + "FROM TBLWIPPRDSTATE_LQ WHERE PRODUCTID = '" + strUnitId + "' AND STATE = '1'";
                    ExecuteSQLNoneQuery(strDataBaseType, strConnectionString, ref strSQL);
                }

                response.code = "0000";
                response.message = "MACBLUE successfully";
                response.time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                response.data = new MACBLUEResponseData { macid = strGeneratedMACID, bluetooth = strGeneratedBlueToothID };
            }
            catch (iMESException.MESException ex)
            {
                response.code = "1111";
                response.message = "MACBLUE ：" + ex.Message;
            }
            catch (Exception ex)
            {
                response.code = "1111";
                response.message = "MACBLUE ：" + ex.Message;
            }
            finally
            {
                drTemp?.Close();
                CloseConnection(cnnTemp);
            }
            strResult = JsonConvert.SerializeObject(response);
            return strResult;
        }

        /// <summary>
        /// 根据序号规则编号生成带起始/结束值约束的完整序号（含前缀+流水号）
        /// </summary>
        private static string funGenerateSerialWithRange(IDbConnection cnnTemp, string SerialTypeNo, string UnitId, string SerialType)
        {
            string strSQL = "";
            DbDataReader drTemp = null;
            DataSet dsTemp = new DataSet();
            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);

            // 检查 UnitId 是否已有对应的值
            string checkField = SerialType == "MAC" ? "MACID" : "BLUETOOTHID";
            string strExistSQL = "SELECT " + checkField + " FROM TBLWIPPRDSTATE_LQ WHERE PRODUCTID = '" + UnitId + "' AND STATE = '1'";
            drTemp = ExecuteSQLQuery_Reader(strExistSQL, cnnTemp);
            if (drTemp.Read())
            {
                string existVal = drTemp[0] is DBNull ? "" : drTemp[0].ToString();
                drTemp.Close();
                if (!string.IsNullOrEmpty(existVal))
                    return existVal;
            }
            drTemp.Close();

            // 读取序号规则 Basis（检查启用）
            strSQL = "SELECT * FROM TBLSYSSERIALRULEBASIS WHERE SERIALTYPENO = '" + SerialTypeNo + "' AND ENABLE = 1";
            ExecuteSQLQuery_Adapter(strSQL, dsTemp, "SerialRuleBasis", cnnTemp);
            if (dsTemp.Tables["SerialRuleBasis"].Rows.Count == 0)
                throw new Exception("[%序号规则(" + SerialTypeNo + ")不存在或未启用!%]");

            // 读取序号规则所有明细则（含前缀 UD 和流水号 SN）
            strSQL = "SELECT * FROM TBLSYSSERIALRULEDETAIL WHERE SERIALTYPENO = '" + SerialTypeNo + "' ORDER BY ITEMNO";
            ExecuteSQLQuery_Adapter(strSQL, dsTemp, "RuleDetail", cnnTemp);
            if (dsTemp.Tables["RuleDetail"].Rows.Count == 0)
                throw new Exception("[%序号规则(" + SerialTypeNo + ")未配置明细!%]");

            int intSerLen = 0;
            int intDecimalType = 1;
            int intPadLeft = 1;
            int intSNIndex = -1;
            string strStartNum = "";
            string strEndNum = "";

            // 添加 Value 列，并处理每个明细项
            dsTemp.Tables["RuleDetail"].Columns.Add("Value");
            for (int i = 0; i < dsTemp.Tables["RuleDetail"].Rows.Count; i++)
            {
                string sourceType = dsTemp.Tables["RuleDetail"].Rows[i]["SOURCETYPE"].ToString();
                switch (sourceType)
                {
                    case "SN":
                        intSerLen = Convert.ToInt32(dsTemp.Tables["RuleDetail"].Rows[i]["SERIALLENGTH"]);
                        intDecimalType = Convert.ToInt32(dsTemp.Tables["RuleDetail"].Rows[i]["DECIMALTYPE"]);
                        intPadLeft = 1;
                        if (dsTemp.Tables["RuleDetail"].Columns.Contains("PADLEFT"))
                            intPadLeft = Convert.ToInt32(dsTemp.Tables["RuleDetail"].Rows[i]["PADLEFT"]);
                        intSNIndex = i;

                        // 读取 STARTNUM / ENDNUM
                        if (dsTemp.Tables["RuleDetail"].Columns.Contains("STARTNUM") && dsTemp.Tables["RuleDetail"].Rows[i]["STARTNUM"] != DBNull.Value)
                            strStartNum = dsTemp.Tables["RuleDetail"].Rows[i]["STARTNUM"].ToString();
                        if (dsTemp.Tables["RuleDetail"].Columns.Contains("ENDNUM") && dsTemp.Tables["RuleDetail"].Rows[i]["ENDNUM"] != DBNull.Value)
                            strEndNum = dsTemp.Tables["RuleDetail"].Rows[i]["ENDNUM"].ToString();
                        break;

                    case "UD":
                        dsTemp.Tables["RuleDetail"].Rows[i]["Value"] = dsTemp.Tables["RuleDetail"].Rows[i]["USERDEFINE"].ToString();
                        break;

                    default:
                        dsTemp.Tables["RuleDetail"].Rows[i]["Value"] = dsTemp.Tables["RuleDetail"].Rows[i]["USERDEFINE"].ToString();
                        break;
                }
            }

            if (intSNIndex < 0)
                throw new Exception("[%序号规则(" + SerialTypeNo + ")未配置流水号!%]");

            // 转换 STARTNUM/ENDNUM 为十进制
            long lngStartNum = 0;
            long lngEndNum = long.MaxValue;
            if (!string.IsNullOrEmpty(strStartNum))
                lngStartNum = funBaseToDecimal(strStartNum, intDecimalType);
            if (!string.IsNullOrEmpty(strEndNum))
                lngEndNum = funBaseToDecimal(strEndNum, intDecimalType);

            // 读取当前最大序号
            strSQL = "SELECT MAXSERIALNO FROM TBLSYSSERIALCREATEMAX WHERE SERIALTYPE = '" + SerialType + "' AND SERIALSTRING = '" + SerialTypeNo + "' AND SERIALLENGTH = " + intSerLen + " AND DECIMALTYPE = " + intDecimalType;
            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
            long lngMaxSerialNo;
            bool blnInsert;
            if (drTemp.Read())
            {
                blnInsert = false;
                lngMaxSerialNo = Convert.ToInt64(drTemp["MAXSERIALNO"]);
            }
            else
            {
                blnInsert = true;
                lngMaxSerialNo = 0;
            }
            drTemp.Close();

            // 起始值约束
            if (!string.IsNullOrEmpty(strStartNum) && lngMaxSerialNo < lngStartNum)
                lngMaxSerialNo = lngStartNum - 1;

            long lngNewSerialNo = lngMaxSerialNo + 1;

            // 结束值检查
            if (!string.IsNullOrEmpty(strEndNum) && lngNewSerialNo > lngEndNum)
                throw new Exception("[%" + SerialType + "序号已达到最大值(" + strEndNum + ")，无法继续生成!%]");

            // 生成流水号字符串
            string strNewSerial = funDecimalToBase(lngNewSerialNo, intDecimalType);
            if (intPadLeft == 1)
                strNewSerial = strNewSerial.PadLeft(intSerLen, '0');

            // 长度检查
            if (strNewSerial.Length > intSerLen)
                throw new Exception("[%" + SerialType + "序号超出长度限制(" + intSerLen + "): " + strNewSerial + "%]");

            // 组装完整序号（前缀 + 流水号）
            string strFullSerial = "";
            for (int j = 0; j < dsTemp.Tables["RuleDetail"].Rows.Count; j++)
            {
                if (j == intSNIndex)
                    strFullSerial += strNewSerial;
                else
                    strFullSerial += dsTemp.Tables["RuleDetail"].Rows[j]["Value"].ToString();
            }

            // 重复检查：在 TBLWIPPRDSTATE_LQ 中查找完整序号
            int retryCount = 0;
            int maxRetry = 100;
            while (retryCount < maxRetry)
            {
                strSQL = "SELECT 1 FROM TBLWIPPRDSTATE_LQ WHERE " + checkField + " = '" + strFullSerial + "' AND PRODUCTID <> '" + UnitId + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())
                {
                    drTemp.Close();
                    break;
                }
                drTemp.Close();
                retryCount++;
                lngNewSerialNo++;
                if (!string.IsNullOrEmpty(strEndNum) && lngNewSerialNo > lngEndNum)
                    throw new Exception("[%" + SerialType + "序号已达到最大值(" + strEndNum + ")，无法继续生成!%]");
                strNewSerial = funDecimalToBase(lngNewSerialNo, intDecimalType);
                if (intPadLeft == 1)
                    strNewSerial = strNewSerial.PadLeft(intSerLen, '0');
                if (strNewSerial.Length > intSerLen)
                    throw new Exception("[%" + SerialType + "序号超出长度限制(" + intSerLen + "): " + strNewSerial + "%]");
                // 重新组装完整序号
                strFullSerial = "";
                for (int j = 0; j < dsTemp.Tables["RuleDetail"].Rows.Count; j++)
                {
                    if (j == intSNIndex)
                        strFullSerial += strNewSerial;
                    else
                        strFullSerial += dsTemp.Tables["RuleDetail"].Rows[j]["Value"].ToString();
                }
            }
            if (retryCount >= maxRetry)
                throw new Exception("[%生成" + SerialType + "序号失败：重试次数过多!%]");

            // 更新 TBLSYSSERIALCREATEMAX
            if (blnInsert)
            {
                strSQL = "INSERT INTO TBLSYSSERIALCREATEMAX (SERIALTYPE, SERIALSTRING, SERIALLENGTH, DECIMALTYPE, MAXSERIALNO) "
                       + "VALUES ('" + SerialType + "', '" + SerialTypeNo + "', " + intSerLen + ", " + intDecimalType + ", " + lngNewSerialNo + ")";
            }
            else
            {
                strSQL = "UPDATE TBLSYSSERIALCREATEMAX SET MAXSERIALNO = " + lngNewSerialNo
                       + " WHERE SERIALTYPE = '" + SerialType + "' AND SERIALSTRING = '" + SerialTypeNo + "'"
                       + " AND SERIALLENGTH = " + intSerLen + " AND DECIMALTYPE = " + intDecimalType
                       + " AND MAXSERIALNO = " + lngMaxSerialNo;
            }
            ExecuteSQLNoneQuery(strDataBaseType, strConnectionString, ref strSQL);

            return strFullSerial;
        }

        /// <summary>
        /// 将指定进制字符串转10进制
        /// </summary>
        private static long funBaseToDecimal(string strValue, int decimalType)
        {
            strValue = strValue.Trim().ToUpper();
            long result = 0;
            int baseVal = decimalType == 1 ? 10 : decimalType == 2 ? 16 : decimalType == 4 ? 34 : 36;

            foreach (char c in strValue)
            {
                int digit;
                if (c >= '0' && c <= '9')
                    digit = c - '0';
                else
                {
                    digit = c - 'A' + 10;
                    if (decimalType == 4)
                    {
                        if (c >= 'J') digit--;
                        if (c >= 'P') digit--;
                    }
                }
                result = result * baseVal + digit;
            }
            return result;
        }

        /// <summary>
        /// 将10进制转指定进制字符串
        /// </summary>
        private static string funDecimalToBase(long value, int decimalType)
        {
            if (value == 0) return "0";
            string chars;
            int baseVal;
            if (decimalType == 1) { baseVal = 10; chars = "0123456789"; }
            else if (decimalType == 2) { baseVal = 16; chars = "0123456789ABCDEF"; }
            else if (decimalType == 4) { baseVal = 34; chars = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; }
            else { baseVal = 36; chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }

            string result = "";
            while (value > 0)
            {
                result = chars[(int)(value % baseVal)] + result;
                value /= baseVal;
            }
            return result;
        }
        #endregion


        #region "自动进出站,搬迁标准进出站"

        // 0102096: [6.0.5] EAP自動報工架構_SDD210906_05-01/ Execute_CI_LOT
        public static object AutoexecutionLot_Lot(ref bool blnEXETriggerOP, Dictionary<string, string> dicPars, Dictionary<string, DataTable> dicPars_DataTable, string FunctionID, DateTime ArriveTime, string UserNo, string ComputerName, bool blnRuleCheck = true)
        {
            object AutoexecutionLot_LotRet = default(object);
            var dtLotState = new DataTable();                      // Load Afer TriggerOP
            var objLot = new kcWIP.clsLot();
            var objSYS = new clsSYSUserLog();
            var objWIP = new kcWIP.clsWIP();
            var objUSR = new iMESUserManager.clsUSRSecurity();
            //var objclsWIP = new clsWIP();
            var objEMS = new kcEMS.clsEMSEquipment();
            var objReverse = new udReverse.clsReverse();
            DataRow drAdd;
            IDbConnection cnnTemp = null;
            var drTemp = default(DbDataReader);
            //OleDbCommand cmmTemp;
            AppSettings objSetting = new AppSettings();

            string strException;
            string strResult;
            int PhaseNo;
            string AreaNo = defString;
            string OPNo = defString;
            string PSNo = defString;
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString); // Create connection

            string strServiceName = "ExecuteLot";


            var dtLotNo = new DataTable();
            dtLotNo.Columns.Add("LotNo", System.Type.GetType("System.String"));
            var drLotAdd = dtLotNo.NewRow();
            drLotAdd["LotNo"] = dicPars["lotno"];
            dtLotNo.Rows.Add(drLotAdd);
            string LotNo = dtLotNo.Rows[0]["LotNo"].ToString();

            string InXML = "";
            string OutXML = "";

            string strRetrunMsg = "";

            var dtChkRuleLot2 = new DataTable("ChkRuleLot"); // minya 20200315
            string strEquipmentNo = defString;
            string strERFMsg = "";
            try
            {

                // 1.依InXml資料與Lot目前狀態比對是否符合
                DataRow drLotState = null;
                var strKernelModule = default(string);
                var strKernelFunctionName = default(string);

                // 檢查USER過帐权限
                DataRow drUser;
                if (!string.IsNullOrEmpty(UserNo))
                {
                    drUser = objUSR.GetUserSecurity(UserNo, 2);
                    if (string.IsNullOrEmpty(drUser["UserNo"].ToString()))
                    {
                        UserNo = "EAP_AGENT";
                        drUser = objUSR.GetUserSecurity(UserNo, 2);
                        if (string.IsNullOrEmpty(drUser["UserNo"].ToString()))
                        {
                            throw new iMESException.MESException("0000-200015", "[%Please provide curuser or set EAP_Agent correct, then execute Lot%] !");
                        }
                    }
                }
                else
                {
                    UserNo = "EAP_AGENT";
                    drUser = objUSR.GetUserSecurity(UserNo, 2);
                    if (string.IsNullOrEmpty(drUser["UserNo"].ToString()))
                    {
                        throw new iMESException.MESException("0000-200015", "[%Please provide curuser or set EAP_Agent correct, then execute Lot%] !");
                    }
                }

                if (!dicPars.ContainsKey("equipmentno"))
                {
                    throw new iMESException.MESException("0000-200002", "[%EquipmentNo%] [%NOT FOUND%]");
                }
                else
                {
                    strEquipmentNo = dicPars["equipmentno"];
                }

                // 2.取得生產批現況資訊
                string refBRNO = defString;
                string refBRExecutionFile = defString;

                string strLots = "(";
                foreach (DataRow drTempLotNo in dtLotNo.Rows)
                    strLots += "'" + drTempLotNo["LotNo"].ToString() + "',";
                strLots = strLots.TrimEnd(',');
                strLots += ")";

                if (funLoadLotStatusJoinOPBusinessRule(strLots, ref dtLotNo) < 0)
                {
                    throw new iMESException.MESException("0000-200091", "[%funLoadLotStatusJoinOPBusinessRule fail%]!");
                }
                if (!(dtLotNo == null) && dtLotNo.Rows.Count > 0) // 取出區域與作業站
                {
                    OPNo = dtLotNo.Rows[0]["OPNo"].ToString();
                    AreaNo = dtLotNo.Rows[0]["AreaNo"].ToString();
                    PSNo = dtLotNo.Rows[0]["PSNo"].ToString();
                }

                // 檢查User是否有此OP的權限------------------------------------------------------------------------------------------------
                // Gary Lu 20121114:這個作業站不在群組內才要進行權限檢查
                if (objUSR.ChkUserOPPriv(UserNo, OPNo) == false)
                {
                    throw new iMESException.MESException("0000-202015", "[%UserNo%]:" + UserNo + "[%NOTHINGSTATE%][%OPPRIVILEGE%], [%OPNo%]:" + OPNo);
                }

                // 檢查User是否有產品區段設定權限------------------------------------------------------------------------------------------------
                if (objUSR.ChkUserPSPriv(UserNo, PSNo) == false)
                {
                    throw new iMESException.MESException("0000-200062", "[%EmployeeNo%]:" + UserNo + "[%has no PS Privilege%], [%PSNo%]:" + PSNo);
                }

                objUSR = null;

                // 6.取得班別
                string ShiftNo = "N/A";
                using (var obj = new clsUSRDepartment())
                {
                    ShiftNo = obj.GetShift(UserNo);
                }


                // 0  : Sucess
                // -1 : Program Error
                // -2 : LotInfo Error
                // -3 : Each Lot Has Different BR
                // -4 : RefLotNo Didn't Setting KERNELMODULE(tblOPBusinessRuleBasis)
                // -5 : RefLotNo Didn't Setting KERNELFUNCTIONNAME(tblOPBusinessRuleBasis)
                // -6 : LotStatus Error
                switch (ChkLotStateAndBRNo(strLots, FunctionID, OPNo))
                {
                    case -1:
                        {
                            throw new iMESException.MESException("0000-200091", "[%ChkLotStateAndBRNo fail%]!");
                        }
                    case -2:
                        {
                            throw new iMESException.MESException("0000-200091", "[%LotNo And OPNo fail!%]");
                        }
                    case -3:
                        {
                            throw new iMESException.MESException("0000-200091", "[%Each Lot Has Different BR%]");
                        }
                    case -4:
                        {
                            throw new iMESException.MESException("0000-200091", "[%RefLotNo%]  " + LotNo + "; [%Not Setting KERNELMODULE(tblOPBusinessRuleBasis)%]");
                        }
                    case -5:
                        {
                            throw new iMESException.MESException("0000-200091", "[%RefLotNo%]  " + LotNo + "; [%Not Setting KERNELFUNCTIONNAME(tblOPBusinessRuleBasis)%]");
                        }
                    case -6:
                        {
                            throw new iMESException.MESException("0000-200091", "[%LotStatus Error%]");
                        }
                }

                foreach (DataRow drTempLotNo in dtLotNo.Rows)
                {
                    if (dtLotNo.Rows.IndexOf(drTempLotNo) == 0)
                    {
                        refBRNO = drTempLotNo["BRNO"].ToString();
                        refBRExecutionFile = drTempLotNo["EXECUTIONFILE"].ToString();
                    }
                    else if (drTempLotNo["BRNO"].ToString() != refBRNO)
                    {
                        // LotBR 與首批不一致
                        throw new iMESException.MESException("0000-200091", "[%LotNo%]:" + drTempLotNo["LotNo"].ToString() + " [%BR%] [%Is Not THE SAME%]");
                    }

                    funCheckStateByLot(ref strKernelModule, ref strKernelFunctionName, drTempLotNo["LotNo"].ToString(), drTempLotNo, FunctionID, OPNo);
                }

                if (FunctionID == "CO")
                {
                    if (refBRExecutionFile.ToUpper() != "BR_L_CO_GEN_M.DLL" && refBRExecutionFile.ToUpper() != "BR_L_CO_GEN.DLL")
                    {
                        //0156845: [6.0.7]调整EAP接口查核支援BR逻辑,增加查核brno
                        if (!ExeBrnoIfSupport(refBRExecutionFile.ToUpper(), refBRNO))
                        {
                            throw new iMESException.MESException("0000-200091", "[%Only Support L_CO_GEN Now%] [%NOWUSE%]:" + refBRNO + "");
                        }

                    }
                }
                else if (refBRExecutionFile.ToUpper() != "BR_L_CI_GEN.DLL")
                {
                    //0156845: [6.0.7]调整EAP接口查核支援BR逻辑,增加查核brno
                    if (!ExeBrnoIfSupport(refBRExecutionFile.ToUpper(), refBRNO))
                    {
                        throw new iMESException.MESException("0000-200091", "[%Only Support L_CI_GEN Now%] [%NOWUSE%]:" + refBRNO + "");
                    }
                }

                // 3.Execution Trigger OP
                if (!dtLotNo.Columns.Contains("blnEXETriggerOP"))
                {
                    using (var dcTemp = new DataColumn())
                    {
                        dcTemp.ColumnName = "blnEXETriggerOP";
                        dcTemp.DataType = Type.GetType("System.Boolean");
                        dcTemp.DefaultValue = false;
                        dtLotNo.Columns.Add(dcTemp);
                    }
                }

                foreach (DataRow drTempLot in dtLotNo.Rows)
                {
                    // If drTempLot("Status") = 0 Then
                    string DescriptionTmp = defString;
                    long NewLotStampTmp = defInteger;
                    switch (objLot.TriggerOP(ref DescriptionTmp, ref NewLotStampTmp, Convert.ToString(drTempLot["LotNo"]), UserNo: UserNo))
                    {

                        case "hold_exceedtime":
                            {
                                tcEAI.clsWIP.BRERFCreateExecute(pUserId: UserNo, pLotNo: Convert.ToString(drTempLot["LotNo"]), pERFType: 1, pHoldTime: 0, pRuleNo: "EXCEEDTIME");
                                throw new iMESException.MESException("0000-200091", "LotNO:" +
                                    drTempLot["LotNo"] + "[%VIOLATE TIME CONTROL,CREATE ERF%]!");
                            }
                        case "futurehold":
                            {
                                tcEAI.clsWIP.BRERFCreateExecute(pUserId: UserNo, pLotNo: Convert.ToString(drTempLot["LotNo"]), pERFType: 3, pHoldTime: 0);
                                throw new iMESException.MESException("0000-200091", "LotNO:" +
                                    drTempLot["LotNo"] + "[%FUTUREHOLD SET,CREATE ERF%]!");
                            }
                        case "futurewait":
                            {
                                throw new iMESException.MESException("0000-200091", "LotNO:" + drTempLot["LotNo"] + "[%FUTUREWAIT%]!");
                            }
                        case "futureos":
                            {
                                throw new iMESException.MESException("0000-200091", "LotNO:" + drTempLot["LotNo"] + "[%FUTURE OS%]!");
                            }

                        default:
                            {
                                // 2020/03/11 Shih Kai, 68676 :自动进出站BR检核-TriggerOP後增加補做TriggerPhase
                                // Trigger Phase
                                drLotState = objLot.GetLotBasisJoinState(LotNo: drTempLot["LotNo"].ToString());  // 取得最新的LotState

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 0, false))) // by Product
                                {
                                    PhaseNo = objLot.GetBusinessRulePhase(drLotState["ProductNo"].ToString(), drLotState["ProductVersion"].ToString(), drLotState["OPNo"].ToString(), drLotState["BRNo"].ToString());
                                }
                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 1, false))) // by Module
                                {
                                    PhaseNo = objLot.GetBusinessRulePhase(drLotState["ModuleNo"].ToString(), drLotState["ModuleVersion"].ToString(), drLotState["OPNo"].ToString(), drLotState["BRNo"].ToString());
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-200015", "LotNo:" +
                                        drTempLot["LotNo"] + ",[%OPREFERENCE ERROR%]!");
                                }

                                // 剛做完TriggerOP,不用再執行Attrib的變更
                                objLot.TriggerPhase_LotState(Convert.ToString(drTempLot["LotNo"]), PhaseNo, UserNo);

                                drTempLot["blnEXETriggerOP"] = true;
                                break;
                            }
                    }
                }


                var drLotRow = objLot.GetLotBasisJoinState(LotNo: LotNo);  // 取得最新的LotState

                string strLotStamp = drLotRow["LotStamp"].ToString();
                string strLotSerial = drLotRow["LotSerial"].ToString();
                string strLogGroupSerial = drLotRow["LogGroupSerial"].ToString();
                int intPhaseNo = Conversions.ToInteger(drLotRow["PhaseNo"]);

                blnEXETriggerOP = true;

                // 4.ReLoad Lotstate Afer Trigger OP In dtLotState
                funLoadLotStatusJoinOPBusinessRule(strLots, ref dtLotState);


                // 20200309 Edison Mantis : 68289: [SEMI WAFER]通用性CI/CO BR檢核
                // 區域設備檢核 Key in Lot Attrib檢核 Component Attrib檢核, Check Control Rule
                // =============================================== 68289 Start ===============================================

                // 5.Xml轉Table

                DataTable dtLotList = new DataTable(), dtLotAttrib = new DataTable(), dtLotError = new DataTable(), dtLotComponent = new DataTable(), dtLotCompAttrib = new DataTable(), dtEquipment = new DataTable(), dtTempAttrib = new DataTable(), dtComponentError = new DataTable();
                DataTable dtAccessory = null;

                // 將批號加入資料表以便檢查設備
                dtLotList.Columns.Add("LotNo");
                DataRow drLotNo;
                drLotNo = dtLotList.NewRow();
                drLotNo["LotNo"] = LotNo;
                dtLotList.Rows.Add(drLotNo);

                if (dicPars_DataTable.Keys.Contains("lotattrib"))
                {
                    dtLotAttrib = dicPars_DataTable["lotattrib"];
                }
                if (dicPars_DataTable.Keys.Contains("loterror"))
                {
                    dtLotError = dicPars_DataTable["loterror"];
                }
                if (dicPars_DataTable.Keys.Contains("lotcompoment"))
                {
                    dtLotComponent = dicPars_DataTable["lotcompoment"];
                }
                if (dicPars_DataTable.Keys.Contains("lotcomponentattrib"))
                {
                    dtLotCompAttrib = dicPars_DataTable["lotcomponentattrib"];
                }
                if (dicPars_DataTable.Keys.Contains("equipment"))
                {
                    dtEquipment = dicPars_DataTable["equipment"];
                }
                else
                {
                    dtEquipment.Columns.Add("EquipmentNo");
                    DataRow drEQP;
                    drEQP = dtEquipment.NewRow();
                    drEQP["EquipmentNo"] = strEquipmentNo;
                    dtEquipment.Rows.Add(drEQP);
                }
                if (dicPars_DataTable.Keys.Contains("tempattrib"))
                {
                    dtTempAttrib = dicPars_DataTable["tempattrib"];
                }
                if (dicPars_DataTable.Keys.Contains("componenterror"))
                {
                    dtComponentError = dicPars_DataTable["componenterror"];
                }
                if (dicPars_DataTable.Keys.Contains("accessorylist"))
                {
                    dtAccessory = dicPars_DataTable["accessorylist"];
                }

                if (dtAccessory == null)
                {
                    dtAccessory = objEMS.LoadEQPACCStateJoinAccState_EAP(EquipmentNo: strEquipmentNo);
                }

                string strCANodeName, strComponentNodeName;
                string strLinkName = "PASS";
                string strMailGroupNo = "";
                string strMsg = "";
                string strRuleNo = defString;
                int intERFType = 0;
                DataTable dtLotRuleData = default(DataTable);
                //DataTable dtLotRuleData = default(DataTable), dtCompRuleData = default(DataTable);

                var dtLotAttrib_Temp = new DataTable();
                //dtLotAttrib_Temp.Columns.Add("LotNo", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("AttribNo", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("AttribType", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribSequence", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribSource", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribPhase", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("AttribValue", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("SaveToLotPropertyNo", Type.GetType("System.String"));
                // 2021/12/1 缺少QCItemNo,於標準BRcheckin會出錯
                dtLotAttrib_Temp.Columns.Add("TestValue", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("QCItemNo", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("Result", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("Result_INT", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("FactorSerial", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("SerialNo", Type.GetType("System.Int32"));
                dtLotAttrib_Temp.Columns.Add("MEMO", Type.GetType("System.String"));
                dtLotAttrib_Temp.Columns.Add("ComponentNo", Type.GetType("System.String"));
                // SPC
                dtLotAttrib_Temp.Columns["TestValue"].Expression = "AttribValue";

                var dtLotCompAttrib_Temp = new DataTable();
                dtLotCompAttrib_Temp.Columns.Add("LotNo", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("ComponentNo", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("AttribNo", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("AttribValue", Type.GetType("System.String"));
                dtLotCompAttrib_Temp.Columns.Add("AttribType", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("AttribSequence", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("AttribSource", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("AttribPhase", Type.GetType("System.Int32"));
                dtLotCompAttrib_Temp.Columns.Add("SaveToLotPropertyNo", Type.GetType("System.String"));

                if (blnRuleCheck)
                {

                    // 預設
                    strCANodeName = "componentattrib";
                    strComponentNodeName = "component";
                    // Call XmlToTable(InXML, dtEquipment, dtLotList, dtLotAttrib, dtLotError, dtLotComponent, dtLotCompAttrib, strLots, LotNo, strCANodeName, strComponentNodeName, refBRNO) 'refBRNO minya 20200312

                    // dtLotAttrib若不包含欄位:LotNo,會出錯誤
                    if (!(dtLotAttrib == null))
                    {
                        if (!dtLotAttrib.Columns.Contains("LotNo"))
                        {
                            dtLotAttrib.Columns.Add("LotNo");
                            if (!(dtLotNo == null) && dtLotNo.Rows.Count > 0)
                            {
                                foreach (DataRow dr in dtLotAttrib.Rows)
                                    dr["LotNo"] = dtLotNo.Rows[0]["LotNo"].ToString();
                            }
                        }
                    }
                    // 6. 基本檢查
                    funBasisCheck(CIorCO: FunctionID, dtLotNo: dtLotNo, dtEquipment: dtEquipment, dtLotList: dtLotList, dtLotAttrib: dtLotAttrib, dtLotError: dtLotError, dtLotComponent: dtLotComponent, dtLotCompAttrib: dtLotCompAttrib, dtTempAttrib: ref dtTempAttrib, strLots: strLots);

                    // 7.格式化Rule Check 資料 並進行ChkControlRule----------------------------------------------------------------------------------------------
                    string strBatchComponent = "";
                    string strAttrib = "";
                    string strCAttrib = "";
                    string strError = "";
                    string strTemp = "";

                    // 7.1 需要判 Rule 的生產批
                    var dtChkRuleLot = new DataTable("ChkRuleLot");
                    string strRuleLot = "";
                    dtChkRuleLot.Columns.Add("LotNo", Type.GetType("System.String"));

                    foreach (DataRow rL in dtLotNo.Rows)
                    {
                        strRuleLot += CombineXMLValueTag(
                                       CombineXMLValue("lotno", CInput(rL["LotNo"].ToString())));
                        dtChkRuleLot.Rows.Add(rL["LotNo"].ToString());
                    }

                    // 7.2 格式化資料Component
                    foreach (DataRow rC in dtLotComponent.Rows)
                    {
                        strBatchComponent += CombineXMLValueTag(
                                 CombineXMLValue("lotno", CInput(rC["LotNo"].ToString())) +
                                 CombineXMLValue("componentno", CInput(rC["ComponentNo"].ToString())));
                    }

                    // 7.3 格式化-Key In Attrib
                    // KeyIn Attrib
                    //20240102,13871,0155146: [6.0.7]EAP接口Execute_CO_LOT，出站输入特性参数时，EAP和产品作业站输入一致，但是会提示报错
                    DataTable attribtemp = null;
                    using (var obj = new kcWIP.clsLot())
                    {
                        attribtemp = obj.ShowTemp_Attrib(LotNo).Tables[0];
                    }


                    if (!(attribtemp == null))
                    {
                        attribtemp.DefaultView.RowFilter = "(AttribPhase = " + intPhaseNo + " or AttribPhase = 99) And AttribSource <> 0";   // CurPhase & All的所有Attrib,除了KeyIn
                        for (int i = 0; i <= attribtemp.DefaultView.Count - 1; i++)
                        {
                            strTemp = CombineXMLValue("lotno", LotNo) +
                                      CombineXMLValue("attribno", CInput(attribtemp.DefaultView[i]["AttribNo"].ToString())) +
                                      CombineXMLValue("attribtype", attribtemp.DefaultView[i]["AttribType"].ToString()) +
                                      CombineXMLValue("attribsequence", attribtemp.DefaultView[i]["AttribSequence"].ToString()) +
                                      CombineXMLValue("attribsource", attribtemp.DefaultView[i]["AttribSource"].ToString()) +
                                      CombineXMLValue("attribphase", attribtemp.DefaultView[i]["AttribPhase"].ToString()) +
                                      CombineXMLValue("savetolotpropertyno", CInput(attribtemp.DefaultView[i]["SaveToLotPropertyNo"].ToString()));
                            if (attribtemp.DefaultView[i]["AttribValue"] is DBNull)
                                strTemp += CombineXMLValue("attribvalue", "");
                            else
                                strTemp += CombineXMLValue("attribvalue", CInput(attribtemp.DefaultView[i]["AttribValue"].ToString()));
                            strAttrib += CombineXMLValueTag(strTemp);
                        }
                        //還原顯示
                        attribtemp.DefaultView.RowFilter = "AttribSource <> 0 And AttribSource <> 1 And (AttribPhase = " + intPhaseNo + " or AttribPhase = 99)";    // Source = Not KeyIn, Not Calculate ,CurPhase and All

                        //Temp:Attrib_KeyIn
                        for (int i = 0; i <= dtLotAttrib.Rows.Count - 1; i++)
                        {
                            if (dtLotAttrib.Rows[i]["AttribValue"] is DBNull)
                                dtLotAttrib.Rows[i]["AttribValue"] = "";

                            DataRow[] drChk = attribtemp.Select("AttribNo='" + dtLotAttrib.Rows[i]["AttribNo"] + "'");
                            if (drChk.Length == 0)
                            {
                                throw new iMESException.MESException("0000-203010", "[%AttribNo%]:" + dtLotAttrib.Rows[i]["AttribNo"].ToString());
                            }
                            else
                            {
                                strTemp = CombineXMLValue("lotno", LotNo) +
                                          CombineXMLValue("attribno", CInput(dtLotAttrib.Rows[i]["AttribNo"].ToString())) +
                                          CombineXMLValue("attribtype", drChk[0]["AttribType"].ToString()) +
                                          CombineXMLValue("attribsequence", drChk[0]["AttribSequence"].ToString()) +
                                          CombineXMLValue("attribsource", drChk[0]["AttribSource"].ToString()) +
                                          CombineXMLValue("attribphase", drChk[0]["AttribPhase"].ToString()) +
                                          CombineXMLValue("attribvalue", CInput(dtLotAttrib.Rows[i]["AttribValue"].ToString())) +
                                          CombineXMLValue("savetolotpropertyno", CInput(drChk[0]["SaveToLotPropertyNo"].ToString()));
                                if (drChk[0]["QCItemNo"] is DBNull)
                                    strTemp += CombineXMLValue("qcitemno", "");
                                else
                                    strTemp += CombineXMLValue("qcitemno", CInput(drChk[0]["QCItemNo"].ToString()));
                                strAttrib += CombineXMLValueTag(strTemp);
                            }
                        }
                    }

                    // 7.4.格式化 Component Attrib
                    foreach (DataRow rCA in dtLotCompAttrib.Rows)
                    {
                        DataSet dsTemp;
                        using (var obj = new kcWIP.clsLot())
                        {
                            dsTemp = obj.ShowTemp_ComponentAttrib(LotNo);
                        }

                        for (int x = 0, loopTo1 = dsTemp.Tables[0].Rows.Count - 1; x <= loopTo1; x++)
                        {
                            if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(rCA["AttribNo"], dsTemp.Tables[0].Rows[x]["AttribNo"], false)))
                            {
                                strCAttrib = strCAttrib + CombineXMLValueTag(
                            CombineXMLValue("lotno", LotNo) +
                            CombineXMLValue("componentno", CInput(dsTemp.Tables[0].Rows[x]["ComponentNo"].ToString())) +
                            CombineXMLValue("attribno", CInput(rCA["AttribNo"].ToString())) +
                            CombineXMLValue("attribtype", dsTemp.Tables[0].Rows[x]["AttribType"].ToString()) +
                            CombineXMLValue("attribsequence", dsTemp.Tables[0].Rows[x]["AttribSequence"].ToString()) +
                            CombineXMLValue("attribsource", dsTemp.Tables[0].Rows[x]["AttribSource"].ToString()) +
                            CombineXMLValue("attribphase", dsTemp.Tables[0].Rows[x]["AttribPhase"].ToString()) +
                            CombineXMLValue("attribvalue", CInput(rCA["AttribValue"].ToString())) +
                            CombineXMLValue("savetolotpropertyno", CInput(dsTemp.Tables[0].Rows[x]["SaveToLotPropertyNo"].ToString())));

                                DataRow drTemp_Rows;
                                drTemp_Rows = dtLotCompAttrib_Temp.NewRow();
                                drTemp_Rows["LotNo"] = LotNo;
                                drTemp_Rows["ComponentNo"] = dsTemp.Tables[0].Rows[x]["ComponentNo"];
                                drTemp_Rows["AttribNo"] = rCA["AttribNo"];
                                drTemp_Rows["AttribType"] = dsTemp.Tables[0].Rows[x]["AttribType"];
                                drTemp_Rows["AttribSequence"] = dsTemp.Tables[0].Rows[x]["AttribSequence"];
                                drTemp_Rows["AttribSource"] = dsTemp.Tables[0].Rows[x]["AttribSource"];
                                drTemp_Rows["AttribPhase"] = dsTemp.Tables[0].Rows[x]["AttribPhase"];
                                drTemp_Rows["AttribValue"] = rCA["AttribValue"].ToString();
                                drTemp_Rows["SaveToLotPropertyNo"] = dsTemp.Tables[0].Rows[x]["SaveToLotPropertyNo"];
                                dtLotCompAttrib_Temp.Rows.Add(drTemp_Rows);
                            }
                        }
                    }

                    // 7.5 格式化不良原因
                    foreach (DataRow rE in dtLotError.Rows)
                    {
                        strError = strError + CombineXMLValueTag(
                     CombineXMLValue("lotno", CInput(rE["LotNo"].ToString())) +
                     CombineXMLValue("componentno", CInput(rE["ComponentNo"].ToString())) +
                     CombineXMLValue("errorno", CInput(rE["ErrorNo"].ToString())) +
                     CombineXMLValue("errorqty", rE["ErrorQty"].ToString()) +
                     CombineXMLValue("errorlevel", rE["ErrorLevel"].ToString()));
                    }

                    // 7.6 Control Rule Check-------------------------------------------------------------------------------------------------------------
                    DataSet dsTestValue = null;

                    //if (ChkControlRule_BatchComponent(dtChkRuleLot, true, UserNo, strRuleLot, strBatchComponent, ref strAttrib, ref strCAttrib, ref strLinkName, ref strMsg, ref strRuleNo, ref intERFType, ref dtLotRuleData, ref dtCompRuleData, ref strMailGroupNo, ref dsTestValue, strError) < 0)
                    if (tcEAI.clsEAP.ChkControlRule(ref dsTestValue, ref dtChkRuleLot, LotNo, UserNo, Conversions.ToLong(strLotStamp), ref strAttrib, ref strLinkName, ref strMsg, ref strRuleNo, ref intERFType, ref strMailGroupNo, strError) < 0)

                    {
                        throw new iMESException.MESException("0000-200091", "[%LotNo%]:" + LotNo + ",Check Control Rule [%FUNCTION%][%Fail%].");
                    }

                    // Check SPC Contorl
                    if (funChkSPCControl_Var(UserNo, LotNo, ref strAttrib, dsTestValue, ref strLinkName, ref intERFType, ref strERFMsg, dtEquipment) < 0)
                    {
                        throw new iMESException.MESException("0000-200091", "[%LotNo%]:" + LotNo + ",Check SPC Contorl [%FUNCTION%][%Fail%].");
                    }
                    strERFMsg = tcEAI.clsEAP.TranslateMsg(strERFMsg);

                    //strAttrib to dtLotAttrib_Temp
                    dtLotAttrib_Temp = ConvertXmlToDataTable(dtLotAttrib_Temp, strAttrib);

                    // 取得RuleNo
                    DataRow[] drSelHoldRule;
                    if (!(dtLotRuleData == null) && dtLotRuleData.Rows.Count > 0)
                    {
                        if (strLinkName == "HOLD")
                        {
                            drSelHoldRule = dtLotRuleData.Select("Linkname= 'HOLD'");
                            if (drSelHoldRule.Length > 0)
                            {
                                strRuleNo = drSelHoldRule[0]["RuleNo"].ToString();
                            }
                        }
                    }

                    // 2020/03/12 Lena, 將 InXml 中的 LiknName、Lot Attrib、Component Attrib 置換為 Control Rule Check 後的結果
                    string strLinkNameTagName = "linkname".ToLower();
                    string strLAttribTagName = "attrib".ToLower();
                    string strCAttribTagName = strCANodeName.ToLower();

                    int intStartIndex, intEndIndex;
                    string strHand, strLast, strChang;
                    string strInXml = InXML;
                    DataRow[] drSel;

                    // LinkName
                    if (!string.IsNullOrEmpty(strLinkName))
                    {
                        intStartIndex = Strings.InStr(strInXml, "<" + strLinkNameTagName + ">");
                        intEndIndex = Strings.InStr(strInXml, "</" + strLinkNameTagName + ">");
                        if (intStartIndex > 0 && intEndIndex > 0)
                        {
                            strHand = strInXml.Substring(0, intStartIndex - 1);
                            strLast = Strings.Mid(strInXml, intEndIndex + strLinkNameTagName.Length + 3);
                            string argname = "LinkName";
                            string argtype = "String";
                            string argdesc = "";
                            strChang = CombineXMLParameter(strLinkNameTagName, argname, argtype, strLinkName, argdesc);
                            strInXml = strHand + strChang + strLast;
                        }
                    }

                    // Lot Attrib
                    if (!string.IsNullOrEmpty(strAttrib))
                    {
                        intStartIndex = Strings.InStr(strInXml, "<" + strLAttribTagName + ">");
                        intEndIndex = Strings.InStr(strInXml, "</" + strLAttribTagName + ">");
                        if (intStartIndex > 0 && intEndIndex > 0)
                        {
                            strHand = strInXml.Substring(0, intStartIndex - 1);
                            strLast = Strings.Mid(strInXml, intEndIndex + strLAttribTagName.Length + 3); // strLAttribTagName.Length + 3 = </strLAttribTagName> 的長度
                            string argtype1 = "String";
                            string argdesc1 = "";
                            strChang = CombineXMLParameterMultiValue(strLAttribTagName, strLAttribTagName, argtype1, strAttrib, argdesc1);
                            strInXml = strHand + strChang + strLast;
                        }
                    }

                    // Component Attrib
                    if (!string.IsNullOrEmpty(strCAttrib))
                    {
                        intStartIndex = Strings.InStr(strInXml, "<" + strCAttribTagName + ">");
                        intEndIndex = Strings.InStr(strInXml, "</" + strCAttribTagName + ">");
                        if (intStartIndex > 0 && intEndIndex > 0)
                        {
                            strHand = strInXml.Substring(0, intStartIndex - 1);
                            strLast = Strings.Mid(strInXml, intEndIndex + strCAttribTagName.Length + 3); // strCAttribTagName.Length + 3 = </strCAttribTagName> 的長度
                            string argtype2 = "String";
                            string argdesc2 = "";
                            strChang = CombineXMLParameterMultiValue(strCAttribTagName, strCAttribTagName, argtype2, strCAttrib, argdesc2);
                            strInXml = strHand + strChang + strLast;
                        }
                    }

                    InXML = strInXml;

                    dtChkRuleLot2 = dtChkRuleLot.Copy();


                }

                // 將LotStamp替換為TriggerOP後的LotStamp
                if (blnEXETriggerOP)
                {
                    string strLotStampTagName = "lotstamp".ToLower();

                    int intStartIndex, intEndIndex;
                    string strHand, strLast, strChang;
                    string strInXml = InXML;
                    DataRow[] drSel;

                    // 取得LotStamp 
                    intStartIndex = Strings.InStr(strInXml, "<" + strLotStampTagName + ">");
                    intEndIndex = Strings.InStr(strInXml, "</" + strLotStampTagName + ">");
                    if (intStartIndex > 0 && intEndIndex > 0)
                    {
                        strHand = strInXml.Substring(0, intStartIndex - 1);
                        strLast = Strings.Mid(strInXml, intEndIndex + strLotStampTagName.Length + 3);
                        string argname1 = "LotStamp";
                        string argtype3 = "Long";
                        string argvalue = Conversions.ToInteger(dtLotState.Rows[0]["LotStamp"]).ToString();
                        string argdesc3 = "";
                        strChang = CombineXMLParameter(strLotStampTagName, argname1, argtype3, argvalue, argdesc3);
                        strInXml = strHand + strChang + strLast;
                        InXML = strInXml;
                    }
                }

                string strcheckinresult = ""; // BR_CheckIn回傳success or fail
                using (var obj = new kcWIP.clsLot())
                {
                    if (FunctionID == "CO")
                    {
                        // 5.取出GoodQty,GoodUnitNo---------------------------------------------------------------------------------------------------
                        DataRow[] drSel;
                        double GoodQty = 0d;

                        drSel = dtLotAttrib_Temp.Select("AttribNo='GoodQty'");
                        if (drSel.Length == 0)
                        {
                            throw new iMESException.MESException("0000-200001", "[%CheckOut%] [%GoodQty%] [%not found%]");
                        }
                        else
                        {
                            GoodQty = Convert.ToDouble(drSel[0]["AttribValue"]);
                        }
                        // 進站之前已扣料過。
                        strcheckinresult = obj.BR_CheckOut(Conversions.ToLong(strLotStamp), LotNo, strLinkName, dtLotAttrib_Temp, dtEquipment, null, null, (decimal)GoodQty, UserNo);

                        strRetrunMsg = strcheckinresult;
                        // 9.Return Value
                        if (!string.IsNullOrEmpty(strRetrunMsg))
                        {
                            strResult = "fail";
                            throw new iMESException.MESException("0000-200011", "[%LotNo%] : " + LotNo + "[%Execute%] [%Fail%].");
                        }
                        else
                        {
                            strException = "";
                            strResult = "success";
                        }
                    }

                    else
                    {
                        strcheckinresult = obj.BR_CheckIn(Conversions.ToLong(strLotStamp), LotNo, strLinkName, dtLotAttrib_Temp, dtEquipment, UserNo, ShiftNo, dtAccessory: dtAccessory);
                        strRetrunMsg = strcheckinresult;

                        // 9.Return Value
                        if (strRetrunMsg == "success")
                        {
                            strException = "";
                            strResult = "success";
                        }
                        else
                        {
                            strResult = "fail";
                            throw new iMESException.MESException("0000-200011", "[%LotNo%] : " + LotNo + "[%Execute%] [%Fail%].");
                        }
                    }
                }



                objSYS.AddEventLog(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, "ExecuteLot", ComputerName: ComputerName);

                if (FunctionID == "CO")
                {
                    //开始生产批转移,生产批转移需要走隐藏站规则，因为有客制，所以调用MEStc的功能，防止后续改动导致EAP出错
                    BRTransferLot_Bin_M(LotNo, UserNo, strLinkName, intERFType, strRuleNo, ComputerName: ComputerName, RuleMsg: strERFMsg);
                }
                else
                {
                    // Call BRTransferLot(LotNo, UserNo, strLinkName, 1)
                    tcEAI.clsEAP.BRTransferLot_Bin(LotNo, UserNo, strLinkName, intERFType, strRuleNo, ComputerName: ComputerName, RuleMsg: strERFMsg);

                }


                lblExitProcedure:
                ;
            }


            catch (iMESException.MESException ex)
            {

                if (FunctionID == "CI")
                {
                    if (dtLotNo.Columns.Contains("blnEXETriggerOP"))
                    {
                        // CheckIn失敗將狀態變更回Queue
                        foreach (DataRow drTempLotInfo in dtLotNo.Rows)
                        {
                            if (Convert.ToBoolean(drTempLotInfo["blnEXETriggerOP"]))
                            {
                                DataRow[] drSel = dtLotState.Select("LotNO='" + drTempLotInfo["LotNo"] + "'".ToString());
                                // Call objReverse.ExecuteReverse(drSel(0)("LotNo"), "AutoExe", Now, , , , , drSel(0)("LotStamp"))
                                // Call objLot.ExeReverseTriggerOP(drSel(0)("LotNo"), drSel(0)("LotSerial"), drSel(0)("LogGroupSerial"), drSel(0)("LotStamp"))
                                ExeReverseTriggerOP_NotUseUndo(UserNo, Convert.ToString(drSel[0]["LotNo"]), Convert.ToString(drSel[0]["LotSerial"]), Conversions.ToInteger(drSel[0]["LotStamp"]), ComputerName);
                            }
                        }
                    }
                }

                strResult = "fail";
                strRetrunMsg = ex.Message;

                objSYS.AddErrorLog_ErrorCode(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, ex.Message + " : " + ex.StackTrace, ComputerName: ComputerName, ErrorCode: Convert.ToString(ex.ErrorCode));

                throw ex;
            }

            catch (Exception ex)
            {

                if (FunctionID == "CI")
                {
                    // CheckIn失敗將狀態變更回Queue
                    if (dtLotNo.Columns.Contains("blnEXETriggerOP"))
                    {
                        foreach (DataRow drTempLotInfo in dtLotNo.Rows)
                        {
                            if (Convert.ToBoolean(drTempLotInfo["blnEXETriggerOP"]))
                            {
                                DataRow[] drSel = dtLotState.Select("LotNO='" + drTempLotInfo["LotNo"] + "'".ToString());
                                // Call objReverse.ExecuteReverse(drSel(0)("LotNo"), "AutoExe", Now, , , , , drSel(0)("LotStamp"))
                                // Call objLot.ExeReverseTriggerOP(drSel(0)("LotNo"), drSel(0)("LotSerial"), drSel(0)("LogGroupSerial"), drSel(0)("LotStamp"))
                                ExeReverseTriggerOP_NotUseUndo(UserNo, Convert.ToString(drSel[0]["LotNo"]), Convert.ToString(drSel[0]["LotSerial"]), Conversions.ToInteger(drSel[0]["LotStamp"]), ComputerName);
                            }
                        }
                    }
                }

                strResult = "fail";
                strRetrunMsg = ex.Message;
                objSYS.AddErrorLog_ErrorCode(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, ex.Message + " : " + ex.StackTrace, ComputerName: ComputerName);

                throw ex;
            }

            finally
            {
                if (!(drTemp == null))
                    drTemp.Close();
                if (!(objLot == null))
                {
                    objLot.Dispose();
                    objLot = null;
                }
                if (!(objSYS == null))
                {
                    objSYS.Dispose();
                    objSYS = null;
                }
                AutoexecutionLot_LotRet = strRetrunMsg;
                CloseConnection(cnnTemp);
            }

            return AutoexecutionLot_LotRet;
        }


        public static short funLoadLotStatusJoinOPBusinessRule(string strLotNo, ref DataTable dtLots)
        {
            short funLoadLotStatusJoinOPBusinessRuleRet = default(short);

            funLoadLotStatusJoinOPBusinessRuleRet = -1;

            try
            {

                using (var ds = new DataSet())
                {
                    AppSettings objSetting = new AppSettings();
                    string argstrDataBaseType = "Null";

                    ExecuteSQLQuery_Adapter(
                        " Select State.*, Basis.MONo, Basis.ProductNo, Basis.ProductVersion, BusinessRule.EXECUTIONFILE,BusinessRule.KERNELMODULE ,BusinessRule.KERNELFUNCTIONNAME,PRDPhase.PHASENO CurPhaseNo, G.SerialNo From tblWIPLotState State  " +
                        " Left Join tblOPBusinessRuleBasis BusinessRule On BusinessRule.BRNO = State.BRNO " +
                        " Left Join (Select PHASENO,FromNode From tblPRDOPBusinessruleRelation Group by PHASENO,FROMNODE)PRDPhase On State.BRNO =PRDPhase.FROMNODE " +
                        " Left Join tblWIPTemp_LotState G ON State.LotNo=G.LotNo " +
                        " Left Join tblWIPLotBasis Basis ON State.LotNo=Basis.BASELOTNO " +
                        " Where State.LotNo In " + strLotNo,
                        ds.Tables.Add("LotState"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                    dtLots = ds.Tables[0];

                    funLoadLotStatusJoinOPBusinessRuleRet = 0;

                }
            }
            catch (Exception e1)
            {
                funLoadLotStatusJoinOPBusinessRuleRet = -1;
                throw;
            }

            return funLoadLotStatusJoinOPBusinessRuleRet;


        }


        public static short ChkLotStateAndBRNo(string strLotNo, string FunctionID, string OPNo)
        {
            short ChkLotStateAndBRNoRet = default(short);

            ChkLotStateAndBRNoRet = -1;
            var dtTemp = new DataTable();

            try
            {

                using (var ds = new DataSet())
                {
                    AppSettings objSetting = new AppSettings();
                    //根据生产批号查询产品编号以及产品版本
                    ExecuteSQLQuery_Adapter(
                              " select ProductNo,ProductVersion from tblWIPLotbasis where BaseLotNo in " + strLotNo,
                              dtTemp, objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                    string condition = "  where OPNo='" + OPNo + "' ";
                    if (dtTemp.Rows.Count > 0)
                    {
                        if (dtTemp.Rows[0]["ProductNo"].ToString() != "")
                        {
                            condition += " and ProductNo='" + dtTemp.Rows[0]["ProductNo"].ToString() + "'";
                        }
                        if (dtTemp.Rows[0]["ProductVersion"].ToString() != "")
                        {
                            condition += " and ProductVersion='" + dtTemp.Rows[0]["ProductVersion"].ToString() + "'";
                        }
                    }
                    //string argstrDataBaseType = "Null";
                    //using (var cn = new OleDbConnection(objSetting.GetConnectionString(strDataBaseType: ref argstrDataBaseType)))
                    //{
                    //    using (var da = new OleDbDataAdapter(" Select State.*, BusinessRule.EXECUTIONFILE,BusinessRule.KERNELMODULE ,BusinessRule.KERNELFUNCTIONNAME,PRDPhase.PHASENO CurPhaseNo From tblWIPLotState State  " + " Left Join tblOPBusinessRuleBasis BusinessRule On BusinessRule.BRNO = State.BRNO " + " Left Join (Select PHASENO,FromNode From tblPRDOPBusinessruleRelation Group by PHASENO,FROMNODE)PRDPhase On State.BRNO =PRDPhase.FROMNODE  " + " Where State.LotNo In " + strLotNo + " And OPNo ='" + OPNo + "' ", cn))
                    //    {
                    //        da.Fill(ds.Tables.Add("LotState"));
                    //    }
                    //}
                    ExecuteSQLQuery_Adapter(
                              " Select State.*, BusinessRule.EXECUTIONFILE,BusinessRule.KERNELMODULE ,BusinessRule.KERNELFUNCTIONNAME,PRDPhase.PHASENO CurPhaseNo From tblWIPLotState State  " +
                              " Left Join tblOPBusinessRuleBasis BusinessRule On BusinessRule.BRNO = State.BRNO " +
                              " Left Join (Select PHASENO,FromNode From tblPRDOPBusinessruleRelation " + condition + " Group by PHASENO,FROMNODE)PRDPhase On State.BRNO =PRDPhase.FROMNODE  " +
                              " Where State.LotNo In " + strLotNo + " And OPNo ='" + OPNo + "' ",
                              ds.Tables.Add("LotState"), objSetting.GetConnectionString(), objSetting.GetDataBaseType());
                    dtTemp = ds.Tables[0];

                    if (dtTemp.Rows.Count == 0)
                    {
                        ChkLotStateAndBRNoRet = -2;
                        return ChkLotStateAndBRNoRet;
                    }

                    if (dtTemp.DefaultView.ToTable(true, "BRNo").Rows.Count > 1)
                    {
                        ChkLotStateAndBRNoRet = -3;
                        return ChkLotStateAndBRNoRet;
                    }

                    foreach (DataRow drTemp in dtTemp.Rows)
                    {

                        if (drTemp["BRNO"].ToString().Contains("SPC"))
                        {
                            ChkLotStateAndBRNoRet = -6;
                            return ChkLotStateAndBRNoRet;
                        }

                        switch (FunctionID)
                        {
                            case "CI":
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drTemp["CurPhaseNO"], 0, false)) && Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drTemp["CurPhaseNO"], 1, false)))
                                    {
                                        ChkLotStateAndBRNoRet = -6;
                                        return ChkLotStateAndBRNoRet;
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drTemp["Status"], 0, false)) && Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drTemp["Status"], 1, false)))
                                    {
                                        ChkLotStateAndBRNoRet = -6;
                                        return ChkLotStateAndBRNoRet;
                                    }

                                    break;
                                }

                            case "CO":
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drTemp["CurPhaseNO"], 2, false)))
                                    {
                                        ChkLotStateAndBRNoRet = -6;
                                        return ChkLotStateAndBRNoRet;
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drTemp["Status"], 1, false)))
                                    {
                                        ChkLotStateAndBRNoRet = -6;
                                        return ChkLotStateAndBRNoRet;
                                    }

                                    break;
                                }

                        }
                    }

                    ChkLotStateAndBRNoRet = 0;

                }
            }
            catch (Exception e1)
            {
                ChkLotStateAndBRNoRet = -1;
                throw;
            }

            return ChkLotStateAndBRNoRet;


        }





        //0156845: [6.0.7] 调整EAP接口查核支援BR逻辑
        public static bool ExeBrnoIfSupport(string brdll, string brno)
        {
            bool blnExecResult = false;
            DbDataReader drTemp;
            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            IDbConnection cnnTemp = null;
            try
            {
                cnnTemp = CreateConnection(strConnectionString);
                string strSQL = "select * from TBLSYSEAPBRNOBASIS where UPPER(BRDLL)='" + brdll + "' and UPPER(BRNO)='" + brno + "'";
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    blnExecResult = true;
                }
                drTemp.Close();
            }
            catch (Exception ex)
            {
                blnExecResult = false;
                throw;
            }
            finally
            {
                CloseConnection(cnnTemp);
            }
            return blnExecResult;
        }







        #endregion

        #region "panleid&unit序号生成"
        public static DataTable InitPanleIdOrUnitId(bool ReserveSerialNo = false, long SerialCount = defInteger, string SerialTypeNo = defString, string LotNo = defString, string PanleId = defString, string ProductNo = defString, string SerialType = defString, string AdditionalXml = "", string location = "")
        {
            DataTable InitPanleIdOrUnitId = default(DataTable);

            AppSettings objSetting = new AppSettings();
            IDbConnection cnnTemp = null;
            string strSQL = defString;
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);
            DataSet dsTemp = new DataSet();
            dsTemp.Tables.Add("InitPanleIdOrUnitId");
            dsTemp.Tables["InitPanleIdOrUnitId"].Columns.Add("SeqNo");

            string strSerialString = "";   // 序號編碼字串

            DbDataReader drTemp = null;

            var datEventTime = DateTime.Now;

            var intSer_Len = default(int);           // 流水號長度.
            var intSer_DT = default(int);            // 流水號進位方式-1:10進位,2:16進位,3:36進位.
            var intSNIndex = -1;           // 流水號所在Index位置
            int intPadLeft = 1;       // 流水號是否向左補零 0:不補零,1:自動補零

            if (SerialCount == defInteger)
                SerialCount = 1L; // 沒有傳入產生序號數量則預設值產生一筆序號
            var colParameters = new Collection();

            var objArgs = new object();
            var arySerial = new ArrayList();           // 流水號陣列

            DataRow drNew;


            string strProductNo = ProductNo;



            try
            {
                // 取出編碼規則
                strSQL = "Select * From tblSYSSerialRuleBasis Where SERIALTYPENO = '" + SerialTypeNo + "'AND ENABLE = 1 ";
                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "SerialRuleBasis", cnnTemp);

                if (dsTemp.Tables["SerialRuleBasis"].Rows.Count == 0)
                {
                    throw new Exception(SerialTypeNo + "[%：序号类别编号不存在或者没有启用！%]");
                }


                // 取出分批編碼明細
                strSQL = "Select * From tblSYSSerialRuleDetail Where SERIALTYPENO='" + SerialTypeNo + "' Order By ItemNo ";
                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "SerialRuleDetail", cnnTemp);

                if (dsTemp.Tables["SerialRuleDetail"].Rows.Count == 0)
                {
                    throw new Exception(SerialTypeNo + "[%：序号类别编号不存在或者没有启用！%]");
                }

                // 新增欄位紀錄該編碼項目此次編碼內容
                dsTemp.Tables["SerialRuleDetail"].Columns.Add("Value");

                for (int i = 0, loopTo = dsTemp.Tables["SerialRuleDetail"].Rows.Count - 1; i <= loopTo; i++)
                {

                    // 依照不同編碼項目取得值
                    switch (dsTemp.Tables["SerialRuleDetail"].Rows[i]["SourceType"].ToString())
                    {

                        case "SN":
                            {

                                // 進位方式(1:10進位,2:16進位,3:36進位)
                                intSer_DT = Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["DecimalType"]);
                                intSer_Len = Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]);
                                if (dsTemp.Tables["SerialRuleDetail"].Columns.Contains("PadLeft"))
                                {
                                    intPadLeft = Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["PadLeft"]);
                                }
                                intSNIndex = i;
                                break;
                            }

                        case "UD":
                            {

                                // 序號編碼項目
                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                {
                                    strSerialString += dsTemp.Tables["SerialRuleDetail"].Rows[i]["UserDefine"].ToString();
                                }

                                dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = dsTemp.Tables["SerialRuleDetail"].Rows[i]["UserDefine"].ToString();
                                break;
                            }

                        case "D1":
                        case "D2":
                        case "M1":
                        case "M2":
                        case "M3":
                        case "Y1":
                        case "Y2":
                        case "Y4":
                        case "W2":
                            {

                                // 序號編碼項目
                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                {
                                    string tableTmp = dsTemp.Tables["SerialRuleDetail"].Rows[i]["SourceType"].ToString();
                                    strSerialString += funExeSerialCreate_Date(ref datEventTime, ref tableTmp);
                                }

                                string tableTmp2 = dsTemp.Tables["SerialRuleDetail"].Rows[i]["SourceType"].ToString();
                                dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = funExeSerialCreate_Date(ref datEventTime, ref tableTmp2);
                                break;
                            }

                        case "MO":
                            {

                                if (LotNo == defString)
                                    throw new iMESException.MESException("0000-200002", "[%LotNo%]");

                                string strMONo = "";
                                strSQL = "Select MONo From tblWIPLotBasis Where BaseLotNo ";
                                strSQL += " = (Select BaseLotNo From tblWIPLotState Where LotNo = '" + LotNo + "')";

                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strMONo = drTemp["MONo"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", "[%MONo%]");
                                }
                                drTemp.Close();

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strMONo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%MONo%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strMONo.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strMONo.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strMONo;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strMONo;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strMONo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%MONo%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strMONo.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strMONo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strMONo.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strMONo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }

                        case "FC":
                            {

                                if (LotNo == defString)
                                    throw new iMESException.MESException("0000-200002", "[%LotNo%]");

                                string strFabCode = "";
                                strSQL = "Select FabCode From tblSMDFactoryBasis Where FactoryNo = (Select FactoryNo From tblWIPLotState Where LotNo = '" + LotNo + "')";
                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strFabCode = drTemp["FabCode"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", "[%FactoryNo%]");
                                }
                                drTemp.Close();

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strFabCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%FabCode%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strFabCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strFabCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strFabCode;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strFabCode;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strFabCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%FabCode%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strFabCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strFabCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strFabCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strFabCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }

                        case "MTC":
                            {

                                if (LotNo == defString)
                                    throw new iMESException.MESException("0000-200002", "[%LotNo%]");

                                string strMOTypeCode = "";

                                strSQL = " Select MT.MOTypeCode From tblWIPLotState LS ";
                                strSQL += "Left Join tblWIPLotBasis LB On LS.BaseLotNo = LB.BaseLotNo ";
                                strSQL += "Left Join tblOEMOBasis MO On LB.MONo = MO.MONo ";
                                strSQL += "Left Join tblSYSMOTypeBasis MT On MO.MOTypeNo = MT.MOTypeNo ";
                                strSQL += "Where LS.LotNo = '" + LotNo + "' ";

                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strMOTypeCode = drTemp["MOTypeCode"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", "[%MOTypeNo%]");
                                }
                                drTemp.Close();

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strMOTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%MOTypeCode%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strMOTypeCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strMOTypeCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strMOTypeCode;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strMOTypeCode;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strMOTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%MOTypeCode%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strMOTypeCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strMOTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strMOTypeCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strMOTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }

                        case "PTC":
                            {

                                if (LotNo == defString)
                                    throw new iMESException.MESException("0000-200002", "[%LotNo%]");

                                string strProductTypeCode = "";

                                strSQL = " Select PT.ProductTypeCode From tblWIPLotState LS ";
                                strSQL += "Left Join tblWIPLotBasis LB On LS.BaseLotNo = LB.BaseLotNo ";
                                strSQL += "Left Join tblPRDProductBasis PB On LB.ProductNo = PB.ProductNo AND LB.ProductVersion = PB.ProductVersion  ";
                                strSQL += "Left Join tblPRDType PT On PB.ProductType = PT.ProductType ";
                                strSQL += "Where LS.LotNo = '" + LotNo + "' ";

                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strProductTypeCode = drTemp["ProductTypeCode"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", "[%ProductType%],[%ProductNo%],[%ProductVersion%]");
                                }
                                drTemp.Close();

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strProductTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%ProductType%],[%ProductNo%],[%ProductVersion%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductTypeCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductTypeCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductTypeCode;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductTypeCode;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strProductTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%ProductType%],[%ProductNo%],[%ProductVersion%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductTypeCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strProductTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductTypeCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strProductTypeCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }

                        case "PN":
                            {

                                if (LotNo == defString)
                                    throw new iMESException.MESException("0000-200002", "[%LotNo%]");

                                //string strProductNo = "";

                                strSQL = " Select PB.ProductNo From tblWIPLotState LS ";
                                strSQL += "Left Join tblWIPLotBasis LB On LS.BaseLotNo = LB.BaseLotNo ";
                                strSQL += "Left Join tblPRDProductBasis PB On LB.ProductNo = PB.ProductNo AND LB.ProductVersion = PB.ProductVersion ";
                                strSQL += "Where LS.LotNo = '" + LotNo + "' ";

                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strProductNo = drTemp["ProductNo"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", "[%ProductNo%]");
                                }
                                drTemp.Close();

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strProductNo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%ProductNo%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductNo.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductNo.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductNo;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductNo;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strProductNo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%ProductNo%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductNo.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strProductNo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductNo.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strProductNo.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }

                        case "PC":
                            {

                                if (LotNo == defString)
                                    throw new iMESException.MESException("0000-200002", "[%LotNo%]");

                                string strProductCode = "";

                                strSQL = " Select PB.ProductCode From tblWIPLotState LS ";
                                strSQL += "Left Join tblWIPLotBasis LB On LS.BaseLotNo = LB.BaseLotNo ";
                                strSQL += "Left Join tblPRDProductBasis PB On LB.ProductNo = PB.ProductNo AND LB.ProductVersion = PB.ProductVersion ";
                                strSQL += "Where LS.LotNo = '" + LotNo + "' ";

                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strProductCode = drTemp["ProductCode"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", "[%ProductNo%],[%ProductVersion%]");
                                }
                                drTemp.Close();

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strProductCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%ProductCode%],[%ProductNo%],[%ProductVersion%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductCode.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductCode;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductCode;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strProductCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%ProductCode%],[%ProductNo%],[%ProductVersion%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strProductCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strProductCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strProductCode.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strProductCode.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }
                        case "FUN":
                            {

                                string strFunString = "";
                                // 2018/04/10 OwenLiu, Mantis:0045761, 增加客製 SerialNoFunction 支援機制
                                string strScripFuncName = dsTemp.Tables["SerialRuleDetail"].Rows[i]["FunctionName"].ToString();
                                MethodInfo mi = null;

                                if (strScripFuncName.ToUpper().StartsWith("FUNC_"))
                                {
                                    using (var objSerialNoFunction = new udSYS_Customer.clsSerialNoFunction())
                                    {
                                        mi = objSerialNoFunction.GetType().GetMethod(strScripFuncName, BindingFlags.Public | BindingFlags.Instance);
                                        if (!(mi == null))
                                        {
                                            try
                                            {
                                                strFunString = Convert.ToString(mi.Invoke(objSerialNoFunction, (object[])objArgs));
                                            }
                                            catch (TargetInvocationException tie)
                                            {
                                                throw tie.InnerException;
                                            }
                                            catch (Exception ex)
                                            {
                                                throw;
                                            }
                                        }
                                        else
                                        {
                                            throw new iMESException.MESException("0000-200091", "[%Function%] [%not found%]: " + dsTemp.Tables["SerialRuleDetail"].Rows[i]["FunctionName"].ToString());
                                        }
                                    }
                                }
                                else
                                {
                                    using (var objSerialNoFunction = new udSYS.clsSerialNoFunction())
                                    {
                                        mi = objSerialNoFunction.GetType().GetMethod(strScripFuncName, BindingFlags.Public | BindingFlags.Instance);
                                        if (!(mi == null))
                                        {
                                            try
                                            {
                                                strFunString = Convert.ToString(mi.Invoke(objSerialNoFunction, (object[])objArgs));
                                            }
                                            catch (TargetInvocationException tie)
                                            {
                                                throw tie.InnerException;
                                            }
                                            catch (Exception ex)
                                            {
                                                throw;
                                            }
                                        }
                                        else
                                        {
                                            throw new iMESException.MESException("0000-200091", "[%Function%] [%not found%]: " + dsTemp.Tables["SerialRuleDetail"].Rows[i]["FunctionName"].ToString());
                                        }
                                    }
                                }


                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strFunString.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", strFunString);
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strFunString.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strFunString.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strFunString;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strFunString;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(strFunString.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", strFunString);
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += strFunString.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strFunString.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strFunString.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(strFunString.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }
                        case "PCB供应商代码":
                            {
                                if (PanleId == defString)
                                {
                                    throw new Exception("PanleId: " + PanleId + " 不能为空!");
                                }

                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 0, false))) // 有指定起訖字串位置
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(PanleId.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "PanleId 长度不足!");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += PanleId.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = PanleId.Substring(Conversions.ToInteger(Operators.SubtractObject(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"], 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 1, false))) // 取得全部字串
                                {

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += PanleId;
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = PanleId;
                                }

                                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["GetData"], 2, false))) // 右側取碼
                                {

                                    // 判斷長度是否足夠
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLess(Operators.AddObject(Operators.SubtractObject(PanleId.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), 1), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"], false)))
                                    {
                                        throw new iMESException.MESException("0000-220021", "[%PanleId%]");
                                    }

                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                    {
                                        strSerialString += PanleId.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(PanleId.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));
                                    }

                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = PanleId.Substring(Conversions.ToInteger(Operators.AddObject(Operators.SubtractObject(Operators.SubtractObject(PanleId.Length, dsTemp.Tables["SerialRuleDetail"].Rows[i]["SearchStart"]), dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]), 1)), Conversions.ToInteger(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialLength"]));

                                }

                                break;
                            }
                        case "基板信息":
                            {
                                if (PanleId == defString)
                                {
                                    throw new Exception("PanleId: " + PanleId + " 不能为空!");
                                }

                                strSerialString += PanleId;
                                dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = PanleId;
                                break;
                            }
                        case "Year_LQ":
                            {


                                strSQL = "SELECT CUSTOMCODE FROM TBLCUSNUMCUSTOM WHERE PRODUCTNO='" + strProductNo + "' AND CUSTOMTYPE='年' AND CUSTOMSOURCE='" + datEventTime.Year.ToString("D4") + "'";

                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strSerialString += drTemp["CUSTOMCODE"].ToString();
                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = drTemp["CUSTOMCODE"].ToString();
                                }
                                else
                                {
                                    throw new Exception("Year_LQ 规则未生成！请检查panleid&unit序号规则_年月周定义设定！");
                                }
                                drTemp.Close();
                                break;
                            }
                        case "Mouth_LQ":
                            {



                                strSQL = @"SELECT CUSTOMCODE  FROM TBLCUSNUMCUSTOM WHERE PRODUCTNO = '" + strProductNo + "' AND CUSTOMTYPE = '月' AND( CUSTOMSOURCE = '" + datEventTime.Month.ToString("D2") + "' OR CUSTOMSOURCE = '" + datEventTime.Month.ToString() + "')";

                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strSerialString += drTemp["CUSTOMCODE"].ToString();
                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = drTemp["CUSTOMCODE"].ToString();
                                }
                                else
                                {
                                    throw new Exception("Mouth_LQ 规则未生成！请检查panleid&unit序号规则_年月周定义设定！");
                                }
                                drTemp.Close();

                                break;
                            }
                        case "Week_LQ":
                            {



                                int dayOfYear = datEventTime.DayOfYear;
                                int week = (dayOfYear + 6) / 7;
                                string WeekNo = week.ToString();

                                strSQL = @"SELECT CUSTOMCODE  FROM TBLCUSNUMCUSTOM WHERE PRODUCTNO = '" + strProductNo + "' AND CUSTOMTYPE = '周' AND CUSTOMSOURCE ='" + WeekNo + "'";

                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strSerialString += drTemp["CUSTOMCODE"].ToString();
                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = drTemp["CUSTOMCODE"].ToString();
                                }
                                else
                                {
                                    throw new Exception("Week_LQ 规则未生成！请检查panleid&unit序号规则_年月周定义设定！");
                                }
                                drTemp.Close();
                                break;
                            }
                        case "Day_LQ":
                            {



                                strSQL = @"SELECT CUSTOMCODE  FROM TBLCUSNUMCUSTOM WHERE PRODUCTNO = '" + strProductNo + "' AND CUSTOMTYPE = '日' AND( CUSTOMSOURCE = '" + datEventTime.Day.ToString("D2") + "' OR CUSTOMSOURCE = '" + datEventTime.Day.ToString() + "')";

                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strSerialString += drTemp["CUSTOMCODE"].ToString();
                                    dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = drTemp["CUSTOMCODE"].ToString();
                                }
                                else
                                {
                                    throw new Exception("Day_LQ 规则未生成！请检查panleid&unit序号规则_年月周日定义设定！");
                                }
                                drTemp.Close();

                                break;
                            }
                        case "位置编号":
                            {

                                //strSerialString += location;
                                dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = location;
                                break;
                            }
                        case "工单属性":
                            {
                                if (LotNo == defString)
                                    throw new iMESException.MESException("0000-200002", "[%LotNo%]");

                                string strMONo = "";
                                strSQL = "Select MONo From tblWIPLotBasis Where BaseLotNo ";
                                strSQL += " = (Select BaseLotNo From tblWIPLotState Where LotNo = '" + LotNo + "')";

                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strMONo = drTemp["MONo"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", "[%MONo%]");
                                }
                                drTemp.Close();

                                // 序號編碼項目
                                //if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["SerialRuleDetail"].Rows[i]["SerialCodeFlag"], 1, false)))
                                //{
                                //    strSerialString += dsTemp.Tables["SerialRuleDetail"].Rows[i]["UserDefine"].ToString();
                                //}
                                string strPropertyNO = "";
                                string value = dsTemp.Tables["SerialRuleDetail"].Rows[i]["UserDefine"].ToString();
                                strSQL = $"Select PROPERTYVALUE From TBLOEMOPROPERTY Where MONO = '{strMONo}' and PROPERTYNO = '{value}' ";
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strPropertyNO = drTemp["PROPERTYVALUE"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-220020", $"{value}属性编号不存在");
                                }
                                drTemp.Close();


                                dsTemp.Tables["SerialRuleDetail"].Rows[i]["Value"] = strPropertyNO;
                                break;
                            }
                    }

                }


                if (arySerial.Count == 0)
                {
                    // 呼叫序號產生，取得目前最大值，並且產生多筆序號，更新系統紀錄
                    // arySerial = funExeSerialCreate_Serial(cnnTemp, "LOTNO", SerialCount, strSerialString, intSer_Len, intSer_DT, ReserveSerialNo)
                    string argSerialType1 = SerialType;
                    arySerial = funExeSerialCreate_Serial(ref cnnTemp, ref argSerialType1, ref SerialCount, ref strSerialString, ref intSer_Len, ref intSer_DT, ref ReserveSerialNo, intPadLeft);
                }

                // 將編碼與流水號合併
                for (int i = 0, loopTo6 = arySerial.Count - 1; i <= loopTo6; i++)
                {

                    strSerialString = "";
                    for (int j = 0, loopTo7 = dsTemp.Tables["SerialRuleDetail"].Rows.Count - 1; j <= loopTo7; j++)
                    {

                        if (j == intSNIndex)
                        {
                            strSerialString += arySerial[0].ToString();
                        }
                        else
                        {
                            strSerialString += dsTemp.Tables["SerialRuleDetail"].Rows[j]["Value"].ToString();
                        }

                    }

                    drNew = dsTemp.Tables["InitPanleIdOrUnitId"].NewRow();
                    drNew["SeqNo"] = strSerialString;
                    dsTemp.Tables["InitPanleIdOrUnitId"].Rows.Add(drNew);

                }


                // 移除多餘Table
                dsTemp.Tables.Remove("SerialRuleBasis");
                dsTemp.Tables.Remove("SerialRuleDetail");

                if (!(dsTemp.Tables["LotStateJoinBasis"] == null))
                    dsTemp.Tables.Remove("LotStateJoinBasis");

                // //Combine return value
                InitPanleIdOrUnitId = dsTemp.Tables[0];
            }
            catch (Exception e1)
            {
                InitPanleIdOrUnitId = null;
                throw;
            }
            finally
            {
                drTemp?.Close();
                dsTemp?.Dispose();
                CloseConnection(cnnTemp);
            }
            return InitPanleIdOrUnitId;
        }



        public static string funExeSerialCreate_Date(ref DateTime EventTime, ref string SourceType)
        {
            string funExeSerialCreate_DateRet = default(string);

            var strResult = default(string);

            try
            {
                switch (SourceType)
                {

                    case "D1":
                        {
                            switch (EventTime.ToString("dd"))
                            {
                                case "01":
                                case "02":
                                case "03":
                                case "04":
                                case "05":
                                case "06":
                                case "07":
                                case "08":
                                case "09":
                                    {
                                        strResult = EventTime.ToString("dd").Substring(1, 1);
                                        break;
                                    }
                                case "10":
                                    {
                                        strResult = "A";
                                        break;
                                    }
                                case "11":
                                    {
                                        strResult = "B";
                                        break;
                                    }
                                case "12":
                                    {
                                        strResult = "C";
                                        break;
                                    }
                                case "13":
                                    {
                                        strResult = "D";
                                        break;
                                    }
                                case "14":
                                    {
                                        strResult = "E";
                                        break;
                                    }
                                case "15":
                                    {
                                        strResult = "F";
                                        break;
                                    }
                                case "16":
                                    {
                                        strResult = "G";
                                        break;
                                    }
                                case "17":
                                    {
                                        strResult = "H";
                                        break;
                                    }
                                case "18":
                                    {
                                        strResult = "I";
                                        break;
                                    }
                                case "19":
                                    {
                                        strResult = "J";
                                        break;
                                    }
                                case "20":
                                    {
                                        strResult = "K";
                                        break;
                                    }
                                case "21":
                                    {
                                        strResult = "L";
                                        break;
                                    }
                                case "22":
                                    {
                                        strResult = "M";
                                        break;
                                    }
                                case "23":
                                    {
                                        strResult = "N";
                                        break;
                                    }
                                case "24":
                                    {
                                        strResult = "O";
                                        break;
                                    }
                                case "25":
                                    {
                                        strResult = "P";
                                        break;
                                    }
                                case "26":
                                    {
                                        strResult = "Q";
                                        break;
                                    }
                                case "27":
                                    {
                                        strResult = "R";
                                        break;
                                    }
                                case "28":
                                    {
                                        strResult = "S";
                                        break;
                                    }
                                case "29":
                                    {
                                        strResult = "T";
                                        break;
                                    }
                                case "30":
                                    {
                                        strResult = "U";
                                        break;
                                    }
                                case "31":
                                    {
                                        strResult = "V";
                                        break;
                                    }
                            }

                            break;
                        }

                    case "D2":
                        {
                            strResult = Strings.Format(DateAndTime.DatePart(DateInterval.Day, EventTime), "00");
                            break;
                        }

                    case "M1":
                        {
                            switch (EventTime.ToString("MM"))
                            {
                                case "01":
                                case "02":
                                case "03":
                                case "04":
                                case "05":
                                case "06":
                                case "07":
                                case "08":
                                case "09":
                                    {
                                        strResult = EventTime.ToString("MM").Substring(1, 1);
                                        break;
                                    }
                                case "10":
                                    {
                                        strResult = "A";
                                        break;
                                    }
                                case "11":
                                    {
                                        strResult = "B";
                                        break;
                                    }
                                case "12":
                                    {
                                        strResult = "C";
                                        break;
                                    }
                            }

                            break;
                        }

                    case "M2":
                        {
                            strResult = Strings.Format(DateAndTime.DatePart(DateInterval.Month, EventTime), "00");
                            break;
                        }

                    case "M3":
                        {
                            int intMonth;
                            intMonth = DateAndTime.DatePart(DateInterval.Month, EventTime);
                            switch (intMonth)
                            {
                                case 1:
                                    {
                                        strResult = "JAN";
                                        break;
                                    }
                                case 2:
                                    {
                                        strResult = "FEB";
                                        break;
                                    }
                                case 3:
                                    {
                                        strResult = "MAR";
                                        break;
                                    }
                                case 4:
                                    {
                                        strResult = "APR";
                                        break;
                                    }
                                case 5:
                                    {
                                        strResult = "MAY";
                                        break;
                                    }
                                case 6:
                                    {
                                        strResult = "JUN";
                                        break;
                                    }
                                case 7:
                                    {
                                        strResult = "JUL";
                                        break;
                                    }
                                case 8:
                                    {
                                        strResult = "AUG";
                                        break;
                                    }
                                case 9:
                                    {
                                        strResult = "SEP";
                                        break;
                                    }
                                case 10:
                                    {
                                        strResult = "OCT";
                                        break;
                                    }
                                case 11:
                                    {
                                        strResult = "NOV";
                                        break;
                                    }
                                case 12:
                                    {
                                        strResult = "DEC";
                                        break;
                                    }
                            }

                            break;
                        }

                    case "Y1":
                        {
                            strResult = Strings.Mid(DateAndTime.DatePart(DateInterval.Year, EventTime).ToString(), 4, 1);
                            break;
                        }

                    case "Y2":
                        {
                            strResult = Strings.Mid(DateAndTime.DatePart(DateInterval.Year, EventTime).ToString(), 3, 2);
                            break;
                        }

                    case "Y4":
                        {
                            strResult = DateAndTime.DatePart(DateInterval.Year, EventTime).ToString();
                            break;
                        }

                    case "W2":
                        {
                            strResult = Strings.Format(DateAndTime.DatePart(DateInterval.WeekOfYear, EventTime, FirstDayOfWeek.Sunday, FirstWeekOfYear.Jan1), "00");
                            break;
                        }

                    default:
                        {
                            throw new iMESException.MESException("0000-200015", "[%SourceType%] is not valid!");
                        }
                }

                // Return
                funExeSerialCreate_DateRet = strResult;
            }

            catch (Exception e1)
            {
                funExeSerialCreate_DateRet = "fail";
                throw;
            }
            finally
            {

            }

            return funExeSerialCreate_DateRet;

        }


        private static ArrayList funExeSerialCreate_Serial(ref IDbConnection cnnTemp, ref string SerialType, ref long SerialCount, ref string SerialString, ref int SerialLength, ref int DecimalType, ref bool ReserveSerialNo, int PadLeft = defInteger)
        {
            ArrayList funExeSerialCreate_SerialRet = default(ArrayList);

            DbDataReader drTemp = null;
            var colSQL = new Collection();
            var colSQL_Rows = new Collection();
            var arySerial = new ArrayList();
            string strSQL = "";
            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);

            try
            {

                if (SerialCount <= 0L)
                {
                    throw new iMESException.MESException("0000-200017", "[%MOQty%]");
                }

                // 取出最大碼.
                bool blnInsert;
                long lngMaxSerialNo; // 起始碼.
                long lngSerialNo_Last; // 最大一個序號.
                var strSerialNo_Last_nn = default(string); // 轉換成10,16,36表示式.

                strSQL = "Select MaxSerialNo From tblSYSSerialCreateMax " + " Where SerialType='" + SerialType + "'" + " And SerialString='" + SerialString + "'" + " And SerialLength=" + SerialLength + " And DecimalType=" + DecimalType;
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    blnInsert = false;
                    lngMaxSerialNo = Conversions.ToLong(drTemp["MaxSerialNo"]);
                }
                else
                {
                    blnInsert = true;
                    lngMaxSerialNo = 0L;
                }
                drTemp.Close();

                // 最大的序號
                lngSerialNo_Last = lngMaxSerialNo + SerialCount;

                if (DecimalType == 1)
                {
                    strSerialNo_Last_nn = lngSerialNo_Last.ToString();
                }
                else if (DecimalType == 2)
                {
                    strSerialNo_Last_nn = Tran10_16(lngSerialNo_Last);
                }
                else if (DecimalType == 3)
                {
                    strSerialNo_Last_nn = Tran10_36(lngSerialNo_Last);
                }

                // 86774: [6.0.5] 序號規則新增34進位序號
                // ===================================== 86774 Start =====================================
                else if (DecimalType == 4)
                {
                    strSerialNo_Last_nn = Tran10_34(lngSerialNo_Last);
                    // ===================================== 86774  End  =====================================

                }

                // 最大碼是否超出序號長度.
                if (strSerialNo_Last_nn != null && strSerialNo_Last_nn.Length > SerialLength)
                {
                    throw new iMESException.MESException("9P12-200028", "[%SerialString%]: " + SerialString + Constants.vbNewLine + "[%SerialLength%]: " + SerialLength + Constants.vbNewLine + "[%SerialNo%]: " + strSerialNo_Last_nn);
                }

                if (ReserveSerialNo == true)
                {
                    // 回填最大碼(利用MaxSerialNo來確保資料的一致性及使用的序號為唯一)
                    if (blnInsert)
                    {
                        strSQL = "Insert into tblSYSSerialCreateMax " + " (SerialType,SerialString,SerialLength,DecimalType,MaxSerialNo) " + " Values('" + SerialType + "','" + SerialString + "'," + SerialLength + "," + DecimalType + "," + lngSerialNo_Last + ")";
                        colSQL.Add(strSQL);
                        colSQL_Rows.Add(1);
                    }
                    else
                    {
                        strSQL = "Update tblSYSSerialCreateMax Set MaxSerialNo=" + lngSerialNo_Last + " Where SerialType='" + SerialType + "'" + " And SerialString='" + SerialString + "'" + " And SerialLength=" + SerialLength + " And DecimalType=" + DecimalType + " And MaxSerialNo=" + lngMaxSerialNo;
                        colSQL.Add(strSQL);
                        colSQL_Rows.Add(1);
                    }

                    ExecuteSQLNoneQuery_ChkRowCount(strDataBaseType, strConnectionString, colSQL, colSQL_Rows);
                }

                for (int i = 1, loopTo = (int)SerialCount; i <= loopTo; i++)
                {
                    if (PadLeft == 0)
                    {
                        if (DecimalType == 1)
                        {
                            arySerial.Add((lngMaxSerialNo + i).ToString());
                        }
                        else if (DecimalType == 2)
                        {
                            arySerial.Add(Tran10_16(lngMaxSerialNo + i).ToString());
                        }
                        else if (DecimalType == 3)
                        {
                            arySerial.Add(Tran10_36(lngMaxSerialNo + i).ToString());
                        }

                        // 86774: [6.0.5] 序號規則新增34進位序號
                        // ===================================== 86774 Start =====================================
                        else if (DecimalType == 4)
                        {
                            arySerial.Add(Tran10_34(lngMaxSerialNo + i).ToString());
                            // ===================================== 86774  End  =====================================
                        }
                    }
                    else if (DecimalType == 1)
                    {
                        arySerial.Add((lngMaxSerialNo + i).ToString().PadLeft(SerialLength, '0'));
                    }
                    else if (DecimalType == 2)
                    {
                        arySerial.Add(Tran10_16(lngMaxSerialNo + i).ToString().PadLeft(SerialLength, '0'));
                    }
                    else if (DecimalType == 3)
                    {
                        arySerial.Add(Tran10_36(lngMaxSerialNo + i).ToString().PadLeft(SerialLength, '0'));
                    }

                    // 86774: [6.0.5] 序號規則新增34進位序號
                    // ===================================== 86774 Start =====================================
                    else if (DecimalType == 4)
                    {
                        arySerial.Add(Tran10_34(lngMaxSerialNo + i).ToString().PadLeft(SerialLength, '0'));
                        // ===================================== 86774  End  =====================================
                    }
                }

                // 回傳最大碼
                funExeSerialCreate_SerialRet = arySerial;
            }

            catch (Exception e1)
            {
                funExeSerialCreate_SerialRet = null;
                throw;
            }
            finally
            {

            }

            return funExeSerialCreate_SerialRet;

        }


        #endregion

        #region "分批客制"
        //客制母批不需要变状态

        // 功能:依dtSplitLot內的資料,執行分批.
        // 傳入值:LotNo,dtSplitLot
        // 傳回值:success(成功), fail(失敗)
        // 修改:2008/08/26,sammi.可由使用者指定SysQty而不自動計算.
        // 修改:2009/08/14,yumei, tblWIPLotLog*新增OPGroupNo欄位
        // 修改:2012/06/18,sammi.新增多人加工處理.
        // 修改:2019/04/25 Lena, 交辦單:W084562019040028 
        // 調整在製品庫分批,當生產批為在製品庫分批且狀態已為99結批時,不建立還原點,不允許還原.(因生產批結批時,已將其所有還原的資料都已刪除,故不能做還原的作業)
        public static string BR_Manual_LotSplit_M(long LotStamp, string MLotNo, int SplitType, string UserNo, DataTable dtSplitLot, string LinkName = defString, string ShiftNo = defString, string AdditionalXml = "", string EventDescription = "", bool blnWIPInv = false, int intUserActiveId = defInteger)
        {
            string BR_Manual_LotSplitRet = default(string);

            // PS1.手動的分批可能發生在任一時點(站中or站間)
            // PS2.手動分批也可是一個BR,若是BR則分批完成,Staus要變更為4

            IDbConnection cnnTemp = null;
            var dsTemp = new DataSet();
            DbDataReader drTemp = null;
            var CollectionSQL = new Collection();
            Collection colToINVLotNo = new Collection();

            DataRow drAdd;
            DataRow[] drSel;
            string MNewLotSerial, SLotNo, SLotSerial, SerialNo;
            int MReverseId = default(int), SReverseId = default(int);
            string MLotSerial, AutoMergeToLotNo;
            var decSplitQty = default(decimal);
            DateTime datEventTime;
            bool blnAutoMerge, blnHaveFromLot, blnHaveSysQty;
            int intOPStatus;
            decimal MLotQtyAfterSplit = defInteger;
            int i;
            string MLogGroupSerial;

            var aryLotProperty = new ArrayList();
            bool blnECN = false;
            // === 2021/09/08 Troy mantis:94662 生產批下線後執行動作紀錄 phase III
            var EventTime = DateTime.Now;
            objLotLog = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle(intUserActiveId, UserNo, EventTime);
            objLotLog.ColSQL = CollectionSQL;
            // ===
            // ===2021/09/13 Troy 生產批歷程，將MCurQty, SysQty移至外層宣告 mantis:94662
            decimal MCurQty, SysQty;

            SLotSerial = "";
            SerialNo = "";
            AutoMergeToLotNo = "";

            string strSQL = "";
            kcWIP.clsLot objLot = new kcWIP.clsLot();

            AppSettings objSetting = new AppSettings();


            string DataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);

            try
            {
                // //Create connection
                cnnTemp = CreateConnection(strConnectionString);

                // 2020/02/12 Eric Mantis:0067304(分批未繼承ECN) 確認是否為IC_FT_PKG
                bool blnIsIC_PKG = false;
                strSQL = "Select Count(ACTIVEMODULE) from TBLSYSFUNCTION Where ActiveModule='IC_FT_PKG'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                if (Convert.ToBoolean(Operators.ConditionalCompareObjectGreater(ExecuteSQLQuery_Scalar(strSQL, cnnTemp), 0, false)))
                    blnIsIC_PKG = true;


                // 1.檢查子批-------------------------------------------------------------------------------------------------------------
                if (dtSplitLot.Select("Action <> 0 And Action <> 1 And Action <> 2").Length > 0)
                {
                    throw new iMESException.MESException("0000-200015", "Action of Split Lot is not Valid Valud(0:Go,1:Jump OP,2:Jump Process)!!");
                }

                // 檢查新分批的子批中是否有FromLotNo
                drSel = dtSplitLot.Select("SplitLotNo ='" + MLotNo + "'");
                if (drSel.Length == 0)
                {
                    blnHaveFromLot = false;
                }
                else
                {
                    // 2020/11/9,Ning,0081028: [6.0.5]分批處理，產品變更/流程變更調整
                    // If drSel(0)("Action") <> 0 Then
                    // Throw New iMESException.MESException("0000-214010", "[SplitLotNo:" & MLotNo & " only support GO action.]")
                    // End If
                    MLotQtyAfterSplit = Convert.ToDecimal(drSel[0]["SplitLotQty"]);
                    blnHaveFromLot = true;
                }

                // 2.加總SplitLotQty------------------------------------------------------------------------------------------------------
                var loopTo = dtSplitLot.Rows.Count - 1;
                for (i = 0; i <= loopTo; i++)
                {
                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectLessEqual(dtSplitLot.Rows[i]["SplitLotQty"], 0, false)))
                    {
                        throw new iMESException.MESException("0000-200017", "SplitLotNo:" +
                            dtSplitLot.Rows[i]["SplitLotNo"] + " SplitQty = 0!!");
                    }
                    decSplitQty = Convert.ToDecimal(Operators.AddObject(decSplitQty, dtSplitLot.Rows[i]["SplitLotQty"]));
                }

                // 3.取出母批相關資料-----------------------------------------------------------------------------------------------------
                datEventTime = DateTime.Now;

                objLot.SHR_Split_GetReference(ref cnnTemp, ref dsTemp, ref SerialNo, MLotNo, datEventTime);

                if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(decSplitQty, dsTemp.Tables["LotState"].Rows[0]["CurQty"], false)))
                {
                    throw new iMESException.MESException("0000-214003", "Sum of SplitLotQty(" + Strings.Format(decSplitQty, "0.####") + ") is not equal CurQty(" + Strings.Format(dsTemp.Tables["LotState"].Rows[0]["CurQty"], "0.####") + ") of LotNo!!");
                }

                // 2020/02/12 Eric Mantis:0067304(分批未繼承ECN) 若產品的CustomerNo及DeviceNo皆不為N/A, 才啟用ECN相關處理
                strSQL = "Select CustomerNo,DeviceNo From tblPRDProductBasis Where ProductNo ='" + dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString() + "'" + " And ProductVersion = '" + dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString() + "'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    if (drTemp["CustomerNo"].ToString() != "N/A" && drTemp["DeviceNo"].ToString() != "N/A" && !string.IsNullOrEmpty(drTemp["CustomerNo"].ToString()) && !string.IsNullOrEmpty(drTemp["DeviceNo"].ToString()))
                    {
                        blnECN = true;
                    }
                }
                drTemp.Close();


                MLotSerial = dsTemp.Tables["LotState"].Rows[0]["LotSerial"].ToString();
                intOPStatus = Conversions.ToInteger(dsTemp.Tables["LotState"].Rows[0]["OPStatus"]);
                MLogGroupSerial = dsTemp.Tables["LotState"].Rows[0]["LogGroupSerial"].ToString();

                // 3.1取出主批之庫房資訊
                if (blnWIPInv)
                {
                    strSQL = "Select * From tblINVWIPInventory_Semi Where LotNo = '" + MLotNo + "'";

                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    // daTemp = New OleDb.OleDbDataAdapter(cmmTemp) 
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "WIPInv_RefLot", cnnTemp);

                    if (dsTemp.Tables["WIPInv_RefLot"].Rows.Count == 0)
                    {
                        throw new iMESException.MESException("0000-202002", "[%LotNo%] : " + MLotNo);
                    }

                }

                // 4.Create ToLot Table for Split Inherit use---------------------------------------------------------------------------
                var dtSplitCont = new DataTable("SplitLot");
                dtSplitCont.Columns.Add("ToLotNo", Type.GetType("System.String"));
                dtSplitCont.Columns.Add("ToBaseLotNo", Type.GetType("System.String"));
                dtSplitCont.Columns.Add("ToLotSerial", Type.GetType("System.String"));
                dtSplitCont.Columns.Add("ToReverseId", Type.GetType("System.Int32"));
                dtSplitCont.Columns.Add("ToLotQty", Type.GetType("System.Decimal"));
                dtSplitCont.Columns.Add("MajorLot", Type.GetType("System.Byte")); // 0:No,1:Yes(應該只有一筆是1)

                // 5.判斷SysQty的來源.
                if (dtSplitLot.Columns.Contains("SplitSysQty") && dtSplitLot.Select("SplitSysQty is null").Length == 0)
                {
                    blnHaveSysQty = true; // 使用前端傳入的SysQty而不自動計算.
                }
                else
                {
                    blnHaveSysQty = false;
                } // 由系統自動計算.

                // 5.母批---------------------------------------------------------------------------------------------------------------
                // 不可以使用LotState上的LotSerial,必須重新產生,否則Undo時會將前一Reverse已備份的BK刪除
                MNewLotSerial = objLot.InitLotSerial(MLotNo);

                // 2019/04/25 Lena, 在製品庫分批且生產批狀態已為99結批,不建立還原點
                if (!blnWIPInv || Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dsTemp.Tables["LotState"].Rows[0]["LotState"], 99, false)))
                {
                    var tmp = dsTemp.Tables["LotState"].Rows[0];
                    string argOPNo = tmp["OPNo"].ToString();
                    udReverse.clsReverse.ReverseType revTypeTmp = udReverse.clsReverse.ReverseType.Split_From;
                    MReverseId = objReverse.NewReverseID(ref MLotNo, ref revTypeTmp, ref MNewLotSerial, ref argOPNo, ref CollectionSQL, Description: "BR Manual Split(From Lot)", Creator: UserNo, CreateDate: datEventTime);
                    tmp["OPNo"] = argOPNo;
                }

                if (SplitType == 1) // BR分批
                {
                    // 加入Cont_Employee
                    strSQL = "Insert into tblWIPCont_Employee(LogGroupSerial,LotSerial,LotNo,OPNo,BRNo,UserNo,FunctionName,ShiftNo,EventTime)" + " Values('" +
                        dsTemp.Tables["LotState"].Rows[0]["LogGroupSerial"] + "','" + MNewLotSerial + "','" + MLotNo + "','" + dsTemp.Tables["LotState"].Rows[0]["OPNo"] +
                        "','" + dsTemp.Tables["LotState"].Rows[0]["BRNo"] + "','" + UserNo + "','BR_Manual_LotSplit','" + ShiftNo + "'," + "To_Date('" + Strings.Format(datEventTime, "yyyy/MM/dd H:mm:ss") +
                        "','YYYY/MM/DD HH24:MI:SS'))";
                    CollectionSQL.Add(strSQL);
                }

                if (intOPStatus == 1)
                {
                    // 變更LotLog的EndTime
                    strSQL = "Select EndTime From tblWIPLotLog Where LotSerial = '" + MLotSerial + "'";
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (drTemp.Read())
                    {
                        strSQL = "Update tblWIPLotLog Set EndTime =  To_Date('" + Strings.Format(Convert.ToDateTime(datEventTime), "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')" + " Where LotSerial = '" + MLotSerial + "'";
                        CollectionSQL.Add(strSQL);

                        // 加入ReverseUpdateContent
                        if (drTemp["EndTime"] is DBNull)
                        {
                            strSQL = "Update tblWIPLotLog Set EndTime = null Where LotSerial = '" + MLotSerial + "'";
                        }
                        else
                        {
                            strSQL = "Update tblWIPLotLog Set EndTime =  To_Date('" + Strings.Format(Convert.ToDateTime(drTemp["EndTime"]), "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')" + " Where LotSerial = '" + MLotSerial + "'";
                        }
                        Collection argcolSQL_Rows = null;
                        objReverse.AddReverseUpdateContent(ref MNewLotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows);
                    }
                    drTemp.Close();

                }

                // 併回處理
                // 檢查母批是否已指定為要併回
                strSQL = "Select FromLotNo,ToLotNo From tblWIPAutoMerge Where FromLotNo = '" + MLotNo + "'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read()) // 是
                {
                    blnAutoMerge = true;
                    AutoMergeToLotNo = drTemp["ToLotNo"].ToString();
                    if (!blnHaveFromLot)
                    {
                        // 刪除母批併回資料(將子批併回資料加入,再後面處理)
                        strSQL = "Delete From tblWIPAutoMerge Where FromLotNo = '" + MLotNo + "'";
                        CollectionSQL.Add(strSQL);
                    }
                }
                else
                {
                    blnAutoMerge = false;
                }
                drTemp.Close();


                if (blnHaveFromLot) // 扣量處理            
                {
                    int intStatus = defInteger;
                    int intGOStatus = defInteger;

                    if (intOPStatus == 1)
                    {
                        if (SplitType == 1)   // BR分批
                        {
                            if (LinkName == "HOLD")
                            {
                                intStatus = 3;
                                intGOStatus = 4;
                            }
                            else if (LinkName == "WAIT")
                            {
                                intStatus = 2;
                                intGOStatus = 4;
                            }
                            else
                            {
                                intStatus = 4;
                                intGOStatus = defInteger;
                            }
                        }
                        else
                        {
                        } // 站中手動分批,不需要變更.                        
                    }

                    // 系統數量.
                    // ===2021/09/13 Troy 生產批歷程，移至外層宣告 mantis:94662
                    // Dim MCurQty, SysQty As Decimal

                    drSel = dtSplitLot.Select("SplitLotNo ='" + MLotNo + "'");
                    MCurQty = Convert.ToDecimal(drSel[0]["SplitLotQty"]);

                    if (blnHaveSysQty)
                    {
                        SysQty = Convert.ToDecimal(drSel[0]["SplitSysQty"]);
                    }
                    else
                    {
                        // 計算系統數量.
                        var objUnit = new udUnitTransferFunction.clsUnitTransferFunction();
                        var colParameters = new Collection();

                        colParameters.Add(dsTemp.Tables["LotState"].Rows[0]["ENGNo"].ToString(), "ENGNo");
                        colParameters.Add(dsTemp.Tables["LotState"].Rows[0]["ENGVersion"].ToString(), "ENGVersion");
                        colParameters.Add(dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString(), "ProductNo");
                        colParameters.Add(dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString(), "ProductVersion");
                        SysQty = Convert.ToDecimal(objUnit.EXETransferQty(dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"].ToString(), dsTemp.Tables["LotState"].Rows[0]["SysUnitNo"].ToString(), (double)MCurQty, colParameters));
                        objUnit = null;
                    }

                    //0370 20260604 母批不走完成状态

                    // 其他修改的資料(LotSerial,NewReverseId內已更新.)
                    strSQL = "Update tblWIPLotState Set CurQty = " + MCurQty + "," + " CurUnitNo = '" +
                        dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"] + "'," + " SysQty = " + SysQty + "," + " SysUnitNo = '" + dsTemp.Tables["LotState"].Rows[0]["SysUnitNo"] +
                        "'," + " EventTime=To_Date('" + Strings.Format(datEventTime, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')," + " EventUserNo='" + UserNo +
                        "'," + " EventDescription='" + EventDescription + "'";
                    // BR分批或手動分批會有不同的處理.
                    if (LinkName != defString)
                        strSQL += ",LinkName='" + LinkName + "'";

                    //0370 20260604 母批不走完成状态

                    //if (intStatus != defInteger)
                    //    strSQL += ",Status=" + intStatus;

                    if (intGOStatus != defInteger)
                        strSQL += ",GOStatus=" + intGOStatus;
                    strSQL += " Where LotNo ='" + MLotNo + "'";
                    CollectionSQL.Add(strSQL);

                    // 2009/9/10,yumei,更新母批tblWIPTemp_Attrib,tblWIPCont_Attrib資料,NewLot_Split只有更新子批----
                    if (intOPStatus == 1)   // 站中
                    {
                        var tmp1 = dsTemp.Tables;
                        var argdtLotState = tmp1["LotState"];
                        var tmp2 = dsTemp.Tables;
                        var argdtTempLotAttrib = tmp2["TempLotAttrib"];
                        var tmp3 = dsTemp.Tables;
                        var argdtLotProperty = tmp3["LotProperty"];
                        var tmp4 = dsTemp.Tables;
                        var argdtLotECNAttrib = tmp4["LotECNAttrib"];
                        objLot.UpdLotAttrib(ref MLotNo, ref MNewLotSerial, ref MLogGroupSerial, (double)MCurQty, argdtLotState, argdtTempLotAttrib, dtLotProperty: argdtLotProperty, dtLotECNAttrib: argdtLotECNAttrib, CollectionSQL: CollectionSQL);

                        //2023/8/22,Ning,143969: 木林森项目：木林森项目，进站后，站分批，母批出站时会按照原始的inputqty计算物料耗用
                        strSQL = "Update tblWIPTemp_LotState Set CurQty = " + MCurQty + " Where LotNo = '" + MLotNo + "'";
                        CollectionSQL.Add(strSQL);
                    }
                    // -------------------------

                    drAdd = dtSplitCont.NewRow();
                    drAdd["ToLotNo"] = MLotNo;
                    drAdd["ToBaseLotNo"] = dsTemp.Tables["LotState"].Rows[0]["BaseLotNo"];
                    drAdd["ToLotSerial"] = MNewLotSerial;
                    drAdd["ToReverseId"] = MReverseId;
                    drAdd["ToLotQty"] = MCurQty;
                    drAdd["MajorLot"] = 1;
                    dtSplitCont.Rows.Add(drAdd);

                    // 母批變更產品
                    // ===生產批歷程，新增boolean，判斷母批是否有改產品
                    bool blnChgProduct = false;
                    // ===
                    var drSelMLot = dtSplitLot.Select("SplitLotNo ='" + MLotNo + "'");
                    drSel = dsTemp.Tables["LotState"].Select("LotNo ='" + MLotNo + "'");

                    string ProcessNo, ProcessVersion, strECNNo, AttribValue;
                    decimal decCurQty = Convert.ToDecimal(dsTemp.Tables["LotState"].Rows[0]["CurQty"]);
                    string MOrgProductNo = dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString();
                    string MOrgProductVersion = dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString();
                    string OPNo = dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString();
                    if ((Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drSelMLot[0]["ProductNo"], MOrgProductNo, false)) || Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drSelMLot[0]["ProductVersion"], MOrgProductVersion, false))) && Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drSelMLot[0]["ProductNo"], defString, false)))
                    {

                        // 取得欲變更的產品單位
                        string strUnitNo = "";
                        strSQL = "Select * From tblPRDProductBasis Where ProductNo ='" +
                            drSelMLot[0]["ProductNo"] + "' And ProductVersion='" + drSelMLot[0]["ProductVersion"] + "' ";
                        // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                        drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                        if (drTemp.Read())
                        {
                            strUnitNo = drTemp["UnitNo"].ToString();
                        }
                        drTemp.Close();


                        // 變更產品
                        objLot.ChgProductOperation(MLotNo, UserNo, MOrgProductNo, MOrgProductVersion, Convert.ToString(drSelMLot[0]["ProductNo"]), Convert.ToString(drSelMLot[0]["ProductVersion"]), strUnitNo,
                            CollectionSQL, RefLotNo: MLotNo);
                        // ===生產批歷程，新增boolean，判斷母批是否有改產品
                        blnChgProduct = true;
                        // B. 更新Temp Attrib Cont Attrib及Log_Report資料 (若在站中intOPStatus = 1)
                        // 取得此生產批於此作業站的ECNNo
                        // 2019/06/04 Edison母批換品號時的OPECN及Temp Attrib Cont Attrib, Log_Report資料
                        if (blnIsIC_PKG && blnECN)
                        {
                            if (intOPStatus == 1)
                            {
                                strSQL = "Select ECNNo_OP From tblWIPLotOPECNRecord Where LotNo = '" + MLotNo + "' And OPNo = '" + OPNo + "'";
                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    strECNNo = drTemp["ECNNo_OP"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-200003", "[%OP%] [%ECNNo%]");
                                }
                                drTemp.Close();


                                strSQL = "Delete From tblWIPTemp_Attrib Where LotNo = '" + MLotNo + "'";
                                CollectionSQL.Add(strSQL);

                                strSQL = "Delete From tblWIPCont_Attrib Where LogGroupSerial = '" + MLogGroupSerial + "'";
                                CollectionSQL.Add(strSQL);

                                strSQL = "Select * From tblPRDOPAttrib Where SerialNo = '" + SerialNo + "' And (ECNNo = '" + strECNNo + "' Or ECNNo = 'N/A')";
                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                // daTemp.SelectCommand = cmmTemp
                                ExecuteSQLQuery_Adapter(strSQL, dsTemp, "OPAttrib", cnnTemp);

                                // drTemp.Close()

                                foreach (DataRow drAttrib in dsTemp.Tables["OPAttrib"].Rows)
                                {
                                    // 變更DefaultValue
                                    if (drAttrib["AttribValue"] is DBNull)
                                    {
                                        AttribValue = "";
                                    }
                                    else
                                    {
                                        switch (drAttrib["AttribValue"].ToString().ToUpper())
                                        {
                                            case "NOW":
                                                {
                                                    AttribValue = iMES_Format_Date(DateTime.Now, strDataBaseType);
                                                    break;
                                                }

                                            case "LOT CURQTY":
                                                {
                                                    AttribValue = decCurQty.ToString();
                                                    break;
                                                }

                                            default:
                                                {
                                                    // 2010/11/25 YF, 預設值若是#GetSpec, 故需傳入ProductNo
                                                    AttribValue = Convert.ToString(objLot.ChangeDefaultValue(drAttrib["AttribValue"].ToString(), MLotNo, ProductNo: drSelMLot[0]["ProductNo"].ToString()));
                                                    break;
                                                }
                                        }
                                    }

                                    // Temp
                                    // 2016/01/27 YF, 加入OrgAttribValue, 將AttribNo保留在OrgAttribValue, 在挑選設備時可判斷#GetEQPRecipe
                                    strSQL = "Insert into tblWIPTemp_Attrib(LotNo, AttribType, EquipmentType, AttribNo, AttribSource, AttribPhase, " + " AttribSequence, AttribValue, QCItemNo, OrgAttribValue, SaveToLotPropertyNo)" + " Values('" + MLotNo + "', 0,'" +
                                        drAttrib["EquipmentType"] + "','" + drAttrib["AttribNo"] + "'," + drAttrib["AttribSource"] + "," + drAttrib["AttribPhase"] +
                                        "," + drAttrib["AttribSequence"] + ",'" + AttribValue + "','" + drAttrib["QCItemNo"] + "','" + drAttrib["AttribValue"] + "'";
                                    if (drAttrib["SaveToLotPropertyNo"] is DBNull)
                                    {
                                        strSQL = strSQL + ",'N/A')";
                                    }
                                    else
                                    {
                                        strSQL = strSQL + ",'" + drAttrib["SaveToLotPropertyNo"] + "')".ToString();
                                    }
                                    CollectionSQL.Add(strSQL);

                                    // Content
                                    strSQL = "Insert into tblWIPCont_Attrib(LotSerial,EquipmentType,AttribNo,AttribValue,LogGroupSerial)" + " Values('" + MNewLotSerial + "','" +
                                        drAttrib["EquipmentType"] + "','" + drAttrib["AttribNo"] + "','" + AttribValue + "','" + OPNo + "')";
                                    CollectionSQL.Add(strSQL);

                                    // Lot Property(因之後都以Update的方式更新,故在此先將 TableType=0 的Property,Insert至tblWIPLotProperty)
                                    if (!(drAttrib["SaveToLotPropertyNo"] is DBNull))
                                    {
                                        // 檢查是否已新增過
                                        if (aryLotProperty.IndexOf(Strings.UCase(drAttrib["SaveToLotPropertyNo"].ToString())) < 0)
                                        {
                                            strSQL = "Select PropertyNo From tblSYSLotPropertyBasis " + " Where PropertyNo = '" +
                                                drAttrib["SaveToLotPropertyNo"] + "'" + " And TableType = 0 " + " And PropertyNo Not In(Select PropertyNo From tblWIPLotProperty " +
                                                " Where LotNo = '" + MLotNo + "'" + " And PropertyNo ='" + drAttrib["SaveToLotPropertyNo"] + "')";
                                            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                            if (drTemp.Read())   // 沒有存在,故須Insert
                                            {
                                                // 因PropertyNo允許大小寫資料,故不可任意轉換,會無法取得資料
                                                strSQL = "Insert into tblWIPLotProperty (LotNo, PropertyNo, PropertyValue)" + " Values('" + MLotNo + "','" +
                                                    drTemp["PropertyNo"] + "','')";
                                                CollectionSQL.Add(strSQL);
                                                aryLotProperty.Add(Strings.UCase(drAttrib["SaveToLotPropertyNo"].ToString()));
                                            }
                                            drTemp.Close();

                                        }
                                    }
                                }

                                // 更新tblWIPLotLog_Report的ECNNo
                                strSQL = "Update tblWIPLotLog_Report Set  ECNNO_OP = '" + strECNNo + "'" + " Where LotNo='" + MLotNo + "' " + " And OPNo='" + OPNo + "'" + " And LoggroupSerial='" + MLogGroupSerial + "'";
                                CollectionSQL.Add(strSQL);
                            }
                        }
                    }

                    drSel = dtSplitLot.Select("SplitLotNo ='" + MLotNo + "'");
                    // 2020/11/9,Ning,0081028: [6.0.5]分批處理，產品變更/流程變更調整, 母批跳流程
                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drSel[0]["Action"], 1, false)) || Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drSel[0]["Action"], 2, false)))
                    {
                        objLot.SetLotStateToNextOP(LotStamp, MLotNo, Convert.ToString(drSel[0]["NodeID"]), EventUserNo: UserNo, EventDescription: EventDescription, colSQL: CollectionSQL, RefLotNo: MLotNo, NewProductNo: Convert.ToString(drSel[0]["ProductNo"]), NewProductVersion: Convert.ToString(drSel[0]["ProductVersion"]));
                        if (blnIsIC_PKG && blnECN && Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drSel[0]["Action"], 2, false)))
                        {

                            var dsECN = new DataSet();
                            var dtECN = new DataTable();
                            dtECN.Columns.Add(new DataColumn("LotNo", Type.GetType("System.String")));
                            dtECN.Columns.Add(new DataColumn("OrgLotNo", Type.GetType("System.String")));
                            dtECN.Columns.Add(new DataColumn("CustomerLotNo", Type.GetType("System.String")));
                            dtECN.Columns.Add(new DataColumn("MONo", Type.GetType("System.String")));

                            drAdd = dtECN.NewRow();
                            drAdd["LotNo"] = MLotNo;
                            drAdd["OrgLotNo"] = dsTemp.Tables["LotState"].Rows[0]["OrgLotNo"].ToString();
                            drAdd["CustomerLotNo"] = dsTemp.Tables["LotState"].Rows[0]["CustomerLotNo"].ToString();
                            drAdd["MONo"] = dsTemp.Tables["LotState"].Rows[0]["MONo"].ToString();
                            dtECN.Rows.Add(drAdd);

                            // 依NodeID取得ProcessNo, ProcessVersion, NodeNo
                            strSQL = "Select ProcessNo, ProcessVersion, NodeNo From tblPRSNodeBasis Where NodeID = '" +
                                drSel[0]["NodeID"] + "'";
                            // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                            if (drTemp.Read())
                            {
                                ProcessNo = drTemp["ProcessNo"].ToString();
                                ProcessVersion = drTemp["ProcessVersion"].ToString();
                            }
                            else
                            {
                                throw new iMESException.MESException("0000-200003", "NodeBasis of NodeID:" +
                                    drSel[0]["NodeID"] + " is not exist!");
                            }
                            drTemp.Close();


                            // 取得流程各站的ECNNo_OP
                            dsECN = objLot.ShowECNOPData(drSel[0]["ProductNo"].ToString(), drSel[0]["ProductVersion"].ToString(), dtECN, ProcessNo, ProcessVersion);

                            // 先刪
                            strSQL = "Delete From TBLWIPLOTOPECNRECORD where LotNo='" + MLotNo + "'";
                            CollectionSQL.Add(strSQL);

                            foreach (DataRow drECN in dsECN.Tables[0].Rows)
                            {
                                strSQL = "Insert into TBLWIPLotOPECNRecord(LotNo,OPNo,ECNNo_OP,Creator,CreateDate,ECNType,AreaNo) " + "Values('" + MLotNo + "','" + drECN["OPNo"].ToString() + "','" + drECN["ECNNo"].ToString() + "','" + UserNo + "', " + " To_Date('" + Strings.Format(datEventTime, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'),'" + drECN["ECNType"].ToString() + "','" + drECN["AreaNo"].ToString() + "')";
                                CollectionSQL.Add(strSQL);
                            }

                            if (dsECN != null)
                                dsECN = null;
                        }
                    }
                    // =====94661,生產批歷程 Phase II LotState變更紀錄
                    var objChangeData = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData.clsChangeLot();
                    objChangeData.SplitType = SplitType;
                    objChangeData.FromLotNo = MLotNo;
                    objChangeData.FromLotSerial = MLotSerial;
                    objChangeData.ToLotNo = MLotNo;
                    objChangeData.ToLotSerial = MNewLotSerial;
                    var clsLotData = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData();
                    clsLotData.ProductNo = dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString();
                    clsLotData.ProductVersion = dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString();
                    clsLotData.CurQty = MCurQty;
                    clsLotData.CurUnitNo = dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"].ToString();
                    clsLotData.SysQty = SysQty;
                    clsLotData.SysUnitNo = dsTemp.Tables["LotState"].Rows[0]["SysUnitNo"].ToString();
                    if (drSel[0]["OPNo"].ToString() != dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString() || drSel[0]["NodeId"].ToString() != dsTemp.Tables["LotState"].Rows[0]["NodeId"].ToString())
                    {
                        clsLotData.OPNo = drSel[0]["OPNo"].ToString();
                        clsLotData.NodeId = drSel[0]["NodeID"].ToString();
                    }
                    else
                    {
                        clsLotData.OPNo = dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString();
                        clsLotData.NodeId = dsTemp.Tables["LotState"].Rows[0]["NodeId"].ToString();
                    }
                    objLotLog.funCreateSQL(clsLotData, ChangeLotData: objChangeData, LotNo: MLotNo, LotSerial: MNewLotSerial, LogGroupSerial: MLogGroupSerial, SysActiveId: 4, ReferenceLotNo: MLotNo);
                    // ===
                    // === 2021/09/08 Troy mantis:94662 生產批下線後執行動作紀錄 phase III 改產品
                    if (blnChgProduct == true)
                    {
                        var objChangeProduct = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData.clsChangeProduct();
                        var clsLotData2 = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData();
                        objChangeProduct.FromProductNo = dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString();
                        objChangeProduct.FromProductVersion = dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString();
                        objChangeProduct.ToProductNo = drSelMLot[0]["ProductNo"].ToString();
                        objChangeProduct.ToProductVersion = drSelMLot[0]["ProductVersion"].ToString();
                        objChangeProduct.ChangePRDType = 4;
                        clsLotData2.ProductNo = drSelMLot[0]["ProductNo"].ToString();
                        clsLotData2.ProductVersion = drSelMLot[0]["ProductVersion"].ToString();
                        clsLotData2.CurQty = MCurQty;
                        clsLotData2.CurUnitNo = dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"].ToString();
                        clsLotData2.SysQty = SysQty;
                        clsLotData2.SysUnitNo = dsTemp.Tables["LotState"].Rows[0]["SysUnitNo"].ToString();
                        if (drSelMLot[0]["OPNo"].ToString() != dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString() || drSelMLot[0]["NodeId"].ToString() != dsTemp.Tables["LotState"].Rows[0]["NodeId"].ToString())
                        {
                            clsLotData2.OPNo = drSelMLot[0]["OPNo"].ToString();
                            clsLotData2.NodeId = drSelMLot[0]["NodeID"].ToString();
                        }
                        else
                        {
                            clsLotData2.OPNo = dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString();
                            clsLotData2.NodeId = dsTemp.Tables["LotState"].Rows[0]["NodeId"].ToString();
                        }
                        objLotLog.funCreateSQL(clsLotData2, ChangeProductData: objChangeProduct, LotNo: MLotNo, LotSerial: MNewLotSerial, LogGroupSerial: dsTemp.Tables["LotState"].Rows[0]["LogGroupSerial"].ToString(), SysActiveId: 6, ReferenceLotNo: MLotNo);
                        blnChgProduct = false;
                    }
                    // ===
                    // 派工處理,子批有繼承母批批號,不須做任何處理
                    // 母批已處理完成,將母批移除
                    drSel = dtSplitLot.Select("SplitLotNo ='" + MLotNo + "'");
                    dtSplitLot.Rows.Remove(drSel[0]);
                    dtSplitLot.AcceptChanges();

                    if (intOPStatus == 1) // 站中,產生一筆對應的LotLog
                    {
                        strSQL = "Insert into tblWIPLotLog (LogGroupSerial,LotNo,LotSerial,OPNo,NodeID,BaseLotNo,StartTime,EndTime,Status,AreaNo,ModuleNo,ModuleVersion,OPGroupNo) " + " Values ('" +
                            dsTemp.Tables["LotState"].Rows[0]["LogGroupSerial"] + "','" + MLotNo + "','" + MNewLotSerial + "','" + dsTemp.Tables["LotState"].Rows[0]["OPNo"] +
                            "','" + dsTemp.Tables["LotState"].Rows[0]["NodeId"] + "','" + dsTemp.Tables["LotState"].Rows[0]["BaseLotNo"] + "'," + "To_Date('" + Strings.Format(datEventTime, "yyyy/MM/dd H:mm:ss") +
                            "','YYYY/MM/DD HH24:MI:SS')," + "To_Date('" + Strings.Format(datEventTime, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'), 0, '" +
                            dsTemp.Tables["LotState"].Rows[0]["AreaNo"] + "','" + dsTemp.Tables["LotState"].Rows[0]["ModuleNo"] + "','" + dsTemp.Tables["LotState"].Rows[0]["ModuleVersion"] +
                            "', '" + dsTemp.Tables["LotState"].Rows[0]["OPGroupNo"] + "')";
                        CollectionSQL.Add(strSQL);
                    }

                    if (blnWIPInv)
                    {
                        // 更新母批分批數量
                        strSQL = "Update tblINVWIPInventory_Semi Set QTY = " + MCurQty;
                        strSQL += "  Where InventoryNo = '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["INVENTORYNO"].ToString() + "'";
                        strSQL += "   And  LotNo = '" + MLotNo + "'";
                        CollectionSQL.Add(strSQL);

                        // 2019/04/25 Lena, 在製品庫分批且生產批狀態已為99結批,不建立還原點
                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dsTemp.Tables["LotState"].Rows[0]["LotState"], 99, false)))
                        {
                            // Undo
                            strSQL = "Update tblINVWIPInventory_Semi Set QTY = " + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["QTY"].ToString();
                            strSQL += "  Where InventoryNo = '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["INVENTORYNO"].ToString() + "'";
                            strSQL += "   And  LotNo = '" + MLotNo + "'";
                            Collection argcolSQL_Rows1 = null;
                            objReverse.AddReverseUpdateContent(ref MNewLotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows1);
                        }
                    }
                }

                // 併回,在併回處理未刪除.

                // 多人加工不需做任何處理.
                else
                {
                    decimal decFinalFailQty = defInteger;

                    if (intOPStatus == 1)
                    {
                        // 不要ReleaseEQP,子批仍在使用.
                        decimal FinalGoodQtyTmp = defInteger, FinalFailQtyTmp = defInteger;
                        objLot.EndOP(ref FinalGoodQtyTmp, ref decFinalFailQty, MLotNo, MNewLotSerial, datEventTime, CollectionSQL, UserNo, EventDescription: EventDescription, CalculateEMP: false);

                        // 2011/11/07 YF, 因母批在站中, 且不保留母批, EndOP也未ReleaseEQP, 故另外計算母批人時機時***********************************
                        // Call SHR_CalculateResource(MLotNo, MLogGroupSerial, MLotSerial, MNewLotSerial, UserNo, datEventTime, cnnTemp, CollectionSQL, , dsTemp.Tables("LotState").Rows(0)("CurQty"))

                        // 2017/12/01,Sammi.人時AutoRun平攤需求,將上工下工資料,整合入舊的多人加工機制.
                        // 2018/04/24,Sammi.分批時,結算人時允許無上下工資料.
                        using (var obj = new kcWIP.clsOperatorState())
                        {
                            var locCollectionSQL_Rows = new Collection();
                            obj.SHR_CO_EMP(ref cnnTemp, ref CollectionSQL, ref locCollectionSQL_Rows, ref objReverse, UserNo, datEventTime, datEventTime, MLotNo, Convert.ToDecimal(dsTemp.Tables["LotState"].Rows[0]["CurQty"]), NewLotSerial: MNewLotSerial, EMPAllowPass: true);
                        }

                        objLot.SHR_COEquipment_N_Release(ref cnnTemp, ref CollectionSQL, MLotNo, MLogGroupSerial, MNewLotSerial, UserNo, datEventTime, InputQty: Convert.ToDecimal(dsTemp.Tables["LotState"].Rows[0]["CurQty"]));
                    }

                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dsTemp.Tables["LotState"].Rows[0]["OPReference"], 1, false)))
                    {
                        // 不正常結束,CompleteFlag=0.
                        objLot.EndModule(MLotNo, MNewLotSerial, datEventTime, CollectionSQL, EventUserNo: UserNo, EventDescription: EventDescription, CompleteFlag: 0, UnUpdateFailQty: decFinalFailQty);
                    }

                    // 2007/07/13,sammi.tblWIPLotBasis vs tblWIPLotState的對應方式.
                    // objDBCom.Split1To1,True:1對1(要檢查母批LotBasis是否要結批),False:1對多(不用檢查).
                    objLot.CloseLot(MLotNo, 100, CollectionSQL, objDBCom.Split1To1, MNewLotSerial, EventTime: datEventTime, EventUserNo: UserNo, EventDescription: EventDescription);
                    // === 2021/09/08 Troy mantis:94662 生產批下線後執行動作紀錄 phase III closeLot
                    objLotLog.funCreateSQL(new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData()
                    { ProductNo = dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString(), ProductVersion = dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString(), CurQty = Convert.ToDecimal(dsTemp.Tables["LotState"].Rows[0]["CurQty"]), CurUnitNo = Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"]), SysQty = Convert.ToDecimal(dsTemp.Tables["LotState"].Rows[0]["CurQty"]), SysUnitNo = Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["SysUnitNo"]), OPNo = Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["OPNo"]), NodeId = Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["NodeId"]), CloseType = 1 }, LotNo: MLotNo, LotSerial: MNewLotSerial, SysActiveId: 17, ReferenceLotNo: MLotNo);
                    // ===
                    // 派工處理,找出母批派工之設備
                    strSQL = "Select EquipmentNo From tblEMSDispatchState Where LotNo = '" + MLotNo + "'";
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (drTemp.Read()) // 是
                    {
                        // 將母批的派工資料拿掉,並重新取出Order
                        objLot.UpdEQPDispatch(Convert.ToString(drTemp["EquipmentNo"]), MLotNo, MNewLotSerial, CollectionSQL);
                    }
                    drTemp.Close();

                }

                // 6.子批----------------------------------------------------------------------------------------------------------------
                string NewBaseLotNo = "";
                decimal decSLotSysQty = defInteger;

                var loopTo1 = dtSplitLot.Rows.Count - 1;
                for (i = 0; i <= loopTo1; i++)
                {
                    SLotNo = dtSplitLot.Rows[i]["SplitLotNo"].ToString().ToUpper();
                    SLotSerial = objLot.InitLotSerial(SLotNo);

                    // 2019/04/25 Lena, 在製品庫分批且生產批狀態已為99結批,不建立還原點
                    if (!blnWIPInv || Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dsTemp.Tables["LotState"].Rows[0]["LotState"], 99, false)))
                    {
                        var tmp5 = dsTemp.Tables["LotState"].Rows[0];
                        string argOPNo1 = tmp5["OPNo"].ToString();
                        udReverse.clsReverse.ReverseType revTypeTmp = udReverse.clsReverse.ReverseType.Split_To;
                        SReverseId = objReverse.NewReverseID(ref SLotNo, ref revTypeTmp, ref SLotSerial, ref argOPNo1, ref CollectionSQL, Description: "BR Manual Split(To Lot)", Creator: UserNo, CreateDate: datEventTime);
                        tmp5["OPNo"] = argOPNo1;
                    }


                    if (blnHaveSysQty)
                    {
                        decSLotSysQty = Convert.ToDecimal(dtSplitLot.Rows[i]["SplitSysQty"]);
                    }
                    // === 2021/09/08 Troy mantis:94662 生產批下線後執行動作紀錄 phase III
                    string NewLotGroupSerial = "";
                    if (!string.IsNullOrEmpty(NewLotGroupSerial))
                    {
                        NewLotGroupSerial = null;
                    }
                    bool blnChgProduct = false;
                    // ===
                    int iAction = -1;
                    if (!int.TryParse(dtSplitLot.Rows[i]["Action"].ToString(), out iAction))
                        iAction = -1;
                    switch (iAction)
                    {
                        case 0:  // Go
                            {
                                if (intOPStatus == 1)
                                {
                                    if (SplitType == 1)   // BR分批
                                    {
                                        if (LinkName == "HOLD")
                                        {
                                            var tmp6 = dtSplitLot.Rows[i];
                                            decimal argNewLotCurQty = Convert.ToDecimal(tmp6["SplitLotQty"]);
                                            var tmp7 = dtSplitLot.Rows[i];
                                            int argNewReturnType = Conversions.ToInteger(tmp7["ReturnType"]);
                                            int argNewStatus = 3;
                                            bool argTriggerOP = true;
                                            string argLinkName = "HOLD";
                                            var tmp8 = dsTemp.Tables;
                                            var argdtLotState1 = tmp8["LotState"];
                                            var tmp9 = dsTemp.Tables;
                                            var argdtLotProperty1 = tmp9["LotProperty"];
                                            var tmp10 = dsTemp.Tables;
                                            var argdtLotProcess = tmp10["LotProcess"];
                                            var tmp11 = dsTemp.Tables;
                                            var argdtOPGroupState = tmp11["OPGroupState"];
                                            var tmp12 = dsTemp.Tables;
                                            var argdtTempLotAttrib1 = tmp12["TempLotAttrib"];
                                            var tmp13 = dsTemp.Tables;
                                            var argdtTempMaterial = tmp13["TempMaterial"];
                                            var tmp14 = dsTemp.Tables;
                                            var argdtTempEquipment = tmp14["TempEquipment"];
                                            var tmp15 = dsTemp.Tables;
                                            var argdtTempQCItem = tmp15["TempQCItem"];
                                            var tmp16 = dsTemp.Tables;
                                            var argdtLotECNAttrib1 = tmp16["LotECNAttrib"];
                                            var tmp17 = dtSplitLot.Rows[i];
                                            string argNewProductNo = tmp17["ProductNo"].ToString();
                                            var tmp18 = dtSplitLot.Rows[i];
                                            string argNewProductVersion = tmp18["ProductVersion"].ToString();
                                            int argGoStatus = 4;
                                            decimal argNewLotSysQtyLog = -999m;

                                            bool NewLotBasisTmp = false;
                                            DataTable dtContAccTmp = null;
                                            objLot.NewLot_Split(ref NewLotBasisTmp, ref argGoStatus, ref NewLotGroupSerial, ref dtContAccTmp, ref NewBaseLotNo, ref argNewLotSysQtyLog,
                                                 MLotNo, MNewLotSerial, SLotNo, ref SLotSerial,
                                                 argNewLotCurQty, CollectionSQL, SerialNo, argNewReturnType, NewStatus: argNewStatus, TriggerOP: argTriggerOP, LinkName: argLinkName, dtLotState: argdtLotState1, dtLotProperty: argdtLotProperty1, dtLotProcess: argdtLotProcess, dtOPGroupState: argdtOPGroupState, dtTempLotAttrib: argdtTempLotAttrib1, dtTempMaterial: argdtTempMaterial, dtTempEquipment: argdtTempEquipment, dtTempQCItem: argdtTempQCItem, dtLotECNAttrib: argdtLotECNAttrib1, NewProductNo: argNewProductNo, NewProductVersion: argNewProductVersion,
                                                Creator: UserNo, datEventTime: datEventTime, NewLotSysQty: decSLotSysQty, SplitType: SplitType, blnIsIC_PKG: blnIsIC_PKG);
                                            tmp6["SplitLotQty"] = argNewLotCurQty;
                                            tmp7["ReturnType"] = argNewReturnType;
                                            tmp17["ProductNo"] = argNewProductNo;
                                            tmp18["ProductVersion"] = argNewProductVersion;
                                        }

                                        else if (LinkName == "WAIT")
                                        {
                                            var tmp33 = dtSplitLot.Rows[i];
                                            decimal argNewLotCurQty2 = Convert.ToDecimal(tmp33["SplitLotQty"]);
                                            var tmp34 = dtSplitLot.Rows[i];
                                            int argNewReturnType2 = Conversions.ToInteger(tmp34["ReturnType"]);
                                            int argNewStatus2 = 2;
                                            bool argTriggerOP2 = true;
                                            string argLinkName1 = "WAIT";
                                            var tmp35 = dsTemp.Tables;
                                            var argdtLotState3 = tmp35["LotState"];
                                            var tmp36 = dsTemp.Tables;
                                            var argdtLotProperty3 = tmp36["LotProperty"];
                                            var tmp37 = dsTemp.Tables;
                                            var argdtLotProcess2 = tmp37["LotProcess"];
                                            var tmp38 = dsTemp.Tables;
                                            var argdtOPGroupState2 = tmp38["OPGroupState"];
                                            var tmp39 = dsTemp.Tables;
                                            var argdtTempLotAttrib3 = tmp39["TempLotAttrib"];
                                            var tmp40 = dsTemp.Tables;
                                            var argdtTempMaterial2 = tmp40["TempMaterial"];
                                            var tmp41 = dsTemp.Tables;
                                            var argdtTempEquipment2 = tmp41["TempEquipment"];
                                            var tmp42 = dsTemp.Tables;
                                            var argdtTempQCItem2 = tmp42["TempQCItem"];
                                            var tmp43 = dsTemp.Tables;
                                            var argdtLotECNAttrib3 = tmp43["LotECNAttrib"];
                                            var tmp44 = dtSplitLot.Rows[i];
                                            string argNewProductNo2 = tmp44["ProductNo"].ToString();
                                            var tmp45 = dtSplitLot.Rows[i];
                                            string argNewProductVersion2 = tmp45["ProductVersion"].ToString();
                                            int argGoStatus1 = 4;
                                            decimal argNewLotSysQtyLog2 = -999m;

                                            bool NewLotBasisTmp = false;
                                            DataTable dtContAccTmp = null;
                                            objLot.NewLot_Split(ref NewLotBasisTmp, ref argGoStatus1, ref NewLotGroupSerial, ref dtContAccTmp, ref NewBaseLotNo, ref argNewLotSysQtyLog2,
                                                 MLotNo, MNewLotSerial, SLotNo, ref SLotSerial,
                                                 argNewLotCurQty2, CollectionSQL, SerialNo, argNewReturnType2, NewStatus: argNewStatus2, TriggerOP: argTriggerOP2, LinkName: argLinkName1, dtLotState: argdtLotState3, dtLotProperty: argdtLotProperty3, dtLotProcess: argdtLotProcess2, dtOPGroupState: argdtOPGroupState2, dtTempLotAttrib: argdtTempLotAttrib3, dtTempMaterial: argdtTempMaterial2, dtTempEquipment: argdtTempEquipment2, dtTempQCItem: argdtTempQCItem2, dtLotECNAttrib: argdtLotECNAttrib3, NewProductNo: argNewProductNo2, NewProductVersion: argNewProductVersion2,
                                                Creator: UserNo, datEventTime: datEventTime, NewLotSysQty: decSLotSysQty, SplitType: SplitType, blnIsIC_PKG: blnIsIC_PKG);
                                            tmp33["SplitLotQty"] = argNewLotCurQty2;
                                            tmp34["ReturnType"] = argNewReturnType2;
                                            tmp44["ProductNo"] = argNewProductNo2;
                                            tmp45["ProductVersion"] = argNewProductVersion2;
                                        }
                                        else
                                        {
                                            // Status(4:代表成功完成BR,紀錄LinkName若TransferLot失敗可以重新再執行TransferLot)
                                            var tmp19 = dtSplitLot.Rows[i];
                                            decimal argNewLotCurQty1 = Convert.ToDecimal(tmp19["SplitLotQty"]);
                                            var tmp20 = dtSplitLot.Rows[i];
                                            int argNewReturnType1 = Conversions.ToInteger(tmp20["ReturnType"]);
                                            int argNewStatus1 = 4;
                                            bool argTriggerOP1 = true;
                                            var tmp21 = dsTemp.Tables;
                                            var argdtLotState2 = tmp21["LotState"];
                                            var tmp22 = dsTemp.Tables;
                                            var argdtLotProperty2 = tmp22["LotProperty"];
                                            var tmp23 = dsTemp.Tables;
                                            var argdtLotProcess1 = tmp23["LotProcess"];
                                            var tmp24 = dsTemp.Tables;
                                            var argdtOPGroupState1 = tmp24["OPGroupState"];
                                            var tmp25 = dsTemp.Tables;
                                            var argdtTempLotAttrib2 = tmp25["TempLotAttrib"];
                                            var tmp26 = dsTemp.Tables;
                                            var argdtTempMaterial1 = tmp26["TempMaterial"];
                                            var tmp27 = dsTemp.Tables;
                                            var argdtTempEquipment1 = tmp27["TempEquipment"];
                                            var tmp28 = dsTemp.Tables;
                                            var argdtTempQCItem1 = tmp28["TempQCItem"];
                                            var tmp29 = dsTemp.Tables;
                                            var argdtLotECNAttrib2 = tmp29["LotECNAttrib"];
                                            var tmp30 = dtSplitLot.Rows[i];
                                            string argNewProductNo1 = tmp30["ProductNo"].ToString();
                                            var tmp31 = dtSplitLot.Rows[i];
                                            string argNewProductVersion1 = tmp31["ProductVersion"].ToString();
                                            var tmp32 = dsTemp.Tables;
                                            var argdtLotLoginState = tmp32["LotLoginState"];
                                            decimal argNewLotSysQtyLog1 = -999m;

                                            bool NewLotBasisTmp = false;
                                            int GoStatusTmp = defInteger;
                                            DataTable dtContAccTmp = null;
                                            objLot.NewLot_Split(ref NewLotBasisTmp, ref GoStatusTmp, ref NewLotGroupSerial, ref dtContAccTmp, ref NewBaseLotNo, ref argNewLotSysQtyLog1,
                                                 MLotNo, MNewLotSerial, SLotNo, ref SLotSerial,
                                                 argNewLotCurQty1, CollectionSQL, SerialNo, argNewReturnType1, NewStatus: argNewStatus1, TriggerOP: argTriggerOP1, LinkName: LinkName, dtLotState: argdtLotState2, dtLotProperty: argdtLotProperty2, dtLotProcess: argdtLotProcess1, dtOPGroupState: argdtOPGroupState1, dtTempLotAttrib: argdtTempLotAttrib2, dtTempMaterial: argdtTempMaterial1, dtTempEquipment: argdtTempEquipment1, dtTempQCItem: argdtTempQCItem1, dtLotECNAttrib: argdtLotECNAttrib2, NewProductNo: argNewProductNo1, NewProductVersion: argNewProductVersion1,
                                                Creator: UserNo, datEventTime: datEventTime, NewLotSysQty: decSLotSysQty, dtLotLoginState: argdtLotLoginState, SplitType: SplitType, blnIsIC_PKG: blnIsIC_PKG);
                                            tmp19["SplitLotQty"] = argNewLotCurQty1;
                                            tmp20["ReturnType"] = argNewReturnType1;
                                            tmp30["ProductNo"] = argNewProductNo1;
                                            tmp31["ProductVersion"] = argNewProductVersion1;
                                        }
                                    }

                                    else // 站中手動分批
                                    {
                                        // 因目前狀態可能是complete,故須保留LinkName.
                                        // 2020/02/12 Eric Mantis:0067304(分批未繼承ECN) 補上傳入ECN繼承參數
                                        var tmp46 = dtSplitLot.Rows[i];
                                        decimal argNewLotCurQty3 = Convert.ToDecimal(tmp46["SplitLotQty"]);
                                        var tmp47 = dtSplitLot.Rows[i];
                                        int argNewReturnType3 = Conversions.ToInteger(tmp47["ReturnType"]);
                                        bool argTriggerOP3 = true;
                                        var tmp48 = dsTemp.Tables;
                                        var argdtLotState4 = tmp48["LotState"];
                                        var tmp49 = dsTemp.Tables;
                                        var argdtLotProperty4 = tmp49["LotProperty"];
                                        var tmp50 = dsTemp.Tables;
                                        var argdtLotProcess3 = tmp50["LotProcess"];
                                        var tmp51 = dsTemp.Tables;
                                        var argdtOPGroupState3 = tmp51["OPGroupState"];
                                        var tmp52 = dsTemp.Tables;
                                        var argdtTempLotAttrib4 = tmp52["TempLotAttrib"];
                                        var tmp53 = dsTemp.Tables;
                                        var argdtTempMaterial3 = tmp53["TempMaterial"];
                                        var tmp54 = dsTemp.Tables;
                                        var argdtTempEquipment3 = tmp54["TempEquipment"];
                                        var tmp55 = dsTemp.Tables;
                                        var argdtTempQCItem3 = tmp55["TempQCItem"];
                                        var tmp56 = dsTemp.Tables;
                                        var argdtLotECNAttrib4 = tmp56["LotECNAttrib"];
                                        var tmp57 = dtSplitLot.Rows[i];
                                        string argNewProductNo3 = tmp57["ProductNo"].ToString();
                                        var tmp58 = dtSplitLot.Rows[i];
                                        string argNewProductVersion3 = tmp58["ProductVersion"].ToString();
                                        var tmp59 = dsTemp.Tables;
                                        var argdtLotLoginState1 = tmp59["LotLoginState"];
                                        decimal argNewLotSysQtyLog3 = -999m;

                                        bool NewLotBasisTmp = false;
                                        int GoStatusTmp = defInteger;
                                        DataTable dtContAccTmp = null;
                                        objLot.NewLot_Split(ref NewLotBasisTmp, ref GoStatusTmp, ref NewLotGroupSerial, ref dtContAccTmp, ref NewBaseLotNo, ref argNewLotSysQtyLog3,
                                             MLotNo, MNewLotSerial, SLotNo, ref SLotSerial,
                                            argNewLotCurQty3, CollectionSQL, SerialNo, argNewReturnType3, TriggerOP: argTriggerOP3, LinkName: dsTemp.Tables["LotState"].Rows[0]["LinkName"].ToString(),
                                            dtLotState: argdtLotState4, dtLotProperty: argdtLotProperty4, dtLotProcess: argdtLotProcess3, dtOPGroupState: argdtOPGroupState3, dtTempLotAttrib: argdtTempLotAttrib4,
                                            dtTempMaterial: argdtTempMaterial3, dtTempEquipment: argdtTempEquipment3, dtTempQCItem: argdtTempQCItem3,
                                            dtLotECNAttrib: argdtLotECNAttrib4, NewProductNo: argNewProductNo3, NewProductVersion: argNewProductVersion3,
                                            Creator: UserNo, datEventTime: datEventTime, NewLotSysQty: decSLotSysQty, dtLotLoginState: argdtLotLoginState1, SplitType: SplitType, blnIsIC_PKG: blnIsIC_PKG);
                                        tmp46["SplitLotQty"] = argNewLotCurQty3;
                                        tmp47["ReturnType"] = argNewReturnType3;
                                        tmp57["ProductNo"] = argNewProductNo3;
                                        tmp58["ProductVersion"] = argNewProductVersion3;
                                    }
                                }

                                else // 站間手動分批
                                {
                                    // 因可能是臨時外包分批,故LinkName要繼承.
                                    // 2020/02/12 Eric Mantis:0067304(分批未繼承ECN) 補上傳入ECN繼承參數
                                    var tmp60 = dtSplitLot.Rows[i];
                                    decimal argNewLotCurQty4 = Convert.ToDecimal(tmp60["SplitLotQty"]);
                                    var tmp61 = dtSplitLot.Rows[i];
                                    int argNewReturnType4 = Conversions.ToInteger(tmp61["ReturnType"]);
                                    bool argTriggerOP4 = false;
                                    string argLinkName2 = dsTemp.Tables["LotState"].Rows[0]["LinkName"].ToString();
                                    var tmp62 = dsTemp.Tables;
                                    var argdtLotState5 = tmp62["LotState"];
                                    var tmp63 = dsTemp.Tables;
                                    var argdtLotProperty5 = tmp63["LotProperty"];
                                    var tmp64 = dsTemp.Tables;
                                    var argdtLotProcess4 = tmp64["LotProcess"];
                                    var tmp65 = dsTemp.Tables;
                                    var argdtOPGroupState4 = tmp65["OPGroupState"];
                                    var tmp66 = dsTemp.Tables;
                                    var argdtLotECNAttrib5 = tmp66["LotECNAttrib"];
                                    var tmp67 = dtSplitLot.Rows[i];
                                    string argNewProductNo4 = tmp67["ProductNo"].ToString();
                                    var tmp68 = dtSplitLot.Rows[i];
                                    string argNewProductVersion4 = tmp68["ProductVersion"].ToString();
                                    decimal argNewLotSysQtyLog4 = -999m;

                                    bool NewLotBasisTmp = false;
                                    int GoStatusTmp = defInteger;
                                    DataTable dtContAccTmp = null;
                                    objLot.NewLot_Split(ref NewLotBasisTmp, ref GoStatusTmp, ref NewLotGroupSerial, ref dtContAccTmp, ref NewBaseLotNo, ref argNewLotSysQtyLog4,
                                         MLotNo, MNewLotSerial, SLotNo, ref SLotSerial,
                                         argNewLotCurQty4, CollectionSQL, NewReturnType: argNewReturnType4, TriggerOP: argTriggerOP4, LinkName: argLinkName2, dtLotState: argdtLotState5, dtLotProperty: argdtLotProperty5, dtLotProcess: argdtLotProcess4, dtOPGroupState: argdtOPGroupState4, dtLotECNAttrib: argdtLotECNAttrib5, NewProductNo: argNewProductNo4, NewProductVersion: argNewProductVersion4,
                                        Creator: UserNo, datEventTime: datEventTime, NewLotSysQty: decSLotSysQty, SplitType: SplitType, blnIsIC_PKG: blnIsIC_PKG);
                                    tmp60["SplitLotQty"] = argNewLotCurQty4;
                                    tmp61["ReturnType"] = argNewReturnType4;
                                    tmp67["ProductNo"] = argNewProductNo4;
                                    tmp68["ProductVersion"] = argNewProductVersion4;
                                }


                                // 檢查是否為倉庫分批
                                if (blnWIPInv)
                                {
                                    // 目前規則一批只能出現在一個庫房
                                    if (dsTemp.Tables["WIPInv_RefLot"] != null && dsTemp.Tables["WIPInv_RefLot"].Rows.Count == 1)
                                    {

                                        // 將資訊複製給子批
                                        strSQL = "INSERT INTO tblINVWIPInventory_Semi (INVENTORYNO,PRODUCTNO,LOTNO, ";
                                        strSQL += "UNITNO,QTY,INPUTDATE,BASELOTNO,BOUGHTEN,BOOKINGFLAG,PRODUCTVERSION) ";
                                        strSQL += "  VALUES   ('" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["INVENTORYNO"].ToString() + "', ";
                                        strSQL += " '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["PRODUCTNO"].ToString() + "', ";
                                        strSQL += " '" + SLotNo + "', ";
                                        strSQL += " '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["UNITNO"].ToString() + "', ";
                                        strSQL = strSQL + "  " + dtSplitLot.Rows[i]["SplitLotQty"] + ", ".ToString();
                                        strSQL += " TO_DATE('" + Strings.Format(dsTemp.Tables["WIPInv_RefLot"].Rows[0]["INPUTDATE"], "yyyy/MM/dd HH:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'), ";
                                        strSQL += " '" + NewBaseLotNo + "',";
                                        strSQL += "  " + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["BOUGHTEN"].ToString() + ", ";
                                        strSQL += "  " + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["BOOKINGFLAG"].ToString() + ", ";
                                        strSQL += " '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["PRODUCTVERSION"].ToString() + "')";

                                        SQLCommandTuning(DataBaseType, ref strSQL);
                                        CollectionSQL.Add(strSQL);

                                        // 2019/04/25 Lena, 在製品庫分批且生產批狀態已為99結批,不建立還原點
                                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dsTemp.Tables["LotState"].Rows[0]["LotState"], 99, false)))
                                        {
                                            // Undo
                                            strSQL = "Delete From tblINVWIPInventory_Semi Where InventoryNo = '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["INVENTORYNO"].ToString() + "'" + " And LotNo = '" + SLotNo + "'";
                                            Collection argcolSQL_Rows2 = null;
                                            objReverse.AddReverseUpdateContent(ref SLotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows2);
                                        }

                                    }

                                }
                                break;
                            }


                        case 1:
                        case 2: // Jump OP,Jump Process '2020/02/12 Eric Mantis:0067304(分批未繼承ECN) 補上傳入ECN繼承參數
                            {
                                var tmp69 = dtSplitLot.Rows[i];
                                decimal argNewLotCurQty5 = Convert.ToDecimal(tmp69["SplitLotQty"]);
                                var tmp70 = dtSplitLot.Rows[i];
                                int argNewReturnType5 = Conversions.ToInteger(tmp70["ReturnType"]);
                                var tmp71 = dtSplitLot.Rows[i];
                                string argNewNodeId = tmp71["NodeID"].ToString();
                                int argNewStatus3 = 0;
                                bool argTriggerOP5 = false;
                                var tmp72 = dsTemp.Tables;
                                var argdtLotState6 = tmp72["LotState"];
                                var tmp73 = dsTemp.Tables;
                                var argdtLotProperty6 = tmp73["LotProperty"];
                                var tmp74 = dsTemp.Tables;
                                var argdtLotProcess5 = tmp74["LotProcess"];
                                var tmp75 = dsTemp.Tables;
                                var argdtOPGroupState5 = tmp75["OPGroupState"];
                                var tmp76 = dsTemp.Tables;
                                var argdtLotECNAttrib6 = tmp76["LotECNAttrib"];
                                var tmp77 = dtSplitLot.Rows[i];
                                string argNewProductNo5 = tmp77["ProductNo"].ToString();
                                var tmp78 = dtSplitLot.Rows[i];
                                string argNewProductVersion5 = tmp78["ProductVersion"].ToString();
                                decimal argNewLotSysQtyLog5 = -999m;

                                bool NewLotBasisTmp = false;
                                int GoStatusTmp = defInteger;
                                DataTable dtContAccTmp = null;
                                objLot.NewLot_Split(ref NewLotBasisTmp, ref GoStatusTmp, ref NewLotGroupSerial, ref dtContAccTmp, ref NewBaseLotNo, ref argNewLotSysQtyLog5,
                                     MLotNo, MNewLotSerial, SLotNo, ref SLotSerial,
                                     argNewLotCurQty5, CollectionSQL, NewReturnType: argNewReturnType5, NewNodeId: argNewNodeId, NewStatus: argNewStatus3, TriggerOP: argTriggerOP5, dtLotState: argdtLotState6, dtLotProperty: argdtLotProperty6, dtLotProcess: argdtLotProcess5, dtOPGroupState: argdtOPGroupState5, dtLotECNAttrib: argdtLotECNAttrib6, NewProductNo: argNewProductNo5, NewProductVersion: argNewProductVersion5,
                                    Creator: UserNo, datEventTime: datEventTime, NewLotSysQty: decSLotSysQty, SplitType: SplitType, blnIsIC_PKG: blnIsIC_PKG);
                                tmp69["SplitLotQty"] = argNewLotCurQty5;
                                tmp70["ReturnType"] = argNewReturnType5;
                                tmp71["NodeID"] = argNewNodeId;
                                tmp77["ProductNo"] = argNewProductNo5;
                                tmp78["ProductVersion"] = argNewProductVersion5;
                                break;
                            }
                    }


                    drAdd = dtSplitCont.NewRow();
                    drAdd["ToLotNo"] = SLotNo;
                    drAdd["ToBaseLotNo"] = NewBaseLotNo;
                    drAdd["ToLotSerial"] = SLotSerial;
                    drAdd["ToReverseId"] = SReverseId;
                    drAdd["ToLotQty"] = dtSplitLot.Rows[i]["SplitLotQty"];
                    if (!blnHaveFromLot && i == 0)
                    {
                        drAdd["MajorLot"] = 1;
                    }
                    else
                    {
                        drAdd["MajorLot"] = 0;
                    }
                    dtSplitCont.Rows.Add(drAdd);

                    // 併回
                    if (blnAutoMerge)
                    {
                        strSQL = "Insert into tblWIPAutoMerge(FromLotNo,ToLotNo) Values ('" + SLotNo + "','" + AutoMergeToLotNo + "')";
                        CollectionSQL.Add(strSQL);
                    }

                    // 2020/11/9 Ning	0081028: [6.0.5]分批處理，產品變更/流程變更調整
                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dtSplitLot.Rows[i]["ProductNo"], dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString(), false)) || Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dtSplitLot.Rows[i]["ProductVersion"], dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString(), false)))
                    {
                        // 取得欲變更的產品單位
                        string strUnitNo = "";
                        strSQL = "Select * From tblPRDProductBasis Where ProductNo ='" +
                            dtSplitLot.Rows[i]["ProductNo"] + "' And ProductVersion='" + dtSplitLot.Rows[i]["ProductVersion"] + "' ";
                        // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                        drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                        if (drTemp.Read())
                        {
                            strUnitNo = drTemp["UnitNo"].ToString();
                        }
                        drTemp.Close();


                        // 變更產品
                        objLot.ChgProductOperation_SplitLot(SLotNo, UserNo, Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["ProductNo"]), Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["ProductVersion"]), Convert.ToString(dtSplitLot.Rows[i]["ProductNo"]), Convert.ToString(dtSplitLot.Rows[i]["ProductVersion"]), strUnitNo, CollectionSQL, RefLotNo: MLotNo, colToINVLotNo: colToINVLotNo);
                        // 若是跳流程, 需以跳流程的流程為最終流程
                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dtSplitLot.Rows[i]["Action"], 1, false)) || Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dtSplitLot.Rows[i]["Action"], 2, false)))
                        {
                            objLot.SetLotStateToNextOP(LotStamp, SLotNo, Convert.ToString(dtSplitLot.Rows[i]["NodeID"]), EventUserNo: UserNo, EventDescription: EventDescription, colSQL: CollectionSQL, RefLotNo: MLotNo, NewProductNo: Convert.ToString(dtSplitLot.Rows[i]["ProductNo"]), NewProductVersion: Convert.ToString(dtSplitLot.Rows[i]["ProductVersion"]));

                            if (blnIsIC_PKG && blnECN && Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(dtSplitLot.Rows[i]["Action"], 2, false)))
                            {

                                string ProcessNo, ProcessVersion;
                                var dsECN = new DataSet();
                                var dtECN = new DataTable();
                                dtECN.Columns.Add("LotNo", Type.GetType("System.String"));
                                dtECN.Columns.Add("OrgLotNo", Type.GetType("System.String"));
                                dtECN.Columns.Add("CustomerLotNo", Type.GetType("System.String"));
                                dtECN.Columns.Add("MONo", Type.GetType("System.String"));

                                drAdd = dtECN.NewRow();
                                drAdd["LotNo"] = SLotNo;
                                drAdd["OrgLotNo"] = dsTemp.Tables["LotState"].Rows[0]["OrgLotNo"].ToString();
                                drAdd["CustomerLotNo"] = dsTemp.Tables["LotState"].Rows[0]["CustomerLotNo"].ToString();
                                drAdd["MONo"] = dsTemp.Tables["LotState"].Rows[0]["MONo"].ToString();
                                dtECN.Rows.Add(drAdd);

                                // 依NodeID取得ProcessNo, ProcessVersion, NodeNo
                                strSQL = "Select ProcessNo, ProcessVersion, NodeNo From tblPRSNodeBasis Where NodeID = '" +
                                    dtSplitLot.Rows[i]["NodeID"] + "'";
                                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                                if (drTemp.Read())
                                {
                                    ProcessNo = drTemp["ProcessNo"].ToString();
                                    ProcessVersion = drTemp["ProcessVersion"].ToString();
                                }
                                else
                                {
                                    throw new iMESException.MESException("0000-200003", "NodeBasis of NodeID:" +
                                        dtSplitLot.Rows[i]["NodeID"] + " is not exist!");
                                }
                                drTemp.Close();


                                // 取得流程各站的ECNNo_OP
                                dsECN = objLot.ShowECNOPData(dtSplitLot.Rows[i]["ProductNo"].ToString(), dtSplitLot.Rows[i]["ProductVersion"].ToString(), dtECN, ProcessNo, ProcessVersion);

                                // 先刪
                                strSQL = "Delete From TBLWIPLOTOPECNRECORD where LotNo='" + SLotNo + "'";
                                CollectionSQL.Add(strSQL);

                                foreach (DataRow drECN in dsECN.Tables[0].Rows)
                                {
                                    strSQL = "Insert into TBLWIPLotOPECNRecord(LotNo,OPNo,ECNNo_OP,Creator,CreateDate,ECNType,AreaNo) " + "Values('" + SLotNo + "','" + drECN["OPNo"].ToString() + "','" + drECN["ECNNo"].ToString() + "','" + UserNo + "', " + " To_Date('" + Strings.Format(datEventTime, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'),'" + drECN["ECNType"].ToString() + "','" + drECN["AreaNo"].ToString() + "')";
                                    CollectionSQL.Add(strSQL);
                                }

                                if (dsECN != null)
                                    dsECN = null;
                            }
                        }
                        blnChgProduct = true;
                    }
                    // =====94661,生產批歷程 Phase II 分批紀錄
                    var objChangeData = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData.clsChangeLot();
                    objChangeData.SplitType = SplitType;
                    objChangeData.FromLotNo = MLotNo;
                    objChangeData.FromLotSerial = MNewLotSerial;
                    objChangeData.ToLotNo = SLotNo;
                    objChangeData.ToLotSerial = SLotSerial;
                    var clsLotDataSplit = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData();
                    clsLotDataSplit.ProductNo = dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString();
                    clsLotDataSplit.ProductVersion = dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString();
                    clsLotDataSplit.CurQty = Convert.ToDecimal(dtSplitLot.Rows[i]["SplitLotQty"]);
                    clsLotDataSplit.CurUnitNo = dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"].ToString();
                    clsLotDataSplit.SysQty = decSLotSysQty;
                    clsLotDataSplit.SysUnitNo = dsTemp.Tables["LotState"].Rows[0]["SysUnitNo"].ToString();
                    if (dtSplitLot.Rows[i]["OPNo"].ToString() != dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString() || dtSplitLot.Rows[i]["NodeId"].ToString() != dsTemp.Tables["LotState"].Rows[0]["NodeId"].ToString())
                    {
                        clsLotDataSplit.OPNo = dtSplitLot.Rows[i]["OPNo"].ToString();
                        clsLotDataSplit.NodeId = dtSplitLot.Rows[i]["NodeId"].ToString();
                    }
                    else
                    {
                        clsLotDataSplit.OPNo = dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString();
                        clsLotDataSplit.NodeId = dsTemp.Tables["LotState"].Rows[0]["NodeId"].ToString();
                    }
                    clsLotDataSplit.LotStamp = 0;
                    objLotLog.funCreateSQL(clsLotDataSplit, ChangeLotData: objChangeData, LotNo: SLotNo, LotSerial: SLotSerial, LogGroupSerial: NewLotGroupSerial, SysActiveId: 4, ReferenceLotNo: MLotNo);
                    // ===
                    // === 2021/09/08 Troy mantis:94662 生產批下線後執行動作紀錄 phase III 產品變更紀錄
                    if (blnChgProduct == true)
                    {
                        var ChangeProduct = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData.clsChangeProduct();
                        ChangeProduct.FromProductNo = dsTemp.Tables["LotState"].Rows[0]["ProductNo"].ToString();
                        ChangeProduct.FromProductVersion = dsTemp.Tables["LotState"].Rows[0]["ProductVersion"].ToString();
                        ChangeProduct.ToProductNo = dtSplitLot.Rows[i]["ProductNo"].ToString();
                        ChangeProduct.ToProductVersion = dtSplitLot.Rows[i]["ProductVersion"].ToString();
                        ChangeProduct.ChangePRDType = 4;
                        var clsLotData3 = new iMESWIPReleaseLogHandler.clsLotReleaseLogHandle.clsLotData();
                        clsLotData3.ProductNo = dtSplitLot.Rows[i]["ProductNo"].ToString();
                        clsLotData3.ProductVersion = dtSplitLot.Rows[i]["ProductVersion"].ToString();
                        clsLotData3.CurQty = Convert.ToDecimal(dtSplitLot.Rows[i]["SplitLotQty"]);
                        clsLotData3.CurUnitNo = dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"].ToString();
                        clsLotData3.SysQty = Convert.ToDecimal(dtSplitLot.Rows[i]["SplitLotQty"]);
                        clsLotData3.SysUnitNo = dsTemp.Tables["LotState"].Rows[0]["SysUnitNo"].ToString();
                        clsLotData3.LotStamp = 0;
                        // === 2021/09/08 Troy mantis:94662 生產批下線後執行動作紀錄 phase III 
                        if (dtSplitLot.Rows[i]["OPNo"].ToString() != dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString() || dtSplitLot.Rows[i]["NodeID"].ToString() != dsTemp.Tables["LotState"].Rows[0]["NodeID"].ToString())
                        {
                            clsLotData3.OPNo = dtSplitLot.Rows[i]["OPNo"].ToString();
                            clsLotData3.NodeId = dtSplitLot.Rows[i]["NodeId"].ToString();
                        }
                        else
                        {
                            clsLotData3.OPNo = dsTemp.Tables["LotState"].Rows[0]["OPNo"].ToString();
                            clsLotData3.NodeId = dsTemp.Tables["LotState"].Rows[0]["NodeId"].ToString();
                        }
                        objLotLog.funCreateSQL(clsLotData3, ChangeProductData: ChangeProduct, LotNo: SLotNo, LotSerial: SLotSerial, LogGroupSerial: NewLotGroupSerial, SysActiveId: 6, ReferenceLotNo: MLotNo);
                    }
                    // ===
                }

                // 檢查是否刪除庫房母批
                if (blnWIPInv & !blnHaveFromLot)
                {
                    if (dsTemp.Tables["WIPInv_RefLot"] != null && dsTemp.Tables["WIPInv_RefLot"].Rows.Count == 1)
                    {

                        strSQL = "Delete From tblINVWIPInventory_Semi Where InventoryNo = '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["InventoryNo"].ToString() + "' And LotNo = '" + MLotNo + "'";
                        CollectionSQL.Add(strSQL);

                        // 2019/04/25 Lena, 在製品庫分批且生產批狀態已為99結批,不建立還原點
                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(dsTemp.Tables["LotState"].Rows[0]["LotState"], 99, false)))
                        {
                            // Undo
                            strSQL = "INSERT INTO TBLINVWIPINVENTORY_SEMI (INVENTORYNO, PRODUCTNO,LOTNO,UNITNO,QTY,INPUTDATE, BASELOTNO,BOUGHTEN,BOOKINGFLAG,PRODUCTVERSION)";
                            strSQL += "  VALUES   ('" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["INVENTORYNO"].ToString() + "', ";
                            strSQL += " '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["PRODUCTNO"].ToString() + "', ";
                            strSQL += " '" + MLotNo + "', ";
                            strSQL += " '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["UNITNO"].ToString() + "', ";
                            strSQL += "  " + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["QTY"].ToString() + ", ";
                            strSQL += " TO_DATE('" + Strings.Format(dsTemp.Tables["WIPInv_RefLot"].Rows[0]["INPUTDATE"], "yyyy/MM/dd HH:mm:ss") + "','YYYY/MM/DD HH24:MI:SS'), ";
                            strSQL += " '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["BASELOTNO"].ToString() + "', ";
                            strSQL += "  " + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["BOUGHTEN"].ToString() + ", ";
                            strSQL += "  " + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["BOOKINGFLAG"].ToString() + ", ";
                            strSQL += " '" + dsTemp.Tables["WIPInv_RefLot"].Rows[0]["PRODUCTVERSION"].ToString() + "')";

                            SQLCommandTuning(DataBaseType, ref strSQL);
                            Collection argcolSQL_Rows3 = null;
                            objReverse.AddReverseUpdateContent(ref SLotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows3);
                        }


                    }
                }


                // 7.分批紀錄
                if (blnWIPInv)
                {
                    // 16 INVSplit(在製品庫分批)
                    objLot.SHR_Split_Inherit(ref cnnTemp, ref CollectionSQL, MLotNo, 16, Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["OPNo"]), UserNo, datEventTime, MLotNo, Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["BaseLotNo"]), MReverseId, MNewLotSerial, decSplitQty, dtSplitCont);
                }
                else
                {
                    objLot.SHR_Split_Inherit(ref cnnTemp, ref CollectionSQL, MLotNo, SplitType, Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["OPNo"]), UserNo, datEventTime, MLotNo, Convert.ToString(dsTemp.Tables["LotState"].Rows[0]["BaseLotNo"]), MReverseId, MNewLotSerial, decSplitQty, dtSplitCont);
                }


                // 8.外包分批
                string OSNo = defString;
                // 8.1是否外包且已出貨(確定)但未回貨
                strSQL = "Select A.OSNo, A.LotNo From tblWIPOSDetail A, tblWIPOSBasis B " + " Where A.LotNo='" + MLotNo + "' And A.Status=0" + " And A.OSNo=B.OSNo And B.Status Not In (0,11)";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    OSNo = drTemp["OSNo"].ToString();
                }
                drTemp.Close();


                if (OSNo != defString)
                {
                    string splitLotNo;

                    // 各子批(可能也會包含原母批)
                    foreach (DataRow rowSplitLot in dtSplitLot.Rows)
                    {
                        splitLotNo = rowSplitLot["SplitLotNo"].ToString();
                        if (splitLotNo != MLotNo)
                        {
                            // 避免PK重複，隨後處理母批
                            strSQL = "Insert Into tblWIPOSDetail (OSNo, LotNo, RCVDate, Status, InputQty, InputUnitNo, GoodQty, ScrapQty, OtherQty, Description, UnitPrice)" + " Select OSNo, '" + splitLotNo + "' As LotNo, RCVDate, Status, " +
                                rowSplitLot["SplitLotQty"] + " As InputQty, InputUnitNo, GoodQty, ScrapQty, OtherQty, Description, UnitPrice" + " From tblWIPOSDetail Where OSNo='" +
                                OSNo + "' And LotNo='" + MLotNo + "'";
                            CollectionSQL.Add(strSQL);
                            // Reverse
                            // 不包含母批
                            strSQL = "Delete From tblWIPOSDetail Where OSNo='" + OSNo + "' And LotNo='" + splitLotNo + "'";
                            Collection argcolSQL_Rows4 = null;
                            objReverse.AddReverseUpdateContent(ref MNewLotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows4);
                        }
                    }

                    // dtSplitLot是否包含母批MLotNo
                    if (blnHaveFromLot)
                    {
                        // 包含母批
                        if (MLotQtyAfterSplit != defInteger)
                        {
                            strSQL = "Update tblWIPOSDetail Set InputQty=" + MLotQtyAfterSplit + " Where OSNo='" + OSNo + "' And LotNo='" + MLotNo + "'";
                            CollectionSQL.Add(strSQL);
                            // Reverse
                            strSQL = "Update tblWIPOSDetail Set InputQty=" + decSplitQty + " Where OSNo='" + OSNo + "'" + " And LotNo='" + MLotNo + "'";
                            Collection argcolSQL_Rows5 = null;
                            objReverse.AddReverseUpdateContent(ref MNewLotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows5);
                        }
                    }
                    else
                    {
                        // 不包含母批
                        strSQL = "Delete From tblWIPOSDetail Where OSNo='" + OSNo + "' And LotNo='" + MLotNo + "'";
                        CollectionSQL.Add(strSQL);
                        // Reverse
                        strSQL = "Insert Into tblWIPOSDetail(OSNo,LotNo,Status,InputQty,InputUnitNo)" + " Values('" + OSNo + "','" + MLotNo + "',0," + decSplitQty + ",'" +
                            dsTemp.Tables["LotState"].Rows[0]["CurUnitNo"] + "')";
                        Collection argcolSQL_Rows6 = null;
                        objReverse.AddReverseUpdateContent(ref MNewLotSerial, ref strSQL, CollectionSQL, colSQL_Rows: argcolSQL_Rows6);
                    }

                }

                // 9.檢查是否允許執行
                Collection argcolSQL_Rows7 = null;
                objLot.ChkLotStamp(MLotNo, LotStamp, CollectionSQL, colSQL_Rows: argcolSQL_Rows7);

                // 11.呼叫執行SQL指令
                ExecuteSQLNoneQuery_UPD(DataBaseType, strConnectionString, CollectionSQL);

                // 若有需要入庫的生產批, 統一在此處理, 此時DB已實際產生子批的相關資料
                if (colToINVLotNo.Count > 0)
                {
                    CollectionSQL.Clear();
                    loopTo = colToINVLotNo.Count;
                    for (i = 1; i <= loopTo; i++)
                    {
                        objLot.SetLotStateToINV(colToINVLotNo[i].ToString(), CollectionSQL, EventUserNo: UserNo);
                    }
                    ExecuteSQLNoneQuery_UPD(DataBaseType, strConnectionString, CollectionSQL);
                }

                // //Return success
                // 因分批後原批號可能不在,故不繼續Transfer,傳出success,一律由使用者手動Transfer
                BR_Manual_LotSplitRet = "success";
            }

            catch (Exception e1)
            {
                BR_Manual_LotSplitRet = "fail";
                throw;
            }
            finally
            {
                CloseConnection(cnnTemp);
                dsTemp.Dispose();
                GC.Collect();

                if (objLot != null)
                {
                    objLot.Dispose();
                }
            }
            return BR_Manual_LotSplitRet;

        }

        #endregion

        #region "隐藏站生产批转移搬迁"
        public static int BRTransferLot_Bin_M(string LotNo, string UserNo, string LinkName, int ERFType = defInteger, string RuleNo = defString, int ScrapQty = defInteger, string RuleMsg = "", string ComputerName = "AUT", bool SPCControl = false, string HoldDescription = defString, bool blnHoldLot = true)
        {
            int BRTransferLot_BinRet = default(int);

            // 此 Function 將執行BR完成後的連續性處理
            // 傳入值:LotNo,UserNo,LinkName,ERFType,RuleNo
            // 傳回值:0(成功), -1(失敗)
            // 撰寫人:sammi
            // 撰寫日:2006/08/14

            // //CCC 07,0607: 將 UserNo 傳入 ERF 開立畫面, 做為 ERF 單的開立人
            // //CCC 07,1218: 修改訊息提示, 加上訊息代碼
            // 2011/01/12 Neil:加入RuleMsg，SPC BR的情況沒有RuleNo需可指定RuleMsg

            string strDescription;
            //var objEAP = new clsEAP();
            DbDataReader drTemp;
            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            IDbConnection cnnTemp = CreateConnection(strConnectionString);

            BRTransferLot_BinRet = -1;

            try
            {

                if (LinkName == "HOLD" && blnHoldLot)
                {
                    BRTransferLot_BinRet = 0; // 放在顯示異常介面之前.若異常開立不成功,重新刷卡即可.
                                              // 開立異常單
                                              //var obj = new clsWIP();
                    if (SPCControl)
                    {
                        tcEAI.clsEAP.BRERFCreateExecute(pUserId: UserNo, pLotNo: LotNo, pERFType: ERFType, pHoldTime: defInteger, pRuleNo: RuleNo, pRepairERF: false, pScrapQty: ScrapQty, pRuleMsg: RuleMsg, pHoldSystem: 1, pHoldDescription: HoldDescription);
                    }
                    else
                    {
                        tcEAI.clsEAP.BRERFCreateExecute(pUserId: UserNo, pLotNo: LotNo, pERFType: ERFType, pHoldTime: defInteger, pRuleNo: RuleNo, pRepairERF: false, pScrapQty: ScrapQty, pRuleMsg: RuleMsg, pHoldSystem: 1, pHoldDescription: RuleNo);
                    }


                    if (RuleNo != defString)
                    {
                        throw new iMESException.MESException("0000-200011", "[%LotNO%]:" + LotNo + "[%VIOLATE RULENO%]:" + RuleNo + "[%CREATEERF%]");
                    }
                    else
                    {
                        throw new iMESException.MESException("0000-200011", "[%LotNO%]:" + LotNo + "[%CREATEERF%]");
                    }
                }
                else if (LinkName == "WAIT")
                {
                    throw new iMESException.MESException("0000-200011", "[%LotNO%]:" + LotNo + "[%WAITBASIS CREATE%]");
                }
                else
                {

                    var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                    string strSQL = "";
                    var objWIP = new kcWIP.clsLot();

                    //判斷品管項目是不是已經都處理完畢，已處理完畢就確認是否需要開立異常單，未處理完畢就強制將LinkName改成NEXT
                    if (blnHoldLot == false)
                    {
                        var dsTempQcitem = objWIP.ShowTemp_QCItem(LotNo: LotNo, AdditionalXml: "<additional><condition> InspType_PQC = 1 </condition></additional>");
                        DataRow[] drSelExe = null;
                        StringBuilder holdDescriptions = new StringBuilder();
                        drSelExe = dsTempQcitem.Tables[0].Select(" ExecuteFlag = 0 ");
                        if (drSelExe.Length == 0) //確認不存在未驗項目的狀況下，進行異常單的開立或者Transfer
                        {
                            strSQL = $" Select HoldDescription  From tblWIPERFCreateData Where LotNo = '{LotNo}' And SPCSerial is not Null ";
                            drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp, strDataBaseType);
                            while (drTemp.Read())
                            {
                                // 確保欄位值不為 NULL
                                if (!drTemp.IsDBNull(0))
                                {
                                    string strholdDescription = drTemp.GetString(0);
                                    strholdDescription = strholdDescription.Replace("&#10;", Environment.NewLine); // 或用 "" 空字串移除
                                    strholdDescription = tcEAI.clsEAP.TranslateMsg(strholdDescription);
                                    holdDescriptions.AppendLine(strholdDescription);
                                }
                            }

                            if (holdDescriptions.Length != 0 && SPCControl)
                                tcEAI.clsEAP.BRERFCreateExecute(pUserId: UserNo, pLotNo: LotNo, pERFType: ERFType, pHoldTime: defInteger, pRuleNo: RuleNo, pRepairERF: false, pScrapQty: ScrapQty, pRuleMsg: RuleMsg, pHoldSystem: 1, pHoldDescription: holdDescriptions.ToString());
                        }
                        else
                            LinkName = "NEXT";
                    }

                    TransferLot_Bin_M(ComputerName, DateTime.Now, UserNo, LotNo, LinkName, result);

                    if (result.ContainsKey("hold_exceedtime"))
                    {
                        tcEAI.clsEAP.BRERFCreateExecute(pUserId: UserNo, pLotNo: LotNo, pERFType: 1, pHoldTime: 0, pRuleNo: "EXCEEDTIME");
                        throw new iMESException.MESException("0000-200091", "[%LotNO%]:" + LotNo + "[%VIOLATE TIME CONTROL,CREATE ERF%]!");
                    }
                    else if (result.ContainsKey("futurehold"))
                    {
                        int intHoldTime = 0;
                        if (result.ContainsKey("holdtime"))
                        {
                            intHoldTime = Conversions.ToInteger(result["holdtime"].ToString());
                        }
                        tcEAI.clsEAP.BRERFCreateExecute(pUserId: UserNo, pLotNo: LotNo, pERFType: 3, pHoldTime: intHoldTime);
                        throw new iMESException.MESException("0000-200091", "[%LotNO%]:" + LotNo + "[%FUTUREHOLD SET,CREATE ERF%]!");
                    }
                    else if (result.ContainsKey("futurewait"))
                    {
                        throw new iMESException.MESException("0000-200091", "[%LotNO%]:" + LotNo + "[%FUTUREWAIT%]!");
                    }
                    else if (result.ContainsKey("futureos"))
                    {
                        throw new iMESException.MESException("0000-200091", "[%LotNO%]:" + LotNo + "[%FUTURE OS%]!");
                    }

                    BRTransferLot_BinRet = 0;

                }
            }

            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                //数据库一定要关闭
                CloseConnection(cnnTemp);
            }

            return BRTransferLot_BinRet;

        }



        public static string TransferLot_Bin_M(string ComputerName, DateTime ArriveTime, string UserNo, string LotNo, string LinkName = defString, Dictionary<string, string> dicReturnValue = null)
        {
            string TransferLot_BinRet = default(string);

            var objOP = new kcOP.clsOpBasis();
            var objBR = new tcWIP_IC.clsBusinessRule();
            var objLot = new kcWIP.clsLot();
            var objSYS = new clsSYSUserLog();

            string NextBRNo;
            var colNextNode = new Collection();
            DataRow drLotState;
            int PhaseNo, HoldTime;

            string[] aryTLot; // ExecuteBR使用
            var dicBRParameter = new Dictionary<string, string>(); // ExecuteBR使用

            string strReturnValue = "";
            var strResult = default(string);
            string strServiceName = "EAItc_DSC.clsWIP.TransferLot";

            // 2007/12/18 Acer 用來存放Future Wait所輸入的Description,解決Future Wait所輸入的Description不會帶到Wait Basis中的錯誤
            string strWaitDescription = defString;
            string iscycle = "";

            IDbConnection cnnTemp = null;
            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            cnnTemp = CreateConnection(strConnectionString);

            try
            {


                // 2010/08/02,Sam.Hsu,傳入給FunctionBR使用之額外參數
                // <parameters>
                // <name>..</name> <type>..</type>
                // <value>
                // <parameterno>..</parameterno>
                // <parametervalue>..</parametervalue>
                // </value>
                // <desc></desc>
                // </parameters>
                // If xmlDoc.DocumentElement.GetElementsByTagName("parameters").Count > 0 Then
                // If xmlDoc.GetElementsByTagName("parameters").Item(0).SelectNodes("value").Count > 0 Then
                // Dim xmlList As Xml.XmlNodeList = xmlDoc.GetElementsByTagName("parameters").Item(0).SelectNodes("value")
                // For j As Integer = 0 To xmlList.Count - 1
                // '將資料存入暫存Collection
                // dicBRParameter.Add(xmlList(j).SelectNodes("parameterno").Item(0).InnerText,
                // xmlList(j).SelectNodes("parametervalue").Item(0).InnerText)
                // Next
                // End If
                // End If

                // //Transfer----------------------------------------------------------------------------------------------------------------
                // objOP = New kcOP.clsOpBasis
                // objBR = New tcWIP_IC.clsBusinessRule

                lblGetNextBR:
                ;


                // 0.檢查是否允許執行TransferLot,防止未執行,一直往下轉移
                drLotState = objLot.GetLotState(LotNo);
                if (drLotState["LotNo"] is DBNull)
                {
                    throw new iMESException.MESException("0000-200003", "LotNo:" + LotNo + " is not exist!");
                }
                else if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drLotState["Status"], 4, false)))
                {
                    throw new iMESException.MESException("0000-203033", "LotNo:" + LotNo);
                }

                // 2007/03/12,sammi.若沒有傳入LinkName,則使用tblWIPLotState.LinkName.
                if (LinkName == defString)
                {
                    LinkName = drLotState["LinkName"].ToString();
                }

                // Success不繼續Go,停止
                if (LinkName != null && LinkName.ToUpper() == "SUCCESS")
                {
                    // 2006/05/23,sammi.做為呼叫端是否繼續轉移的依據.
                    // strReturnValue = CombineXMLReturnValue("stopflag", "StopFlag", "Integer", "", 1, "")
                    dicReturnValue["stopflag"] = 1.ToString();
                    goto lblExit;
                }

                switch (LinkName)
                {
                    case "ABORTOP":
                        {
                            // 以後再處理
                            goto lblExit;
                            break;
                        }
                }

                // 2009/09/14,yumei,生產批數量為零(GoodQty=0)時,結束該流程,入不良品倉(LotState=12,ScrapINV)----
                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["CurQty"], 0, false)))
                {
                    decimal FinalGoodQtyTmp = defInteger;
                    decimal FinalFailQtyTmp = defInteger;
                    objLot.EndOP(ref FinalGoodQtyTmp, ref FinalFailQtyTmp, LotNo, UserNo: UserNo, ReleaseEQP: true);
                    goto lblExit;
                }
                // -----------------------------------------------------------





                // 1.取出下一個BusinessRule
                NextBRNo = objLot.GetNextBR(LotNo, LinkName);

                if (NextBRNo == "END")    // 沒有下一個BR,要換Node
                {
                    // PS.不建議在此區塊內使用上述已取出的drLotState,因下述每個個別執行的Function都有可能去變更LotState
                    // 作業站成功完成,LotLog為有意義的資料
                    decimal FinalGoodQtyTmp = defInteger;
                    decimal FinalFailQtyTmp = defInteger;
                    objLot.EndOP(ref FinalGoodQtyTmp, ref FinalFailQtyTmp, LotNo, UserNo: UserNo, ReleaseEQP: true);

                    // FutureHold/FutureWait檢查
                    string HoldDescriptionTmp = "";
                    if (objLot.ChkFutureHold(ref HoldDescriptionTmp, LotNo, 1))
                    {
                        HoldTime = 1; // HoldTime:End
                        goto lblFutureHold; // 至WinForm開單
                    }

                    else if (objLot.ChkFutureWait(ref strWaitDescription, LotNo, 1))
                    {
                        // Future Wait
                        objLot.SetLotStateToWait(Conversions.ToLong(objLot.GetLotState(LotNo)["LotStamp"]), LotNo, 3, 1, UserNo, WaitDescription: strWaitDescription);
                        goto lblFutureWait;
                    }




                    //换NODE前看一下是否有隐藏站，如果有隐藏站的话，生产批状态变成该作业站的完成状态；而不是下一站的待进站状态
                    DataSet dsTemp = new DataSet();
                    string OPNO = "";
                    string FROMNODENO = "";
                    strSQL = $@"SELECT * FROM TBLWIPLOTSTATE WHERE LOTNO='{LotNo}'";
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "OPNO", cnnTemp);
                    if (dsTemp.Tables["OPNO"].Rows.Count > 0)
                    {
                        OPNO = dsTemp.Tables["OPNO"].Rows[0]["OPNO"].ToString();
                    }

                    strSQL = $@" Select A.GROUPNO From TBLPRSNODEBASIS A 
                             join tblwiplotstate B on A.processno = B.processno and A.processversion = B.processversion where B.LOTNO = '{LotNo}' AND NODENO='{OPNO}' AND A.GROUPNO IS NOT NULL";
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "GROUPNO", cnnTemp);
                    if (dsTemp.Tables["GROUPNO"].Rows.Count > 0)
                    {
                        FROMNODENO = "GROUP" + dsTemp.Tables["GROUPNO"].Rows[0]["GROUPNO"].ToString();
                    }
                    else
                    {
                        FROMNODENO = OPNO;
                    }

                    strSQL = $@"Select A.* From tblPRSNodeRelation A 
                             join tblwiplotstate B on A.processno = B.processno and A.processversion = B.processversion and A.FROMNODENO = '{FROMNODENO}'
                             where B.LOTNO = '{LotNo}' 
                             and A.LinkName = 'PASS1' ";
                    ExecuteSQLQuery_Adapter(strSQL, dsTemp, "tblPRSNodeRelation", cnnTemp);
                    if (dsTemp.Tables["tblPRSNodeRelation"].Rows.Count > 0)
                    {
                        goto lblExit;
                    }
                    else
                    {
                        if (iscycle == "1")
                        {
                            LinkName = "CYCLE";
                        }
                    }

                    // 取出下一Node{colNextNode:NodeID,NodeNo,ProcessNo,NextNodeType,PSNo(資料不一定都有)}
                    colNextNode = objLot.GetNextNode(LotNo, "Null", LinkName, AdditionalXml: "");
                    switch (colNextNode["NextNodeType"].ToString())
                    {
                        case "OP":
                        case "PRS":
                        case "MOD":
                            {
                                objLot.SetLotStateToNextOP(Conversions.ToLong(drLotState["LotStamp"]), LotNo, Convert.ToString(colNextNode["NodeID"]), EventUserNo: UserNo);

                                // 取出LotState目前的BRNo(已轉換)
                                NextBRNo = Convert.ToString(objLot.GetLotState(LotNo)["BRNo"]);
                                if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(objOP.GetBusinessRule(NextBRNo)["RuleMethod"], 0, false)))    // Automatic
                                {
                                    var colParameters = new Collection();
                                    // TriggerOP
                                    long NewLotStampTmp = defInteger;
                                    strReturnValue = objLot.TriggerOP(ref strWaitDescription, ref NewLotStampTmp, LotNo, UserNo: UserNo, ComputerNo: ComputerName);
                                    if (strReturnValue == "hold_exceedtime")
                                    {
                                        // 2008/01/04,sammi.違反時效管制.
                                        goto lblHold_ExceedTime;
                                    }
                                    else if (strReturnValue == "futurehold")
                                    {
                                        HoldTime = 0; // HoldTime:Start
                                        goto lblFutureHold;
                                    }
                                    else if (strReturnValue == "futurewait")
                                    {
                                        goto lblFutureWait;
                                    }
                                    else if (strReturnValue == "futureos")
                                    {
                                        goto lblFutureOS;
                                    }
                                    drLotState = objLot.GetLotBasisJoinState(LotNo: LotNo);   // 取得最新的LotState
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 0, false))) // by Product
                                    {
                                        PhaseNo = objLot.GetBusinessRulePhase(drLotState["ProductNo"].ToString(), drLotState["ProductVersion"].ToString(), drLotState["OPNo"].ToString(), NextBRNo);
                                    }
                                    else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 1, false))) // by Module
                                    {
                                        PhaseNo = objLot.GetBusinessRulePhase(drLotState["ModuleNo"].ToString(), drLotState["ModuleVersion"].ToString(), drLotState["OPNo"].ToString(), NextBRNo);
                                    }
                                    else
                                    {
                                        throw new iMESException.MESException("0000-200015", "LotNo:" + LotNo + " OPReference is not valid!");
                                    }
                                    // Trigger Phase(剛做完TriggerOP,不用再執行Attrib的變更)
                                    objLot.TriggerPhase_LotState(LotNo, PhaseNo, UserNo);

                                    // 加入參數
                                    colParameters.Add(UserNo, "UserNo");

                                    // 2010/08/02,Sam.Hsu
                                    // 加入額外參數，若有相同參數以傳入之參數取代
                                    // ExecuteBR中會再加入LotNo,LotSerial,MONo,ProductNo,ProductVersion,OPNo
                                    // 因此不可再傳入上述參數
                                    if (dicBRParameter.Count > 0)
                                    {
                                        if (dicBRParameter.ContainsKey("UserNo") == true)
                                        {
                                            colParameters.Remove("UserNo");
                                        }
                                        foreach (KeyValuePair<string, string> KeyVal in dicBRParameter)
                                            colParameters.Add(KeyVal.Value, KeyVal.Key);
                                    }

                                    // 執行BR
                                    LinkName = objBR.ExecuteBR(LotNo, NextBRNo, colParameters);

                                    // 06/04/25,sammi.檢查LinkName是否為多批.若是只須執行轉移即可,不用繼續往下做.
                                    aryTLot = Strings.Split(LinkName, ";"); // LinkName=PASS or LinkName=L001,PASS;L002,PASS;L003:Rework
                                    if (aryTLot.Length == 1)
                                    {
                                        // 原本的轉移,仍延用原LotNo
                                        // 繼續找下一個BR,Success不繼續Go,停止
                                        if (LinkName.ToUpper() == "SUCCESS")
                                        {
                                            // 2006/05/23,sammi.做為呼叫端是否繼續轉移的依據.
                                            strReturnValue = iMESCore.Base.iMESComXML.CombineXMLReturnValue("stopflag", "StopFlag", "Integer", "", 1.ToString(), "");
                                            goto lblExit;
                                        }
                                        else
                                        {
                                            goto lblGetNextBR;
                                        }
                                    }
                                    else
                                    {
                                        goto lblLotTransfer;
                                    }

                                }

                                break;
                            }

                        case "END":
                            {
                                objLot.SetLotStateToNextOP(Conversions.ToLong(drLotState["LotStamp"]), LotNo, Convert.ToString(colNextNode["NodeID"]), EventUserNo: UserNo);

                                // 93/09/13,讓流程轉移時,第一個OP的第一個AutoBR可自動執行                        '
                                // Q1.SetLotStateToNextOP可能入庫(Status = 11),以避免
                                // Q2.SetLotStateToNextOP可能轉移至Group內的OP上(則BR自動執行,將無法選擇要執行那個Group內的OP),目前沒有避免
                                // 2008/11/28,sammi.Lot可能結批,故不一定會有資料,加上drLotState("LotNo").ToString <> ""的判斷.
                                // 取出LotState目前的BRNo(已轉換)
                                drLotState = objLot.GetLotState(LotNo);
                                if (!string.IsNullOrEmpty(drLotState["LotNo"].ToString()) && Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["Status"], 0, false))) // 避免Q1
                                {
                                    NextBRNo = drLotState["BRNo"].ToString();
                                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(objOP.GetBusinessRule(NextBRNo)["RuleMethod"], 0, false)))    // Automatic
                                    {
                                        var colParameters = new Collection();
                                        // TriggerOP
                                        long NewLotStampTmp = defInteger;
                                        strReturnValue = objLot.TriggerOP(ref strWaitDescription, ref NewLotStampTmp, LotNo, UserNo: UserNo, ComputerNo: ComputerName);
                                        if (strReturnValue == "hold_exceedtime")
                                        {
                                            // 2008/01/04,sammi.違反時效管制.
                                            goto lblHold_ExceedTime;
                                        }
                                        else if (strReturnValue == "futurehold")
                                        {
                                            HoldTime = 0; // HoldTime:Start
                                            goto lblFutureHold;
                                        }
                                        else if (strReturnValue == "futurewait")
                                        {
                                            goto lblFutureWait;
                                        }
                                        else if (strReturnValue == "futureos")
                                        {
                                            goto lblFutureOS;
                                        }
                                        drLotState = objLot.GetLotBasisJoinState(LotNo: LotNo);   // 取得最新的LotState
                                        if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 0, false))) // by Product
                                        {
                                            PhaseNo = objLot.GetBusinessRulePhase(drLotState["ProductNo"].ToString(), drLotState["ProductVersion"].ToString(), drLotState["OPNo"].ToString(), NextBRNo);
                                        }
                                        else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 1, false))) // by Module
                                        {
                                            PhaseNo = objLot.GetBusinessRulePhase(drLotState["ModuleNo"].ToString(), drLotState["ModuleVersion"].ToString(), drLotState["OPNo"].ToString(), NextBRNo);
                                        }
                                        else
                                        {
                                            throw new iMESException.MESException("0000-200015", "LotNo:" + LotNo + " OPReference is not valid!");
                                        }
                                        // Trigger Phase(剛做完TriggerOP,不用再執行Attrib的變更)
                                        objLot.TriggerPhase_LotState(LotNo, PhaseNo, UserNo);

                                        // 加入參數
                                        colParameters.Add(UserNo, "UserNo");

                                        // 2010/08/02,Sam.Hsu
                                        // 加入額外參數，若有相同參數以傳入之參數取代
                                        // ExecuteBR中會再加入LotNo,LotSerial,MONo,ProductNo,ProductVersion,OPNo
                                        // 因此不可再傳入上述參數
                                        if (dicBRParameter.Count > 0)
                                        {
                                            if (dicBRParameter.ContainsKey("UserNo") == true)
                                            {
                                                colParameters.Remove("UserNo");
                                            }
                                            foreach (KeyValuePair<string, string> KeyVal in dicBRParameter)
                                                colParameters.Add(KeyVal.Value, KeyVal.Key);
                                        }

                                        // 執行BR
                                        LinkName = objBR.ExecuteBR(LotNo, NextBRNo, colParameters);

                                        // 06/04/25,sammi.檢查LinkName是否為多批.若是只須執行轉移即可,不用繼續往下做.
                                        aryTLot = Strings.Split(LinkName, ";"); // LinkName=PASS or LinkName=L001,PASS;L002,PASS;L003:Rework
                                        if (aryTLot.Length == 1)
                                        {
                                            // 原本的轉移,仍延用原LotNo
                                            // 繼續找下一個BR,Success不繼續Go,停止
                                            if (LinkName.ToUpper() == "SUCCESS")
                                            {
                                                // 2006/05/23,sammi.做為呼叫端是否繼續轉移的依據.
                                                // strReturnValue = CombineXMLReturnValue("stopflag", "StopFlag", "Integer", "", 1, "")
                                                dicReturnValue["stopflag"] = 1.ToString();
                                                goto lblExit;
                                            }
                                            else
                                            {
                                                goto lblGetNextBR;
                                            }
                                        }
                                        else
                                        {
                                            goto lblLotTransfer;
                                        }

                                    }
                                }

                                break;
                            }

                        case "ANDGROUP":
                        case "ORGROUP":  // Group
                            {
                                objLot.SetLotStateToNextOP(Conversions.ToLong(drLotState["LotStamp"]), LotNo, Convert.ToString(colNextNode["NodeID"]), EventUserNo: UserNo);
                                break;
                            }

                        case "ANDGROUPOP":  // ANDGroup的OP
                            {
                                objLot.SetLotStateToOtherGroupOP(Conversions.ToLong(drLotState["LotStamp"]), LotNo, true, Convert.ToString(colNextNode["NodeID"]), EventUserNo: UserNo);
                                break;
                            }

                        default:
                            {
                                // Immediate Wait
                                objLot.SetLotStateToWait(Conversions.ToLong(drLotState["LotStamp"]), LotNo, 2, UserNo: UserNo);
                                break;
                            }

                    }
                }

                else if (NextBRNo == defString)    // 找不到下一個BR
                {
                    // Immediate Wait
                    objLot.SetLotStateToWait(Conversions.ToLong(drLotState["LotStamp"]), LotNo, 2, UserNo: UserNo);
                }

                else    // Find next BR
                {
                    // 檢查是否Trigger Phase
                    drLotState = objLot.GetLotBasisJoinState(LotNo: LotNo);   // 取得最新的LotState
                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 0, false))) // by Product
                    {
                        PhaseNo = objLot.GetBusinessRulePhase(drLotState["ProductNo"].ToString(), drLotState["ProductVersion"].ToString(), drLotState["OPNo"].ToString(), NextBRNo);
                    }
                    else if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(drLotState["OPReference"], 1, false))) // by Module
                    {
                        PhaseNo = objLot.GetBusinessRulePhase(drLotState["ModuleNo"].ToString(), drLotState["ModuleVersion"].ToString(), drLotState["OPNo"].ToString(), NextBRNo);
                    }
                    else
                    {
                        throw new iMESException.MESException("0000-200015", "LotNo:" + LotNo + " OPReference is not valid!");
                    }

                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectNotEqual(drLotState["PhaseNo"], PhaseNo, false)))
                    {
                        objLot.TriggerPhase(LotNo, PhaseNo, EventUserNo: UserNo);
                    }

                    if (Convert.ToBoolean(Operators.ConditionalCompareObjectEqual(objOP.GetBusinessRule(NextBRNo)["RuleMethod"], 0, false)))    // Automatic
                    {
                        var colParameters = new Collection();
                        // 更新LotState的BR
                        objLot.SetLotStateToNextBR(Conversions.ToLong(drLotState["LotStamp"]), LotNo, NextBRNo, EventUserNo: UserNo);
                        // 加入參數
                        colParameters.Add(UserNo, "UserNo");

                        // 2010/08/02,Sam.Hsu
                        // 加入額外參數，若有相同參數以傳入之參數取代
                        // ExecuteBR中會再加入LotNo,LotSerial,MONo,ProductNo,ProductVersion,OPNo
                        // 因此不可再傳入上述參數
                        if (dicBRParameter.Count > 0)
                        {
                            if (dicBRParameter.ContainsKey("UserNo") == true)
                            {
                                colParameters.Remove("UserNo");
                            }
                            foreach (KeyValuePair<string, string> KeyVal in dicBRParameter)
                                colParameters.Add(KeyVal.Value, KeyVal.Key);
                        }

                        // 執行BR
                        LinkName = objBR.ExecuteBR(LotNo, NextBRNo, colParameters);

                        // 06/04/25,sammi.檢查LinkName是否為多批.若是只須執行轉移即可,不用繼續往下做.
                        aryTLot = Strings.Split(LinkName, ";"); // LinkName=PASS or LinkName=L001,PASS;L002,PASS;L003:Rework
                        if (aryTLot.Length == 1)
                        {
                            // 原本的轉移,仍延用原LotNo
                            // 繼續找下一個BR,Success不繼續Go,停止
                            if (LinkName.ToUpper() == "SUCCESS")
                            {
                                // 2006/05/23,sammi.傳出LinkName,做為呼叫端是否繼續轉移的依據.
                                // strReturnValue = CombineXMLReturnValue("stopflag", "StopFlag", "Integer", "", 1, "")
                                dicReturnValue["stopflag"] = 1.ToString();
                                goto lblExit;
                            }
                            else
                            {
                                goto lblGetNextBR;
                            }
                        }
                        else
                        {
                            goto lblLotTransfer;
                        }
                    }

                    else // Manual
                    {
                        objLot.SetLotStateToNextBR(Conversions.ToLong(drLotState["LotStamp"]), LotNo, NextBRNo, EventUserNo: UserNo);
                    }

                }

                goto lblExit;

                lblHold_ExceedTime:
                ;

                // strReturnValue = CombineXMLReturnValue("hold_exceedtime", "Hold_ExceedTime", "String", "", "Hold_ExceedTime", "")
                dicReturnValue["Hold_ExceedTime"] = "Hold_ExceedTime";
                goto lblExit;

                lblFutureHold:
                ;

                // strReturnValue = CombineXMLReturnValue("futurehold", "FutureHold", "String", "", "FutureHold", "")
                // strReturnValue += CombineXMLReturnValue("holdtime", "holdtime", "String", "", HoldTime, "")
                dicReturnValue["FutureHold"] = "FutureHold";
                dicReturnValue["HoldTime"] = HoldTime.ToString();
                goto lblExit;

                lblFutureWait:
                ;

                strReturnValue = iMESCore.Base.iMESComXML.CombineXMLReturnValue("futurewait", "FutureWait", "String", "", "FutureWait", "");
                dicReturnValue["FutureWait"] = "FutureWait";
                // 2012/02/10 YF, 回傳Wait Description
                if (strWaitDescription != defString)
                {
                    // strReturnValue += CombineXMLReturnValue("waitdescription", "WaitDescription", "String", "", strWaitDescription, "")
                    dicReturnValue["WaitDescription"] = strWaitDescription;
                }
                goto lblExit;

                lblFutureOS:
                ;

                // strReturnValue = CombineXMLReturnValue("futureos", "FutureOS", "String", "", "FutureOS", "")
                dicReturnValue["FutureOS"] = "FutureOS";
                goto lblExit;

                lblLotTransfer:
                ;


                // BR可能執行了分批,系統必須轉移傳出的批號
                string strRS;
                string[] aryLink;
                int i;
                var loopTo = aryTLot.Length - 1;
                for (i = 0; i <= loopTo; i++)
                {
                    do
                    {
                        try
                        {
                            aryLink = Strings.Split(aryTLot[i], ","); // aryTLot(i) = L001,PASS
                            if (aryLink.Length > 0 && string.IsNullOrEmpty(aryLink[0]))
                            {
                                break;
                            }
                            // Transfer Lot
                            if (aryLink.Length == 1) // LinkName預設為Pass
                            {
                                // strInXmlParameter = CombineXMLParameter("lotno", "LotNo", "String", aryLink(0), "")
                                Dictionary<string, string> argdicReturnValue = null;
                                strRS = TransferLot_Bin_M(ComputerName, DateTime.Now, UserNo, aryLink[0], dicReturnValue: argdicReturnValue);
                            }
                            else
                            {
                                // strInXmlParameter = CombineXMLParameter("lotno", "LotNo", "String", aryLink(0), "")
                                // strInXmlParameter = strInXmlParameter & CombineXMLParameter("linkname", "LinkName", "String", aryLink(1), "")
                                Dictionary<string, string> argdicReturnValue1 = null;
                                strRS = TransferLot_Bin_M(ComputerName, DateTime.Now, UserNo, aryLink[0], aryLink[1], dicReturnValue: argdicReturnValue1);
                            }

                            Dictionary<string, string> argdicReturnValue2 = null;
                            strRS = TransferLot_Bin_M(ComputerName, DateTime.Now, UserNo, aryLink[0], dicReturnValue: argdicReturnValue2);
                            if (strRS != "success")
                            {
                                throw new iMESException.MESException("0000-203036", "Transfer Lot fail," + strResult);
                            }
                        }
                        catch (iMESException.MESException ex)
                        {
                            throw;
                        }
                        catch (Exception e1)
                        {
                            throw;
                        }
                        finally
                        {
                        }
                    }
                    while (false);
                }

                goto lblExit;

                lblExit:
                ;


                strResult = "success";

                objSYS.AddEventLog(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, "TransferLot,LinKname:" + LinkName, ComputerName: ComputerName);
            }

            catch (iMESException.MESException ex)
            {

                strResult = ex.Message + " : " + ex.StackTrace;
                objSYS.AddErrorLog_ErrorCode(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, strResult, ComputerName: ComputerName, ErrorCode: Convert.ToString(ex.ErrorCode));

                throw ex;
            }

            catch (Exception ex)
            {

                strResult = ex.Message + " : " + ex.StackTrace;
                objSYS.AddErrorLog_ErrorCode(strServiceName, UserNo, "LotNo", LotNo, DateTime.Now, strResult, ComputerName: ComputerName);

                throw ex;
            }

            finally
            {
                if (!(objLot == null))
                    objLot = null;
                if (!(objOP == null))
                    objOP = null;
                if (!(objBR == null))
                    objBR = null;
                if (!(objSYS == null))
                    objSYS = null;

                //数据库一定要关闭
                CloseConnection(cnnTemp);

                // 將各部份之XML字串組起來並傳出
                TransferLot_BinRet = strResult;


            }

            return TransferLot_BinRet;

        }


        #endregion
        /// <summary>
        /// 写入字符串日志，固定路径 D:\meslog\eai
        /// </summary>
        /// <param name="message">日志内容</param>
        public static void WriteLog(string message)
        {
            try
            {
                // 固定文件夹路径
                string logDirectory = @"D:\meslog\eai";

                // 不存在则创建目录
                if (!Directory.Exists(logDirectory))
                {
                    Directory.CreateDirectory(logDirectory);
                }

                // 按日期生成日志文件
                string fileName = $"Log_{DateTime.Now:yyyyMMdd}.txt";
                string fullPath = Path.Combine(logDirectory, fileName);

                // 拼接时间与日志内容
                string logLine = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}  {message}{Environment.NewLine}";

                // 追加写入文件
                File.AppendAllText(fullPath, logLine);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"日志写入异常：{ex.Message}");
            }
        }
        public string SetLotStateToNextBR(long LotStamp, string LotNo, string BRNo, string AdditionalXml = "", string EventUserNo = "", string EventDescription = "", Collection colSQL = null)
        {
            string SetLotStateToNextBRRet = default(string);
            // 此 Function 將使 Lot 的現況移到下一個 Business Rule
            // 傳入值: 索引值
            // 傳回值: success(成功), fail(失敗)

            var CollectionSQL = new Collection();

            var datEventTime = DateTime.Now;

            try
            {
                // 呼叫執行SQL指令(1:Run)
                strSQL = "Update tblWIPLotState Set BRNo ='" + BRNo + "'," + " EventTime=To_Date('" + Strings.Format(datEventTime, "yyyy/MM/dd H:mm:ss") + "','YYYY/MM/DD HH24:MI:SS')," + " EventUserNo='" + EventUserNo + "'," + " EventDescription='" + EventDescription + "'," + " Status = 1 " + " Where LotNo ='" + LotNo + "'";
                CollectionSQL.Add(strSQL);

                // 2006/07/12,sammi.檢查是否允許執行
                Collection argcolSQL_Rows = null;
                objLot.ChkLotStamp(LotNo, LotStamp, CollectionSQL, colSQL_Rows: argcolSQL_Rows);

                if (colSQL == null)
                {
                    // 呼叫執行SQL指令
                    ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);
                }
                else
                {
                    for (int i = 1, loopTo = CollectionSQL.Count; i <= loopTo; i++)
                        colSQL.Add(CollectionSQL[i]);
                }

                // 2019/10/28 Yenru , Add SignalR BroadCast 
                try
                {
                    // 站內移轉
                    // 設備:加工設備生產批狀態變更、未加工設備刪除顯示生產批。
                    // 作業站:生產批狀態變更。
                    using (var objMDS = new kcWIP.clsMDS())
                    {

                        var drLotInfo = objLot.GetLotState(LotNo);
                        var dTEQPInfo = objLot.ShowTemp_Equipment(LotNo).Tables[0];
                        string strEQPList = "";
                        var oParameter = new Dictionary<string, string>();

                        // 整理設備資訊
                        foreach (DataRow drTemp in dTEQPInfo.Rows)
                            strEQPList += drTemp["EquipmentNo"].ToString() + ",";
                        strEQPList = strEQPList.TrimEnd(',');

                        oParameter.Add("ProcessType", "SetLotStateToNextBR");
                        oParameter.Add("lotno", LotNo);
                        oParameter.Add("orgopno", drLotInfo["OPNO"].ToString());
                        oParameter.Add("equiplist", strEQPList);

                        objMDS.SignalRDataSummary(oParameter);

                        // 20200917 雋辰 ,SignalR 生產任務(派工頁簽)
                        oParameter["ProcessType"] = "SetLotStateToNextBR_Dispatch";
                        objMDS.SignalRDataSummary(oParameter);
                    }
                }
                catch (Exception ex)
                {
                }

                // Return success
                SetLotStateToNextBRRet = "success";
            }

            catch (Exception e1)
            {
                SetLotStateToNextBRRet = "fail";
                throw;

            } // New Exception("kcWIP.SetLotStateToNextBR: " & e1.Message)
            return SetLotStateToNextBRRet;

        }


        public static Collection GetNextNode(string LotNo, string NodeID = defString, string LinkName = defString, string AdditionalXml = "")
        {
            Collection GetNextNodeRet = default(Collection);
            // 此 Function 將取得LotNo目前Node的下一Node,或是依指定NodeID,LinkName取得下一Node
            // 傳入值: 索引值
            // 傳回值: Collection(成功), fail(失敗)

            IDbConnection cnnTemp = null;
            DbDataReader drTemp = null;
            var colGetNextNode = new Collection();
            string GroupNodeID, CurNodeID, NextNodeID, NextNodeNo;
            int GroupType;    // 6:AND,7:OR

            try
            {
                cnnTemp = CreateConnection(strConnectionString);

                // 1.依LotNo取出NodeID,PSNo
                if (NodeID == defString)
                {
                    strSQL = "Select NodeID From tblWIPLotState Where LotNo ='" + LotNo + "'";
                    // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                    drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                    if (drTemp.Read())
                    {
                        CurNodeID = drTemp["NodeID"].ToString();
                    }
                    else
                    {
                        colGetNextNode.Add("WAIT", "NextNodeType");
                        goto lblExitProcedure;
                    }
                    drTemp.Close();
                }

                else
                {
                    CurNodeID = NodeID;
                }

                // 2.檢查OPGroupState內是否有未執行OP(OPGroupState內的一定是要執行的,不執行的不會加入OPGroupState)
                strSQL = "Select GroupType,GroupNodeID, NodeID From tblWIPOPGroupState Where LotNo ='" + LotNo + "'" + " And NodeID ='" + CurNodeID + "'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    GroupType = Conversions.ToInteger(drTemp["GroupType"]);
                    GroupNodeID = drTemp["GroupNodeID"].ToString();

                    drTemp.Close();


                    if (GroupType == 6) // AND Group
                    {
                        strSQL = "Select NodeID,OPNo From tblWIPOPGroupState Where LotNo ='" + LotNo + "'" + " And NodeID <> '" + CurNodeID + "'" + " And ExecuteFlag = 0 "; // 剔除目前的OP,未執行之OP
                                                                                                                                                                             // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                        drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                        if (drTemp.Read())
                        {
                            colGetNextNode.Add(drTemp["NodeID"], "NodeID");
                            colGetNextNode.Add(drTemp["OPNo"], "NodeNo");         // OPNo
                            colGetNextNode.Add("ANDGROUPOP", "NextNodeType");
                            goto lblExitProcedure;
                        }
                        else    // 用GroupNodeID找下個Node
                        {
                            CurNodeID = GroupNodeID;
                        }
                        drTemp.Close();
                    }


                    else if (GroupType == 7) // OR Group
                    {
                        CurNodeID = GroupNodeID;
                    }
                }
                else
                {
                    drTemp.Close();

                }


                lblGetNextNode:
                ;



                // 3.依 CurNodeID,LinkName 取出 NextNodeID
                strSQL = "Select ToNodeID,ToNodeNo From tblPRSNodeRelation Where FromNodeID ='" + CurNodeID + "'";
                if (LinkName == defString || LinkName == null)
                {
                    strSQL = strSQL + " And LinkName ='PASS'";
                }
                else
                {
                    strSQL = strSQL + " And LinkName ='" + LinkName.ToUpper() + "'";
                }
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (!drTemp.Read())  // 沒有找到下一節點
                {
                    drTemp.Close();

                    colGetNextNode.Add("WAIT", "NextNodeType");
                    goto lblExitProcedure;
                }

                // 找到下一節點---------------------------------------------------------------------------------------------------------------
                NextNodeID = drTemp["ToNodeID"].ToString();
                NextNodeNo = drTemp["ToNodeNo"].ToString();
                drTemp.Close();


                // '4.檢查下一節點是否不執行
                // strSQL = "Select OPNo From tblWIPLotNotExecuteOP " & _
                // " Where LotNo = '" & LotNo & "' And OPNo = '" & NextNodeNo & "'"
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp)
                // drTemp = cmmTemp.ExecuteReader()
                // If drTemp.Read Then '不執行,繼續找下一Node,linkname變更為Pass
                // drTemp.Close()
                // CurNodeID = NextNodeID
                // LinkName = "PASS"
                // GoTo lblGetNextNode
                // Else
                // drTemp.Close()
                // End If

                // ----------------------------------------------------------------------------------------------------------------------------
                // 5.依 NextNodeID 取出 Node 的基本資料
                strSQL = "Select ProcessNo, ProcessVersion, NodeID, NodeNo, NodeVersion, NodeType From tblPRSNodeBasis " + " Where NodeID ='" + NextNodeID + "'";
                // cmmTemp = New OleDb.OleDbCommand(strSQL, cnnTemp) 
                drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                if (drTemp.Read())
                {
                    int iNodeType = -1;
                    if (!int.TryParse(drTemp["NodeType"].ToString(), out iNodeType))
                        iNodeType = -1;
                    switch (iNodeType)
                    {
                        case 0:  // OP
                            {
                                colGetNextNode.Add(NextNodeID, "NodeID");
                                colGetNextNode.Add(drTemp["NodeNo"], "NodeNo");                  // OPNo
                                colGetNextNode.Add(drTemp["NodeVersion"], "NodeVersion");        // NodeVersion
                                colGetNextNode.Add(drTemp["ProcessNo"], "ProcessNo");            // ProcessNo
                                colGetNextNode.Add(drTemp["ProcessVersion"], "ProcessVersion");  // ProcessVersion
                                colGetNextNode.Add("OP", "NextNodeType");
                                break;
                            }


                        case 1:  // Sub Process
                            {
                                colGetNextNode.Add(NextNodeID, "NodeID");
                                colGetNextNode.Add(drTemp["NodeNo"], "NodeNo");                  // Sub ProcessNo
                                colGetNextNode.Add(drTemp["NodeVersion"], "NodeVersion");        // NodeVersion(可能是*)
                                colGetNextNode.Add(drTemp["ProcessNo"], "ProcessNo");            // ProcessNo
                                colGetNextNode.Add(drTemp["ProcessVersion"], "ProcessVersion");  // ProcessVersion
                                colGetNextNode.Add("PRS", "NextNodeType");
                                break;
                            }


                        case 6:  // And Group
                            {
                                colGetNextNode.Add(NextNodeID, "NodeID");
                                colGetNextNode.Add(drTemp["NodeNo"], "NodeNo");                  // GroupNo(Ex:GROUP6)
                                colGetNextNode.Add(drTemp["NodeVersion"], "NodeVersion");        // NodeVersion
                                colGetNextNode.Add(drTemp["ProcessNo"], "ProcessNo");            // ProcessNo
                                colGetNextNode.Add(drTemp["ProcessVersion"], "ProcessVersion");  // ProcessVersion
                                colGetNextNode.Add("ANDGROUP", "NextNodeType");
                                break;
                            }


                        case 7:  // OR Group
                            {
                                colGetNextNode.Add(NextNodeID, "NodeID");
                                colGetNextNode.Add(drTemp["NodeNo"], "NodeNo");                  // GroupNo(Ex:GROUP7)
                                colGetNextNode.Add(drTemp["NodeVersion"], "NodeVersion");        // NodeVersion
                                colGetNextNode.Add(drTemp["ProcessNo"], "ProcessNo");            // ProcessNo
                                colGetNextNode.Add(drTemp["ProcessVersion"], "ProcessVersion");  // ProcessVersion
                                colGetNextNode.Add("ORGROUP", "NextNodeType");
                                break;
                            }


                        case 9: // END
                            {
                                colGetNextNode.Add(NextNodeID, "NodeID");
                                colGetNextNode.Add(drTemp["NodeNo"], "NodeNo");                  // OPNo
                                colGetNextNode.Add(drTemp["NodeVersion"], "NodeVersion");        // NodeVersion
                                colGetNextNode.Add(drTemp["ProcessNo"], "ProcessNo");            // ProcessNo
                                colGetNextNode.Add(drTemp["ProcessVersion"], "ProcessVersion");  // ProcessVersion
                                colGetNextNode.Add("END", "NextNodeType");
                                break;
                            }


                        case 2:  // Module
                            {
                                colGetNextNode.Add(NextNodeID, "NodeID");
                                colGetNextNode.Add(drTemp["NodeNo"], "NodeNo");                  // Module
                                colGetNextNode.Add(drTemp["NodeVersion"], "NodeVersion");        // NodeVersion(可能是*)
                                colGetNextNode.Add(drTemp["ProcessNo"], "ProcessNo");            // ProcessNo
                                colGetNextNode.Add(drTemp["ProcessVersion"], "ProcessVersion");  // ProcessVersion
                                colGetNextNode.Add("MOD", "NextNodeType");
                                break;
                            }

                        default:
                            {
                                colGetNextNode.Add("WAIT", "NextNodeType");
                                break;
                            }

                    }
                }
                else
                {
                    throw new iMESException.MESException("0000-200003", "[%Process%] [%Nodeinformation%] [%not found%], [%please check%] [%processbasis%]" + Constants.vbCrLf + "[%NodeID%]: " + NextNodeID);
                }
                drTemp.Close();


                lblExitProcedure:
                ;


                GetNextNodeRet = colGetNextNode;
            }

            catch (Exception e1)
            {
                GetNextNodeRet = null;
                throw;
            } // New Exception("kcWIP.GetNextNode: " & e1.Message)

            finally
            {
                // 關閉連線
                CloseConnection(cnnTemp);

            }
            return GetNextNodeRet;

        }

        /// <summary>
        /// 产生位置号与序号(逐字抽出自 funTrackOut_Inquiry 原 :2829-2873,行为不变)
        /// </summary>
        private static bool funInitDieSerial(
            ref List<ArrayList> aryMessage, ref List<ArrayList> aryException,
            string PanleId, string strMLotNo, string strProductNo, string strProductVersion,
            string strSeqNoRule, string strSeqNoType, string strSeqNoSize, string strDirection,
            int intColumn, int intLine, string[,] unitIdOrPannids, string[,] locations,
            IDbConnection cnnTemp)
        {
            string strSQL = default(string);
            DbDataReader drTemp = null;
            string strUnitIdOrPannid = "";//UnitId或者Pannid

            try
            {
                funInitlocation(locations, strSeqNoSize, strDirection, intColumn, intLine);

                for (int i = 0; i < intLine; i++)
                {
                    for (int j = 0; j < intColumn; j++)
                    {
                        PanelidOrUnitId:
                        //校验生成的序号是否有禁用字符
                        DataTable dtSeqNo = InitPanleIdOrUnitId(ReserveSerialNo: false, SerialCount: 1L, SerialTypeNo: strSeqNoRule, LotNo: strMLotNo, PanleId: PanleId, ProductNo: strProductNo, SerialType: strSeqNoType, location: locations[i, j]);

                        if (dtSeqNo.Rows.Count == 0)
                        {
                            clsERP.combineMessage(ref aryMessage, mmsg: "[%产品编号%] :" + strProductNo + " [%产品版本%] :" + strProductVersion + "[%生成序号失败%]");
                            return false;
                        }

                        strUnitIdOrPannid = Conversions.ToString(dtSeqNo.Rows[0]["SeqNo"]);

                        //校验生成的UnitId是否有禁用字符
                        strSQL = $"SELECT DISABLE FROM TBLCUSDISABLEDFIELD WHERE PRODUCTNO='{strProductNo}'";
                        drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                        while (drTemp.Read())
                        {
                            if (strUnitIdOrPannid.Contains(drTemp["DISABLE"].ToString()))
                            {
                                InitPanleIdOrUnitId(ReserveSerialNo: true, SerialCount: 1L, SerialTypeNo: strSeqNoRule, LotNo: strMLotNo, PanleId: PanleId, ProductNo: strProductNo, SerialType: strSeqNoType, location: locations[i, j]);
                                goto PanelidOrUnitId;
                                //clsERP.combineMessage(ref aryMessage, mmsg: "[%序号生成%] : " + strUnitIdOrPannid + "存在禁用字符 :" + drTemp["DISABLE"].ToString() + "，请重新生成!");
                                //return false;
                            }
                        }
                        drTemp.Close();
                        strSQL = $"SELECT UNITID FROM TBLPCSDIELOG_LQ WHERE UNITID='{strUnitIdOrPannid}'";
                        drTemp = ExecuteSQLQuery_Reader(strSQL, cnnTemp);
                        if (drTemp.Read())
                        {
                            clsERP.combineMessage(ref aryMessage, mmsg: "[%UNITID在表TBLPCSDIELOG_LQ中已存在%]");
                            return false;
                        }
                        drTemp.Close();
                        //直接回写序号，防止被占用
                        InitPanleIdOrUnitId(ReserveSerialNo: true, SerialCount: 1L, SerialTypeNo: strSeqNoRule, LotNo: strMLotNo, PanleId: PanleId, ProductNo: strProductNo, SerialType: strSeqNoType, location: locations[i, j]);
                        unitIdOrPannids[i, j] = strUnitIdOrPannid;
                    }
                }

                return true;
            }
            finally
            {
                drTemp?.Close();
            }
        }

        /// <summary>
        /// 写入客制表 TBLPCSDIELOG_LQ(逐字抽出自 funTrackOut_Inquiry 原 :3171-3185,行为不变)
        /// </summary>
        private static void funSaveDieLog(
            string PanleId, string inLotNo, string EQPID, string strOPNO,
            int intColumn, int intLine, string carrierId, string strMNewLotSerial,
            string[,] unitIdOrPannids, string[,] locations, Collection CollectionSQL)
        {
            string strSQL = default(string);

            for (int i = 0; i < intLine; i++)
            {
                for (int j = 0; j < intColumn; j++)
                {
                    strSQL = $@"INSERT INTO TBLPCSDIELOG_LQ ( PANLEID,UNITID,LINE,""COLUMN"",EQPID,OPNO,LOTNO,CREATEDATE,LOCATIONNO ) VALUES('{PanleId}', '{unitIdOrPannids[i, j]}', '{i + 1}', '{j + 1}', '{EQPID}', '{strOPNO}', '{inLotNo}', SYSDATE, '{locations[i, j]}')";
                    CollectionSQL.Add(strSQL);

                    //回复处理
                    strSQL = $"DELETE FROM TBLPCSDIELOG_LQ WHERE PANLEID='{PanleId}' AND LOTNO='{inLotNo}'";

                    objReverse.AddReverseUpdateContent(ref strMNewLotSerial, ref strSQL, CollectionSQL);
                    SaveWIPPrdStateLog_M(LotNo: inLotNo, ProductID: unitIdOrPannids[i, j], EQPID: EQPID, OPNo: strOPNO, State: 1, ProductType: "1", CarrierID: carrierId, LotSerial: strMNewLotSerial, colSQL: CollectionSQL);

                }
            }
        }

        /// <summary>
        /// (xg)解析 mapdata 找出为 0 的位置,依产品走位设定换算成 LOCATIONNO 后打不良(BADFLAG=2、REASONNO='来料异常')
        /// (xg)当传入 unitIdOrPannids 与 MotherLotNo 时，同时将不良品批次归属改回母批，并更新客制状态表 tblwipprdstate_LQ(STATE=2)
        /// </summary>
        /// <param name="MapData">EAP 送出之良品图,依行列自然顺序(row-major)排列,0=不良、1=良品</param>
        /// <param name="strSeqNoSize">该产品之起始角(TBLPRDPRODUCTBASIS.STARTPOINT)</param>
        /// <param name="strDirection">该产品之走向(TBLPRDPRODUCTBASIS.DIRECTION)</param>
        /// <param name="unitIdOrPannids">(xg)各位置对应之 UNITID 二维阵列，传 null 则不更新客制状态表</param>
        /// <param name="MotherLotNo">(xg)母批批号，传 null 则不良品 LOTNO 不变更</param>
        //(xg)原签名: public static bool funMarkBadByMapData(ref List<ArrayList> aryMessage, string PanleId, string LotNo, string MapData, string strSeqNoSize, string strDirection, int intColumn, int intLine, Collection colSQL)
        //(xg)改签名: 新增 unitIdOrPannids, MotherLotNo 两个可选参数
        public static bool funMarkBadByMapData(
            ref List<ArrayList> aryMessage,
            string PanleId, string LotNo, string MapData,
            string strSeqNoSize, string strDirection,
            int intColumn, int intLine, Collection colSQL,
            string[,] unitIdOrPannids = null, string MotherLotNo = null)
        {
            string strSQL = default(string);

            //未传 mapdata 则不打不良、不报错
            if (string.IsNullOrEmpty(MapData))
            {
                return true;
            }

            //长度校验
            if (MapData.Length != intColumn * intLine)
            {
                clsERP.combineMessage(ref aryMessage, mmsg: "[%mapdata长度%]:" + MapData.Length + " [%与行列数不符%]:" + intColumn + "*" + intLine);
                return false;
            }

            //建立与写入 die log 时同源的走位对照表：LOCATIONNO 系沿走位路径编号，
            //并非 mapdata 之行列自然顺序，故不可直接取 k+1(否则仅「左上+全部横向」一种设定会打对)
            string[,] locations = new string[intLine, intColumn];
            funInitlocation(locations, strSeqNoSize, strDirection, intColumn, intLine);

            //(xg)新增: 当传入了 unitIdOrPannids 与 MotherLotNo 时，一并执行不良品归母批 + 客制状态表更新
            bool bolUpdateState = (unitIdOrPannids != null && !string.IsNullOrEmpty(MotherLotNo));

            for (int k = 0; k < MapData.Length; k++)
            {
                //0 = 不良、1 = 良品
                if (MapData[k] == '0')
                {
                    //mapdata 第 k 位 → 第 (k / intLine) 行、第 (k % intLine) 列
                    int intRow = k / intLine;
                    int intCol = k % intLine;
                    string strLocationNo = locations[intCol, intRow];

                    if (bolUpdateState)
                    {
                        //(xg)新增1.更新 TBLPCSDIELOG_LQ：打不良标记 + 改批次归属为母批 LOTNO=MotherLotNo（只分良品，不分不良品）
                        //strSQL = $@"UPDATE TBLPCSDIELOG_LQ SET BADFLAG = 2, REASONNO = '来料异常', LOTNO = '{MotherLotNo}' WHERE LOCATIONNO = '{strLocationNo}' AND PANLEID = '{PanleId}' AND LOTNO = '{LotNo}'";
                        strSQL = $@"UPDATE TBLPCSDIELOG_LQ SET BADFLAG = 2, REASONNO = '来料异常' WHERE LOCATIONNO = '{strLocationNo}' AND PANLEID = '{PanleId}' AND LOTNO = '{LotNo}'";
                        colSQL.Add(strSQL);

                        //(xg)新增2.更新客制状态表 tblwipprdstate_LQ：不良品状态 STATE 改为 2
                        string strUnitId = unitIdOrPannids[intCol, intRow];
                        strSQL = $@"UPDATE TBLWIPPRDSTATE_LQ SET STATE = 2 WHERE PRODUCTID = '{strUnitId}' AND PRODUCTTYPE = '1' AND STATE = 1";
                        colSQL.Add(strSQL);
                    }
                    else
                    {
                        //原版行为：仅打不良标记 BADFLAG=2、REASONNO='来料异常'，不做批次归属变更
                        strSQL = $@"UPDATE TBLPCSDIELOG_LQ SET BADFLAG = 2, REASONNO = '来料异常' WHERE LOCATIONNO = '{strLocationNo}' AND PANLEID = '{PanleId}' AND LOTNO = '{LotNo}'";
                        colSQL.Add(strSQL);
                    }
                }
            }

            return true;
        }


        /// <summary>
        /// 产生位置号与序号并写入 TBLPCSDIELOG_LQ(自 funTrackOut_Inquiry 逐字抽出,行为不变)
        /// </summary>
        /// <param name="MotherLotNo">母批批号,供序号产生器使用(等同首站接口的 strMLotNo)</param>
        /// <param name="LotNo">记录批号,写入客制表使用;有分批时为子批(等同首站接口的 inLotNo)</param>
        public static bool funCreateDieLog(
            ref List<ArrayList> aryMessage, ref List<ArrayList> aryException,
            string PanleId, string MotherLotNo, string LotNo, string EQPID, string OPNO,
            string ProductNo, string ProductVersion,
            string SeqNoRule, string SeqNoType, string SeqNoSize, string Direction,
            int intColumn, int intLine, string CarrierId, string LotSerial,
            Collection colSQL, IDbConnection cnnTemp)
        {
            string[,] unitIdOrPannids = new string[intLine, intColumn];
            string[,] locations = new string[intLine, intColumn];

            //产生位置号与序号：序号产生器用母批
            if (!funInitDieSerial(ref aryMessage, ref aryException, PanleId, MotherLotNo, ProductNo, ProductVersion, SeqNoRule, SeqNoType, SeqNoSize, Direction, intColumn, intLine, unitIdOrPannids, locations, cnnTemp))
            {
                return false;
            }

            //写入客制表：die log 用记录批号（有分批时为子批）
            funSaveDieLog(PanleId, LotNo, EQPID, OPNO, intColumn, intLine, CarrierId, LotSerial, unitIdOrPannids, locations, colSQL);

            return true;
        }

















        /// <summary>
        /// 出站
        /// </summary>
        /// <param name="aryMessage"></param>
        /// <param name="aryException"></param>
        /// <param name="MONO"></param>
        /// <param name="EQPID"></param>
        /// <param name="PanleId"></param>
        /// <param name="Column"></param>
        /// <param name="Line"></param>
        /// <param name="carrierId"></param>
        /// <param name="Qty"></param>
        /// <returns></returns>
        // 17单:作业站属性存在即生效(M7)——服务端直查 TBLOPPROPERTY
        private static bool funOPPropertyExists_LQ(string OPNO, string PropertyNo, IDbConnection cnnTemp)
        {
            DataTable dt = new DataTable();
            string strSQL = $"SELECT 1 FROM TBLOPPROPERTY WHERE OPNO='{OPNO}' AND PROPERTYNO='{PropertyNo}' AND ISSUESTATE=2";
            ExecuteSQLQuery_Adapter(strSQL, dt, cnnTemp);
            return dt.Rows.Count > 0;
        }

        // 17单 M6(内联,EAItc 不引用 MEStc_LQ):TRAY 上无 carrier 则寿命+1(门槛),
        // 达报废(3)/维修(2)则保留该状态,未触门槛才置闲置(0)——等价 MEStc_LQ.clsEQP.EditCarrierLife + M6 优先序
        private static void funUnbindTrayLife_LQ(string CarrierId, string TrayId, string UserNo, string strDataBaseType, string strConnectionString, IDbConnection cnnTemp)
        {
            // 删该 carrier 在 TRAY 的绑定明细
            Collection colDel = new Collection();
            colDel.Add($"delete from TBLWIPTRAYSTATE_LQ where trayid='{TrayId}' and carrierid='{CarrierId}'");
            ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, colDel);

            // TRAY 上是否还有 carrier
            DataTable dtRest = new DataTable();
            ExecuteSQLQuery_Adapter($"select 1 from TBLWIPTRAYSTATE_LQ where trayid='{TrayId}'", dtRest, cnnTemp);
            if (dtRest.Rows.Count > 0) return;

            // 取 TRAY 的 CarrierType
            string strType = "";
            DataTable dtCt = new DataTable();
            ExecuteSQLQuery_Adapter($"select CarrierType from tblWIPCarrierState where CarrierNo='{TrayId}'", dtCt, cnnTemp);
            if (dtCt.Rows.Count > 0) strType = dtCt.Rows[0]["CarrierType"].ToString();

            Collection colLife = new Collection();
            string strNewState = "0"; // 默认闲置
            DataTable dtSet = new DataTable();
            ExecuteSQLQuery_Adapter($"select ALERTCOUNT,LIMITCOUNT,SCRAPCOUNT from TBLCUSCARRIERLIFESET where CARRIERTYPE='{strType}'", dtSet, cnnTemp);
            if (dtSet.Rows.Count > 0)
            {
                DataTable dtLife = new DataTable();
                ExecuteSQLQuery_Adapter($"select ACCUMULATEQTY,ACCTOTALUSEDQTY from TBLCUSCARRIERLIFE where CARRIERNO='{TrayId}'", dtLife, cnnTemp);
                if (dtLife.Rows.Count > 0)
                {
                    decimal accQty = decimal.Parse(dtLife.Rows[0]["ACCUMULATEQTY"].ToString());
                    decimal accTotal = decimal.Parse(dtLife.Rows[0]["ACCTOTALUSEDQTY"].ToString());
                    decimal limitCnt = decimal.Parse(dtSet.Rows[0]["LIMITCOUNT"].ToString());
                    decimal scrapCnt = decimal.Parse(dtSet.Rows[0]["SCRAPCOUNT"].ToString());
                    if (accTotal + 1 >= scrapCnt) strNewState = "3";      // 报废
                    else if (accQty + 1 >= limitCnt) strNewState = "2";   // 维修
                    colLife.Add($"update TBLCUSCARRIERLIFE set ACCUMULATEQTY=ACCUMULATEQTY+1, ACCTOTALUSEDQTY=ACCTOTALUSEDQTY+1, REVISER='{UserNo}', REVISEDATE=sysdate where CARRIERNO='{TrayId}'");
                }
            }
            // M6 优先序:门槛(3/2)优先,未触门槛才置闲置(0)
            colLife.Add($"update TBLWIPCARRIERSTATE set CARRIERSTATE={strNewState} where CARRIERNO='{TrayId}'");
            ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, colLife);
        }

        // 17单 需求二/三:依作业站属性自动解绑(TRAY / 小载具)+ 分批出站(隐藏站转移)
        // 回传 false=属性分支执行失败;bolHandled=true 表示已处理完成,呼叫端不再走标准判型出站
        private static bool funAutoUnbindCheckOut_LQ(ref List<ArrayList> aryMessage, string Type, string strProductID_Auto, string strCarrierID_Auto, string EQPID, out bool bolHandled)
        {
            bolHandled = false;
            AppSettings objSetting = new AppSettings();
            string strDataBaseType = objSetting.GetDataBaseType();
            string strConnectionString = objSetting.GetConnectionString(strDataBaseType);
            IDbConnection cnnTemp = CreateConnection(strConnectionString);
            const string UserNo = "EAP";
            try
            {
                // 1.由 ID 反查母批 LotNo
                //   ★同一载具上可能同时存在多笔 STATE=1 明细:依载具分批出站后,片(PRODUCTTYPE=0)的明细列
                //     仍挂在已分批结批消耗的母批上,与新子批的颗明细共存于同一 CARRIERID。
                //     若不加区别地取第一笔,可能取到已结批的批号(Oracle 不保证回传顺序),
                //     下一步在 TBLWIPLOTSTATE 便查无该批而退回标准流程,现象即为「解绑逻辑触发不了」,
                //     且随着该载具每次成功解绑而累积残留列,失败机率愈来愈高。
                //     故此处 inner join TBLWIPLOTSTATE 只取仍在制的批,并明确排序确保结果稳定。
                string strSQL;
                string strIdCond = Type == "2"
                                   ? $"P.CARRIERID = '{strCarrierID_Auto}'"
                                   : $"P.PRODUCTID = '{strProductID_Auto}'";
                strSQL = $@"select distinct P.LOTNO as LotNo from TBLWIPPRDSTATE_LQ P inner join TBLWIPLOTSTATE S on S.LOTNO = P.LOTNO where {strIdCond} and P.STATE = 1 order by 1";
                DataTable dtLot = new DataTable();
                ExecuteSQLQuery_Adapter(strSQL, dtLot, cnnTemp);
                if (dtLot.Rows.Count == 0)
                {
                    // 找不到明细,交回标准流程;留下讯息供现场判读,否则此处静默退出无从追查
                    clsERP.combineMessage(ref aryMessage, mmsg: (Type == "2" ? strCarrierID_Auto : strProductID_Auto) + "[%：在TBLWIPPRDSTATE_LQ查无仍在制的在制明细(STATE=1),不执行自动解绑,按标准流程出站%]");
                    return true;
                }
                string strMLotNo = dtLot.Rows[0]["LotNo"].ToString();
                if (dtLot.Rows.Count > 1)
                {
                    // 对应到多个仍在制的生产批属资料异常;取排序后第一笔续行,并留下讯息供现场厘清,不静默带过
                    string strLots = "";
                    foreach (DataRow rLot in dtLot.Rows)
                        strLots += (strLots == "" ? "" : ",") + rLot["LotNo"].ToString();
                    clsERP.combineMessage(ref aryMessage, mmsg: (Type == "2" ? strCarrierID_Auto : strProductID_Auto) + "[%：对应到多个在制生产批%](" + strLots + ")[%,已取%]" + strMLotNo + "[%续行,请确认明细资料%]");
                }

                // 2.取母批在制信息
                DataTable dtSt = new DataTable();
                strSQL = $"SELECT A.OPNO,A.LOTSTAMP,A.CURQTY,A.CURUNITNO,A.LOTSERIAL,B.PRODUCTNO,B.PRODUCTVERSION FROM TBLWIPLOTSTATE A LEFT JOIN TBLWIPLOTBASIS B ON A.LOTNO = B.BASELOTNO WHERE A.LOTNO = '{strMLotNo}'";
                ExecuteSQLQuery_Adapter(strSQL, dtSt, cnnTemp);
                if (dtSt.Rows.Count == 0)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: strMLotNo + "[%：在TBLWIPLOTSTATE查无该批在制资料,不执行自动解绑,按标准流程出站%]");
                    return true;
                }
                string strOPNO = dtSt.Rows[0]["OPNO"].ToString();
                long lngLotStamp = Conversions.ToLong(dtSt.Rows[0]["LOTSTAMP"].ToString());
                string strUnitNo = dtSt.Rows[0]["CURUNITNO"].ToString();
                string strProductNo = dtSt.Rows[0]["PRODUCTNO"].ToString();
                string strProductVersion = dtSt.Rows[0]["PRODUCTVERSION"].ToString();

                // 3.读作业站属性(M7 存在即生效)+ M8 互斥
                bool blnAutoTray = funOPPropertyExists_LQ(strOPNO, "自动解绑TRAY", cnnTemp);
                bool blnUnitUnbind = funOPPropertyExists_LQ(strOPNO, "unit出站解绑载具", cnnTemp);
                if (blnAutoTray && blnUnitUnbind)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: "[%本作业站同时设定【自动解绑TRAY】与【unit出站解绑载具】,请择一%]");
                    return false;
                }
                if (!blnAutoTray && !blnUnitUnbind)
                {
                    // 无属性,走标准流程;留下讯息指明查的是哪一站,便于现场核对作业站属性维护
                    clsERP.combineMessage(ref aryMessage, mmsg: strOPNO + "[%：未设定【自动解绑TRAY】或【unit出站解绑载具】属性,不执行自动解绑,按标准流程出站%]");
                    return true;
                }

                bool blnByCarrier = blnAutoTray; // true=一 carrier 一批(解绑TRAY);false=一 unit 一批(解绑小载具)

                // 4.B1 防呆:一 carrier 一批时,存在未绑载具单位则挡下(否则 Σ子批≠CurQty)
                if (blnByCarrier)
                {
                    DataTable dtNoCar = new DataTable();
                    ExecuteSQLQuery_Adapter($"select count(*) as CNT from TBLWIPPRDSTATE_LQ where LotNo='{strMLotNo}' and producttype=1 and state=1 and (carrierid is null or carrierid='')", dtNoCar, cnnTemp);
                    if (dtNoCar.Rows.Count > 0 && decimal.Parse(dtNoCar.Rows[0]["CNT"].ToString()) > 0)
                    {
                        clsERP.combineMessage(ref aryMessage, mmsg: "[%存在未绑定载具的单位,不可出站%]");
                        return false;
                    }
                }

                // 5.分组(carrier / unit)
                DataTable dtGroup = new DataTable();
                if (blnByCarrier)
                    ExecuteSQLQuery_Adapter($"select carrierid as KEYID, count(*) as CNT from TBLWIPPRDSTATE_LQ where LotNo='{strMLotNo}' and producttype=1 and state=1 group by carrierid", dtGroup, cnnTemp);
                else
                    ExecuteSQLQuery_Adapter($"select productid as KEYID, 1 as CNT from TBLWIPPRDSTATE_LQ where LotNo='{strMLotNo}' and producttype=1 and state=1", dtGroup, cnnTemp);
                if (dtGroup.Rows.Count == 0)
                {
                    clsERP.combineMessage(ref aryMessage, mmsg: strMLotNo + "[%：查无PRODUCTTYPE=1且STATE=1的在制明细,无法分批,不执行自动解绑,按标准流程出站%]");
                    return true;
                }

                // 6.取子批号(整批拆分,不含母批;母批以分批結批消耗)
                List<string> lstSubLot = new List<string>();
                using (kcSYS.clsSYSEng objSYSEng = new kcSYS.clsSYSEng())
                {
                    for (int k = 0; k < dtGroup.Rows.Count; k++)
                        lstSubLot.Add(objSYSEng.GetSplitLotNo(true, strMLotNo, ""));
                }

                // 7.建分批表
                DataTable dtSplitLot = new DataTable("SplitLot");
                dtSplitLot.Columns.Add("SplitLotNo", typeof(string));
                dtSplitLot.Columns.Add("SplitLotQty", typeof(decimal));
                dtSplitLot.Columns.Add("SplitSysQty", typeof(decimal));
                dtSplitLot.Columns.Add("Action", typeof(int));
                dtSplitLot.Columns.Add("NodeID", typeof(string));
                dtSplitLot.Columns.Add("ReturnType", typeof(int));
                dtSplitLot.Columns.Add("FromProductNo", typeof(string));
                dtSplitLot.Columns.Add("FromProductVersion", typeof(string));
                dtSplitLot.Columns.Add("ProductNo", typeof(string));
                dtSplitLot.Columns.Add("ProductVersion", typeof(string));
                dtSplitLot.Columns.Add("UnitNo", typeof(string));
                dtSplitLot.Columns.Add("OPNo", typeof(string));
                dtSplitLot.Columns.Add("KeyId", typeof(string));
                for (int k = 0; k < dtGroup.Rows.Count; k++)
                {
                    DataRow dr = dtSplitLot.NewRow();
                    dr["SplitLotNo"] = lstSubLot[k];
                    dr["SplitLotQty"] = dtGroup.Rows[k]["CNT"];
                    dr["SplitSysQty"] = dtGroup.Rows[k]["CNT"];
                    dr["Action"] = 0;
                    dr["NodeID"] = "";
                    dr["ReturnType"] = 0;
                    dr["FromProductNo"] = strProductNo;
                    dr["FromProductVersion"] = strProductVersion;
                    dr["ProductNo"] = strProductNo;
                    dr["ProductVersion"] = strProductVersion;
                    dr["UnitNo"] = strUnitNo;
                    dr["OPNo"] = strOPNO;
                    dr["KeyId"] = dtGroup.Rows[k]["KEYID"].ToString();
                    dtSplitLot.Rows.Add(dr);
                }

                // 8.执行分批(kernel;整批拆分,母批消耗结批)
                //   SplitType 必须为 1(BR分批):kc 註明「若是BR則分批完成,Status要變更為4」,
                //   子批 Status=4 才允许後續 BRTransferLot_Bin_M(否则 0000-203033)。SplitType=0 是站中手動分批,不變更狀態。
                using (kcWIP.clsLot objLot = new kcWIP.clsLot())
                {
                    //   LinkName 必须传 "PASS":子批 LINKNAME 若留空,後續 TransferLot_Bin_M 会以空字串去 GetNextBR,
                    //   查无下一个 BR 而报「Next BR is not exist」。传 PASS 不影响 Status(仅 HOLD/WAIT 走别的分支)。
                    objLot.BR_Manual_LotSplit(lngLotStamp, strMLotNo, 1, UserNo, dtSplitLot, LinkName: "PASS");
                }

                // 9.明细更新(carrier:清 TRAYID 留 carrierid;unit:清 carrierid/LOCATIONNO)
                Collection CollectionSQL = new Collection();
                // TBLPCSDIELOG_LQ 的两种比对键分开收集:PANLEID 是整片 panel 一起更新(粗),
                // UNITID 只动一颗(精确)。粗的先执行、精确的后执行,同一片 panel 的单位分散在
                // 不同载具(=不同子批)时,才不会被 panel 那笔回头盖掉。
                Collection colDiePanel = new Collection();
                Collection colDieUnit = new Collection();
                bool blnPanelCloned = false;   // 有补过子批片明细才需要让母批片明细退场
                Dictionary<string, string> dicTrayCarrier = new Dictionary<string, string>();
                foreach (DataRow dr in dtSplitLot.Rows)
                {
                    string strSubLot = dr["SplitLotNo"].ToString();
                    string strKey = dr["KeyId"].ToString();
                    string strSubOP = strOPNO;
                    DataTable dtSub = new DataTable();
                    ExecuteSQLQuery_Adapter($"select OPNO from tblwiplotstate where LotNo='{strSubLot}'", dtSub, cnnTemp);
                    if (dtSub.Rows.Count > 0) strSubOP = dtSub.Rows[0]["OPNO"].ToString();

                    if (blnByCarrier)
                    {
                        // 明细须锁定母批:同一载具上若有其他批的残留单位,未锁批会被一并改挂到子批
                        DataTable dtCar = new DataTable();
                        ExecuteSQLQuery_Adapter($"select TRAYID from TBLWIPPRDSTATE_LQ where carrierid='{strKey}' and producttype=1 and state=1 and lotno='{strMLotNo}'", dtCar, cnnTemp);
                        if (dtCar.Rows.Count > 0)
                        {
                            // 取第一个非空 TRAYID(不可用 Rows[0],该列 TRAYID 可能为空而漏掉整段解绑)
                            string strTray = "";
                            foreach (DataRow rTray in dtCar.Rows)
                            {
                                string strTmpTray = rTray["TRAYID"].ToString();
                                if (!string.IsNullOrEmpty(strTmpTray)) { strTray = strTmpTray; break; }
                            }
                            if (!string.IsNullOrEmpty(strTray) && !dicTrayCarrier.ContainsKey(strKey)) dicTrayCarrier.Add(strKey, strTray);
                        }
                        // 子批号等于母批号代表未真正分批,补片明细会变成自我复制,故略过
                        bool blnDoPanel = strSubLot != strMLotNo;

                        // 颗明细改挂前先补履历(来源列此时仍在母批上)
                        if (blnDoPanel) funAddUnitLogForSubLot_LQ(strMLotNo, strSubLot, strSubOP, strKey, CollectionSQL);

                        CollectionSQL.Add($"update tblwipprdstate_LQ set lotno='{strSubLot}', opno='{strSubOP}', TRAYID='', TRAYPOSITION='' where carrierid='{strKey}' and producttype='1' and state='1' and lotno='{strMLotNo}'");

                        // 片明细依子批各补一笔
                        if (blnDoPanel)
                        {
                            funAddPanelRowsForSubLot_LQ(strMLotNo, strSubLot, strSubOP, strKey, CollectionSQL, cnnTemp);
                            blnPanelCloned = true;
                        }

                        // 同步产品履历表 TBLPCSDIELOG_LQ 的批号与作业站:
                        // 依该载具下每列的 PRODUCTTYPE 决定比对键——0=Panel 用 PANLEID,1=Unit 用 UNITID
                        DataTable dtDie = new DataTable();
                        ExecuteSQLQuery_Adapter($"select PRODUCTID, PRODUCTTYPE from TBLWIPPRDSTATE_LQ where carrierid='{strKey}' and state=1 and lotno='{strMLotNo}'", dtDie, cnnTemp);
                        foreach (DataRow rDie in dtDie.Rows)
                        {
                            bool blnPanel = rDie["PRODUCTTYPE"].ToString() == "0";
                            string strKeyCol = blnPanel ? "PANLEID" : "UNITID";
                            string strDieSQL = $"update TBLPCSDIELOG_LQ set LOTNO='{strSubLot}', OPNO='{strSubOP}' where {strKeyCol}='{rDie["PRODUCTID"]}'";
                            if (blnPanel) colDiePanel.Add(strDieSQL); else colDieUnit.Add(strDieSQL);
                        }
                    }
                    else
                    {
                        CollectionSQL.Add($"update tblwipprdstate_LQ set lotno='{strSubLot}', opno='{strSubOP}', carrierid=null, LOCATIONNO=null where productid='{strKey}' and producttype='1' and state='1'");

                        // 同步产品履历表 TBLPCSDIELOG_LQ:一 unit 一批,分组键即 UNITID
                        colDieUnit.Add($"update TBLPCSDIELOG_LQ set LOTNO='{strSubLot}', OPNO='{strSubOP}' where UNITID='{strKey}'");
                    }
                }
                // 先粗后精:panel 层全部更新完,再让 unit 层逐颗覆写成各自子批
                foreach (string s in colDiePanel) CollectionSQL.Add(s);
                foreach (string s in colDieUnit) CollectionSQL.Add(s);

                // 母批片明细退场:必须排在所有子批片明细 insert 之后(那些 insert 以这些列为来源)
                if (blnPanelCloned)
                {
                    CollectionSQL.Add($"update TBLWIPPRDSTATE_LQ set STATE=0 where lotno='{strMLotNo}' and producttype='0' and state=1");
                }

                ExecuteSQLNoneQuery_UPD(strDataBaseType, strConnectionString, CollectionSQL);

                // 10.carrier:解绑TRAY + 寿命门槛(M6)
                if (blnByCarrier)
                {
                    foreach (KeyValuePair<string, string> kv in dicTrayCarrier)
                        funUnbindTrayLife_LQ(kv.Key, kv.Value, UserNo, strDataBaseType, strConnectionString, cnnTemp);
                }

                // 11.逐子批出站转移(BRTransferLot_Bin_M 内含隐藏站规则 —— M11)。
                //    子批 Status 已由步骤 8 的 BR 分批(SplitType=1)置为 4,此处直接转移;比照母本 clsEAP.cs:2975→2987。
                foreach (DataRow dr in dtSplitLot.Rows)
                {
                    string strSubLot = dr["SplitLotNo"].ToString();
                    string strComputerName = System.Net.Dns.GetHostName();

                    BRTransferLot_Bin_M(strSubLot, UserNo, "PASS", 0, defString, ComputerName: strComputerName, RuleMsg: "");
                }

                clsERP.combineMessage(ref aryMessage, mmsg: strMLotNo + "[%：出站并自动解绑成功%]");
                bolHandled = true;
                return true;
            }
            catch (Exception ex)
            {
                clsERP.combineMessage(ref aryMessage, mmsg: "[%自动解绑出站失败%]:" + ex.Message);
                return false;
            }
            finally
            {
                CloseConnection(cnnTemp);
            }
        }

        // 17单(内联,EAItc 不引用 MEStc_LQ):依载具分批时,片(PRODUCTTYPE=0)明细依子批各补一笔
        // 现况列 + 一笔履历列。★片与颗的对应以产品履历 TBLPCSDIELOG_LQ 的 PANLEID/UNITID 为准,
        // 不可直接沿用载具上的片列——同一载具的片未必与该载具的颗同片,而同一片的颗又会散落到不同子批。
        // ★母批原片列的退场(STATE=0)由呼叫端在所有子批处理完后统一执行:先退场会让后续子批取不到来源列。
        // 与 MEStc_LQ.clsWIP.funAddPanelRowsForSubLot_LQ 等价,履历写入比照 14 单既有模式。
        private static void funAddPanelRowsForSubLot_LQ(string LotNo, string strSubLot, string strSubOP,
                                                        string strCarrierId, Collection colSQL, IDbConnection cnnTemp)
        {
            DataTable dtPanel = new DataTable();
            ExecuteSQLQuery_Adapter($"select distinct D.PANLEID from TBLPCSDIELOG_LQ D where D.UNITID in (select PRODUCTID from TBLWIPPRDSTATE_LQ where carrierid='{strCarrierId}' and producttype='1' and state='1' and lotno='{LotNo}')", dtPanel, cnnTemp);

            foreach (DataRow drPanel in dtPanel.Rows)
            {
                string strPanelId = drPanel["PANLEID"].ToString();
                if (string.IsNullOrEmpty(strPanelId)) continue;

                colSQL.Add($"insert into TBLWIPPRDSTATE_LQ (LOTNO,PRODUCTID,EQPID,STATE,OPNO,CARRIERID,PRODUCTTYPE,CREATEDATE,TRAYID,TRAYPOSITION) select '{strSubLot}',PRODUCTID,EQPID,1,'{strSubOP}',CARRIERID,PRODUCTTYPE,SYSDATE,'','' from TBLWIPPRDSTATE_LQ where lotno='{LotNo}' and productid='{strPanelId}' and producttype='0' and state=1");
                colSQL.Add($"insert into TBLWIPPRDLOG_LQ (LOTNO,PRODUCTID,EQPID,OPNO,CARRIERID,PRODUCTTYPE,CREATEDATE) select '{strSubLot}',PRODUCTID,EQPID,'{strSubOP}',CARRIERID,PRODUCTTYPE,SYSDATE from TBLWIPPRDSTATE_LQ where lotno='{LotNo}' and productid='{strPanelId}' and producttype='0' and state=1");
            }
        }

        // 17单(内联):颗明细改挂子批时补一笔履历。★必须在颗明细被 update 改挂之前加入集合。
        private static void funAddUnitLogForSubLot_LQ(string LotNo, string strSubLot, string strSubOP,
                                                      string strCarrierId, Collection colSQL)
        {
            colSQL.Add($"insert into TBLWIPPRDLOG_LQ (LOTNO,PRODUCTID,EQPID,OPNO,CARRIERID,PRODUCTTYPE,CREATEDATE) select '{strSubLot}',PRODUCTID,EQPID,'{strSubOP}',CARRIERID,PRODUCTTYPE,SYSDATE from TBLWIPPRDSTATE_LQ where lotno='{LotNo}' and carrierid='{strCarrierId}' and producttype='1' and state=1");
        }

    }


}
