using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using AMESCoreStudio.WebApi;
using AMESCoreStudio.WebApi.Models.AMES;
using AMESCoreStudio.CommonTools.Result;
using AMESCoreStudio.WebApi.Controllers.BAS;
using AMESCoreStudio.WebApi.DTO.AMES;
using AMESCoreStudio.WebApi.Enum;
using AMESCoreStudio.WebApi.Controllers.BLL;
using Microsoft.Extensions.Configuration;

namespace AMESCoreStudio.WebApi.Controllers.AMES
{
    /// <summary>
    /// 過站判斷
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class BarCodeCheck1Controller : ControllerBase
    {
        private readonly AMESContext _context;
        private readonly IConfiguration _config;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public BarCodeCheck1Controller(AMESContext context, IConfiguration config)
        {
            _config = config;
            _context = context;
        }

        #region 過站判斷
        /// <summary>
        /// 過站判斷
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        [HttpPost("PassIngByCheck")]

        public async Task<ActionResult<ResultModel<string>>> CheckBarCodeCheck([FromBody] BarCodeCheckDto barCodeCheckDto)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };

            try
            {
                #region 相關資料 Null給空白
                // KP||NG Input
                if (barCodeCheckDto.inputItems == null)
                    barCodeCheckDto.inputItems = new List<BarCodeCheckDto.inputItem>();
                else
                    barCodeCheckDto.inputItems = barCodeCheckDto.inputItems.Where(w => !string.IsNullOrWhiteSpace(w.inputType)).ToList();

                // 治具 Input
                if (barCodeCheckDto.outfits == null)
                    barCodeCheckDto.outfits = new List<BarCodeCheckDto.Outfit>();
                else
                    barCodeCheckDto.outfits = barCodeCheckDto.outfits.Where(w => !string.IsNullOrWhiteSpace(w.inputData)).ToList();
                #endregion

                #region 欄位資料空值判斷
                if (string.IsNullOrWhiteSpace(barCodeCheckDto.wipNo))
                {
                    resultModel.Msg = "請輸入工單號碼";
                    return Ok(resultModel);
                }

                if (string.IsNullOrWhiteSpace(barCodeCheckDto.barcode))
                {
                    resultModel.Msg = "請輸入內部條碼";
                    return Ok(resultModel);
                }

                if (string.IsNullOrWhiteSpace(barCodeCheckDto.unitNo))
                {
                    resultModel.Msg = "請輸入生產單位";
                    return Ok(resultModel);
                }

                if (barCodeCheckDto.stationID == 0)
                {
                    resultModel.Msg = "請輸入作業站代碼";
                    return Ok(resultModel);
                }

                if (barCodeCheckDto.line == 0)
                {
                    resultModel.Msg = "請輸入線別代碼";
                    return Ok(resultModel);
                }
                #endregion

                #region 宣告各個Controller
                WipInfosController wipInfosController = new WipInfosController(_context);
                WipMACController wipMACController = new WipMACController(_context);
                WipBarcodeOtherController wipBarcodeOtherController = new WipBarcodeOtherController(_context);
                BarcodeItemsController barcodeItemsController = new BarcodeItemsController(_context);
                BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
                BarcodeItemChangesController barcodeItemChangesController = new BarcodeItemChangesController(_context);
                RuleStationsController ruleStationsController = new RuleStationsController(_context);
                MaterialKpController materialKpController = new MaterialKpController(_context);
                #endregion

                #region 宣告參數
                // 料號ID
                int itemID = 0;
                // 料號
                string item = string.Empty;
                // 存放要更新BarCodeItem
                var update_BarCodeItem = new List<BarcodeItem>();
                var insert_BarCodeItemChange = new List<BarcodeItemChange>();
                // Burn In
                bool burnIn = false;
                #endregion

                #region 判斷UserID 
                if (barCodeCheckDto.userID != 0)
                {
                    if (_context.UserInfoes.Where(w => w.UserID == barCodeCheckDto.userID).Count() == 0)
                    {
                        resultModel.Success = false;
                        resultModel.Msg = "找不到UserID【" + barCodeCheckDto.userID + "】資料";
                        return resultModel;
                    }
                }
                #endregion

                #region 判斷序號為出貨條碼,並轉成內部條碼
                var ByExtraNo = await barcodeInfoesController.GetBarcodeInfoesByExtraNo(barCodeCheckDto.barcode);
                if (ByExtraNo.Value.Count() != 0)
                {
                    barCodeCheckDto.extNo = barCodeCheckDto.barcode;
                    barCodeCheckDto.barcode = ByExtraNo.Value.FirstOrDefault().BarcodeNo;
                }
                #endregion

                // 抓流程ID
                var q_wipinfo = await wipInfosController.GetWipInfoByWipNo(barCodeCheckDto.wipNo);
                barCodeCheckDto.flowRule = q_wipinfo.Value.Where(w => w.UnitNO == barCodeCheckDto.unitNo).FirstOrDefault().FlowRuleID;

                #region 判斷工單狀態
                resultModel = (ResultModel<string>)await CheckWipNoSationAsync(wipNo: barCodeCheckDto.wipNo, unitNo: barCodeCheckDto.unitNo
                               , flowRuleID: barCodeCheckDto.flowRule, line: barCodeCheckDto.line, stationID: barCodeCheckDto.stationID, barCodeNo: barCodeCheckDto.barcode);
                if (!resultModel.Success)
                    return resultModel;
                #endregion

                #region 判斷序號區間

                resultModel = (ResultModel<string>)CheckBarCodeByWipNo(wipNo: barCodeCheckDto.wipNo, barcode: barCodeCheckDto.barcode);
                if (!resultModel.Success)
                    return resultModel;

                #endregion

                #region 判斷序號狀態
                resultModel = (ResultModel<string>)await GetCheckBarCodeStation(wipno: barCodeCheckDto.wipNo, barcode: barCodeCheckDto.barcode);
                if (!resultModel.Success)
                    return resultModel;
                #endregion

                #region 判斷序號流程
                resultModel = (ResultModel<string>)await CheckBarCodeFlowAsync(wipno: barCodeCheckDto.wipNo, barcode: barCodeCheckDto.barcode
                                                                    , unitno: barCodeCheckDto.unitNo, stationID: barCodeCheckDto.stationID);
                if (!resultModel.Success)
                    return resultModel;
                #endregion

                barCodeCheckDto.wipID = q_wipinfo.Value.Where(w => w.UnitNO == barCodeCheckDto.unitNo).FirstOrDefault().WipID;
                barCodeCheckDto.flowRule = q_wipinfo.Value.Where(w => w.UnitNO == barCodeCheckDto.unitNo).FirstOrDefault().FlowRuleID;
                barCodeCheckDto.barcodeID = BarCodeToID(barCodeCheckDto.barcode).Result;
                item = q_wipinfo.Value.FirstOrDefault().GetWipAtt.ItemNO;
                itemID = ItemNoToItemID(item).Result;

                //// 抓RulseStationID
                //var q_rulestation = await ruleStationsController.GetRuleStationByFlow(barCodeCheckDto.flowRule, 0, 0);
                //barCodeCheckDto.ruleStationID = q_rulestation.Value.Where(w => w.StationID == barCodeCheckDto.station).FirstOrDefault().RuleStationID;

                #region 燒機判斷
                resultModel = (ResultModel<string>)await GetCheckBurn(barCodeCheckDto.wipNo, barCodeCheckDto.barcodeID, barCodeCheckDto.stationID);
                if (!resultModel.Success)
                    return resultModel;
                else if (resultModel.Msg == "BurnIn")
                    burnIn = true;
                #endregion

                StationsesController stationsesController = new StationsesController(_context);
                var station = await stationsesController.GetStations(barCodeCheckDto.stationID);

                #region KeyParts 判斷
                // 不是維修跑KeyParts判斷
                if (barCodeCheckDto.barcodeType != "S")
                {
                    if (barCodeCheckDto.inputItems.Where(w => !w.inputType.ToUpper().StartsWith("NG")).Any())
                    {

                        var barcodeItemKPDto = new BarcodeItemKPDto
                        {
                            wipNo = barCodeCheckDto.wipNo,
                            barCodeNo = barCodeCheckDto.barcode,
                            unitNo = barCodeCheckDto.unitNo,
                            ststionUnitNo = station.Value.Where(w => w.StationID == barCodeCheckDto.stationID).FirstOrDefault().UnitNo,
                            inputKP = barCodeCheckDto.inputItems.Where(w => !w.inputType.ToUpper().StartsWith("NG")).ToList()
                        };

                        var resultKeyParts = await CheckBarCodeKPAsync(barcodeItemKPDto);
                        if (!resultKeyParts.Success)
                            return (ResultModel<string>)resultKeyParts;
                    }
                }
                #endregion

                #region 治具判斷
                var resultOutfit = await CheckBarCodeOutfitAsync(barCodeCheckDto.outfits);
                if (!resultOutfit.Success)
                    return (ResultModel<string>)resultOutfit;
                #endregion

                // 維修過站 組件需獨立判斷
                if (barCodeCheckDto.barcodeType == "S")
                {
                    // 確認新舊組件序號是否都有值
                    if (barCodeCheckDto.inputItems.Where(w => w.inputType.ToUpper() != "NG" &&
                    (string.IsNullOrWhiteSpace(w.inputData) || string.IsNullOrWhiteSpace(w.oldInputData))).Any())
                    {
                        resultModel.Msg = "工單號碼【" + barCodeCheckDto.wipNo + "】維修過站資料有缺新舊組件序號,請確認";
                        resultModel.Success = false;
                        return resultModel;
                    }

                    // 用BarCodeID And WipID 取BarCodeItem
                    var q_BarCodeItem = await barcodeItemsController.GetBarcodeItemByBarCodeID(barCodeCheckDto.barcodeID);

                    foreach (var KPs in barCodeCheckDto.inputItems)
                    {
                        // 用舊組件序號比對
                        var barCodeItem = q_BarCodeItem.Value.Where(w => w.PartNo == KPs.oldInputData).FirstOrDefault();

                        if (barCodeItem != null)
                        {
                            var MaterialKps = (await materialKpController.GetMaterialKpByItemID(itemID)).ToList();
                            MaterialKps = MaterialKps.OrderBy(o => o.KpSeq).ToList();
                            if (MaterialKps.Count == 0)
                            {
                                resultModel.Msg = "工單號碼【" + barCodeCheckDto.wipNo + "】找不到相關Key Parts對應";
                            }
                            else
                            {
                                var q_Kp = MaterialKps.Where(w => w.KpNo.ToUpper() == barCodeItem.ItemNo.ToUpper()).FirstOrDefault();
                                if (q_Kp != null)
                                {
                                    #region 比對序號長度是否正確
                                    if (!string.IsNullOrWhiteSpace(q_Kp.Length.ToString()))
                                    {
                                        if (q_Kp.Length != KPs.inputData.Length && q_Kp.Length != 0)
                                            resultModel.Msg += "組件序號【" + KPs.inputData + "】 與組件名稱【" + q_Kp.KpName + "】長度不符合</br>";
                                    }
                                    #endregion

                                    #region 前置碼正確
                                    if (!string.IsNullOrWhiteSpace(q_Kp.Title))
                                    {
                                        if (!KPs.inputData.ToUpper().StartsWith(q_Kp.Title.ToUpper()))
                                            resultModel.Msg += "組件序號【" + KPs.inputData + "】 與組件名稱【" + q_Kp.Title + "】前置碼不符合</br>";
                                    }
                                    #endregion

                                    #region 組件代碼-組件序號是否重複
                                    var checkDataRedundancy = await barcodeItemsController.GetBarcodeItemByDataRedundancy(q_Kp.KpNo, KPs.inputData);
                                    if (checkDataRedundancy.Value.Count() != 0)
                                    {
                                        resultModel.Msg += "組件名稱【" + q_Kp.KpName + "】已有相同組件序號【" + KPs.inputData + "】紀錄 </br>";
                                    }
                                    #endregion

                                    #region 判斷組件序號是否在製狀態
                                    if (q_Kp.KpNo.ToUpper() == "04")
                                    {

                                        var BarCodeInfo = await barcodeInfoesController.GetBarcodeInfoesByNo(KPs.inputData);
                                        if (BarCodeInfo.Value.Where(w => w.StatusID != -1).Any())
                                        {
                                            resultModel.Msg += "組件序號【" + KPs.inputData + "】 目前是在製狀態</br>";
                                        }
                                    }
                                    #endregion

                                    #region 判斷MAC區間
                                    // 安勤不需要判斷MAC區間
                                    if (q_Kp.KpNo.ToUpper().Contains("MAC"))
                                    {
                                        var wipMAC = wipMACController.GetWipMAC(barCodeCheckDto.wipNo).Result.Value;
                                        if (wipMAC.Count() == 0)
                                        {
                                            resultModel.Msg += "工單號碼【" + barCodeCheckDto.wipNo + "】 找不到綁定MAC區間</br>";
                                        }
                                        else
                                        {
                                            // 判斷是否符合區間
                                            if (KPs.inputData.Length != 12 && KPs.inputData.Length != 6)
                                            {
                                                resultModel.Msg += "組件序號【" + KPs.inputData + "】 綁定MAC不足12碼或6碼 </br>";
                                            }
                                            else
                                            {
                                                // 長度12碼 判斷前置碼
                                                if (KPs.inputData.Length == 12)
                                                {
                                                    if (!wipMAC.Where(w => KPs.inputData.StartsWith(w.Title)).Any())
                                                    {
                                                        resultModel.Msg += $"組件序號【{KPs.inputData}】與MAC【{string.Join('、', wipMAC.Select(s => s.Title).ToList())}】前置碼不符合 </br>";
                                                    }
                                                }
                                                // 長度6碼 抓WIPMAC 前6碼補足 12碼
                                                else if (KPs.inputData.Length == 6)
                                                {
                                                    var wipMacItem = wipMAC.FirstOrDefault();
                                                    KPs.inputData = wipMacItem.Title + KPs.inputData;
                                                }

                                                var InputMacTitle = KPs.inputData.Substring(0, 6).ToUpper();
                                                var InputMacNo = Convert.ToInt32(KPs.inputData.Substring(6, 6), 16);
                                                if (!wipMAC.Where(w => Convert.ToInt32(w.StartNO, 16) <= InputMacNo &&
                                                                      InputMacNo <= Convert.ToInt32(w.EndNO, 16) &&
                                                                      w.Title == InputMacTitle).Any())
                                                {
                                                    resultModel.Msg += "組件序號【" + KPs.inputData + "】 與工單設定MAC區間不符合 </br>";
                                                }
                                            }
                                        }
                                    }
                                    #endregion

                                    #region 判斷出貨序號
                                    // 當KP_NAME是 EXT_NO 判斷組件-出貨序號 是否有在區間
                                    if (q_Kp.KpNo.ToUpper() == "95")
                                    {

                                        var WipBarCodeOther = await wipBarcodeOtherController.CheckWipBarcodeOtherByNo(barCodeCheckDto.wipNo, KPs.inputData);
                                        if (WipBarCodeOther.Value.Count() == 0)
                                        {
                                            resultModel.Msg += "組件序號【" + KPs.inputData + "】 與工單設定出貨序號區間不符合 </br>";
                                        }
                                        else
                                        {
                                            //resultModel.Data = new List<string> { KPs.inputData };
                                            //resultModel.Msg = "EXT_NO";
                                        }
                                    }
                                    #endregion
                                }
                            }

                            barCodeItem.PartNo = KPs.inputData;
                            barCodeItem.UpdateDate = DateTime.Now;
                            update_BarCodeItem.Add(barCodeItem);

                            insert_BarCodeItemChange.Add(new BarcodeItemChange
                            {
                                WipID = barCodeCheckDto.wipID,
                                StationID = barCodeCheckDto.stationID,
                                BarcodeID = barCodeCheckDto.barcodeID,
                                ItemNo = barCodeItem.ItemNo,
                                PartNoOld = KPs.oldInputData,
                                ChangeType = "RP",
                                KpItemNo = KPs.inputData,
                                CreateUserID = barCodeCheckDto.userID
                            });
                        }
                        else
                        {
                            resultModel.Msg = $"內部條碼【{barCodeCheckDto.barcode}】找不到已綁定Kp序號【{KPs.oldInputData}】";
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(resultModel.Msg))
                    {
                        resultModel.Success = false;
                        return resultModel;
                    }

                    // 將InputItem清空
                    barCodeCheckDto.inputItems = new List<BarCodeCheckDto.inputItem>();
                }

                //var NextStopCloseStation = await CheckNextStopCloseStation(barCodeCheckDto.wipNo, barCodeCheckDto.unitNo, barCodeCheckDto.station);

                #region 判斷為CHECK站.組件是否都有資料
                // 判斷作業站是否為CHECK站 Station_Type == C

                if (station.Value.Where(w => w.TypeNo == "C").Any())
                //if (CheckNextStopCloseStation(barCodeCheckDto.wipNo, barCodeCheckDto.unitNo, barCodeCheckDto.station).Result.Success)
                {
                    // 過站輸入組件數量
                    var inputKPQty = barCodeCheckDto.inputItems.Where(w => !w.inputData.Contains("$")).Count();

                    // 已記錄組件數量
                    // var BarCodeItems = _context.BarcodeItems.Where(w => w.BarcodeID == barCodeCheckDto.barcodeID);
                    var BarCodeItems = _context.BarcodeItems.Where(w => w.BarcodeID == barCodeCheckDto.barcodeID && w.WipID == barCodeCheckDto.wipID);
                    var Stations = _context.Stationses.Where(w => w.UnitNo == barCodeCheckDto.unitNo);

                    var BarCodeItemsQty = BarCodeItems.Where(w => Stations.Any(s => s.StationID == w.StationID)).Count();

                    // WipKp DB 設定綁定組件數量 + 製程判斷
                    var wipKpQty = _context.WipKps.Where(w => w.WipNo == barCodeCheckDto.wipNo
                                                           && w.UnitNo == barCodeCheckDto.unitNo
                                                           ).Count();

                    if (wipKpQty != inputKPQty + BarCodeItemsQty)
                    {
                        resultModel.Success = false;
                        resultModel.Msg = "組件資料筆數不符,請確認";
                        return resultModel;
                    }
                }
                #endregion

                #region  判斷下一站為完工時.治具是否都有資料
                //// 過站輸入組件數量
                //var inputKPQty = barCodeCheckDto.outfits.Count();

                //// 已記錄組件數量
                //var BarCodeItemsQty = _context.BarcodeOutfits.Where(w => w.BarcodeID == barCodeCheckDto.barcodeID
                //                                                 && w.WipID == barCodeCheckDto.wipID).Count();
                //// WipKp DB 設定綁定組件數量
                //var wipKpQty = _context.WipKps.Where(w => w.WipNo == barCodeCheckDto.wipNo
                //                                       && w.UnitNo == barCodeCheckDto.unitNo).Count();

                //if (wipKpQty != inputKPQty + BarCodeItemsQty)
                //{
                //    resultModel.Success = false;
                //    resultModel.Msg = "該作業站為流程最後最後一站,組件資料筆數不符,請確認";
                //    return resultModel;
                //}
                #endregion

                // 過站判斷正常 往下處理Table

                #region 內部序號輸入後新增 or 更新
                if (barCodeCheckDto.inputItems.Where(w => w.inputData.Contains("$")).Count() != 0)
                    barCodeCheckDto.ruleStatus = "F";
                else
                    barCodeCheckDto.ruleStatus = "P";

                var result_CUTableMsg = await CU_Tables(barCodeCheckDto, burnIn);
                if (!string.IsNullOrWhiteSpace(result_CUTableMsg))
                {
                    resultModel.Msg = "內部序號【" + barCodeCheckDto.barcode + "】 過站失敗,錯誤訊息:<br/>";
                    resultModel.Msg += result_CUTableMsg;
                    resultModel.Success = false;
                    return resultModel;
                }

                // 維修組件更換
                foreach (var item_barCodeItem in update_BarCodeItem)
                {
                    await barcodeItemsController.PutBarcodeItems(item_barCodeItem.BarcodeItemID, item_barCodeItem);
                }

                foreach (var item_barCodeItemChange in insert_BarCodeItemChange)
                {
                    await barcodeItemChangesController.PostBarcodeItemChanges(item_barCodeItemChange);
                }

                // 燒機In 修改狀態
                if (burnIn)
                {
                    resultModel.Msg = "內部序號【" + barCodeCheckDto.barcode + "】 燒機In 完成!";
                }
                else
                {
                    resultModel.Msg = "內部序號【" + barCodeCheckDto.barcode + "】 過站完成!";
                }


                resultModel.Success = true;
                return resultModel;
                #endregion
            }
            catch (Exception ex)
            {
                resultModel.Success = false;
                resultModel.Msg = ex.Message;
                return resultModel;
            }
        }
        #endregion

