/// <summary> /// 要merge的小工單,先確認該工單所有的檢驗項目是否都完成了 /// </summary> /// <param name="equipmentName"></param> /// <param name="lot"></param> /// <returns></returns> public static bool CheckQCInspectionDone(string woLot) { //利用小工單號確認是否還有QC未檢驗的資料(包含FAI、PQC、PPK) //只要有一張未檢,則代表檢驗未完成,回傳false,反之 var qcLitst = QCInspectionInfoEx.GetInspDataListByWOLot(woLot); if (qcLitst.Count != 0) { return(false); } return(true); }
public static void SaveQCData(string InspectionNo, QCType qcType, LotNonActiveInfo lot, EquipmentInfo equipment, string batchID, QCStatus status, string objectType, TransactionStamp txnStamp) { QCInspectionInfoEx inspection = null; var lotNonActiveInfoEx = lot.ChangeTo <LotNonActiveInfoEx>(); #region 產生檢驗單 inspection = InfoCenter.Create <QCInspectionInfo>().ChangeTo <QCInspectionInfoEx>(); inspection.InspectionNo = InspectionNo; inspection.QCTYPE = qcType.ToCimesString(); inspection.OperationName = lotNonActiveInfoEx.OperationName; inspection.EquipmentName = equipment.EquipmentName; inspection.DeviceName = lotNonActiveInfoEx.DeviceName; inspection.BatchID = batchID; inspection.Status = status.ToCimesString(); inspection.CreateUser = txnStamp.UserID; inspection.CreateTime = txnStamp.RecordTime; inspection.InsertToDB(txnStamp.UserID, txnStamp.RecordTime); #endregion if (inspection == null) { //檢驗單主檔沒有資料 throw new Exception(TextMessage.Error.T00060("QCData")); } #region 產生檢驗單對象 //新增一筆資料到MES_QC_INSP_OBJ var inspectionObject = InfoCenter.Create <QCInspectionObjectInfo>(); if (inspectionObject.InfoState == InfoState.NewCreate) { inspectionObject.QC_INSP_SID = inspection.QC_INSP_SID; inspectionObject.ObjectType = objectType; inspectionObject.OBJECTSID = lotNonActiveInfoEx.ID; inspectionObject.ObjectName = lotNonActiveInfoEx.Lot; //COMPLOT inspectionObject.ItemName1 = lotNonActiveInfoEx.ComponentLot; //WOLOT inspectionObject.ItemName2 = lotNonActiveInfoEx.WorkOrderLot; //MATERIALLOT inspectionObject.ItemName3 = lotNonActiveInfoEx.MaterialLot; //OP1機台 inspectionObject.ItemName5 = lotNonActiveInfoEx.ProcessEquipment; inspectionObject.Quantity = 1; inspectionObject.Unit = lotNonActiveInfoEx.Unit; inspectionObject.InsertToDB(txnStamp.UserID, txnStamp.RecordTime); } #endregion }
/// <summary> /// 確定 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnOK_Click(object sender, EventArgs e) { try { #region 確認選擇結果,如果是選擇NG,確認是否有選擇原因碼 string result = ""; if (rdbOK.Checked) { result = "OK"; } else if (rdbNG.Checked) { result = "NG"; //確認是否有選擇原因碼 ddlFAIReasonCode.Must(lblFAIReasonCode); } else if (rdbPASS.Checked) { result = "PASS"; } else if (rdbCLOSE.Checked) { result = "CLOSE"; //確認是否有選擇原因碼 ddlFAIReasonCode.Must(lblFAIReasonCode); } #endregion TransactionStamp txnStamp = new TransactionStamp(User.Identity.Name, ProgramRight, ProgramRight, ApplicationName); using (var cts = CimesTransactionScope.Create()) { #region 更新檢驗主檔[MES_QC_INSP] //取得檢驗主檔資料 var QCInsepctionData = InfoCenter.GetBySID <QCInspectionInfo>(_SelectedQCData.QCInspectionSID).ChangeTo <QCInspectionInfoEx>(); //原因碼 ReasonCategoryInfo reason = null; //有選擇原因碼才更新[NG_Category]及[NG_Reason] if (string.IsNullOrEmpty(ddlFAIReasonCode.SelectedValue) == false) { reason = InfoCenter.GetBySID <ReasonCategoryInfo>(ddlFAIReasonCode.SelectedValue); QCInsepctionData.NG_Category = reason.Category; QCInsepctionData.NG_Reason = reason.Reason; } //如果判定結果為結單的話,則必須把結單時間及人員資料寫回資料庫 if (result == "CLOSE") { QCInsepctionData.FINISHTIME = txnStamp.RecordTime; QCInsepctionData.FINISHUSER = txnStamp.UserID; } QCInsepctionData.NG_Description = ttbDescr.Text; QCInsepctionData.Result = result; QCInsepctionData.Status = "Finished"; QCInsepctionData.UpdateToDB(txnStamp.UserID, txnStamp.RecordTime); #endregion #region 更新機台檢驗主檔[CST_WIP_CMM] if (_CSTWIPCMMList != null) { //更新檢驗主檔的QCInspectionSID欄位 _CSTWIPCMMList.ForEach(data => { data.QCInspectionSID = QCInsepctionData.ID; data.UpdateToDB(); }); } #endregion #region 更新機台資訊 //取得相同BatchID的檢驗資料 var QCDataList = QCInspectionInfoEx.GetDataListByBatchID(_SelectedQCData.BatchID); //相同BatchID都已完成檢驗旗標 bool isAllFinish = true; QCDataList.ForEach(p => { if (!(p.Status == "Finished")) { isAllFinish = false; } }); //取得lot資料 var lot = InfoCenter.GetBySID <LotInfo>(_SelectedQCData.ObjectSID); //更新機台屬性[FAICOUNT] CustomizeFunction.UpdateFAI(_SelectedQCData.EquipmentName, lot.Lot, (rdbNG.Checked) ? true : false, txnStamp); //如果相同的BatchID都檢驗完成或選擇結果為NG時,則更新狀態為IDLE及更新FAICOUNT if (isAllFinish) { //取得機台狀態資料 var newStateInfo = EquipmentStateInfo.GetEquipmentStateByState("IDLE"); var equipData = EquipmentInfo.GetEquipmentByName(_SelectedQCData.EquipmentName); //更新機台狀態 EMSTransaction.ChangeState(equipData, newStateInfo, txnStamp); } #endregion //如果判定結果選擇為NG,則必須拆批送待判 if (rdbNG.Checked) { //判定NG直接拆批及送待判工作站 CustomizeFunction.SplitDefectLot(_SelectedQCData.ComponentLot, ttbDescr.Text, reason, txnStamp); } cts.Complete(); } ClearField(); AjaxFocus(ttbLot); _ProgramInformationBlock.ShowMessage(TextMessage.Hint.T00614("")); } catch (Exception ex) { HandleError(ex); } }
/// <summary> /// 確定 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnOK_Click(object sender, EventArgs e) { try { #region 確認選擇結果,如果是選擇NG,確認是否有選擇原因碼 string result = ""; if (rdbOK.Checked) { result = "OK"; } else if (rdbNG.Checked) { result = "NG"; //確認是否有選擇原因碼 ddlPQCReasonCode.Must(lblPQCReasonCode); } #endregion TransactionStamp txnStamp = new TransactionStamp(User.Identity.Name, ProgramRight, ProgramRight, ApplicationName); using (var cts = CimesTransactionScope.Create()) { #region 更新檢驗主檔[MES_QC_INSP] //取得檢驗主檔資料 var QCInsepctionData = InfoCenter.GetBySID <QCInspectionInfo>(_SelectedQCData.QCInspectionSID).ChangeTo <QCInspectionInfoEx>(); //有選擇原因碼才更新[NG_Category]及[NG_Reason] if (string.IsNullOrEmpty(ddlPQCReasonCode.SelectedValue) == false) { var reason = InfoCenter.GetBySID <ReasonCategoryInfo>(ddlPQCReasonCode.SelectedValue); QCInsepctionData.NG_Category = reason.Category; QCInsepctionData.NG_Reason = reason.Reason; } QCInsepctionData.NG_Description = ttbDescr.Text; QCInsepctionData.Result = result; QCInsepctionData.Status = "Finished"; QCInsepctionData.UpdateToDB(txnStamp.UserID, txnStamp.RecordTime); #endregion #region 更新自主檢數據內容[CST_EDC_COMP] bool inSpec = true; gvComponentEDC.Rows.LoopDo <GridViewRow>((p, i) => { // 取得TextBox Control var ttbEDC = p.FindControl("ttbEDC") as TextBox; if (ttbEDC.Text.IsNullOrEmpty()) { AjaxFocus(ttbEDC); throw new Exception(TextMessage.Error.T00043(GetUIResource("CenterHoleData"))); } // 是否符合規格判斷 var measureVal = ttbEDC.Text.ToDecimal(); if (measureVal > _SAICenterHole.Remark02.ToDecimal()) { inSpec = false; } if (measureVal < _SAICenterHole.Remark03.ToDecimal()) { inSpec = false; } var lotData = ComponentInfo.GetComponentByComponentID(_SelectedQCData.ComponentLot); // 將量測資料記錄到客製表 var edcCompInfo = InfoCenter.Create <CSTEDCComponentInfo>(); edcCompInfo.ComponentID = _SelectedQCData.ComponentLot; edcCompInfo.Data = measureVal; edcCompInfo.UpSpecification = _SAICenterHole.Remark02.ToDecimal(); edcCompInfo.LowSpecification = _SAICenterHole.Remark03.ToDecimal(); edcCompInfo.INSPEC = inSpec == true ? "OK" : "NG"; edcCompInfo.Lot = (lotData == null) ? "" : lotData.CurrentLot; edcCompInfo["LINKSID"] = txnStamp.LinkSID; edcCompInfo["PARAMETER"] = "SC" + (i + 1).ToString(); edcCompInfo.InsertToDB(txnStamp.UserID, txnStamp.RecordTime); }); #endregion #region 更新機台狀態及更新檢驗單對應的批號資料 //如果選擇結果為NG時,則更新機台狀態及更新檢驗單對應的批號資料 if (rdbNG.Checked) { //取得機台狀態資料 var newStateInfo = EquipmentStateInfo.GetEquipmentStateByState("DOWN"); var equipData = EquipmentInfo.GetEquipmentByName(_SelectedQCData.EquipmentName); //如果機台狀態為IDLE,則變更狀態為DOWN if (equipData.CurrentState == "IDLE") { //更新機台狀態 EMSTransaction.ChangeState(equipData, newStateInfo, txnStamp); } else { //如果機台狀態不為IDLE,則註記機台[USERDEFINECOL01]為Y EMSTransaction.ModifyEquipmentSystemAttribute(equipData, "USERDEFINECOL01", "Y", txnStamp); } //上一次的檢驗單號資料 QCInspectionInfoEx previousInspectionData = null; //依據機台及料號查詢,然後用建立時間逆排序,找出所有FAI及MPQC的檢驗單號資料 var QCDataList = QCInspectionInfoEx.GetInspDataListByEquipmentAndDevice(QCInsepctionData.EquipmentName, QCInsepctionData.DeviceName); //如果筆數大於1,則目前檢驗單號的索引值 if (QCDataList.Count > 1) { //找出目前檢驗單號的索引值 var NGIndex = QCDataList.FindIndex(p => p.InspectionNo == QCInsepctionData.InspectionNo); //如果找到的索引值不是最後一筆的話,則找出上一次的檢驗單號資料 if (NGIndex != (QCDataList.Count - 1)) { //找出上一次的檢驗單號資料 previousInspectionData = QCDataList[NGIndex + 1]; } } //取得目前檢驗單號的批號子單元資料 var componentList = ComponentInfoEx.GetDataByInspectionNo(QCInsepctionData.InspectionNo); componentList.ForEach(component => { //取得批號資料 var lotData = LotInfo.GetLotByLot(component.CurrentLot); //更新欄位[PQCNGFLAG] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGFLAG", "Y", txnStamp); //更新欄位[PQCNGNO] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGNO", QCInsepctionData.InspectionNo, txnStamp); }); if (previousInspectionData != null) { //取得上一次檢驗單號的批號子單元資料 var previousComponentList = ComponentInfoEx.GetDataByInspectionNo(previousInspectionData.InspectionNo); //取得不需要註記的ComponentID var passInspectionDataList = QCInspectionObjectInfo.GetInspectionObjects(previousInspectionData); previousComponentList.ForEach(component => { //確認是否為不需要註記的ComponentID if (passInspectionDataList.FindIndex(p => p.ItemName1 == component.ComponentID) == -1) { //取得批號資料 var lotData = LotInfo.GetLotByLot(component.CurrentLot); //更新欄位[PQCNGFLAG] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGFLAG", "Y", txnStamp); //更新欄位[PQCNGNO] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGNO", QCInsepctionData.InspectionNo, txnStamp); } }); } } #endregion cts.Complete(); } ClearField(); AjaxFocus(ttbLot); _ProgramInformationBlock.ShowMessage(TextMessage.Hint.T00614("")); } catch (Exception ex) { HandleError(ex); } }
/// <summary> /// 確定 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnOK_Click(object sender, EventArgs e) { try { #region 確認選擇結果,如果是選擇NG,確認是否有選擇原因碼 string result = ""; if (rdbOK.Checked) { result = "OK"; } else if (rdbNG.Checked) { result = "NG"; //確認是否有選擇原因碼 ddlPQCReasonCode.Must(lblPQCReasonCode); } else if (rdbCLOSE.Checked) { result = "CLOSE"; //確認是否有選擇原因碼 ddlPQCReasonCode.Must(lblPQCReasonCode); } #endregion TransactionStamp txnStamp = new TransactionStamp(User.Identity.Name, ProgramRight, ProgramRight, ApplicationName); using (var cts = CimesTransactionScope.Create()) { #region 更新檢驗主檔[MES_QC_INSP] //取得檢驗主檔資料 var QCInsepctionData = InfoCenter.GetBySID <QCInspectionInfo>(_SelectedQCData.QCInspectionSID).ChangeTo <QCInspectionInfoEx>(); //原因碼 ReasonCategoryInfo reason = null; //有選擇原因碼才更新[NG_Category]及[NG_Reason] if (string.IsNullOrEmpty(ddlPQCReasonCode.SelectedValue) == false) { reason = InfoCenter.GetBySID <ReasonCategoryInfo>(ddlPQCReasonCode.SelectedValue); QCInsepctionData.NG_Category = reason.Category; QCInsepctionData.NG_Reason = reason.Reason; } //如果判定結果為結單的話,則必須把結單時間及人員資料寫回資料庫 if (result == "CLOSE") { QCInsepctionData.FINISHTIME = txnStamp.RecordTime; QCInsepctionData.FINISHUSER = txnStamp.UserID; } QCInsepctionData.NG_Description = ttbDescr.Text; QCInsepctionData.Result = result; QCInsepctionData.Status = "Finished"; QCInsepctionData.UpdateToDB(txnStamp.UserID, txnStamp.RecordTime); #endregion #region 更新機台檢驗主檔[CST_WIP_CMM] if (_CSTWIPCMMList != null) { //更新檢驗主檔的QCInspectionSID欄位 _CSTWIPCMMList.ForEach(data => { data.QCInspectionSID = QCInsepctionData.ID; data.UpdateToDB(); }); } #endregion #region 更新機台狀態及更新檢驗單對應的批號資料 //如果選擇結果為NG時,則更新機台狀態及更新檢驗單對應的批號資料 if (rdbNG.Checked) { //取得機台狀態資料 var newStateInfo = EquipmentStateInfo.GetEquipmentStateByState("DOWN"); var equipData = EquipmentInfo.GetEquipmentByName(_SelectedQCData.EquipmentName); //如果機台狀態為IDLE,則變更狀態為DOWN if (equipData.CurrentState == "IDLE") { //更新機台狀態 EMSTransaction.ChangeState(equipData, newStateInfo, txnStamp); } else { //如果機台狀態不為IDLE,則註記機台[USERDEFINECOL01]為Y EMSTransaction.ModifyEquipmentSystemAttribute(equipData, "USERDEFINECOL01", "Y", txnStamp); } //上一次的檢驗單號資料 QCInspectionInfoEx previousInspectionData = null; //依據機台及料號查詢,然後用建立時間逆排序,找出所有FAI及PQC的檢驗單號資料 var QCDataList = QCInspectionInfoEx.GetInspDataListByEquipmentAndDevice(QCInsepctionData.EquipmentName, QCInsepctionData.DeviceName); //如果筆數大於1,則目前檢驗單號的索引值 if (QCDataList.Count > 1) { //找出目前檢驗單號的索引值 var NGIndex = QCDataList.FindIndex(p => p.InspectionNo == QCInsepctionData.InspectionNo); //如果找到的索引值不是最後一筆的話,則找出上一次的檢驗單號資料 if (NGIndex != (QCDataList.Count - 1)) { //找出上一次的檢驗單號資料 previousInspectionData = QCDataList[NGIndex + 1]; } } //取得目前檢驗單號的批號子單元資料 var componentList = ComponentInfoEx.GetDataByInspectionNo(QCInsepctionData.InspectionNo); componentList.ForEach(component => { //取得批號資料 var lotData = LotInfo.GetLotByLot(component.CurrentLot); //更新欄位[PQCNGFLAG] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGFLAG", "Y", txnStamp); //更新欄位[PQCNGNO] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGNO", QCInsepctionData.InspectionNo, txnStamp); }); if (previousInspectionData != null) { //取得上一次檢驗單號的批號子單元資料 var previousComponentList = ComponentInfoEx.GetDataByInspectionNo(previousInspectionData.InspectionNo); //取得不需要註記的ComponentID var passInspectionDataList = QCInspectionObjectInfo.GetInspectionObjects(previousInspectionData); previousComponentList.ForEach(component => { //確認是否為不需要註記的ComponentID if (passInspectionDataList.FindIndex(p => p.ItemName1 == component.ComponentID) == -1) { //取得批號資料 var lotData = LotInfo.GetLotByLot(component.CurrentLot); //更新欄位[PQCNGFLAG] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGFLAG", "Y", txnStamp); //更新欄位[PQCNGNO] WIPTransaction.ModifyLotComponentSystemAttribute(lotData, component, "PQCNGNO", QCInsepctionData.InspectionNo, txnStamp); } }); } } #endregion //如果判定結果選擇為NG,則必須拆批送待判 if (rdbNG.Checked) { //判定NG直接拆批及送待判工作站 CustomizeFunction.SplitDefectLot(_SelectedQCData.ComponentLot, ttbDescr.Text, reason, txnStamp); } cts.Complete(); } ClearField(); AjaxFocus(ttbLot); _ProgramInformationBlock.ShowMessage(TextMessage.Hint.T00614("")); } catch (Exception ex) { HandleError(ex); } }
/// <summary> /// 輸入機台/序號 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void ttbEquipOrCompLot_TextChanged(object sender, EventArgs e) { try { //清除資料 _QCTable.Rows.Clear(); string currentState = "Wait" + _QCType; string equipmentName = ""; //檢查是否有輸入機台/序號 ttbEquipOrCompLot.Must(lblEquipOrCompLot); #region 檢查輸入的內容在MES_QC_INSP_OBJ.ITEM1是否有符合的資料,如果沒有,則檢查機台 var QCDataObjList = QCInspectionObjectInfoEx.GetDataListByComponentLot(ttbEquipOrCompLot.Text); if (QCDataObjList.Count == 0) { var QCInspectionDataList = QCInspectionInfoEx.GetDataListByEquip(ttbEquipOrCompLot.Text, _QCType); if (QCInspectionDataList.Count == 0) { //找不到檢驗資料!! throw new Exception(RuleMessage.Error.C00038()); } else { //取得檢驗機台名稱 equipmentName = QCInspectionDataList[0].EquipmentName; } #region 取得檢驗清單 //string currentState = "WaitPPK"; QCInspectionDataList.ForEach(qcData => { //只有狀態為WaitPPK才可以加入清單 if (qcData.Status == currentState) { //取得檢驗明細 var QCInspectionObjList = QCInspectionObjectInfo.GetInspectionObjects(qcData); QCInspectionObjList.ForEach(qcObjData => { var row = _QCTable.NewRow(); row["Equipment"] = qcData.EquipmentName; row["Device"] = qcData.DeviceName; row["SN"] = qcObjData.ItemName1; row["Status"] = qcData.PassFlag == "Y" ? "PASS" : GetUIResource("WaitQC"); row["QCINSPSID"] = qcData.ID; _QCTable.Rows.Add(row); }); } }); #endregion } else { //取得檢驗主檔 var QCInspectionData = InfoCenter.GetBySID <QCInspectionInfo>(QCDataObjList[0].QC_INSP_SID).ChangeTo <QCInspectionInfoEx>(); //確認檢驗主檔狀態是否為WaitPPK if (QCInspectionData.Status != currentState) { //序號:{0} 檢驗主檔狀態為{1},不可以執行 throw new Exception(RuleMessage.Error.C10100(ttbEquipOrCompLot.Text, QCInspectionData.Status)); } //取得檢驗機台名稱 equipmentName = QCInspectionData.EquipmentName; //取得檢驗資料 var row = _QCTable.NewRow(); row["Equipment"] = QCInspectionData.EquipmentName; row["Device"] = QCInspectionData.DeviceName; row["SN"] = QCDataObjList[0].ItemName1; row["Status"] = QCInspectionData.PassFlag == "Y" ? "PASS" : GetUIResource("WaitQC"); row["QCINSPSID"] = QCInspectionData.ID; _QCTable.Rows.Add(row); } #endregion #region 檢查機台是否存在 _EquipData = EquipmentInfo.GetEquipmentByName(equipmentName); if (_EquipData == null) { //請輸入正確的機台/序號! throw new Exception(RuleMessage.Error.C10066()); } #endregion if (_QCTable.Rows.Count == 0) { //機台:{0},查無任何檢驗資料。 throw new Exception(RuleMessage.Error.C10053(equipmentName)); } //顯示檢驗清單 gvQC.SetDataSource(_QCTable, true); btnOK.Enabled = true; //設置初始勾選狀態 CheckBox ckbSelectAll = gvQC.HeaderRow.FindControl("ckbSelectAll") as CheckBox; ckbSelectAll.Checked = true; ckbSelectAll_CheckedChanged(null, EventArgs.Empty); } catch (Exception ex) { ClearField(); AjaxFocus(ttbEquipOrCompLot); HandleError(ex); } }
/// <summary> /// 輸入機台/序號 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void ttbEquipOrCompLot_TextChanged(object sender, EventArgs e) { try { //清除資料 _QCTable.Rows.Clear(); string equipmentName = ""; //檢查是否有輸入機台/序號 ttbEquipOrCompLot.Must(lblEquipOrCompLot); #region 檢查輸入的內容在MES_QC_INSP_OBJ.ITEM1是否有符合的資料,如果沒有,則檢查機台 var QCDataObjList = QCInspectionObjectInfoEx.GetDataListByComponentLot(ttbEquipOrCompLot.Text); if (QCDataObjList.Count == 0) { var QCDataList = QCInspectionInfoEx.GetDataListByEquip(ttbEquipOrCompLot.Text, _QCType); if (QCDataList.Count == 0) { //找不到檢驗資料!! throw new Exception(RuleMessage.Error.C00038()); } else { //取得檢驗機台名稱 equipmentName = QCDataList[0].EquipmentName; } } else { //取得檢驗機台名稱 equipmentName = InfoCenter.GetBySID <QCInspectionInfo>(QCDataObjList[0].QC_INSP_SID).EquipmentName; } #endregion #region 檢查機台是否存在 _EquipData = EquipmentInfo.GetEquipmentByName(equipmentName); if (_EquipData == null) { //請輸入正確的機台/序號! throw new Exception(RuleMessage.Error.C10066()); } #endregion #region 檢查機台狀態是否為WaitReceiveFAI/WaitReceivePPK string currentState = "WaitReceive" + _QCType; //如果傳入參數是FAI,則必須檢查機台狀態 if (_QCType == CustomizeFunction.QCType.FAI.ToCimesString()) { if (_EquipData.CurrentState != currentState) { //[00902]機台狀態不是{0},不可使用{1}規則! throw new Exception(TextMessage.Error.T00902(currentState, _ProgramInformationBlock.ProgramRight)); } } #endregion #region 顯示檢驗清單 //取得檢驗主檔 var qcInspectionDataList = QCInspectionInfoEx.GetDataListByEquip(equipmentName, _QCType); if (qcInspectionDataList.Count == 0) { //機台:{0},查無任何檢驗資料。 throw new Exception(RuleMessage.Error.C10053(equipmentName)); } qcInspectionDataList.ForEach(qcData => { //只有狀態為WaitReceivePPK/WaitReceiveFAI/WaitReceivePQC才可以加入清單 if (qcData.Status == currentState) { //取得檢驗明細 var QCInspectionObjList = QCInspectionObjectInfo.GetInspectionObjects(qcData); QCInspectionObjList.ForEach(qcObjData => { var row = _QCTable.NewRow(); row["Equipment"] = qcData.EquipmentName; row["Device"] = qcData.DeviceName; row["SN"] = qcObjData.ItemName1; row["Status"] = qcData.PassFlag == "Y" ? "PASS" : GetUIResource("WaitQC"); row["QCINSPSID"] = qcData.ID; _QCTable.Rows.Add(row); }); } }); if (_QCTable.Rows.Count == 0) { //機台:{0},查無任何檢驗資料。 throw new Exception(RuleMessage.Error.C10053(equipmentName)); } gvQC.SetDataSource(_QCTable, true); #endregion btnOK.Enabled = true; btnReject.Enabled = true; } catch (Exception ex) { ClearField(); AjaxFocus(ttbEquipOrCompLot); HandleError(ex); } }
/// <summary> /// 確定 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnOK_Click(object sender, EventArgs e) { /******************************************************************* * PPK判定後須執行事項: * 1. 依照判定的BATCHID+料號,將所屬單號資料更新。 * 2. 依照判定狀態更新CST_WIP_PPK結果。 * 3. 如同一個BATCHID都判定完成,變更機台狀態,從PPK變IDLE。 * 如一個BATCHID有兩個料號,需兩個料號都判定完成才可以變更機台狀態。 ******************************************************************/ try { //取得所選擇的料號名稱 var deviceName = ddlDevice.SelectedValue; #region 確認選擇結果,如果是選擇NG,確認是否有選擇原因碼及選擇結果及檢驗清單的勾選是否符合 string result = ""; if (rdbOK.Checked) { result = "OK"; } else if (rdbNG.Checked) { result = "NG"; //確認是否有選擇原因碼 ddlPPKReasonCode.Must(lblPPKReasonCode); if (SelectedNGData() == false) { //PPK結果選擇NG,檢驗清單至少勾選一筆資料! throw new Exception(RuleMessage.Error.C10070()); } } else if (rdbCLOSE.Checked) { result = "CLOSE"; //確認是否有選擇原因碼 ddlPPKReasonCode.Must(lblPPKReasonCode); } #endregion TransactionStamp txnStamp = new TransactionStamp(User.Identity.Name, ProgramRight, ProgramRight, ApplicationName); using (var cts = CimesTransactionScope.Create()) { #region 更新檢驗主檔清單[MES_QC_INSP] _QCInspectionDataList.ForEach(QCInspectionData => { //符合選擇的料號才進行資料更新 if (QCInspectionData.DeviceName == deviceName) { //有選擇原因碼才更新[NG_Category]及[NG_Reason] if (string.IsNullOrEmpty(ddlPPKReasonCode.SelectedValue) == false) { var reason = InfoCenter.GetBySID <ReasonCategoryInfo>(ddlPPKReasonCode.SelectedValue); QCInspectionData.NG_Category = reason.Category; QCInspectionData.NG_Reason = reason.Reason; } //如果判定結果為結單的話,則必須把結單時間及人員資料寫回資料庫 if (result == "CLOSE") { QCInspectionData.FINISHTIME = txnStamp.RecordTime; QCInspectionData.FINISHUSER = txnStamp.UserID; } QCInspectionData.NG_Description = ttbDescr.Text; QCInspectionData.Result = result; QCInspectionData.Status = "Finished"; QCInspectionData.UpdateToDB(txnStamp.UserID, txnStamp.RecordTime); } }); #endregion #region 更新機台資訊及檢驗工件結果 //取某一支工件序號的資料來傳入UpdatePPK var updateLot = InfoCenter.GetBySID <LotInfo>(_QCInspectionObjDataList[0].OBJECTSID).ChangeTo <LotInfoEx>(); //更新[CST_WIP_PPK.PPKCOUNT] CustomizeFunction.UpdatePPK(_QCInspectionDataList[0].EquipmentName, updateLot.DeviceName, updateLot.DeviceVersion, (rdbNG.Checked) ? "false" : "true"); //將介面上所勾選/不勾選的資料對應到MES_QC_INSP_OBJ.ITEM4的欄位 for (int i = 0; i < gvQC.Rows.Count; i++) { var thisCheckBox = (CheckBox)gvQC.Rows[i].FindControl("ckbDefectSelect"); if (thisCheckBox.Checked) { _QCInspectionObjDataList[i].ItemName4 = "NG"; } else { _QCInspectionObjDataList[i].ItemName4 = "OK"; } _QCInspectionObjDataList[i].UpdateToDB(txnStamp.UserID, txnStamp.RecordTime); } //更新機台檢驗主檔 _CSTWIPCMMList.ForEach(data => { data.UpdateToDB(); }); //取得相同BatchID的檢驗資料 (理論上應該都完成檢驗...) //如果是雙料號,每次判定要分料號判定 var QCDataList = QCInspectionInfoEx.GetDataListByBatchIDAndDeviceName(_QCInspectionDataList[0].BatchID, deviceName); //如果是雙料號,每次判定要分料號判定,但是機台的狀態要該batchID都判定通過,才算PPK完成 var QCDAllataList = QCInspectionInfoEx.GetDataListByBatchID(_QCInspectionDataList[0].BatchID); #region 如果相同的BatchID都檢驗完成時,則更新機台狀態為IDLE //相同BatchID都已完成檢驗旗標 //如果是雙料號,每次判定要分料號判定,但是機台的狀態要該batchID都判定通過,才算PPK完成 bool isAllFinish = true; QCDAllataList.ForEach(p => { if (p.Status != "Finished") { isAllFinish = false; } }); if (isAllFinish) { //取得機台狀態資料 var newStateInfo = EquipmentStateInfo.GetEquipmentStateByState("IDLE"); //檢查機台是否存在 var equipData = EquipmentInfo.GetEquipmentByName(_QCInspectionDataList[0].EquipmentName); if (equipData == null) { //[00885]機台{0}不存在! throw new Exception(TextMessage.Error.T00885(_QCInspectionDataList[0].EquipmentName)); } //更新機台狀態 EMSTransaction.ChangeState(equipData, newStateInfo, txnStamp); } #endregion #region 如果相同的BatchID都檢驗完成且結果都為OK時,則更新機台檢驗資料及更新COUNT //相同BatchID都已完成檢驗及結果都為OK旗標 bool isAllFinishAndOK = true; QCDataList.ForEach(p => { if (!(p.Status == "Finished" && p.Result == "OK")) { isAllFinishAndOK = false; } }); if (isAllFinishAndOK) { //取得AutoMerge原因碼 var reasonCategory = ReasonCategoryInfo.GetReasonCategoryByCategoryNameAndReason("CustomizeReason", "AutoMerge"); if (reasonCategory == null) { //[00030]{0}:{1}不存在! throw new Exception(TextMessage.Error.T00030("", "CustomizeReason- AutoMerge")); } _QCInspectionObjDataList.ForEach(Data => { //更新機台檢驗資料 Data.UpdateToDB(txnStamp.UserID, txnStamp.RecordTime); }); var mergeList = _QCInspectionObjDataList.Select(p => p.ItemName2).Distinct().ToList(); foreach (var lot in mergeList) { var lotData = LotInfoEx.GetLotByWorkOrderLot(lot); //確認FAI是否已經檢驗完成 if (CustomizeFunction.CheckFAI(_QCInspectionDataList[0].EquipmentName, lotData.Lot)) { //執行AutoMerge CustomizeFunction.AutoMerge(lotData.InventoryLot, txnStamp, reasonCategory); } } } #endregion #endregion cts.Complete(); } ClearField(); AjaxFocus(ttbEquipOrCompLot); _ProgramInformationBlock.ShowMessage(TextMessage.Hint.T00614("")); } catch (Exception ex) { HandleError(ex); } }
/// <summary> /// 輸入機台/序號 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void ttbEquipOrCompLot_TextChanged(object sender, EventArgs e) { try { QCInspectionInfoEx QCInspectionData = new QCInspectionInfoEx(); //檢查是否有輸入機台/序號 ttbEquipOrCompLot.Must(lblEquipOrCompLot); #region 檢查輸入的內容在MES_QC_INSP_OBJ.ITEM1是否有符合的資料,如果沒有,則檢查機台 var QCDataObjList = QCInspectionObjectInfoEx.GetDataListByComponentLot(ttbEquipOrCompLot.Text); if (QCDataObjList.Count == 0) { var QCDataList = QCInspectionInfoEx.GetDataListByEquip(ttbEquipOrCompLot.Text, CustomizeFunction.QCType.PPK.ToCimesString()); if (QCDataList.Count == 0) { //請輸入正確的機台/序號! throw new Exception(RuleMessage.Error.C10066()); } //取得檢驗主檔資訊 QCInspectionData = QCDataList[0]; } else { //取得檢驗主檔資訊 QCInspectionData = InfoCenter.GetBySID <QCInspectionInfo>(QCDataObjList[0].QC_INSP_SID).ChangeTo <QCInspectionInfoEx>(); } //檢查機台資料及狀態 CheckEquipCurrentState(QCInspectionData.EquipmentName); #endregion #region 查詢相同的BatchID的檢驗主檔清單 _QCInspectionDataList = QCInspectionInfoEx.GetDataListByBatchID(QCInspectionData.BatchID); if (_QCInspectionDataList.Count == 0) { //檢驗單號:{0} 查無相同的BatchID throw new Exception(RuleMessage.Error.C10110(QCInspectionData.InspectionNo)); } #endregion //設置機台名稱 ttbEquip.Text = QCInspectionData.EquipmentName; //取得不重複的料號清單 var deviceList = _QCInspectionDataList.FindAll(p => p.Status == CustomizeFunction.QCStatus.PPK.ToCimesString()).Select(p => p.DeviceName).Distinct().ToList(); //var deviceList = _QCInspectionDataList.Select(p => p.DeviceName).Distinct().ToList(); #region 設置料號資料(DropDownList) //清除資料 ddlDevice.Items.Clear(); //加入清單 foreach (var deviceName in deviceList) { ddlDevice.Items.Add(new ListItem(deviceName, deviceName)); } if (ddlDevice.Items.Count != 1) { ddlDevice.Items.Insert(0, ""); } else { ddlDevice.SelectedIndex = 0; ddlDevice_SelectedIndexChanged(null, EventArgs.Empty); } #endregion } catch (Exception ex) { ClearField(); AjaxFocus(ttbEquipOrCompLot); HandleError(ex); } }