Beispiel #1
0
        private static bool ExistInflowWip(FabAoEquipment eqp, JobFilterInfo info)
        {
            var wf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_ALLOW_RUN_DOWN_TIME);

            if (wf == null || wf.Factor == 0)
            {
                return(false);
            }

            decimal inflowHour = (decimal)wf.Criteria[0];

            if (inflowHour <= 0)
            {
                return(false);
            }

            var     idleTime   = eqp.GetIdleRunTime();
            decimal adjustHour = inflowHour - Convert.ToDecimal(idleTime.TotalHours);

            if (adjustHour <= 0)
            {
                return(false);
            }

            var inflowQty = InFlowMaster.GetAllowRunDownWip(eqp, info.ProductID, info.ProductVersion, info.OwnerType, info.Step, adjustHour);

            return(inflowQty > 0);
        }
Beispiel #2
0
        private static bool IsFilterDummyWaitEqp(this JobFilterInfo info, FabAoEquipment eqp, List <FabAoEquipment> eqpList)
        {
            if (eqpList == null)
            {
                return(false);
            }

            WeightFactor wf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_DUMMY_WAIT_EQP_FILTER);

            if (wf == null || wf.Factor == 0)
            {
                return(false);
            }

            //연속진행인 경우
            if (info.IsRunning)
            {
                return(false);
            }

            var waitEqps = eqpList.FindAll(x => x.IsDummyWait);

            bool isFilter = waitEqps.Count > 0;

            return(isFilter);
        }
Beispiel #3
0
        internal static double GetNewAssignNeedCnt(this JobFilterInfo info, FabAoEquipment eqp, double inflowHour, double workCnt)
        {
            double reqCnt  = info.GetRequiredEqpCnt(eqp, (decimal)inflowHour);
            double needCnt = GetNewAssignNeedCnt(reqCnt, workCnt);

            return(needCnt);
        }
Beispiel #4
0
        private static bool IsFilterRunMode(this JobFilterInfo info, FabAoEquipment eqp, List <JobFilterInfo> jobList)
        {
            WeightFactor wf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_RUN_MODE_FILTER);

            if (wf == null || wf.Factor == 0)
            {
                return(false);
            }

            //연속진행인 경우
            if (info.IsRunning)
            {
                return(false);
            }

            string eqpGroup = eqp.TargetEqp.EqpGroup;
            string runMode  = eqp.GetCurrentRunMode();

            var branchStep = BranchStepMaster.GetBranchStep(eqpGroup, runMode);

            if (branchStep == null)
            {
                return(false);
            }

            if (branchStep.IsAllProduct)
            {
                return(false);
            }

            var productList = branchStep.ProductList;

            if (productList == null || productList.Count == 0)
            {
                return(false);
            }

            string productID = info.ProductID;
            string ownerType = info.OwnerType;

            bool isFilter = true;

            if (branchStep.IsLoadable(productID, ownerType))
            {
                isFilter = false;
            }

            if (isFilter)
            {
                string defaultOwnerType = SiteConfigHelper.GetDefaultOwnerType();
                if (ExistRemainWip(jobList, productList, defaultOwnerType) == false)
                {
                    isFilter = false;
                }
            }

            return(isFilter);
        }
Beispiel #5
0
        public static decimal GetInflowQty(JobFilterInfo info, AoEquipment aeqp, decimal inflowHour, int excludeStepCnt)
        {
            string  productID = info.ProductID;
            string  prodVer   = info.ProductVersion;
            string  owerType  = info.OwnerType;
            FabStep step      = info.Step;

            return(GetInflowQty(productID, prodVer, owerType, step, aeqp, inflowHour, excludeStepCnt));
        }
Beispiel #6
0
        public static void SetSetupTime(this JobFilterInfo info, AoEquipment aeqp)
        {
            FabLot lot = info.Sample;

            if (lot == null)
            {
                return;
            }

            info.SetupTime = SetupMaster.GetSetupTime(aeqp, lot);

            var eqp = aeqp.ToFabAoEquipment();
        }