        #region FQC抽驗過站
        /// <summary>
        /// FQC抽驗過站
        /// </summary>
        /// <param name="inhouseNo">入庫單號</param>
        /// <param name="seqID">順序</param>
        /// <param name="userID">UserID</param>
        /// <returns></returns>
        [HttpGet("PassIngByFQC")]
        public async Task<ActionResult<ResultModel<string>>> PassingByFQC(string inhouseNo, int seqID, int userID)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            var InhouseMaster = await _context.FqcInhouseMasters.Where(w => w.InhouseNo == inhouseNo && w.SeqID == seqID)
                                                                .FirstOrDefaultAsync();
            if (InhouseMaster != null)
            {
                RuleStationsController ruleStationsController = new RuleStationsController(_context);
                var CheckFQC = await ruleStationsController.GetRuleStationByWipNoCheckFQC(InhouseMaster.WipNo);
                // 有設定FQC站別
                if (CheckFQC.Value.Data.Count() != 0)
                {
                    var RuleStation = CheckFQC.Value.Data.FirstOrDefault();
                    // 取FQC抽驗單號
                    var InhouseDetail = await _context.FqcInhouseDetails.Where(w => w.InhouseNo == inhouseNo && w.SeqID == seqID)
                                                                        .ToListAsync();
                    BarCodeCheckDto barCodeCheckDto = new BarCodeCheckDto();
                    barCodeCheckDto.line = -1;
                    barCodeCheckDto.ruleStatus = "P";
                    barCodeCheckDto.stationID = RuleStation.Station.StationID;
                    barCodeCheckDto.userID = userID;
                    barCodeCheckDto.barcodeType = "M";
                    foreach (var item in InhouseDetail)
                    {
                        // 用箱號抽驗
                        if (item.SerialType == "B")
                        {
                            var BarcodeNo = await _context.BarcodeInfoes.Where(w => w.BoxNo == item.SerialNo).ToListAsync();
                            foreach (var barcode in BarcodeNo)
                            {
                                barCodeCheckDto.unitNo = _context.WipInfos.Where(w => w.WipID == barcode.WipID).FirstOrDefault().UnitNO;
                                barCodeCheckDto.wipID = barcode.WipID;
                                barCodeCheckDto.barcode = barcode.BarcodeNo;
                                barCodeCheckDto.barcodeID = barcode.BarcodeID;
                                barCodeCheckDto.extNo = barcode.ExtraBarcodeNo;
                                barCodeCheckDto.flowRule = _context.WipInfos.Where(w => w.WipID == barcode.WipID).FirstOrDefault().FlowRuleID;
                                barCodeCheckDto.wipNo = _context.WipInfos.Where(w => w.WipID == barcode.WipID).FirstOrDefault().WipNO;

                                var result_CUTableMsg = await CU_Tables(barCodeCheckDto, false);
                                if (string.IsNullOrWhiteSpace(result_CUTableMsg))
                                {
                                    resultModel.Success = true;
                                    resultModel.Msg = "FQC過站完成";
                                }
                                else
                                {
                                    resultModel.Msg = result_CUTableMsg;
                                }
                            }
                        } // 條碼
                        else
                        {
                            var BarcodeNo = await _context.BarcodeInfoes.Where(w => w.BarcodeNo == item.SerialNo).FirstOrDefaultAsync();
                            if (BarcodeNo != null)
                            {
                                barCodeCheckDto.unitNo = _context.WipInfos.Where(w => w.WipID == BarcodeNo.WipID).FirstOrDefault().UnitNO;
                                barCodeCheckDto.wipID = BarcodeNo.WipID;
                                barCodeCheckDto.barcode = BarcodeNo.BarcodeNo;
                                barCodeCheckDto.barcodeID = BarcodeNo.BarcodeID;
                                barCodeCheckDto.extNo = BarcodeNo.ExtraBarcodeNo;
                                barCodeCheckDto.flowRule = _context.WipInfos.Where(w => w.WipID == BarcodeNo.WipID).FirstOrDefault().FlowRuleID;
                            }

                            var result_CUTableMsg = await CU_Tables(barCodeCheckDto, false);
                            if (string.IsNullOrWhiteSpace(result_CUTableMsg))
                            {
                                resultModel.Success = true;
                                resultModel.Msg = "FQC過站完成";
                            }
                            else
                            {
                                resultModel.Msg = result_CUTableMsg;
                            }
                        }
                    }
                }
                else
                {
                    resultModel.Msg = $"該筆工單號碼【{InhouseMaster.WipNo}】,無設定FQC站別";
                }
            }
            else
            {
                resultModel.Msg = "找不到該筆FQC單號";
            }
            return resultModel;
        }
        #endregion

        #region 判斷過站完成新增or更新 Table
        /// <summary>
        /// 判斷過站完成新增or更新 Table
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <param name="burnIn">T:燒機In</param>
        /// <returns></returns>
        private async Task<string> CU_Tables(BarCodeCheckDto barCodeCheckDto, bool burnIn)
        {
            string Msg = string.Empty;
            using (var tran = _context.Database.BeginTransaction())
            {
                try
                {
                    if (!burnIn)
                    {
                        // 條碼主檔
                        var result_BarcodeInfo = Table_BarcodeInfo(barCodeCheckDto).Result;
                        if (result_BarcodeInfo.Success)
                        {
                            // 將BarCodeID補上
                            if (barCodeCheckDto.barcodeID == 0)
                                barCodeCheckDto.barcodeID = result_BarcodeInfo.Data.FirstOrDefault().BarcodeID;
                        }
                        else
                        {
                            Msg += "BarcodeInfo_Error:" + result_BarcodeInfo.Msg + "<br/>";
                        }

                        // 條碼紀錄
                        var result_BarcodeWip = Table_BarcodeWip(barCodeCheckDto).Result;
                        if (!result_BarcodeWip.Success)
                        {
                            Msg += "BarcodeWip_Error:" + result_BarcodeWip.Msg + "<br/>";
                        }

                        // 工單各站數量資料檔
                        var result_WipStation = Table_WipStation(barCodeCheckDto).Result;
                        if (!result_WipStation.Success)
                        {
                            Msg += "WipStation_Error:" + result_WipStation.Msg + "<br/>";
                        }

                        // 各班別數量資料檔
                        var result_WipClass = Table_WipClass(barCodeCheckDto).Result;
                        if (!result_WipClass.Success)
                        {
                            Msg += "WipClass_Error:" + result_WipClass.Msg + "<br/>";
                        }

                        // 工單各站數量資料檔 – By TIME
                        var result_WipTime = Table_WipTime(barCodeCheckDto).Result;
                        if (!result_WipTime.Success)
                        {
                            Msg += "WipTime_Error:" + result_WipTime.Msg + "<br/>";
                        }

                        // 條碼過站資料檔
                        var result_BarcodeStation = Table_BarcodeStation(barCodeCheckDto).Result;
                        if (!result_BarcodeStation.Success)
                        {
                            Msg += "BarcodeStation_Error:" + result_BarcodeStation.Msg + "<br/>";
                        }

                        // 組件资料
                        var result_BarcodeItem = Table_BarcodeItem(barCodeCheckDto).Result;
                        if (!result_BarcodeItem.Success)
                        {
                            Msg += "BarcodeItem_Error:" + result_BarcodeItem.Msg + "<br/>";
                        }

                        // 條碼治具
                        var result_BarcodeOutfit = Table_BarcodeOutfit(barCodeCheckDto).Result;
                        if (!result_BarcodeOutfit.Success)
                        {
                            Msg += "BarcodeOutfit_Error:" + result_BarcodeOutfit.Msg + "<br/>";
                        }

                        // 設備資料檔 使用次數
                        var result_OutfitInfo = Table_OutfitInfo(barCodeCheckDto).Result;
                        if (!result_OutfitInfo.Success)
                        {
                            Msg += "OutfitInfo_Error:" + result_OutfitInfo.Msg + "<br/>";
                        }

                        // 不良資料檔
                        var result_NgInfo = Table_NgInfo(barCodeCheckDto).Result;
                        if (!result_NgInfo.Success)
                        {
                            Msg += "NgInfo_Error:" + result_NgInfo.Msg + "<br/>";
                        }

                        // 過站為PASS狀態
                        if (barCodeCheckDto.ruleStatus == "P")
                        {
                            // 判斷是否為第一站
                            if (CheckNowFirstStation(barCodeCheckDto.wipNo, barCodeCheckDto.unitNo, barCodeCheckDto.stationID) == "Y")
                            {
                                BarcodeStationController barcodeStationController = new BarcodeStationController(_context);
                                var CheckBarcodeStation = barcodeStationController.GetBarcodeStationByBarCodeID(barCodeCheckDto.barcodeID);
                                if (CheckBarcodeStation.Result.Value.Where(w => w.RuleStatus == "P" && w.WipID == barCodeCheckDto.wipID
                                                                                && w.StationID == barCodeCheckDto.stationID).Count() == 1)
                                {
                                    WipInfosController wipInfosController = new WipInfosController(_context);
                                    var result_wipInfos = await wipInfosController.PutWipinfoByCompleteQTY(barCodeCheckDto.wipID);
                                    if (!result_wipInfos.Success)
                                    {
                                        Msg += "wipInfos_Error:" + result_wipInfos.Msg + "<br/>";
                                    }
                                }
                            }
                        }

                        // 判斷下一站為完工站
                        if (CheckNextStopCloseStation(barCodeCheckDto.flowRule, barCodeCheckDto.stationID, barCodeCheckDto.ruleStatus).Result.Success)
                        {
                            var result_wipInfoAllClost = await CheckWipNoBarCodeAllClost(barCodeCheckDto.wipNo, barCodeCheckDto.unitNo, barCodeCheckDto.stationID);
                            if (!result_wipInfoAllClost.Success)
                            {
                                Msg += "wipInfosAllClost_Error:" + result_wipInfoAllClost.Msg + "<br/>";
                            }
                        }
                    }

                    // 燒入資料檔
                    var result_BurnInfo = Table_BurnInfo(barCodeCheckDto).Result;
                    if (!result_BurnInfo.Success)
                    {
                        Msg += "BurnInfo_Error:" + result_BurnInfo.Msg + "<br/>";
                    }

                    // 判斷是否有DB更新錯誤
                    if (string.IsNullOrWhiteSpace(Msg))
                    {
                        await tran.CommitAsync();
                    }
                    else
                    {
                        await tran.RollbackAsync();
                    }
                }

                catch (Exception ex)
                {
                    Msg = "過站新增系統錯誤:" + ex.Message;
                    await tran.RollbackAsync();
                }
            }

            return Msg;
        }

        /// <summary>
        /// BarcodeInfo-條碼資料檔
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        private async Task<ResultModel<BarcodeInfo>> Table_BarcodeInfo(BarCodeCheckDto barCodeCheckDto)
        {
            // 抓取生產單位的狀態代碼
            FactoryUnitsController factoryUnitsController = new FactoryUnitsController(_context);
            string StatusNo = factoryUnitsController.GetFactoryUnit(barCodeCheckDto.unitNo).Result.Value.FirstOrDefault().UnitCode;

            // 查看是否有資料
            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var barcodeInfo = barcodeInfoesController.GetBarcodeInfoes(barCodeCheckDto.barcodeID)
                             .Result.Value.FirstOrDefault();

            // 新增
            if (barcodeInfo == null)
            {
                barcodeInfo = new BarcodeInfo
                {
                    BarcodeNo = barCodeCheckDto.barcode,
                    StationID = barCodeCheckDto.stationID,
                    LocationID = -1,
                    WipID = barCodeCheckDto.wipID,
                    RuleStatus = barCodeCheckDto.ruleStatus,
                    StatusID = 1,
                    SysType = "S",
                    StatusNo = StatusNo,
                    CreateUserID = barCodeCheckDto.userID
                };

                if (CheckNextStopCloseStation(barCodeCheckDto.flowRule, barCodeCheckDto.stationID, barCodeCheckDto.ruleStatus).Result.Success)
                {
                    barcodeInfo.StatusID = -1;
                }

                return await barcodeInfoesController.PostBarcodeInfoes(barcodeInfo);
            }
            // 更新
            else
            {
                barcodeInfo.StationID = barCodeCheckDto.stationID;
                barcodeInfo.RuleStatus = barCodeCheckDto.ruleStatus;
                barcodeInfo.StatusNo = StatusNo;
                barcodeInfo.WipID = barCodeCheckDto.wipID;
                barcodeInfo.StatusID = 1;
                if (!string.IsNullOrWhiteSpace(barCodeCheckDto.extNo))
                    barcodeInfo.ExtraBarcodeNo = barCodeCheckDto.extNo;

                if (CheckNextStopCloseStation(barCodeCheckDto.flowRule, barCodeCheckDto.stationID, barCodeCheckDto.ruleStatus).Result.Success)
                {
                    barcodeInfo.StatusID = -1;
                }
                return await barcodeInfoesController.PutBarcodeInfoes(barcodeInfo);
            }
        }

        /// <summary>
        /// BarcodeStation-條碼過站資料檔
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        private async Task<ResultModel<BarcodeStation>> Table_BarcodeStation(BarCodeCheckDto barCodeCheckDto)
        {
            BarcodeStationController barcodeStationController = new BarcodeStationController(_context);
            // 新增 BarCodeStation
            BarcodeStation barcodeStation = new BarcodeStation
            {
                BarcodeID = barCodeCheckDto.barcodeID,
                WipID = barCodeCheckDto.wipID,
                StationID = barCodeCheckDto.stationID,
                RuleStatus = barCodeCheckDto.ruleStatus, //F 不良 
                InputDate = DateTime.Now,
                LineId = barCodeCheckDto.line,
                CreateUserID = barCodeCheckDto.userID,
                FlowRuleID = barCodeCheckDto.flowRule
            };
            return await barcodeStationController.PostBarcodeStation(barcodeStation);
        }

        /// <summary>
        /// BarcodeItem-組件资料
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        private async Task<ResultModel<BarcodeItem>> Table_BarcodeItem(BarCodeCheckDto barCodeCheckDto)
        {
            BarcodeItemsController barcodeItemsController = new BarcodeItemsController(_context);
            var KeyPartsItem = barCodeCheckDto.inputItems.Where(w => !w.inputData.Contains("$")).ToList();
            var result = new ResultModel<BarcodeItem>() { Success = true };
            // 新增 BarCodeStation
            for (int i = 0; i < KeyPartsItem.Count(); i++)
            {
                var barcodeItem = new BarcodeItem
                {
                    BarcodeID = barCodeCheckDto.barcodeID,
                    WipID = barCodeCheckDto.wipID,
                    StationID = barCodeCheckDto.stationID,
                    ItemNo = KeyPartsItem[i].inputType,
                    PartNo = KeyPartsItem[i].inputData,
                    SysType = "S",
                    CreateUserID = barCodeCheckDto.userID,
                    CreateDate = DateTime.Now,
                    UpdateDate = DateTime.Now,
                    KpItemNo = KeyPartsItem[i].kpItemNo
                };
                result = await barcodeItemsController.PostBarcodeItems(barcodeItem);
                if (!result.Success)
                    return result;
            }

            return result;
        }

        /// <summary>
        /// BarcodeOutfit-治具資料
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        private async Task<ResultModel<BarcodeOutfit>> Table_BarcodeOutfit(BarCodeCheckDto barCodeCheckDto)
        {
            BarcodeOutfitController barcodeOutfitController = new BarcodeOutfitController(_context);
            var OutfitsItem = barCodeCheckDto.outfits;
            var result = new ResultModel<BarcodeOutfit>() { Success = true };
            // 新增 BarCodeStation
            foreach (var item in OutfitsItem)
            {
                var barcodeOutfit = new BarcodeOutfit
                {
                    BarcodeNo = barCodeCheckDto.barcode,
                    WipNo = barCodeCheckDto.wipNo,
                    OutfitNo = item.inputData,
                    StationID = barCodeCheckDto.stationID,
                    CreateUserID = barCodeCheckDto.userID,
                    CreateDate = DateTime.Now,
                    UpdateUserID = barCodeCheckDto.userID,
                    UpdateDate = DateTime.Now
                };
                result = await barcodeOutfitController.PostBarcodeOutfit(barcodeOutfit);
                if (!result.Success)
                    return result;
            }

            return result;
        }

        /// <summary>
        /// OutfitInfo-設備資料檔 使用次數
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        private async Task<ResultModel<OutfitInfo>> Table_OutfitInfo(BarCodeCheckDto barCodeCheckDto)
        {
            OutfitInfoesController outfitInfoesController = new OutfitInfoesController(_context);
            var OutfitsItem = barCodeCheckDto.outfits;
            var result = new ResultModel<OutfitInfo>() { Success = true };
            // 新增 BarCodeStation
            foreach (var item in OutfitsItem.Where(w => !string.IsNullOrWhiteSpace(w.inputData)))
            {
                var outfitInfo = await outfitInfoesController.GetOutfitInfoByOutfitNo(item.inputData.ToUpper());
                if (outfitInfo.Value != null)
                {
                    outfitInfo.Value.UseTimes += 1;
                    outfitInfo.Value.TotalTimes += 1;
                    outfitInfo.Value.UpdateDate = DateTime.Now;

                    result = await outfitInfoesController.PutOutfitInfo(outfitInfo.Value.OutfitID, outfitInfo.Value);
                    if (!result.Success)
                        return result;
                }

                WipAlarmsController wipAlarmsController = new WipAlarmsController(_context);
                var wipAlarms = await wipAlarmsController.GetWipAlarmByOutfit(barCodeCheckDto.wipNo, item.inputData.Trim().ToUpper());
                // 判斷確認治具編號是否已到預警提醒
                if (outfitInfoesController.GetOutfitInfoByAlertTimes(item.inputData.Trim().ToUpper()).Result.Value == "Y")
                {
                    if (!wipAlarms.Value.Where(w => w.AlarmTypeID == (int)EnumWipAlarm.EnumTypeId.OutfitAlert).Any())
                    {
                        string MailGroup = "OUTFIT_ALARM";
                        string Subject = $"[AMES系統通知] 治具編號:{item.inputData.Trim().ToUpper()},預警提前通知";
                        string Body = "";

                        await new MailController(_context, _config).PostMail(Subject, Body, MailGroup, "", false);

                        WipAlarm wipAlarm = new WipAlarm();
                        wipAlarm.AlarmTypeID = (int)EnumWipAlarm.EnumTypeId.OutfitAlert;
                        wipAlarm.WipNO = barCodeCheckDto.wipNo;
                        wipAlarm.AlarmParam = item.inputData.ToUpper();
                        wipAlarm.AlarmValue = "1";
                        wipAlarm.AlarmDesc = Subject;
                        wipAlarm.AlarmDateTime = DateTime.Now;

                        await wipAlarmsController.PostWipAlarm(wipAlarm);
                    }
                }
                //// 確認治具編號使用次數已經超過預計次數
                //if (outfitInfoesController.GetOutfitInfoByOverUseTimes("").Result.Value == "Y")
                //{

                //}
            }
            return result;
        }

        /// <summary>
        /// BurnInfo-燒入資料檔
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task<ResultModel<BurnInfo>> Table_BurnInfo(BarCodeCheckDto model)
        {
            var result = new ResultModel<BurnInfo>() { Success = true };

            // 判斷作業站是否為燒機站 Station_Type == B 
            StationsesController stationsesController = new StationsesController(_context);
            var station = await stationsesController.GetStations(model.stationID);
            if (station.Value.Where(w => w.TypeNo == "B").Any())
            {

                // 判斷是否有燒機時間
                WipBoardController wipBoardController = new WipBoardController(_context);
                var wipBoardTime = wipBoardController.GetWipBoardToBITime(model.wipNo).Result.Value;
                WipSystemController wipSystemController = new WipSystemController(_context);
                var wipSystemTime = wipSystemController.GetWipSystemToBITime(model.wipNo).Result.Value;
                decimal PlanHour = 0;
                if (wipBoardTime > 0)
                    PlanHour = (decimal)wipBoardTime;
                else
                    PlanHour = (decimal)wipSystemTime;

                BurnInfoeController burnInfoeController = new BurnInfoeController(_context);
                // 判斷燒機時間是否足夠
                var burnInfos = await burnInfoeController.GetBurnInfosByBarcodeID(model.barcodeID);
                if (burnInfos.Value.Count() != 0)
                {
                    // 取實際燒機完成時間 空白資料
                    var item = burnInfos.Value.Where(w => string.IsNullOrWhiteSpace(w.FinishTime.ToString())).FirstOrDefault();
                    if (item != null)
                    {
                        item.FinishTime = DateTime.Now;
                        item.OutUserID = model.userID;
                        item.UpdateDate = DateTime.Now;
                        item.UpdateUserID = model.userID;
                        result = await burnInfoeController.PutBurnInfo(item);
                    }
                    else // 新增一筆
                    {
                        // 新增 BarCodeStation
                        var burnInfo = new BurnInfo
                        {
                            BarcodeID = model.barcodeID,
                            WipNo = model.wipNo,
                            BurnPlanHour = PlanHour,
                            StartTime = DateTime.Now,
                            ScheduleFinishTime = DateTime.Now.AddMinutes((double)PlanHour * 60),
                            InUserID = model.userID,
                            Status = 0,
                            CreateUserID = model.userID,
                            UpdateUserID = model.userID
                        };
                        result = await burnInfoeController.PostBurnInfo(burnInfo);
                    }
                }
                else
                {
                    // 新增 BarCodeStation
                    var burnInfo = new BurnInfo
                    {
                        BarcodeID = model.barcodeID,
                        WipNo = model.wipNo,
                        BurnPlanHour = PlanHour,
                        StartTime = DateTime.Now,
                        ScheduleFinishTime = DateTime.Now.AddMinutes((double)PlanHour * 60),
                        InUserID = 0,
                        Status = 0,
                        CreateUserID = model.userID,
                        UpdateUserID = model.userID
                    };
                    result = await burnInfoeController.PostBurnInfo(burnInfo);
                }
            }
            return result;
        }


        /// <summary>
        /// NgInfo-測試不良基本資料檔
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        private async Task<ResultModel<NgInfo>> Table_NgInfo(BarCodeCheckDto barCodeCheckDto)
        {
            NgInfoController ngInfoController = new NgInfoController(_context);
            NgComponentsController ngComponentsController = new NgComponentsController(_context);
            var NgItem = barCodeCheckDto.inputItems.Where(w => w.inputData.Contains("$")).ToList();
            var result = new ResultModel<NgInfo>() { Success = true };
            var result_NgComponent = new ResultModel<NgComponent>();

            // 新增 NgInfo
            if (NgItem.Count != 0)
            {
                // 判斷是否不良代碼
                IQueryable<NGReason> q = _context.NGReasons;
                foreach (var item in NgItem.Select(s => s.inputData))
                {
                    if (!q.Where(w => w.NGReasonNo.Trim().ToUpper() == item.Replace("$", "").Trim().ToUpper()
                                      && w.Status == "A").Any())
                    {
                        result.Success = false;
                        result.Msg = $"查無不良代碼【{item.Replace("$", "").Trim().ToUpper()}】";
                        return result;
                    }
                }

                NgInfo ngInfo = new NgInfo
                {
                    TypeNo = _context.Stationses.Where(w => w.StationID == barCodeCheckDto.stationID).FirstOrDefault().TestType,
                    OperatorID = 0,
                    FixtureNo = "NA",
                    BarcodeID = barCodeCheckDto.barcodeID,
                    ReasonNo = NgItem[0].inputData.Replace("$", ""),
                    ProgramNo = "N/A",
                    MachineNo = "N/A",
                    StationId = barCodeCheckDto.stationID,
                    WipId = barCodeCheckDto.wipID,
                    CreateUserID = barCodeCheckDto.userID,
                    UpdateUserID = barCodeCheckDto.userID
                };
                result = await ngInfoController.PostNgInfo(ngInfo);

                if (!result.Success)
                    return result;

                foreach (var NGNo in NgItem)
                {
                    NgComponent ngComponent = new NgComponent
                    {
                        NgID = result.Data.FirstOrDefault().NgID,
                        LocationNo = string.IsNullOrWhiteSpace(NGNo.oldInputData) ? "N/A" : NGNo.oldInputData,
                        NgNo = NGNo.inputData.Replace("$", ""),
                        CreateUserID = barCodeCheckDto.userID,
                        UpdateUserID = barCodeCheckDto.userID
                    };
                    result_NgComponent = await ngComponentsController.PostNgComponent(ngComponent);

                    // NgComponent 錯誤
                    if (!result_NgComponent.Success)
                    {
                        result.Success = false;
                        result.Msg = result_NgComponent.Msg;
                        return result;
                    }

                    // 累計預警
                    WipAlarmsController wipAlarmsController = new WipAlarmsController(_context);
                    await wipAlarmsController.PostWipAlarm4ErrorCode(barCodeCheckDto.wipNo, NGNo.inputData.Replace("$", ""));
                }
            }
            return result;
        }

        /// <summary>
        /// BarcodeWip-檔案用途    條碼工單資料檔
        /// </summary>
        /// <param name="barCodeCheckDto"></param>
        /// <returns></returns>
        private async Task<ResultModel<BarcodeWip>> Table_BarcodeWip(BarCodeCheckDto barCodeCheckDto)
        {
            BarcodeWipController barcodeWipController = new BarcodeWipController(_context);

            var barcodeWip = barcodeWipController.GetBarcodeWipByTwoKey(barCodeCheckDto.barcodeID, barCodeCheckDto.wipID).Result.Value;

            if (barcodeWip == null)
            {
                barcodeWip = new BarcodeWip
                {
                    BarcodeID = barCodeCheckDto.barcodeID,
                    WipID = barCodeCheckDto.wipID,
                    CreateUserID = barCodeCheckDto.userID
                };

                return await barcodeWipController.PostBarcodeWip(barcodeWip);
            }
            else
            {
                return await barcodeWipController.PutBarcodeWip(barcodeWip);
            }
        }

        /// <summary>
        /// WipStation
        /// </summary>
        /// <returns></returns>
        private async Task<ResultModel<WipStation>> Table_WipStation(BarCodeCheckDto barCodeCheckDto)
        {
            WipStationController wipStationController = new WipStationController(_context);
            var wipStation = new WipStation();
            var resut = new ResultModel<WipStation>();
            // 判斷是否有資料
            var queryWipStation = await wipStationController.GetWipStation4QRS009(barCodeCheckDto.wipID, barCodeCheckDto.stationID);
            wipStation = queryWipStation.Value.Where(w => w.RuleStatus == barCodeCheckDto.ruleStatus
                                                    && w.CreateDate.ToString("yyyy/MM/dd") == DateTime.Now.ToString("yyyy/MM/dd"))
                .FirstOrDefault();
            // 有資料加1 後續判斷第一次過站
            if (wipStation != null)
            {
                BarcodeStationController barcodeStationController = new BarcodeStationController(_context);
                var barcodeStation = await barcodeStationController.GetBarcodeStationByKey(barCodeCheckDto.barcodeID,
                                            barCodeCheckDto.wipID, barCodeCheckDto.stationID, barCodeCheckDto.flowRule);
                if (barcodeStation.Value == null)
                {
                    wipStation.FirstCnt += 1;
                }
                wipStation.PassCnt += 1;
                resut = await wipStationController.PutWipStation(wipStation);
            }
            else
            {
                wipStation = new WipStation
                {
                    WipID = barCodeCheckDto.wipID,
                    RuleStatus = barCodeCheckDto.ruleStatus,
                    StationID = barCodeCheckDto.stationID,
                    FirstCnt = 1,
                    PassCnt = 1,
                    CreateUserID = barCodeCheckDto.userID
                };
                resut = await wipStationController.PostWipStation(wipStation);
            }
            return resut;
        }

        /// <summary>
        /// WipClass-各班別數量資料檔
        /// </summary>
        /// <returns></returns>
        private async Task<ResultModel<WipClass>> Table_WipClass(BarCodeCheckDto barCodeCheckDto)
        {
            WipClassController wipClassController = new WipClassController(_context);
            var wipClass = new WipClass();
            var resut = new ResultModel<WipClass>();

            // 取ClassID 
            int ClassID = -1;
            ClassInfoesController classInfoesController = new ClassInfoesController(_context);
            var classInfo = await classInfoesController.GetClassInfoByUnit(barCodeCheckDto.unitNo);
            if (classInfo.Value.Count() != 0)
            {
                var ID = classInfo.Value.Where(w => DateTime.Parse(DateTime.Now.ToString("yyyy/MM/dd") + " " + w.BeginTime) <= DateTime.Now
                                   && DateTime.Now <= DateTime.Parse(DateTime.Now.ToString("yyyy/MM/dd") + " " + w.EndTime))
                                                .FirstOrDefault();

                if (ID != null)
                {
                    ClassID = ID.ClassID;
                }
            }


            // 判斷是否有資料
            var queryWipClass = await wipClassController.GetWipClassByData(barCodeCheckDto.wipID, barCodeCheckDto.stationID, barCodeCheckDto.ruleStatus);
            queryWipClass = queryWipClass.Value.Where(w => w.CreateDate.ToString("yyyy/MM/dd") == DateTime.Now.ToString("yyyy/MM/dd")).ToList();

            // 有資料加1 後續判斷第一次過站
            if (queryWipClass.Value.Where(w => w.ClassID == ClassID).Any())
            {
                wipClass = queryWipClass.Value.FirstOrDefault();
                BarcodeStationController barcodeStationController = new BarcodeStationController(_context);
                var barcodeStation = await barcodeStationController.GetBarcodeStationByKey(barCodeCheckDto.barcodeID,
                                            barCodeCheckDto.wipID, barCodeCheckDto.stationID, barCodeCheckDto.flowRule);
                if (barcodeStation.Value == null)
                {
                    wipClass.FirstCnt += 1;
                }
                wipClass.PassCnt += 1;
                resut = await wipClassController.PutWipClass(wipClass);
            }
            else
            {
                wipClass = new WipClass
                {
                    WipID = barCodeCheckDto.wipID,
                    RuleStatus = barCodeCheckDto.ruleStatus,
                    StationID = barCodeCheckDto.stationID,
                    ClassID = ClassID,
                    FirstCnt = 1,
                    PassCnt = 1,
                    CreateUserID = barCodeCheckDto.userID
                };
                resut = await wipClassController.PostWipClass(wipClass);
            }


            return resut;
        }

        /// <summary>
        /// WipTime-工單各站數量資料檔 – By TIME
        /// </summary>
        /// <returns></returns>
        private async Task<ResultModel<WipTime>> Table_WipTime(BarCodeCheckDto barCodeCheckDto)
        {
            WipTimeController wipTimeController = new WipTimeController(_context);
            var wipTime = new WipTime();
            var resut = new ResultModel<WipTime>();

            // 取SegmentID 
            int SegmentID = -1;
            TimeSegmentsController timeSegmentsController = new TimeSegmentsController(_context);
            var timeSegment = await timeSegmentsController.GetTimeSegment();
            if (timeSegment.Value.Count() != 0)
            {
                var ID = timeSegment.Value.Where(w => DateTime.Parse(DateTime.Now.ToString("yyyy/MM/dd") + " " + w.StartTime) <= DateTime.Now
                                   && DateTime.Now <= DateTime.Parse(DateTime.Now.ToString("yyyy/MM/dd") + " " + w.EndTime))
                                               .FirstOrDefault();

                if (ID != null)
                {
                    SegmentID = ID.SegmentID;
                }
            }



            // 判斷是否有資料
            var queryWipTime = await wipTimeController.GetWipTimeByData(barCodeCheckDto.wipID, barCodeCheckDto.stationID, barCodeCheckDto.ruleStatus);
            queryWipTime = queryWipTime.Value.Where(w => w.CreateDate.ToString("yyyy/MM/dd") == DateTime.Now.ToString("yyyy/MM/dd")).ToList();
            // 有資料加1 後續判斷第一次過站
            if (queryWipTime.Value.Where(w => w.SegmentID == SegmentID).Any())
            {
                wipTime = queryWipTime.Value.FirstOrDefault();
                BarcodeStationController barcodeStationController = new BarcodeStationController(_context);
                var barcodeStation = await barcodeStationController.GetBarcodeStationByKey(barCodeCheckDto.barcodeID,
                                            barCodeCheckDto.wipID, barCodeCheckDto.stationID, barCodeCheckDto.flowRule);
                if (barcodeStation.Value == null)
                {
                    wipTime.FirstCnt += 1;
                }
                wipTime.PassCnt += 1;
                resut = await wipTimeController.PutWipTime(wipTime);
            }
            else
            {
                wipTime = new WipTime
                {
                    WipID = barCodeCheckDto.wipID,
                    RuleStatus = barCodeCheckDto.ruleStatus,
                    StationID = barCodeCheckDto.stationID,
                    SegmentID = SegmentID,
                    FirstCnt = 1,
                    PassCnt = 1,
                    CreateUserID = barCodeCheckDto.userID
                };
                resut = await wipTimeController.PostWipTime(wipTime);
            }

            return resut;
        }

        #endregion

        /// <summary>
        /// 判斷工單狀態
        /// </summary>
        /// <param name="wipno">工單號碼</param>
        /// <param name="unitno">生產單位</param>
        /// <param name="line">線別</param>
        /// <param name="flowrule">流程</param>
        /// <param name="stationID">作業站ID</param>
        /// <returns></returns>
        [HttpGet("CheckWipNoSation")]
        public IActionResult GetCheckWipNoSation(string wipno, string unitno, int line, int flowrule, int stationID)
        {
            var result = CheckWipNoSationAsync(wipNo: wipno, unitNo: unitno, flowRuleID: flowrule, line: line, stationID: stationID);
            return Ok(result.Result);
        }

        /// <summary>
        /// 內部序號查詢工單號碼
        /// </summary>
        /// <param name="barcode">內部序號</param>
        /// <returns>Success:true or false</returns>
        [HttpGet("BarCodeFromWip")]
        public IResultModel CheckBarCodeFromWip(string barcode)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            if (barcode.Length <= 4)
            {
                resultModel.Msg = "內部序號小於4個字數";
                return resultModel;
            }

            WipInfosController wipInfosController = new WipInfosController(_context);
            // 內部序號扣除流水號 查詢
            IQueryable<WipBarcode> q = _context.WipBarcodes.Where(w => w.StartNO.Substring(0, (barcode.Length - 4)) == (barcode.Substring(0, (barcode.Length - 4))));
            if (!q.Any())
            {
                resultModel.Msg = "找不到內部序號【" + barcode + "】 對應相關工單號碼";
                return resultModel;
            }
            else
            {
                try
                {
                    var No = int.Parse(barcode.Substring(barcode.Length - 4, 4));
                    foreach (var item in q)
                    {
                        int StartNo = int.Parse(item.StartNO.Substring(item.StartNO.Length - 4, 4));
                        int EndNo = int.Parse(item.EndNO.Substring(item.EndNO.Length - 4, 4));
                        if (StartNo <= No && No <= EndNo)
                        {
                            resultModel.Success = true;
                            resultModel.Msg = q.Select(s => s.WipNO).FirstOrDefault();
                            return resultModel;
                        }
                    }
                    resultModel.Msg = "工單號碼【" + q.Select(s => s.WipNO).FirstOrDefault() + "】 找不到範圍內的內部序號";
                }
                catch (Exception ex)
                {
                    resultModel.Msg = ex.Message;
                }
            }

            return resultModel;
        }

        /// <summary>
        /// 查詢序號是否有在該工單 條碼區間內
        /// </summary>
        /// <param name="barcode">內部序號</param>
        /// <param name="wipNo">工單號碼</param>
        [HttpGet("CheckBarCodeByWipNo")]
        public IResultModel CheckBarCodeByWipNo(string barcode, string wipNo)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            if (barcode.Length <= 4)
            {
                resultModel.Msg = "內部序號小於4個字數";
                return resultModel;
            }

            // 內部序號扣除流水號 查詢
            IQueryable<WipBarcode> q = _context.WipBarcodes.Where(w => w.WipNO == wipNo);
            if (!q.Any())
            {
                resultModel.Msg = "找不到工單號碼【" + wipNo + "】 綁定條碼區間";
                return resultModel;
            }
            else
            {
                try
                {
                    IQueryable<WipInfo> WipInfo = _context.WipInfos.Where(w => w.WipNO == wipNo);
                    //流水號碼數以工單數量的位數決定
                    int snLen = WipInfo.Select(s => s.PlanQTY.ToString().Length).FirstOrDefault();
                    if (snLen < 4) snLen = 4;
                    // 93200036400001 9320003640001
                    var No = int.Parse(barcode.Substring(barcode.Length - snLen, snLen));
                    foreach (var item in q.Where(w => w.StartNO.Substring(0, barcode.Length - snLen) == barcode.Substring(0, barcode.Length - snLen)
                                                        && w.StartNO.Length == barcode.Length))
                    {
                        int StartNo = int.Parse(item.StartNO.Substring(item.StartNO.Length - snLen, snLen));
                        int EndNo = int.Parse(item.EndNO.Substring(item.EndNO.Length - snLen, snLen));
                        if (StartNo <= No && No <= EndNo)
                        {
                            resultModel.Success = true;
                            return resultModel;
                        }
                    }
                    resultModel.Msg = "工單號碼【" + wipNo + "】 找不到範圍內的內部序號【" + barcode + "】";
                }
                catch (Exception ex)
                {
                    resultModel.Msg = ex.Message;
                }
            }

            return resultModel;
        }

        /// <summary>
        /// 內部序號查詢目前生產單位
        /// </summary>
        /// <param name="barcode">內部序號</param>
        /// <returns>Success:true or false</returns>
        [HttpGet("BarCodeToUnit")]
        public async Task<IResultModel> GetBarCodeToUnitAsync(string barcode)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            if (barcode.Length <= 4)
            {
                resultModel.Msg = "內部序號小於4個字數";
                return resultModel;
            }

            int BarCodeID = BarCodeToID(barcode).Result;

            if (BarCodeID == 0)
            {
                resultModel.Msg = "找不到內部序號【" + barcode + "】 對應BarCodeID";
                return resultModel;
            }

            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var q = await barcodeInfoesController.GetBarcodeInfoes(BarCodeID);
            resultModel.Msg = "內部序號【" + barcode + "】目前在" +
                               q.Value.Select(s => s.GetWipInfo.GetFactoryUnit.UnitName).FirstOrDefault();

            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 內部序號查詢目前站別
        /// </summary>
        /// <param name="barcode">內部序號</param>
        /// <returns>Success:true or false</returns>
        [HttpGet("BarCodeToStation")]
        public async Task<IResultModel> GetBarCodeToStationAsync(string barcode)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            if (barcode.Length <= 4)
            {
                resultModel.Msg = "內部序號小於4個字數";
                return resultModel;
            }

            int BarCodeID = BarCodeToID(barcode).Result;

            if (BarCodeID == 0)
            {
                resultModel.Msg = "找不到內部序號【" + barcode + "】 對應BarCodeID";
                return resultModel;
            }

            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var q = await barcodeInfoesController.GetBarcodeInfoes(BarCodeID);
            resultModel.Msg = "內部序號【" + barcode + "】目前在" +
                               q.Value.Select(s => s.GetStation.StationName).FirstOrDefault();

            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 內部序號是否鎖定
        /// </summary>
        /// <param name="barcode">內部序號</param>
        /// <returns>Success:true or false</returns>
        [HttpGet("BarCodeLock")]
        public async Task<IResultModel> CheckBarCodeLockAsync(string barcode)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            if (barcode.Length <= 4)
            {
                resultModel.Msg = "內部序號小於4個字數";
                return resultModel;
            }

            int BarCodeID = BarCodeToID(barcode).Result;

            if (BarCodeID == 0)
            {
                //resultModel.Msg = "找不到內部序號【" + barcode + "】 對應BarCodeID";
                resultModel.Success = true;
                return resultModel;
            }

            BarcodeLockController barcodeLockController = new BarcodeLockController(_context);
            var q = await barcodeLockController.GetBarcodeLockByBarCodeID(BarCodeID);
            if (q.Value.Where(w => w.LockStatus == 0).Any())
            {
                resultModel.Msg = "內部序號【" + barcode + "】在當前站別被鎖定,不可過站";
                return resultModel;
            }

            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 內部序號是否報廢
        /// </summary>
        /// <param name="barcode">內部序號</param>
        /// <returns>Success:true or false</returns>
        [HttpGet("BarCodeScrapped")]
        public async Task<IResultModel> CheckBarCodeScrappedAsync(string barcode)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            if (barcode.Length <= 4)
            {
                resultModel.Msg = "內部序號小於4個字數";
                return resultModel;
            }

            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var q = await barcodeInfoesController.GetBarcodeInfoesByNo(barcode);
            if (q.Value.Count() == 0)
            {
                resultModel.Success = true;
                resultModel.Msg = "找不到內部序號【" + barcode + "】 對應BarCodeID";
                return resultModel;
            }
            else if (q.Value.Any(w => w.RuleStatus == "S"))
            {
                resultModel.Msg = "內部序號【" + barcode + "】已報廢或轉賣, 不可繼續過站!";
                return resultModel;

            }

            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 確認內部條碼流動
        /// </summary>
        /// <param name="wipno">工單號碼</param>
        /// <param name="barcode">內部條碼</param>
        /// <param name="unitno">生產單位編號</param>
        /// <param name="stationID">作業站編號</param>
        /// <returns></returns>
        [HttpGet("BarCodeFlow")]
        public async Task<IResultModel> CheckBarCodeFlowAsync(string wipno, string barcode, string unitno, int stationID)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            WipInfosController wipInfosController = new WipInfosController(_context);
            var q = await wipInfosController.GetWipInfoByWipNo(wipno);

            // 找該筆工單號碼的生產單位代號
            var q1 = q.Value.Where(w => w.UnitNO == unitno).FirstOrDefault();

            // 取工單號碼開立的 WipID、生產單位
            var wipinfo = q.Value.Select(s => new { s.WipID, s.UnitNO }).ToList();

            // 取BarCodeID
            int BarCodeID = await BarCodeToID(barcode);

            // 取內部序號過站紀錄
            BarcodeStationController barcodeStationController = new BarcodeStationController(_context);
            var BarCodeStations = await barcodeStationController.GetBarcodeStationByBarCodeID(BarCodeID);
            BarCodeStations = BarCodeStations.Value.ToList();

            // 判斷需要前製程是否已經投入
            if (q1.InputFlag == "Y")
            {
                // 有BarCodeID
                if (BarCodeID != 0)
                {
                    // 判斷是否有前製程過站資料
                    // SMT(S)->DIP(D)
                    if (unitno == "D")
                    {
                        int? WipID = wipinfo.Where(w => w.UnitNO == "S").Select(s => s.WipID).FirstOrDefault();
                        if (WipID == null)
                        {
                            resultModel.Msg = "該工單號碼【" + wipno + "】的前製程生產單位尚未建立工單基本資料";
                            return resultModel;
                        }

                        if (!BarCodeStations.Value.Where(w => w.BarcodeID == BarCodeID && w.WipID == WipID && w.RuleStatus == "P").Any())
                        {
                            resultModel.Msg = "該內部序號【" + barcode + "】前製程生產單位尚未有過站紀錄";
                            return resultModel;
                        }
                    }
                    // DIP(D)->板卡測試(I)
                    else if (unitno == "I")
                    {
                        int? WipID = wipinfo.Where(w => w.UnitNO == "D").Select(s => s.WipID).FirstOrDefault();
                        if (WipID == null)
                        {
                            resultModel.Msg = "該工單號碼【" + wipno + "】的前製程生產單位尚未建立工單基本資料";
                            return resultModel;
                        }

                        if (!BarCodeStations.Value.Where(w => w.BarcodeID == BarCodeID && w.WipID == WipID && w.RuleStatus == "P").Any())
                        {
                            resultModel.Msg = "該內部序號【" + barcode + "】前製程生產單位尚未有過站紀錄";
                            return resultModel;
                        }
                    }
                    // 板卡測試(I)->板卡包裝(P)
                    else if (unitno == "P")
                    {
                        int? WipID = wipinfo.Where(w => w.UnitNO == "I").Select(s => s.WipID).FirstOrDefault();
                        if (WipID == null)
                        {
                            resultModel.Msg = "該工單號碼【" + wipno + "】的前製程生產單位尚未建立工單基本資料";
                            return resultModel;
                        }

                        if (!BarCodeStations.Value.Where(w => w.BarcodeID == BarCodeID && w.WipID == WipID && w.RuleStatus == "P").Any())
                        {
                            resultModel.Msg = "該內部序號【" + barcode + "】前製程生產單位尚未有過站紀錄";
                            return resultModel;
                        }
                    }
                    // 組裝(B)->系統測試(T)->成品包裝(O)
                    else if (unitno == "T")
                    {
                        int? WipID = wipinfo.Where(w => w.UnitNO == "B").Select(s => s.WipID).FirstOrDefault();
                        if (WipID == null)
                        {
                            resultModel.Msg = "該工單號碼【" + wipno + "】的前製程生產單位尚未建立工單基本資料";
                            return resultModel;
                        }

                        if (!BarCodeStations.Value.Where(w => w.BarcodeID == BarCodeID && w.WipID == WipID && w.RuleStatus == "P").Any())
                        {
                            resultModel.Msg = "該內部序號【" + barcode + "】前製程生產單位尚未有過站紀錄";
                            return resultModel;
                        }
                    }
                    else if (unitno == "O")
                    {
                        int? WipID = wipinfo.Where(w => w.UnitNO == "T").Select(s => s.WipID).FirstOrDefault();
                        if (WipID == null)
                        {
                            resultModel.Msg = "該工單號碼【" + wipno + "】的前製程生產單位尚未建立工單基本資料";
                            return resultModel;
                        }

                        if (!BarCodeStations.Value.Where(w => w.BarcodeID == BarCodeID && w.WipID == WipID && w.RuleStatus == "P").Any())
                        {
                            resultModel.Msg = "該內部序號【" + barcode + "】前製程生產單位尚未有過站紀錄";
                            return resultModel;
                        }
                    }
                }
                // 沒有BarCodeID
                else
                {
                    if (unitno != "S" && unitno != "B")
                    {
                        resultModel.Msg = "該工單號碼【" + wipno + "】前製程式尚未投產";
                        return resultModel;
                    }
                }
            }

            #region 判斷作業站順序
            // 抓流程順序資料
            RuleStationsController ruleStationsController = new RuleStationsController(_context);
            var ruleStations = await ruleStationsController.GetRuleStationByFlow(q1.FlowRuleID, 0);
            if (ruleStations.Value.Count() == 0)
            {
                resultModel.Msg = "該工單號碼【" + wipno + "】的流程編號尚未設定流程";
                return resultModel;
            }

            // 該作業站 RuleStationID
            int? RuleStationID = ruleStations.Value.Where(w => w.StationID == stationID).Select(s => s.RuleStationID).FirstOrDefault();
            if (RuleStationID == null || RuleStationID == 0)
            {
                resultModel.Msg = "該工單號碼【" + wipno + "】的流程未設定此作業站";
                return resultModel;
            }

            // 判斷序號目前是否有重複過站
            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var BarcodeInfos = await barcodeInfoesController.GetBarcodeInfoesByNo(barcode);
            BarcodeInfos = BarcodeInfos.Value.ToList();
            if (BarcodeInfos.Value.Where(w => w.StationID == stationID).Any())
            {
                resultModel.Msg = "該內部序號【" + barcode + "】已刷過此站";
                return resultModel;
            }

            // 取目前工單ID
            int wipID = q1.WipID;
            int flowRuleID = q1.FlowRuleID;

            resultModel = (ResultModel<string>)await GetBarCodeLastStopRuleStationID(wipID, BarCodeID, stationID, flowRuleID);
            if (!resultModel.Success)
                return resultModel;

            #endregion
            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 確認工單狀態
        /// </summary>
        /// <param name="wipNo">工單號碼</param>
        /// <param name="unitNo">生產單位</param>
        /// <param name="flowRuleID">流程</param>
        /// <param name="line">線別</param>
        /// <param name="stationID">作業站</param>
        /// <param name="barCodeNo">生產條碼</param>
        /// <returns></returns>
        private async Task<ResultModel<string>> CheckWipNoSationAsync(string wipNo, string unitNo, int flowRuleID, int line, int stationID = 0, string barCodeNo = "")
        {
            ResultModel<string> resultModel = new ResultModel<string>();

            resultModel.Success = false;

            WipInfosController wipInfosController = new WipInfosController(_context);

            var q = await wipInfosController.GetWipInfoByWipNo(wipNo);
            if (q.Value.Count() == 0)
            {
                resultModel.Msg = "找不到工單號碼【" + wipNo + "】";
                return resultModel;
            }

            var WipNoItem = q.Value.Where(w => w.WipNO == wipNo && w.UnitNO == unitNo).ToList();
            if (WipNoItem.Count == 0)
            {
                resultModel.Msg = "工單號碼【" + wipNo + ",尚未設定此生產單位";
                return resultModel;
            }

            if (!WipNoItem.Where(w => w.FlowRuleID == flowRuleID).Any())
            {
                resultModel.Msg = "工單號碼【" + wipNo + "】,尚未設定此流程站";
                return resultModel;
            }


            if (!WipNoItem.Where(w => w.LineID == line).Any())
            {
                resultModel.Msg = "工單號碼【" + wipNo + "】,尚未設定此線別";
                return resultModel;
            }

            if (WipNoItem.Where(w => w.StatusNO == "E").Any())
            {
                resultModel.Msg = "工單號碼【" + wipNo + "】,該工單已經投入完工,請切換工單";
                return resultModel;
            }

            if (WipNoItem.Where(w => w.StatusNO == "C").Any())
            {
                resultModel.Msg = "工單號碼【" + wipNo + "】,該工單已刪除,請切換工單";
                return resultModel;
            }

            // 判斷是否是投入站
            var RuleStation = await _context.RuleStations.Where(w => w.FlowRuleID == flowRuleID && w.StationID == stationID)
                             .FirstOrDefaultAsync();
            if (RuleStation != null)
            {
                if (RuleStation.Sequence == 1)
                {
                    int WipID = WipNoItem.FirstOrDefault().WipID;
                    LineInfoesController lineInfoesController = new LineInfoesController(_context);
                    var q2 = await lineInfoesController.GetLineInfoByWipID(WipID);
                    if (!q2.Value.Where(w => w.LineID == line).Any())
                    {
                        //因維修後投入站 不須重開線
                        if (!await _context.BarcodeInfoes.Where(w => w.WipID == WipNoItem.FirstOrDefault().WipID && w.BarcodeNo == barCodeNo).AnyAsync())
                        {
                            resultModel.Msg = $"工單號碼【{wipNo}】,工單尚未開線,不可過站";
                            return resultModel;
                        }
                        //resultModel.Msg = "工單號碼【" + wipNo + "】,工單尚未開線,不可過站";
                        //return resultModel;
                    }
                }
            }

            // 已投入數量>=工單數量
            if (CheckNowFirstStation(wipNo, unitNo, stationID) == "Y")
            {
                var FirstWipInfo = WipNoItem.FirstOrDefault();
                if (FirstWipInfo.CompleteQTY >= FirstWipInfo.PlanQTY)
                {
                    resultModel.Msg = "工單號碼【" + wipNo + "】,已投入數量>=工單數量,請在確認";
                    return resultModel;
                }
            }

            // 該筆工單號碼鎖定
            WipLockController wipLockController = new WipLockController(_context);
            var q3 = await wipLockController.GetWipLockByWipNO(wipNo);
            if (q3.Data.Where(w => w.LockStatus == "0" && w.StationID == 0).Any())
            {
                resultModel.Msg = "工單號碼【" + wipNo + "】,已被鎖定,不可過站";
                return resultModel;
            }

            // StationID = 0 代表批次鎖定
            else if (q3.Data.Where(w => w.LockStatus == "0" && w.StationID == stationID).Any())
            {
                resultModel.Msg = "工單號碼【" + wipNo + "】,工單在當前站別被鎖定,不可過站";
                return resultModel;
            }
            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 判斷序號狀態
        /// </summary>
        /// <param name="wipno">工單號碼</param>
        /// <param name="barcode">內部序號</param>
        /// <returns></returns>
        [HttpGet("CheckBarCodeStation")]
        public async Task<IResultModel> GetCheckBarCodeStation(string wipno, string barcode)
        {
            ResultModel<string> resultModel = new ResultModel<string>();

            #region 內部序號是否被鎖定
            resultModel = (ResultModel<string>)await CheckBarCodeLockAsync(barcode);
            if (!resultModel.Success)
                return resultModel;
            #endregion

            #region 內部序號是否被報廢
            resultModel = (ResultModel<string>)await CheckBarCodeScrappedAsync(barcode);
            if (!resultModel.Success)
                return resultModel;
            #endregion

            #region 找尋內部序號(工單號碼) 並與接收工單號碼是否一致
            //resultModel = (ResultModel<string>)CheckBarCodeFromWip(barcode);
            //if (!resultModel.Success)
            //    return resultModel;
            //else if (resultModel.Msg != wipno.ToUpper())
            //{
            //    resultModel.Msg = "工單號碼【" + wipno + "】與內部序號所帶出工單號碼【" + resultModel.Msg + "】不一致";
            //    resultModel.Success = false;
            //    return resultModel;
            //}
            #endregion

            return resultModel;
        }

        /// <summary>
        /// 燒機判斷
        /// </summary>
        /// <param name="wipno">工單號碼</param>
        /// <param name="barcodeID">內部序號ID</param>
        /// <param name="stationID">作業站ID</param>
        /// <returns></returns>
        private async Task<IResultModel> GetCheckBurn(string wipno, int barcodeID, int stationID)
        {
            ResultModel<string> resultModel = new ResultModel<string>();

            // 判斷作業站是否為燒機站
            StationsesController stationsesController = new StationsesController(_context);
            var station = await stationsesController.GetStations(stationID);
            // Station_Type = B 燒機站
            if (station.Value.Where(w => w.TypeNo == "B").Any())
            {
                // 判斷是否有燒機時間
                WipBoardController wipBoardController = new WipBoardController(_context);
                var wipBoardTime = wipBoardController.GetWipBoardToBITime(wipno).Result.Value;
                WipSystemController wipSystemController = new WipSystemController(_context);
                var wipSystemTime = wipSystemController.GetWipSystemToBITime(wipno).Result.Value;
                if (wipBoardTime <= 0 && wipSystemTime <= 0)
                {
                    resultModel.Success = false;
                    resultModel.Msg = "請確認燒機時間是否有填寫或者格式有誤";
                    return resultModel;
                }

                // 判斷燒機時間是否足夠
                BurnInfoeController burnInfoeController = new BurnInfoeController(_context);
                var burnInfo = await burnInfoeController.GetBurnInfosByBarcodeID(barcodeID);
                if (burnInfo.Value.Count() != 0)
                {
                    // 取實際燒機完成時間 空白資料
                    var item = burnInfo.Value.Where(w => string.IsNullOrWhiteSpace(w.FinishTime.ToString())).FirstOrDefault();
                    if (item != null)
                    {
                        // 現在時間 < 預計排程時間
                        if (DateTime.Now < item.ScheduleFinishTime)
                        {
                            resultModel.Success = false;
                            resultModel.Msg = "燒機排程完成時間【" + item.ScheduleFinishTime + "】尚未到達";
                            return resultModel;
                        }
                    }
                    else // 燒機資料都有填入實際燒機時間
                    {
                        resultModel.Msg = "BurnIn";
                    }
                }
                else
                // 沒有BurnInfo = Burn In
                {
                    resultModel.Msg = "BurnIn";
                }
                resultModel.Success = true;
                return resultModel;
            }
            else
            {
                resultModel.Success = true;
                return resultModel;
            }
        }

        /// <summary>
        /// 確認組件狀態
        /// </summary>
        /// <returns></returns>
        [HttpGet("BarCodeKP")]
        public async Task<IResultModel> CheckBarCodeKPAsync([FromQuery] BarcodeItemKPDto barcodeItemKPDto)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };
            try
            {
                #region 判斷是否有工單
                WipInfosController wipInfosController = new WipInfosController(_context);
                var wipinfo = await wipInfosController.GetWipInfoByWipNo(barcodeItemKPDto.wipNo);
                wipinfo = wipinfo.Value.Where(w => w.UnitNO == barcodeItemKPDto.unitNo).ToList();
                if (wipinfo.Value.Count() == 0)
                {
                    resultModel.Msg = "找不到工單號碼【" + barcodeItemKPDto.wipNo + "】";
                    return resultModel;
                }
                #endregion

                #region 判斷是否有輸入工單料號
                WipAttsController wipAttsController = new WipAttsController(_context);
                string ItemNo = (await wipAttsController.GetWipAtt(wipinfo.Value.FirstOrDefault().WipNO)).Value.ItemNO;
                if (string.IsNullOrWhiteSpace(ItemNo))
                {
                    resultModel.Msg = "工單號碼【" + barcodeItemKPDto.wipNo + "】,找不到工程編號";
                    return resultModel;
                }
                #endregion

                #region 判斷工單料號是否有在料號基本檔
                MaterialItemController materialItemController = new MaterialItemController(_context);
                var MaterialItem = await materialItemController.GetMaterialItemByItemNO(ItemNo);
                if (MaterialItem == null)
                {
                    resultModel.Msg = "工程編號【" + ItemNo + "】,在工程編號基本資料檔找不到";
                    return resultModel;
                }
                #endregion

                #region 確認是否有設定key Parts資料
                WipKpsController wipKpsController = new WipKpsController(_context);
                var wipKps = (await wipKpsController.GetWipKpByWipNo(barcodeItemKPDto.wipNo)).Value.ToList();
                wipKps = wipKps.Where(w => w.UnitNo == barcodeItemKPDto.unitNo).OrderBy(o => o.KpSeq).ToList();
                if (wipKps.Count != 0)
                {
                    #region 判斷內部序號是否有過站紀錄
                    var BarCodeID = await BarCodeToID(barcodeItemKPDto.barCodeNo);
                    //if (BarCodeID == 0)
                    //{
                    //    resultModel.Msg = "內部序號【" + BarCodeID + "】,在條碼資料檔找不到";
                    //    return resultModel;
                    //}
                    #endregion

                    #region 判斷組件序號是否有紀錄
                    BarcodeItemsController barcodeItemsController = new BarcodeItemsController(_context);
                    var BarCodeItems = (await barcodeItemsController.GetBarcodeItemByBarCodeID(BarCodeID)).Value.ToList();
                    // BarCodeItems = BarCodeItems.Where(w => w.S.UnitNo == barcodeItemKPDto.ststionUnitNo).ToList();
                    BarCodeItems = BarCodeItems.Where(w => w.S.UnitNo == barcodeItemKPDto.unitNo && w.WipID == wipinfo.Value.FirstOrDefault().WipID).ToList();
                    #endregion

                    // 計算過站時刷的組件數量與已經存BarCodeItems
                    var KPQty = barcodeItemKPDto.inputKP.Count + BarCodeItems.Count();
                    #region 刷入組件數量超過
                    if (KPQty > wipKps.Count)
                    {
                        resultModel.Msg = "組件數量已刷超過設定數量,請確認";
                        return resultModel;
                    }
                    #endregion

                    #region 比對組件資料
                    var CheckMsg = string.Empty;
                    int x = BarCodeItems.Count();

                    for (int i = 0; i < barcodeItemKPDto.inputKP.Count; i++)
                    {

                        // 按照順序
                        var wipKpsItem = wipKps[x + i];
                        var barcodeKPDtoItem = barcodeItemKPDto.inputKP[i];
                        // 有KpNo以KpNo為主
                        if (!string.IsNullOrWhiteSpace(barcodeKPDtoItem.inputType))
                        {
                            wipKpsItem = wipKps.Where(w => w.KpNo.ToUpper() == barcodeKPDtoItem.inputType.ToUpper()).FirstOrDefault();

                            if (wipKpsItem == null)
                            {
                                wipKpsItem = wipKps[x + i];
                            }
                        }

                        #region 比對序號長度是否正確
                        if (!string.IsNullOrWhiteSpace(wipKpsItem.Length.ToString()))
                        {
                            if (wipKpsItem.Length != barcodeKPDtoItem.inputData.Length && wipKpsItem.Length != 0)
                                CheckMsg += "組件序號【" + barcodeKPDtoItem.inputData + "】 與組件名稱【" + wipKpsItem.KpName + "】長度不符合</br>";
                        }
                        #endregion

                        #region 前置碼正確
                        if (!string.IsNullOrWhiteSpace(wipKpsItem.Title))
                        {
                            if (!barcodeKPDtoItem.inputData.ToUpper().StartsWith(wipKpsItem.Title.ToUpper()))
                                CheckMsg += "組件序號【" + barcodeKPDtoItem.inputData + "】 與組件名稱【" + wipKpsItem.Title + "】前置碼不符合</br>";
                        }
                        #endregion

                        #region 組件代碼-組件序號是否重複
                        // 判斷KP順序後是否重複=N
                        if (wipKps.Where(w => w.KpSeq == wipKpsItem.KpSeq && w.IsRepeat == "N").Any())
                        {
                            var checkDataRedundancy = await barcodeItemsController.GetBarcodeItemByPartNo(barcodeKPDtoItem.inputData);
                            if (checkDataRedundancy.Value.Count() != 0)
                            {
                                CheckMsg += "組件名稱【" + wipKpsItem.KpName + "】已有相同組件序號【" + barcodeKPDtoItem.inputData + "】紀錄 </br>";
                            }
                        }

                        #endregion

                        #region 判斷組件序號是否在製狀態
                        if (wipKpsItem.KpNo.ToUpper() == "04")
                        {
                            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
                            var BarCodeInfo = await barcodeInfoesController.GetBarcodeInfoesByNo(barcodeKPDtoItem.inputData);
                            if (BarCodeInfo.Value.Where(w => w.StatusID != -1).Any())
                            {
                                CheckMsg += "組件序號【" + barcodeKPDtoItem.inputData + "】 目前是在製狀態</br>";
                            }
                        }
                        #endregion

                        #region 判斷MAC區間
                        // 安勤不需要判斷MAC區間
                        if (wipKpsItem.KpNo.ToUpper().Contains("MAC"))
                        {
                            WipMACController wipMACController = new WipMACController(_context);
                            var wipMAC = wipMACController.GetWipMAC(barcodeItemKPDto.wipNo).Result.Value;
                            if (wipMAC.Count() == 0)
                            {
                                CheckMsg += "工單號碼【" + barcodeItemKPDto.wipNo + "】 找不到綁定MAC區間</br>";
                            }
                            else
                            {
                                // 判斷是否符合區間
                                if (barcodeKPDtoItem.inputData.Length != 12 && barcodeKPDtoItem.inputData.Length != 6)
                                {
                                    CheckMsg += "組件序號【" + barcodeKPDtoItem.inputData + "】 綁定MAC不足12碼或6碼 </br>";
                                }
                                else
                                {
                                    // 長度12碼 判斷前置碼
                                    if (barcodeKPDtoItem.inputData.Length == 12)
                                    {
                                        if (!wipMAC.Where(w => barcodeKPDtoItem.inputData.StartsWith(w.Title)).Any())
                                        {
                                            CheckMsg += $"組件序號【{barcodeKPDtoItem.inputData}】與MAC【{string.Join('、', wipMAC.Select(s => s.Title).ToList())}】前置碼不符合 </br>";
                                        }
                                    }
                                    // 長度6碼 抓WIPMAC 前6碼補足 12碼
                                    else if (barcodeKPDtoItem.inputData.Length == 6)
                                    {
                                        var wipMacItem = wipMAC.FirstOrDefault();
                                        barcodeKPDtoItem.inputData = wipMacItem.Title + barcodeKPDtoItem.inputData;
                                    }

                                    var InputMacTitle = barcodeKPDtoItem.inputData.Substring(0, 6).ToUpper();
                                    var InputMacNo = Convert.ToInt32(barcodeKPDtoItem.inputData.Substring(6, 6), 16);
                                    if (!wipMAC.Where(w => Convert.ToInt32(w.StartNO, 16) <= InputMacNo &&
                                                          InputMacNo <= Convert.ToInt32(w.EndNO, 16) &&
                                                          w.Title == InputMacTitle).Any())
                                    {
                                        CheckMsg += "組件序號【" + barcodeKPDtoItem.inputData + "】 與工單設定MAC區間不符合 </br>";
                                    }
                                }
                            }
                        }
                        #endregion

                        #region 判斷出貨序號
                        // 當KP_NAME是 EXT_NO 判斷組件-出貨序號 是否有在區間
                        if (wipKpsItem.KpNo.ToUpper() == "95")
                        {
                            WipBarcodeOtherController wipBarcodeOtherController = new WipBarcodeOtherController(_context);
                            var WipBarCodeOther = await wipBarcodeOtherController.CheckWipBarcodeOtherByNo(barcodeItemKPDto.wipNo, barcodeKPDtoItem.inputData);
                            if (WipBarCodeOther.Value.Count() == 0)
                            {
                                CheckMsg += "組件序號【" + barcodeKPDtoItem.inputData + "】 與工單設定出貨序號區間不符合 </br>";
                            }
                            else
                            {
                                resultModel.Data = new List<string> { barcodeKPDtoItem.inputData };
                                resultModel.Msg = barcodeKPDtoItem.inputData;
                            }
                        }
                        #endregion
                    }

                    if (!string.IsNullOrWhiteSpace(CheckMsg))
                    {
                        resultModel.Msg = CheckMsg;
                        return resultModel;
                    }
                    #endregion
                }
                #endregion
                resultModel.Success = true;
                return resultModel;
            }
            catch (Exception ex)
            {
                resultModel.Success = false;
                resultModel.Msg = ex.Message;
                return resultModel;
            }
        }

        /// <summary>
        /// 確認治具狀態
        /// </summary>
        /// <returns></returns>
        //[HttpGet("BarCodeOutfit")]
        private async Task<IResultModel> CheckBarCodeOutfitAsync([FromQuery] List<BarCodeCheckDto.Outfit> outfit)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };

            #region 判斷是否有治具編號
            OutfitInfoesController outfitInfoesController = new OutfitInfoesController(_context);
            foreach (var outfitNo in outfit)
            {
                var q = await outfitInfoesController.GetOutfitInfoByOutfitNo(outfitNo.inputData.ToUpper());

                if (q.Value == null)
                {
                    resultModel.Msg = "中央治具找不到該治具編號【" + outfitNo.inputData + "】";
                    return resultModel;
                }
            }
            #endregion
            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 確認組件數量正確
        /// </summary>
        /// <param name="wipno">工單號碼</param>
        /// <param name="barcode">內部條碼</param>
        /// <param name="unitno">生產單位</param>
        /// <returns></returns>
        [HttpGet("CheckBarCodeKPQty")]
        public async Task<IResultModel> CheckBarCodeKPQtyAsync(string wipno, string barcode, string unitno)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };

            #region 判斷是否有工單
            WipInfosController wipInfosController = new WipInfosController(_context);
            var q = await wipInfosController.GetWipInfoByWipNo(wipno);
            q = q.Value.Where(w => w.UnitNO == unitno).ToList();
            if (q.Value.Count() == 0)
            {
                resultModel.Msg = "找不到工單號碼【" + wipno + "】";
                return resultModel;
            }
            #endregion

            #region 判斷是否有輸入工單料號
            WipAttsController wipAttsController = new WipAttsController(_context);
            string ItemNo = (await wipAttsController.GetWipAtt(q.Value.FirstOrDefault().WipNO)).Value.ItemNO;
            if (string.IsNullOrWhiteSpace(ItemNo))
            {
                resultModel.Msg = "工單號碼【" + wipno + "】,找不到工程編號";
                return resultModel;
            }
            #endregion

            #region 判斷工單料號是否有在料號基本檔
            MaterialItemController materialItemController = new MaterialItemController(_context);
            var MaterialItem = await materialItemController.GetMaterialItemByItemNO(ItemNo);
            if (MaterialItem == null)
            {
                resultModel.Msg = "工程編號【" + ItemNo + "】,在工程編號基本資料檔找不到";
                return resultModel;
            }
            #endregion

            #region 確認是否有設定key Parts資料
            MaterialKpController materialKpController = new MaterialKpController(_context);
            var MaterialKps = (await materialKpController.GetMaterialKpByItemID(MaterialItem.ItemID)).ToList();
            MaterialKps = MaterialKps.Where(w => w.StationType == unitno).ToList();
            if (MaterialKps.Count != 0)
            {
                #region 判斷內部序號是否有過站紀錄
                var BarCodeID = await BarCodeToID(barcode);
                //if (BarCodeID == 0)
                //{
                //    resultModel.Msg = "內部序號【" + barcode + "】,在條碼資料檔找不到";
                //    return resultModel;
                //}
                #endregion

                #region 判斷組件序號是否有紀錄
                BarcodeItemsController barcodeItemsController = new BarcodeItemsController(_context);
                var BarCodeItems = (await barcodeItemsController.GetBarcodeItems(BarCodeID)).Value.ToList();
                BarCodeItems = BarCodeItems.Where(w => w.WipID == q.Value.FirstOrDefault().WipID).ToList();
                if (BarCodeItems.Count == 0)
                {
                    resultModel.Msg = "內部序號【" + barcode + "】,在條碼組件件資料檔找不到";
                    return resultModel;
                }
                #endregion

                #region 判斷組件數量是否正確
                // 先把出貨序號拿掉
                MaterialKps = MaterialKps.Where(w => w.KpName.ToUpper() != "EXT_NO").ToList();
                if (MaterialKps.Count != BarCodeItems.Count)
                {
                    resultModel.Msg = "組件對應數量【" + MaterialKps.Count + "】不等於條碼組件數量【" + BarCodeItems.Count + "】";
                    return resultModel;
                }
                #endregion
            }
            #endregion

            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 內部序號找BarCodeID
        /// </summary>
        /// <param name="BarCode">內部條碼</param>
        /// <returns>0:找不到</returns>
        private async Task<int> BarCodeToID(string BarCode)
        {
            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var q = await barcodeInfoesController.GetBarcodeInfoesByNo(BarCode);
            if (!q.Value.Any())
                return 0;
            else
                return q.Value.FirstOrDefault().BarcodeID;

        }

        /// <summary>
        /// 料號找料號ID
        /// </summary>
        /// <param name="ItemNo">料號</param>
        /// <returns>0:找不到</returns>
        private async Task<int> ItemNoToItemID(string ItemNo)
        {
            MaterialItemController materialItemController = new MaterialItemController(_context);
            var q = await materialItemController.GetMaterialItemByItemNO(ItemNo);
            if (q == null)
                return 0;
            else
                return q.ItemID;
        }

        /// <summary>
        /// 取得上一個作業站RuleStationID
        /// </summary>
        /// <param name="wipID">工單ID</param>
        /// <param name="barCodeID">BarCodeID</param>
        /// <param name="stationID">目前作業站ID</param>
        /// <param name="flowRuleID">工單流程ID</param>
        /// <returns>true:false</returns>
        private async Task<IResultModel> GetBarCodeLastStopRuleStationID(int wipID, int barCodeID, int stationID, int flowRuleID)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };

            // 用作業站抓 有設定下一站為該站的資料
            RulesController rulesController = new RulesController(_context);
            var rules = await rulesController.GetRulesByFlowRuleID(flowRuleID);
            // 取得目前BarCodeInfo 站別
            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var barcodeInfo = barcodeInfoesController.GetBarcodeInfoes(barCodeID).Result.Value.FirstOrDefault();

            if (rules.Value.Count() == 0)
            {
                resultModel.Msg = "找不到該筆工單流程之流程設定相關資料,請確認";
                return resultModel;
            }
            //else if (barcodeInfo == null)
            //{
            //    resultModel.Msg = "該內部序號尚未投入,請確認";
            //    return resultModel;
            //}
            else
            {
                // 有過站紀錄
                if (barcodeInfo != null)
                {
                    // 如果BarCodeInfo 結案,判斷當下作業站是否第一站
                    if (barcodeInfo.StatusID == -1)
                    {
                        if (barcodeInfo.WipID == wipID)
                        {
                            resultModel.Msg = "該內部序號在目前生產製程已完工,請確認";
                            return resultModel;
                        }

                        if (!rules.Value.Where(w => w.StationID == stationID && w.RuleSeq == 1 && w.RuleStatus == "P").Any())
                        {
                            resultModel.Msg = "目前作業站不是第一站,請確認";
                            return resultModel;
                        }
                        resultModel.Success = true;
                        return resultModel;
                    }

                    // 目前BarCodeInfo StationID 取得相對應下個流程StationID
                    var rulesByBarCodeInfoStationID = rules.Value.Where(w => w.StationID == barcodeInfo.StationID).ToList();
                    // 當下個流程 != 目前過站流程
                    if (rulesByBarCodeInfoStationID.Where(w => w.NextStationID == stationID && w.RuleStatus == barcodeInfo.RuleStatus).Count() == 0)
                    {
                        var Nextstation = rulesByBarCodeInfoStationID.Where(w => w.RuleStatus == barcodeInfo.RuleStatus).ToList();
                        var StationName = Nextstation.Select(s => s.NextStation.StationName).ToArray();
                        resultModel.Msg = "該內部序號下一個作業站應該是:" + String.Join('、', StationName) + " ,請確認";
                        return resultModel;
                    }
                }
                // 沒有過站紀錄 判斷是否為投入站
                else
                {
                    if (!rules.Value.Where(w => w.StationID == stationID && w.RuleSeq == 1 && w.RuleStatus == "P").Any())
                    {
                        resultModel.Msg = "該內部序號尚未投入,請確認";
                        return resultModel;
                    }
                }
            }

            //if (rules.Value.Count() != 0)
            //{
            //    // 抓有設定下一站=目前作業站的上一站
            //    var nowruleSations = rules.Value.Select(s => new { s.StationID, s.RuleStatus }).ToList();
            //    // 取得目前BarCode 最新過站資料

            //    if (nowruleSations.Where(w => w.StationID == barcodeInfo.StationID
            //                          && w.RuleStatus == barcodeInfo.RuleStatus).Count() == 0)
            //    {
            //        resultModel.Msg = "找不到上一個作業站過站紀錄,請確認";
            //        return resultModel;
            //    }
            //}

            resultModel.Success = true;
            return resultModel;
        }

        /// <summary>
        /// 確認下一站為完工
        /// </summary>
        /// <param name="flowRuleId">流程ID</param>
        /// <param name="stationID">作業站ID</param>
        /// <param name="ruleStatus">過站狀態 Pass or Fail</param>
        /// <returns>Success(true)是 (false)不是</returns>
        [HttpGet("CheckNextStopCloseStation")]
        public async Task<ResultModel<string>> CheckNextStopCloseStation(int flowRuleId, int stationID, string ruleStatus)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = false };

            // 取得流程
            RuleStationsController ruleStationsController = new RuleStationsController(_context);
            var ruleStations = await _context.RuleStations.Where(w => w.FlowRuleID == flowRuleId).ToListAsync();
            if (ruleStations.Any())
            {
                // 在RuleStation 找不到該作業站
                if (!ruleStations.Where(w => w.StationID == stationID).Any())
                    return resultModel;

                var rules = await _context.Ruleses.Where(w => w.FlowRuleID == flowRuleId).ToListAsync();

                // 當下一站SatationID= 1000 代表完工站
                if (rules.Where(w => w.StationID == stationID && w.NextStationID == 1000 && w.RuleStatus == ruleStatus).Any())
                {
                    resultModel.Success = true;
                    return resultModel;
                }
            }
            return resultModel;
        }

        /// <summary>
        /// 確認目前該站是否為第一站
        /// </summary>
        /// <param name="wipno">工單號碼</param>
        /// <param name="unitNo">生產單位ID</param>
        /// <param name="stationID">作業站ID</param>
        /// <returns>Y:是 N:不是</returns>
        //[HttpGet("CheckNowFirstStation")]
        private string CheckNowFirstStation(string wipno, string unitNo, int stationID)
        {

            WipInfosController wipInfosController = new WipInfosController(_context);
            var q = _context.WipInfos.Where(w => w.WipNO == wipno && w.UnitNO == unitNo).FirstOrDefault();

            if (q != null)
            {
                // 取得流程
                RuleStationsController ruleStationsController = new RuleStationsController(_context);
                var ruleStations = ruleStationsController.GetRuleStationByFlow(q.FlowRuleID, 0).Result.Value.ToList();
                if (ruleStations.Count() != 0)
                {

                    // 用目前站別判斷順序是不是 1
                    if (ruleStations.Where(w => w.StationID == stationID && w.Sequence == 1 && w.StationType == "M").Any())
                        return "Y";
                }
            }
            return "N";
        }

        /// <summary>
        /// 判斷生產中工單是否已經全部完工 自動更新
        /// </summary>
        /// <param name="wipno">工單號碼</param>
        /// <param name="unitNo">生產單位ID</param>
        /// <param name="stationID">StationID</param>
        /// <returns></returns>
        [HttpGet("CheckWipNoBarCodeAllClost")]
        public async Task<IResultModel> CheckWipNoBarCodeAllClost(string wipno, string unitNo, int stationID)
        {
            ResultModel<string> resultModel = new ResultModel<string> { Success = true };
            WipInfosController wipInfosController = new WipInfosController(_context);
            var wipInfo = wipInfosController.GetWipInfoByWipNo(wipno).Result.Value.FirstOrDefault(w => w.UnitNO == unitNo);

            if (wipInfo != null)
            {
                int wipID = wipInfo.WipID;

                // 取Rules 最後一站為完工站的Station及狀態 
                RulesController rulesController = new RulesController(_context);
                var rules = await rulesController.GetRulesByFlowRuleID(wipInfo.FlowRuleID);
                var lastStation = rules.Value.Where(w => w.NextStationID == 1000).Select(s => new { s.StationID, s.RuleStatus }).ToList();

                BarcodeStationController barcodeStationController = new BarcodeStationController(_context);
                var barcodeStations = await barcodeStationController.GetBarcodeStationByWipID(wipID);

                // ByLastStation Count = 工單數 (完工)
                var closeWipQty = 0;
                foreach (var item in lastStation)
                {
                    closeWipQty += barcodeStations.Value.Where(w => item.StationID == w.StationID && item.RuleStatus == w.RuleStatus)
                                                        .Select(s => s.BarcodeID).Distinct().Count();
                }

                if (wipInfo.PlanQTY == closeWipQty)
                {
                    var result = await wipInfosController.PutWipinfoToStatusNO(wipID, "E");
                    if (!result.Success)
                    {
                        resultModel.Success = false;
                        resultModel.Msg = result.Msg;
                        return resultModel;
                    }

                    resultModel.Success = true;
                    resultModel.Msg = "完工";
                }
            }
            return resultModel;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="WipID"></param>
        /// <returns></returns>
        [HttpGet("CreateBarcodeInfobyPCS038")]
        public async Task<IResultModel> CreateBarcodeInfobyPCS038(int WipID)
        {

            ResultModel<string> resultModel = new ResultModel<string> { Success = true };
            WipInfosController wipinfoConteroller = new WipInfosController(_context);

            var wipinfo = wipinfoConteroller.GetWipInfo(WipID).Result.Value;
            if (wipinfo != null)
            {
                string wipNO = wipinfo.Select(s => s.WipNO).FirstOrDefault();

                WipBarcodeController BarcodeConteroller = new WipBarcodeController(_context);
                var wipbarcode = BarcodeConteroller.GetWipBarcode(wipNO);
                string resultMsg = "";
                if (wipbarcode != null)
                {

                    foreach (var item in wipbarcode.Result.Value)
                    {
                        string start = item.StartNO;
                        string end = item.EndNO;

                        // 取得流水號的長度
                        int serialLength = start.Length - 4;

                        // 將起始跟結束序號的流水號轉換為數字
                        int startSerial = int.Parse(start.Substring(start.Length - 4));
                        int endSerial = int.Parse(end.Substring(end.Length - 4));


                        // 進行序號展開
                        for (int i = startSerial; i <= endSerial; i++)
                        {
                            string serial = i.ToString().PadLeft(4, '0');
                            string code = start.Substring(0, start.Length - 4);

                            string barcode = code + serial;
                            BarCodeCheckDto barCodeCheckDto = new BarCodeCheckDto();
                            barCodeCheckDto.unitNo = wipinfo.FirstOrDefault().UnitNO;
                            barCodeCheckDto.wipID = WipID;
                            barCodeCheckDto.barcode = barcode;
                            barCodeCheckDto.barcodeID = 0;
                            barCodeCheckDto.extNo = "";
                            barCodeCheckDto.flowRule = wipinfo.FirstOrDefault().FlowRuleID;
                            barCodeCheckDto.wipNo = wipNO;
                            var result_BarcodeInfo = Table_BarcodeInfo(barCodeCheckDto).Result;

                            if (result_BarcodeInfo.Success)
                            {
                                resultMsg += $"{code + serial} 內部條碼:產生成功!!!" + "</br>";
                            }
                            else
                            {
                                resultMsg += $"{code + serial} 內部條碼:產生失敗!!!原因:" + result_BarcodeInfo.Msg + "</br>";
                            }


                        }

                        resultModel.Success = true;






                    }
                }
                else
                {
                    resultModel.Success = false;
                    resultModel.Msg = "工單資料沒有設定生產序號區間";
                }


            }
            else
            {
                resultModel.Success = false;
                resultModel.Msg = "查無工單";
            }
            return resultModel;
        }

        /// <summary>
        /// 確認治具是否已達到預警提前次數
        /// </summary>
        /// <param name="WipNo"></param>
        private async void CheckOutfitAlert(string WipNo)
        {

        }

    }
}