Beispiel #7
0
        private static bool IsWaitSmallSizeLot(AoEquipment aeqp, JobFilterInfo info, FabLot lot, double waitQty, double setupTime, double ratio, StepTime st)
        {
            var step = lot.CurrentFabStep;

            if (step == null)
            {
                return(false);
            }

            var stdStep = step.StdStep;

            if (stdStep == null || stdStep.IsInputStep)
            {
                return(false);
            }

            FabAoEquipment eqp = aeqp.ToFabAoEquipment();

            TimeSpan firstInflowTime = TimeSpan.FromMinutes(setupTime);
            decimal  allowTime       = 3m;

            WeightFactor wf;

            WeightHelper.TryGetEqpWeightFactor(eqp, Constants.WF_ALLOW_RUN_DOWN_TIME, out wf);
            if (wf != null)
            {
                allowTime = (decimal)wf.Criteria[0];
            }

            double inflowQty1 = Convert.ToDouble(InFlowAgent.GetInflowQty(info, aeqp, (decimal)firstInflowTime.TotalHours, 0));
            double inflowQty2 = Convert.ToDouble(InFlowAgent.GetInflowQty(info, aeqp, allowTime, 0));

            double waitQty1 = waitQty + inflowQty1;
            double waitQty2 = waitQty + inflowQty2;

            //Setup 시간 이내에 유입이 있나?
            if (LcdHelper.IsIncludeInRange(waitQty, waitQty1 * 0.95d, waitQty1 * 1.05d))
            {
                //지정된 시간내에 유입재공이 있나?
                if (LcdHelper.IsIncludeInRange(waitQty, waitQty2 * 0.95d, waitQty2 * 1.05d))
                {
                    double requiredSec = st.TactTime * waitQty2;

                    bool isSmall = requiredSec < setupTime * 60 * ratio;

                    return(isSmall);
                }
            }

            return(false);
        }
Beispiel #8
0
        public static int GetWorkingEqpCount(this FabStdStep stdStep, JobFilterInfo info, bool checkProductVersion = true, bool onlyParent = true)
        {
            if (info == null)
            {
                return(0);
            }

            string productID = info.ProductID;
            string prodVer   = info.ProductVersion;
            string ownerType = info.OwnerType;
            string ownerID   = info.OwnerID;

            return(GetWorkingEqpCount(stdStep, productID, prodVer, ownerType, ownerID, checkProductVersion, onlyParent));
        }
Beispiel #9
0
        public static List <FabAoEquipment> InitJobFilterInfo(this JobFilterInfo info, FabAoEquipment eqp, Dictionary <string, List <FabAoEquipment> > workingEqps)
        {
            info.IsRunning = eqp.CheckIsRunning(info);

            var key = FilterHelper.GetJobFilterKey(info);

            List <FabAoEquipment> eqpList;

            workingEqps.TryGetValue(key, out eqpList);

            if (eqpList == null || eqpList.Count == 0)
            {
                info.IsNoAssign = true;
            }

            info.SetHarmonicTactInfo(eqp, eqpList);
            info.SetSetupTime(eqp);

            return(eqpList);
        }
Beispiel #10
0
        private static double GetRequiredEqpCnt(this JobFilterInfo info, FabAoEquipment eqp, decimal inflowHour)
        {
            decimal inflowQty = InFlowAgent.GetInflowQty(info, eqp, inflowHour, 0);

            decimal avtTact = info.HarmonicAvgTact;

            if (eqp.IsParallelChamber)
            {
                avtTact = info.HarmonicAvgTact / eqp.GetChamberCapacity();
            }

            decimal inflowSec   = inflowHour * 3600;
            double  requiredEqp = Convert.ToSingle(inflowQty * avtTact / Math.Max(inflowSec, 1));

            if (requiredEqp <= 0)
            {
                requiredEqp = 0;
            }

            return(requiredEqp);
        }
Beispiel #11
0
        private static bool IsFilterNewEqpAssign(JobFilterInfo info, FabAoEquipment eqp, double inflowHour, int workCnt, out string reason)
        {
            reason = string.Empty;

            double needCnt = Math.Round(info.GetNewAssignNeedCnt(eqp, inflowHour, workCnt), 2);

            bool isFilter = needCnt < 1;

            if (isFilter)
            {
                reason = string.Format("HOUR({0}):REQ({1}), WORK({2}):{3} < 1",
                                       Math.Round(inflowHour, 2),
                                       Math.Round(needCnt, 2),
                                       workCnt,
                                       needCnt);
            }

            info.NewAssignNeedCount = needCnt;

            return(needCnt < 1);
        }
Beispiel #12
0
        public static bool CheckIsRunning(this FabAoEquipment eqp, JobFilterInfo info)
        {
            if (eqp.Loader.IsBlocked())
            {
                return(false);
            }

            string shopID     = eqp.TargetEqp.ShopID;
            string stepID     = info.Step.StepID;
            string productID  = info.ProductID;
            string productVer = info.ProductVersion;
            string ownerType  = info.OwnerType;
            string ownerID    = info.OwnerID;

            if (eqp.IsLastPlan(shopID, stepID, productID, productVer, ownerType, ownerID))
            {
                return(true);
            }

            return(false);
        }
Beispiel #13
0
        private object CreateInstance(JobActivatorScope scope, ActivationContext context)
        {
            var filterInfo = new JobFilterInfo(_filterProvider.GetFilters(context.BackgroundJob.Job));

            BeforeActivation(context, filterInfo.ActivationFilters);
            var activatedContext = ActivateJob(scope, context);

            AfterActivation(activatedContext, filterInfo.ActivationFilters);

            if (activatedContext.Exception != null)
            {
                throw activatedContext.Exception;
            }

            if (activatedContext.Instance == null)
            {
                throw new InvalidOperationException(
                          String.Format("JobActivator returned NULL instance of the '{0}' type.", context.BackgroundJob.Job.Type));
            }

            return(activatedContext.Instance);
        }
Beispiel #14
0
        private static bool IsFilterInflowMoreThenRemainArrMtype(this JobFilterInfo info, FabAoEquipment eqp)
        {
            if (InputMart.Instance.GlobalParameters.ApplyArrangeMType == false)
            {
                return(false);
            }

            WeightFactor wf;

            WeightHelper.TryGetEqpWeightFactor(eqp, Constants.WF_MIN_MOVEQTY_PRIORITY, out wf);

            if (wf == null || wf.Factor == 0)
            {
                return(false);
            }

            FabLot lot = info.Sample;

            if (info.IsRunning)
            {
                return(false);
            }

            if (lot == null)
            {
                return(false);
            }

            var list = lot.CurrentEqpArrange.EqpArrrangeSet.Items.FindAll(x => x.ActivateType == ActivateType.M);

            if (list == null || list.Count == 0)
            {
                return(false);
            }

            float minMoveQty = (int)wf.Criteria[0] / 2;

            float tactTime = (float)SiteConfigHelper.GetDefaultTactTime().TotalSeconds;

            StepTime st = info.Step.GetStepTime(eqp.EqpID, info.ProductID);

            if (st != null)
            {
                tactTime = st.TactTime;
            }

            Time inflowTime = Time.FromSeconds(minMoveQty * tactTime);

            decimal inflowQty = InFlowAgent.GetInflowQty(lot, eqp, (decimal)inflowTime.TotalHours, 0);

            Time endTime           = eqp.Now + inflowTime;
            bool isContinueNextDay = ShopCalendar.StartTimeOfNextDay(eqp.NowDT) <= endTime;

            foreach (var item in list)
            {
                int remainQty = item.RemainQty;
                if (isContinueNextDay && item.IsDailyMode)
                {
                    remainQty += item.LimitQty;
                }

                //limit(M) 잔여 수량이 MIN_MOVEQTY의 1 / 2 이상인 경우 체크 제외.
                if (remainQty >= minMoveQty)
                {
                    continue;
                }

                if (remainQty < inflowQty)
                {
                    info.FilterReason = string.Format("Remain:{0} < Inflow:{1}", remainQty, inflowQty);
                    return(true);
                }
            }

            return(false);
        }
Beispiel #15
0
 public static void SetHarmonicTactInfo(this JobFilterInfo info, AoEquipment aeqp, List <FabAoEquipment> eqplist)
 {
     info.HarmonicTact    = GetHarmonicTact(aeqp, eqplist, info);
     info.HarmonicAvgTact = info.HarmonicTact * (eqplist == null ? 1 : eqplist.Count);
 }
Beispiel #16
0
 public static string GetJobFilterKey(JobFilterInfo info)
 {
     return(ResHelper.CreateKeyForJobFilter(info.Step.ShopID, info.Step.StepID, info.ProductID, info.ProductVersion, info.OwnerType));
 }
Beispiel #17
0
        private static decimal GetHarmonicTact(AoEquipment aeqp, List <FabAoEquipment> eqplist, JobFilterInfo info)
        {
            List <FabAoEquipment> assigned = new List <FabAoEquipment>();

            if (eqplist != null)
            {
                assigned.AddRange(eqplist);
            }

            //신규 추가인 경우 해당 설비를 포함하여 TactTime 계산
            if (info.IsRunning == false)
            {
                assigned.Add(aeqp as FabAoEquipment);
            }

            decimal harmonicTact = TimeHelper.GetHarmonicTactTime(info.Step, assigned, info.ProductID);

            return(harmonicTact);
        }
Beispiel #18
0
        private static bool IsFilterSetup(this JobFilterInfo info, AoEquipment aeqp)
        {
            WeightFactor wf = WeightHelper.GetWeightFactor(aeqp.Target.Preset, Constants.WF_SETUP_FILTERING);

            if (wf == null || wf.Factor == 0)
            {
                return(false);
            }

            FabLot lot = info.Sample;

            if (lot == null)
            {
                return(false);
            }

            FabAoEquipment eqp  = aeqp.ToFabAoEquipment();
            var            step = info.Step;

            //if (eqp.EqpID == "CHPIL300" && eqp.NowDT >= LcdHelper.StringToDateTime("20200119 105032")
            //	&& lot.CurrentProductID == "CW42512AB000")
            //	Console.WriteLine("B");

            if (eqp.IsLastPlan(lot))
            {
                return(false);
            }

            double setupTime = info.SetupTime;

            if (setupTime <= 0)
            {
                return(false);
            }

            double ratio = Convert.ToDouble(wf.Criteria[0]);

            double continuousQty = info.WaitSum;

            if (continuousQty > 0)
            {
                continuousQty += InFlowMaster.GetContinuousQty(lot, step);
            }

            if (eqp.IsParallelChamber)
            {
                continuousQty = continuousQty / eqp.GetChamberCapacity();
            }

            var st = step.GetStepTime(aeqp.EqpID, info.ProductID);

            if (st == null)
            {
                return(false);
            }

            double tactTime = st.TactTime;
            double workSec  = Math.Round(continuousQty * tactTime, 2);
            double setupSec = Math.Round(setupTime * 60 * ratio, 2);

            bool isFilter = workSec < setupSec;

            if (isFilter == false)
            {
                return(false);
            }

            //단순 Setup > Tact Time 일 경우 Inflow를 고려
            //다른 곳에서 진행중인가? Yes : 필터, No: 소량검사
            if (SimHelper.IsAnyWorking(eqp, lot) == false)
            {
                //기다려도 오지 않는 작은 Lot인가? Yes : 필터하지 않음. No : 필터
                if (IsWaitSmallSizeLot(aeqp, info, lot, continuousQty, setupTime, ratio, st))
                {
                    isFilter = false;
                }
            }

            if (isFilter)
            {
                info.FilterReason = string.Format("SetupTime:{0} > {1}(Qty:{2} * Tact:{3})", setupSec, workSec, continuousQty, st.TactTime);
            }

            return(isFilter);
        }
Beispiel #19
0
        public static List <JobFilterInfo> CreateJobList(AoEquipment aeqp, IList <IHandlingBatch> list)
        {
            Dictionary <string, JobFilterInfo> joblist
                = new Dictionary <string, JobFilterInfo>();

            FabAoEquipment eqp  = aeqp as FabAoEquipment;
            var            last = eqp.GetLastPlan();

            if (last != null)
            {
                FabPlanInfo plan = last;

                string shopID    = plan.Step.StepID;
                string stepID    = plan.StepID;
                string productID = plan.ProductID;
                string prodVer   = plan.ProductVersion;
                string ownerType = plan.OwnerType;
                string ownerID   = plan.OwnerID;

                string key = GetJobFilterKey(shopID, stepID, productID, prodVer, ownerType);

                JobFilterInfo info = CreateHelper.CreateDispatchFilterInfo(plan.FabStep, productID, prodVer, ownerType, ownerID);
                info.IsEmpty = true;

                joblist.Add(key, info);
                eqp.LastPlanFilterInfo = info;
            }

            foreach (IHandlingBatch hb in list)
            {
                FabLot lot = hb.ToFabLot();

                lot.DispatchFilterInfo = null;

                string productID = lot.CurrentProductID;
                string prodVer   = lot.CurrentProductVersion;
                string ownerType = lot.CurrentFabPlan.OwnerType;
                string ownerID   = lot.OwnerID;

                FabStep step = lot.CurrentFabStep;

                string key = GetJobFilterKey(step.ShopID, step.StepID, productID, prodVer, ownerType);

                JobFilterInfo info;
                if (joblist.TryGetValue(key, out info) == false)
                {
                    joblist.Add(key, info = CreateHelper.CreateDispatchFilterInfo(step, productID, prodVer, ownerType, ownerID));
                }

                if (hb.HasContents)
                {
                    foreach (FabLot item in hb.Contents)
                    {
                        info.LotList.Add(item);
                        info.WaitSum += item.UnitQty;

                        item.DispatchFilterInfo = info;
                        item.CurrentFabPlan.LotFilterInfo.Clear();
                    }
                }
                else
                {
                    info.LotList.Add(lot);
                    info.WaitSum += lot.UnitQty;

                    lot.DispatchFilterInfo = info;
                    lot.CurrentFabPlan.LotFilterInfo.Clear();
                }

                info.IsEmpty = false;
            }

            foreach (var info in joblist.Values)
            {
                info.WorkingEqpCnt = info.Step.StdStep.GetWorkingEqpCount(info, true, false);

                info.ExistInflowWip = info.WaitSum > 0;
                if (info.ExistInflowWip == false)
                {
                    if (ExistInflowWip(eqp, info))
                    {
                        info.ExistInflowWip = true;
                    }
                }
            }

            return(joblist.Values.ToList());
        }
Beispiel #20
0
        private static bool IsFilterNewEqpAssign(this JobFilterInfo info, FabAoEquipment eqp, List <FabAoEquipment> workingEqpList)
        {
            WeightFactor wf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_NEW_EQP_ASSIGN_FILTERING);

            if (wf == null || wf.Factor == 0)
            {
                return(false);
            }

            //연속진행인 경우
            if (info.IsRunning)
            {
                return(false);
            }

            //Setup이 필요없는 제품의 경우 Filter 제외(2019.12.16 - by.liujian(유건))
            if (eqp.IsParallelChamber == false)
            {
                var setupTime = info.SetupTime;
                if (setupTime <= 0)
                {
                    return(false);
                }
            }

            ////NoAssign 제품의 경우는 IsFilterSetup로 체크(bong - J/C 증가로 제외)
            //if (info.IsNoAssign)
            //    return false;

            //if (eqp.EqpID == "FHMPH100" && eqp.NowDT >= LcdHelper.StringToDateTime("20200113 203008"))
            //	Console.WriteLine("B");

            double param1 = (double)wf.Criteria[0];
            double param2 = (double)wf.Criteria[1];

            //if (info.IsNoAssign)
            //{
            //	WeightFactor awf = WeightHelper.GetWeightFactor(eqp.Target.Preset, Constants.WF_ALLOW_RUN_DOWN_TIME);
            //	if (awf != null && awf.Factor != 0)
            //		param1 = param1 + Convert.ToDouble(awf.Criteria[0]);
            //}

            int workCnt = workingEqpList != null ? workingEqpList.Count : 0;

            //param1
            string reason;
            bool   isFilter = IsFilterNewEqpAssign(info, eqp, param1, workCnt, out reason);

            //param2
            if (isFilter == false && workCnt > 0)
            {
                if (param2 > param1)
                {
                    isFilter = IsFilterNewEqpAssign(info, eqp, param2, workCnt, out reason);
                }
            }

            if (isFilter)
            {
                info.FilterReason = reason;
            }

            return(isFilter);
        }
Beispiel #21
0
        internal static List <FabLot> WaitForPrevStepWip_Dummy(IDispatchContext ctx, FabAoEquipment eqp)
        {
            List <JobFilterInfo> jobList = ctx.Get <List <JobFilterInfo> >(Constants.JobGroup, null);

            if (jobList == null)
            {
                return(null);
            }

            FabPlanInfo last = eqp.GetLastPlan();             //eqp.LastPlan as FabPlanInfo;

            if (last == null)
            {
                return(null);
            }

            //if (eqp.EqpID == "THWEM200" && LcdHelper.StringToDateTime("20191021235617") <= eqp.NowDT)
            //	Console.WriteLine();

            JobState state = InFlowMaster.GetJobState(last.ProductID, last.OwnerType);

            if (state == null)
            {
                return(null);
            }

            var holdWips   = state.GetHoldWipList(last.FabStep, last.ProductVersion);
            var prvRunWips = state.GetPrevStepRunWipList(last.FabStep, last.ProductVersion);

            JobFilterInfo        minSetupJobFilter     = null;
            List <JobFilterInfo> filteredList          = new List <JobFilterInfo>();
            Dictionary <string, JobFilterInfo> current = new Dictionary <string, JobFilterInfo>();

            foreach (var info in jobList)
            {
                if (info.IsEmpty)
                {
                    continue;
                }

                string key = FilterHelper.GetJobFilterKey(info);
                current.Add(key, info);

                if (FilterHelper.CheckIsRunning(eqp, info))
                {
                    filteredList.Add(info);
                    continue;
                }

                if (info.FilterType != DispatchFilter.None)
                {
                    filteredList.Add(info);
                    continue;
                }

                if (info.SetupTime == 0)
                {
                    continue;
                }

                if (minSetupJobFilter == null)
                {
                    minSetupJobFilter = info;
                }

                if (minSetupJobFilter.SetupTime > info.SetupTime)
                {
                    minSetupJobFilter = info;
                }
            }

            if (minSetupJobFilter == null)
            {
                return(null);
            }

            Dictionary <string, FabLot> avableLots = new Dictionary <string, FabLot>();

            foreach (var lot in holdWips)
            {
                if (eqp.IsLastPlan(lot.CurrentShopID, last.StepID, lot.CurrentProductID, lot.CurrentProductVersion, lot.OwnerType, lot.OwnerID))
                {
                    continue;
                }

                string key = FilterHelper.GetJobFilterKey(lot.CurrentShopID, last.StepID, lot.CurrentProductID, lot.CurrentProductVersion, lot.OwnerType);
                if (current.ContainsKey(key))
                {
                    continue;
                }

                Time  remainHold = lot.HoldTime - (eqp.NowDT - lot.HoldStartTime);
                float setupTime  = SetupMaster.GetSetupTime(eqp, lot);

                if (remainHold.TotalMinutes + setupTime < minSetupJobFilter.SetupTime)
                {
                    if (avableLots.ContainsKey(key) == false)
                    {
                        avableLots.Add(key, lot);
                    }
                }
            }

            foreach (var lot in prvRunWips)
            {
                string lastShopID         = last.ShopID;
                string lastStepID         = last.StepID;
                string currProductID      = lot.CurrentProductID;
                string origProductVersion = lot.OrigProductVersion;
                string ownerType          = lot.OwnerType;
                string ownerID            = lot.OwnerID;

                //TODO : bong - product version ??
                if (eqp.IsLastPlan(lastShopID, lastStepID, currProductID, origProductVersion, ownerType, ownerID))
                {
                    continue;
                }

                string key = FilterHelper.GetJobFilterKey(lastShopID, lastStepID, currProductID, origProductVersion, ownerType);
                if (current.ContainsKey(key))
                {
                    continue;
                }

                Time tranferTime = TransferMaster.GetTransferTime(lot, eqp);
                Time setupTime   = SetupMaster.GetSetupTime(eqp, lastShopID, lastStepID, currProductID, origProductVersion, ownerType, ownerID);

                if (tranferTime + setupTime < minSetupJobFilter.SetupTime)
                {
                    if (avableLots.ContainsKey(key) == false)
                    {
                        avableLots.Add(key, lot);
                    }
                }
            }

            Dictionary <string, List <FabAoEquipment> > workingEqps = ResHelper.GetWorkingEqpInfos(eqp, true);

            List <FabLot> list = new List <FabLot>();

            foreach (var lot in avableLots.Values)
            {
                FabPlanInfo plan  = EntityControl.Instance.CreateLoadInfo(lot, last.Step) as FabPlanInfo;
                FabLot      dummy = CreateHelper.CreateDispatchDummyLot(last.FabStep, plan);
                dummy.LotID = "DUMMY_PREVSTEP";

                JobFilterInfo jobfilter = CreateHelper.CreateDispatchFilterInfo(last.Step as FabStep, lot.CurrentProductID, lot.OrigProductVersion, lot.OwnerType, lot.OwnerID);
                jobfilter.InitJobFilterInfo(eqp, workingEqps);
                jobfilter.LotList.Add(dummy);
                dummy.DispatchFilterInfo = jobfilter;

                list.Add(dummy);
            }

            return(list);
        }