BomItem.cs
*BomItem.cs*
using Bartech.SGCore.Base;
using Bartech.SGCore.Base.Web;
using Bartech.SGCore.Helpers;
using Bartech.SGCore.Local.DataObjects;
using Bartech.SGCore.Local.Services;
using Bartech.SGCore.Logic.Shared.Messages;
using Bartech.SGCore.Model;
using Bartech.SGCore.Model.API.Request;
using Bartech.SGCore.Model.API.Request.Common;
using Bartech.SGCore.Model.API.Response;
using Bartech.SGCore.Model.ContextData;
using Bartech.SGCore.Model.Messages;
using Bartech.xTrace.TSE.Services;
using DevExpress.Xpo;
using DevExpress.Xpo.Helpers;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using xTrace03_SG_Data;
namespace Bartech.SGCore.Local
{
[XModule("BOM_Item", "Modul pro načítání komponent", ModuleGroupType.Part, applicationType: xTraceApplicationType.BomItem)]
public class SGBomItem : SGModuleLocal
{
#region konstrukor
public SGBomItem(SGSession session)
: base(session)
{
m_dxSession = Session.Resolve<SGDxSessionLocker>();
m_inputBatchService = Session.Resolve<InputBatchService>();
m_componentCheckSvc = session.Resolve<ComponentCheckService>();
//m_dataForwardSvc = Session.Resolve<TSEDataForwardService>();
m_prodSvc = Session.Resolve<ProductService>();
Session.GlobalContext.SetBOMComponents(new FullyObservableCollection<BusItem>());
m_globalContextComponents = new ObservableCollection<BusItem>();
m_wholeContextComponents = new ObservableCollection<BusItem>();
AllowedInDevs = new SGDeviceType[] { SGDeviceType.Scanner, SGDeviceType.API };
katalog = new DOKatalogParams(this, "Material");
}
#endregion
#region privatni promenne
private SGDxSessionLocker m_dxSession;
private ProductService m_prodSvc;
private InputBatchService m_inputBatchService;
private ComponentCheckService m_componentCheckSvc;
private string m_alarmCDOnNoTechnlogyData;
private bool m_useBlocker;
private int m_ioBlockDefinition = 1;
private long m_lastJobID;
private BusOperation m_lastOperation;
private bool m_sendAlarmCDOnNoTechnlogyData;
private bool m_addImmediatelyToBatchOp;
TSEDataForwardService m_dataForwardSvc;
ObservableCollection<BusItem> m_globalContextComponents;
ObservableCollection<BusItem> m_wholeContextComponents;
private bool m_checkSlot;
private string m_slotRegEx;
private bool m_WaitForProgram;
private bool m_waitingForSlot;
private BusItem m_CurrentComponent;
private bool m_prepared;
private bool m_continuousFilling;
private LogMessage tmp_message = null;
private bool m_isPositionNeeded;
private List<BusItem> m_currentComponentList;
private List<long> m_positionIDList;
private bool m_isDockingCartAccepted;
private DOKatalogParams katalog;
private bool m_ignorePaste;
private bool m_loadReferenciesForSlot;
private bool m_loadOrderRequired;
private bool m_debugLogActive;
private bool m_clearLoadedComponentsOnJobChanged;
private bool m_showBomOnlyForSlots;
private bool m_sendOnlyOneComponent;
#endregion
public bool CheckSlot { get => m_checkSlot; set => Set(() => CheckSlot, ref m_checkSlot, value); }
public string SlotRegex { get => m_slotRegEx; set => Set(() => SlotRegex, ref m_slotRegEx, value); }
#region public properties
public bool ContinuousFilling { get => m_continuousFilling; private set => m_continuousFilling = value; }
public bool Prepared { get { return m_prepared; } set { Set(() => Prepared, ref m_prepared, value); } }
public bool CheckFinished
{
get
{
if (m_ignorePaste)
return Session.GlobalContext.BOMComponents.Where(x => x.IsPaste == false).All(x => x.Matched || x.PositionMatched);
else
return Session.GlobalContext.BOMComponents.All(c => c.Matched || c.PositionMatched);
}
}
public bool ShowBomOnlyForSlots { get => m_showBomOnlyForSlots; }
#endregion
#region Private methods
private void Block()
{
if (m_useBlocker) Session.Resolve<IOPortBlockerService>().Block(m_ioBlockDefinition);
}
public bool CreateInputBatch(string batchCD, long productID)
{
DOInputBatch doInputBatch = new DataObjects.DOInputBatch(this);
bool rc = doInputBatch.Add(batchCD, string.Empty, string.Empty, 0, DateTime.MinValue, batchCD, productID, DateTime.MinValue);
return rc;
}
#endregion
#region module overrides
protected override bool OnSetParameters()
{
string s = Session.SysParams.TryGetString(this, "AlarmCDOnNoTechnologyData", "A00203", "Kód alarmu, který se vyvolá pokud nejsou nastaveny technologické časy.");
Session.Alarm.AlarmExists(s, out m_sendAlarmCDOnNoTechnlogyData);
m_alarmCDOnNoTechnlogyData = s;
m_useBlocker = Session.SysParams.GetBoolean(this, "UseBlocker", true, "Určuje, zda má modul má modul nastavovat blokaci pracoviště");
m_ioBlockDefinition = Session.SysParams.GetInt32(this, "IOBlockDefinition", 1, "Určuje, která definice blokování v modulu IOPortBlockerService se má použít (1=BlockState, 2=BlockState2)");
ContinuousFilling = Session.SysParams.GetParamValue(this, "ContinuousFilling", false, "Určuje, zda se má čekat na další komponenty i po načtení všech požadovaných komponent");
var dataPorts = Session.SysParams.TryGetString(this, "ForwardingCOMports", "", "Řetězec definující přeposílání dat mezi COM porty (např: port 1 přeposlat na port 5 a port 2 na port 6: \"1=>5;2=>6\")");
if (dataPorts != String.Empty)
{
m_dataForwardSvc.CreateMappingCOMports(dataPorts);
}
m_addImmediatelyToBatchOp = Session.SysParams.GetParamValue(this, "AddImmediatelyToBatchOp", false, "Určuje, zda se má komponenta okamžitě uložit k operaci");
m_checkSlot = Session.SysParams.GetParamValue(this, "CheckSlot", false, "Určuje, zda se má načítat a ověřovat slot, kam se komponenta do stroje zakládá.");
m_slotRegEx = Session.SysParams.TryGetString(this, "SlotRegEx", "", "RegEx na slot, který se načte scannerem.");
m_WaitForProgram = Session.SysParams.GetParamValue(this, "WaitForProgram", false, "Jestli je true, potom modul bude cekat az se v GlobalContext.CurrentMachineProgram nastavi program.");
m_isPositionNeeded = Session.SysParams.GetParamValue(this, "IsPositionNeeded", false, "Jestli je true, tak je po načtení komponenty potřeba načíst pozici");
m_isDockingCartAccepted = Session.SysParams.GetBoolean(this, "IsDockingCartAccepted", false, "Jestli je true, tak povoluje načítání vozíků s materiálem");
m_ignorePaste = Session.SysParams.GetBoolean(this, "IgnorePaste", false, "Je-li true, tak se nenacita material typu pasta v setupu");
m_loadReferenciesForSlot = Session.SysParams.GetBoolean(this, "LoadReferenciesForSlot", false, "Je-li true, dojde k načtení šarže komponenty pouze pro referenční slot");
m_loadOrderRequired = Session.SysParams.GetBoolean(this, "OrderRequired", false, "Je-li true, tak se musí načítat součásky v pořádí podle kusovníku");
m_debugLogActive = Session.SysParams.GetBoolean(this, "DebugLogActive", false, "Zapinani debugovych hlaseni");
m_clearLoadedComponentsOnJobChanged = Session.SysParams.GetBoolean(this, "ClearLoadedComponentsOnJobChanged", false, "Je-li true, tak při změně jobu dojde k automatickému odnačtení a smazání doposud načteného materiálu");
m_showBomOnlyForSlots = Session.SysParams.GetBoolean(this, "ShowBomOnlyForSlots", false, "Je-li true, tak se v záložce Kusovník zobrazí požadovaný materiál pouze pro požadované sloty nikoli celý jak byl původně načten");
m_sendOnlyOneComponent = Session.SysParams.GetBoolean(this, "SendOnlyOneComponents", true, "Je-li true, tak se v záložce Kusovník zobrazí požadovaný materiál pouze pro požadované sloty nikoli celý jak byl původně načten");
return base.OnSetParameters();
}
public override void StartLevel(SGTreeModuleData mdata)
{
if (Session.Job.GetEffectiveDOJob().JobID != m_lastJobID || Session.CycleContext.OperationOverride != m_lastOperation)
{
LoadComponents(true);
Block();
return;
}
if (Prepared) return;
base.StartLevel(mdata);
}
//!!TODO!! - prepsat celu tuto silenost ala BomItemReplacer
public override SGLMState HandlePortData(SGTreeModuleData mdata, SGReceivedData data)
{
SGLMState s = SGLMState.NotHandled;
if (mdata.LevelState == SGLevelState.Echo)
{
s = SGLMState.Handled;
if (m_WaitForProgram && !Session.GlobalContext.CurrentMachineProgram.IsSet)
{
Message = Log(LogMsg.IAC_GET_PROGRAMNO_Waiting);
return s;
}
if (!m_waitingForSlot)
{
m_CurrentComponent = new BusItem();
if (m_isDockingCartAccepted)
Message = Log(LogMsg.SMT_WaitingForComponentOrDockingCart);
else
Message = Log(LogMsg.SMT_WaitingForComponent);
}
else
Message = Log(LogMsg.BOM_ITEM_WaitingForSlotOrComponent, m_CurrentComponent.ComponentCD);
}
else
{
s = SGLMState.NotHandled;
if (data.DataType == DataType.InputBatch)
{
s = SGLMState.Handled | SGLMState.ResetIndex;
// tady se musi z barcode vyparsovat 3 group (P)MAT, (L)BATCH, (S)BATCHSN
string regexText = Session.Data.GetCodeDef(data).RegexText;
var regx = new Regex(regexText).Match(data.Text);
if (regx.Success)
{
s = SGLMState.Handled;
// NVCZ kod se musi optimalizovat do lepsi podoby aby to bylo unoverzalni
string compCD = regx.Groups["MATCD"].Value.TrimEnd();
string batch = regx.Groups["BATCHCD"].Value.Trim();
string sn = regx.Groups["BATCHSN"].Value.Trim();
bool pbSnOnly = string.IsNullOrEmpty(batch) && !string.IsNullOrEmpty(sn);
bool pbBatchAndSn = !string.IsNullOrEmpty(batch) && !string.IsNullOrEmpty(sn);
bool pbCompAndBatch = !string.IsNullOrEmpty(compCD) && !string.IsNullOrEmpty(batch);
BusInputBatchSerial bibSn = null;
BusInputBatch bib = null;
//pokud se musi dodrzet poradi nacitani zkontroluju, ze nacitam SX prvniho nematchnuteho zaznamu
if (m_loadOrderRequired && compCD != Session.GlobalContext.BOMComponents.Where(x => x.Matched == false && x.IsSlotNeeded == true).FirstOrDefault().ComponentCD)
{
Message = Log(LogMsg.BOM_ITEM_IncorrectMaterial, compCD);
return SGLMState.Handled | SGLMState.Fail;
}
// tady by se melo osetrit co nacitam za kod. pokud sn tak najdu prvni inputbatchsn a inputbatch abych vedel soucastku, pokud kod soucastku a sarze tak musim hledat prvni soucastku v kusovniku a pak dotahovat sarzi
// pokud by me dosla v kodu sarze a sn nebo sn sarze mel bych prvni hledat sarzi a sn a potom se divat na komponentu
// najdi soucastku v ciselniku
m_currentComponentList = GetAllComponentsForCode(compCD);
m_CurrentComponent = m_currentComponentList.ElementAtOrDefault(0);
BusItem componentClone;
if (SetError(m_CurrentComponent != null, LogMsg.SMT_ComponentUnwanted, sn, batch, compCD))
{
//
if (m_loadReferenciesForSlot)
{
m_positionIDList = GetAllPositionsForCode(compCD, m_CurrentComponent.MachineID, m_CurrentComponent.MachineSideCD, m_CurrentComponent.RequestedSlot);
}
else
m_positionIDList = GetAllPositionsForCode(compCD);
bool addToCollection = false;
s = CheckComponent(m_CurrentComponent, out addToCollection);
if ((s & SGLMState.OK) == SGLMState.OK)
{
// najdi prvni komponentu co nema match
m_CurrentComponent = GetFirstUnMatchedComponentFromBom(compCD);
// mam neco?
if (m_CurrentComponent == null)
{
Message = Log(LogMsg.SMT_ComponentAlreadyInList, compCD);
return s;
}
else
{
componentClone = m_CurrentComponent.Clone();
}
// najdi inputbatch
bib = m_inputBatchService.GetInputBatch(m_dxSession, batch, componentClone.ComponentID, true);
// pokud neexistuje a mam zalozit tak to udelej
if (bib == null && m_CurrentComponent.BatchMustExist)
{
Message = Log(LogMsg.DRYER_BatchNotFound, batch);
return SGLMState.Handled | SGLMState.Fail;
}
if (bib == null && !m_CurrentComponent.BatchMustExist && CreateInputBatch(batch, componentClone.ComponentID))
bib = m_inputBatchService.GetInputBatch(m_dxSession, batch, componentClone.ComponentID, true);
if (bib.IsBlocked)
{
Message = Log(LogMsg.INPUTBATCH_IsBlocked, bib.BatchCD, bib.ComponentCD, bib.BlockedMessage);
m_CurrentComponent = null;
bib = null;
return SGLMState.Handled | SGLMState.Fail;
}
var inputBatchSN = new BusInputBatchSerial(m_inputBatchService);
if (SetError(bib != null, LogMsg.BATCH_BatchSnNotFound, data.Text, batch, sn) && m_componentCheckSvc.CanUseComponent(this, m_dxSession, inputBatchSN, bib, SetError, Log, ref tmp_message))
{
// nastav sarzi do komponenty
componentClone.SetInputBatch(batch, sn);
componentClone.SetInputBatchID(bib.OID);
//pokud je vypnute nacitani slotu nebo u dane komponenty neni pozadovany konkretni slot
if (!m_checkSlot || !m_CurrentComponent.IsSlotNeeded)
{
componentClone.SetAsMatched();
}
// pokud se ma nacitat slot (feeder) pak jestli ho mas nacteny dej do seznamu a nastav IsMatch
else if (componentClone.SlotMatched)
{
componentClone.SetAsMatched();
}
else
m_waitingForSlot = true;
m_CurrentComponent = componentClone;
}
else if (tmp_message != null)
{
s = SGLMState.Handled | SGLMState.Fail;
Message = tmp_message;
}
if (componentClone.Matched && addToCollection)
{
foreach (long position in m_positionIDList)
{
BusItem component;
if (!m_CurrentComponent.IsSlotNeeded)
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD).FirstOrDefault();
else
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD && x.FullRequestedSlot.Equals(m_CurrentComponent.FullRequestedSlot)).FirstOrDefault();
component.SetInputBatch(batch, sn);
component.SetInputBatchID(bib.OID);
component.SetAsMatched();
SetGlobalCollectionItem(component);
Session.CycleContext.Components.Add(component);
}
Message = Log(LogMsg.BOM_ITEM_ComponentLoaded, m_CurrentComponent.ComponentName);
Session.Messenger.Send<GlobalCollectionBusItemCollectionChanged>(new GlobalCollectionBusItemCollectionChanged(Session.GlobalContext.BOMComponents));
m_CurrentComponent = null;
}
}
}
}
// jestli cekam na slot a mam komponentu
}
else if (m_waitingForSlot && m_CurrentComponent != null && data.DeviceType == SGDeviceType.Scanner)
{
// slot bude v regexu
var slotRegx = new Regex(m_slotRegEx).Match(data.Text);
Regex slotRegex = new Regex(m_slotRegEx);
Match m = slotRegex.Match(data.Text);
if (m.Success)
{
s = SGLMState.Handled | SGLMState.ResetIndex;
string machineid = slotRegx.Groups["MachineNUM"].Value.TrimEnd();
string side = slotRegx.Groups["Side"].Value.TrimEnd();
string slot = slotRegx.Groups["PosNUM"].Value.TrimEnd();
// najdi komponentu na machineid, side a slotu
var c = GetComponentFromBom(m_CurrentComponent.ComponentCD, machineid, side, slot);
if (m_loadReferenciesForSlot)
{
m_positionIDList = GetAllPositionsForCode(m_CurrentComponent.ComponentCD, m_CurrentComponent.MachineID, m_CurrentComponent.MachineSideCD, m_CurrentComponent.RequestedSlot);
}
else
m_positionIDList = GetAllPositionsForCode(m_CurrentComponent.ComponentCD);
if (SetError(c != null, LogMsg.BOM_ITEM_ComponentForIncorrectSlot, m_CurrentComponent.ComponentCD, machineid, side, slot))
{
var batch = m_CurrentComponent.InputBatchCD;
var sn = m_CurrentComponent.InputBatchSerialCD;
var bibid = m_CurrentComponent.InputBatchID;
m_CurrentComponent = c;
m_CurrentComponent.SetInputBatch(batch, sn);
m_CurrentComponent.SetUsedSlot(slot);
if (m_CurrentComponent.SlotMatched)
{
foreach (var position in m_positionIDList)
{
BusItem component;
if (!m_CurrentComponent.IsSlotNeeded)
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD).FirstOrDefault();
else
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD && x.FullRequestedSlot.Equals(m_CurrentComponent.FullRequestedSlot)).FirstOrDefault();
component.SetInputBatch(batch, sn);
component.SetInputBatchID(m_CurrentComponent.InputBatchID);
component.SetAsMatched();
component.SetUsedSlot(slot);
SetGlobalCollectionItem(component);
Session.CycleContext.Components.Add(component);
}
Message = Log(LogMsg.BOM_ITEM_SlotChecked, m_CurrentComponent.FullRequestedSlot);
Session.Messenger.Send<GlobalCollectionBusItemCollectionChanged>(new GlobalCollectionBusItemCollectionChanged(Session.GlobalContext.BOMComponents));
m_CurrentComponent = null;
m_waitingForSlot = false;
s |= SGLMState.OK;
}
}
s |= SGLMState.Fail;
}
}
//zpracovani dat, ktere prisly z HTTP-API
else if (data.DeviceType == SGDeviceType.API)
{
IEnumerable<BusItem> responseBusItemEnumerable;
if (m_sendOnlyOneComponent)
{
responseBusItemEnumerable = Session.GlobalContext.BOMComponents.Where(x => x.Matched == false).Take(1);
}
else
{
responseBusItemEnumerable = Session.GlobalContext.BOMComponents;
}
if (data.Data is ApiRequestDataComponents)
{
ApiRequestDataComponents httpApiDataComponentsDataRequest = data.Data as ApiRequestDataComponents;
if (httpApiDataComponentsDataRequest == null)
return SGLMState.NotHandled;
s = HandleComponentData(httpApiDataComponentsDataRequest.ComponentCD);
if ((s & SGLMState.OK) == SGLMState.OK)
{
Session.Messenger.Send(new HttpApiResponseMessage(new ApiResponseDataComponents()
{
Result = "",
Text = "",
GlobalContextComponents = responseBusItemEnumerable,
WaitingForSlot = m_CurrentComponent.IsSlotNeeded
}));
}
else
{
Session.Messenger.Send(new HttpApiResponseMessage(new ApiResponseDataComponents()
{
Result = "error",
Text = Message.TextFormatted,
GlobalContextComponents = responseBusItemEnumerable,
}));
}
}
else if (data.Data is ApiRequestDataComponentSlot)
{
ApiRequestDataComponentSlot httpApiRequestDataComponentSlot = data.Data as ApiRequestDataComponentSlot;
if (httpApiRequestDataComponentSlot == null)
return SGLMState.NotHandled;
if (!string.IsNullOrEmpty(httpApiRequestDataComponentSlot.Slot))
s = HandlePositionData(httpApiRequestDataComponentSlot.Slot);
else
s = HandlePositionData(httpApiRequestDataComponentSlot.MachineNumber, httpApiRequestDataComponentSlot.MachineSide, httpApiRequestDataComponentSlot.Position);
if ((s & SGLMState.OK) == SGLMState.OK)
{
Session.Messenger.Send(new HttpApiResponseMessage(new ApiResponseDataComponents()
{
Result = "",
Text = "",
GlobalContextComponents = responseBusItemEnumerable
}));
}
else
{
Session.Messenger.Send(new HttpApiResponseMessage(new ApiResponseDataComponents()
{
Result = "error",
Text = Message == null ? "Neznámá chyba" : Message.TextFormatted,
GlobalContextComponents = responseBusItemEnumerable
}));
}
}
else if (mdata.GotControl && data.Data is ApiRequestDataCheckActualStep)
{
SendActualStep();
return SGLMState.Handled;
}
}
else if (m_isDockingCartAccepted && data.DataType == DataType.Carrier)
{
s = HandleDockingCartData(data.Text);
}
else if (!ContinuousFilling)
{
// ukonceni pripravi materialu
if (data.Text == "C0304")
{
if (Prepared) return SGLMState.Handled | SGLMState.OK;
Prepared = true;
foreach (var c in Session.GlobalContext.BOMComponents) { c.SetAsMatched(); }
// odeslat zpravu do eteru
Session.Messenger.Send<InputBatchGroupChangedMessage>(new InputBatchGroupChangedMessage());
Message = Log(LogMsg.SMT_ComponentPreparationFinished);
return SGLMState.Handled | SGLMState.UpLevel;
}
}
}
LogResult();
return s;
}
public override void Clear()
{
Session.GlobalContext.BOMComponents.Clear();
Session.CycleContext.Components.Clear();
Session.Messenger.Send<GlobalCollectionBusItemCollectionChanged>(new GlobalCollectionBusItemCollectionChanged(Session.GlobalContext.BOMComponents));
m_lastJobID = 0;
if (m_lastOperation != null)
{
m_lastOperation.Clear();
}
Prepared = false;
base.Clear();
}
public override SGLMState ModuleChecker(SGTreeModuleData mdata)
{
SGLMState s;
if (ContinuousFilling)
{
s = base.ModuleChecker(mdata);
}
else
{
Prepared = CheckFinished;
if (Prepared)
{ // odeslat zpravu do eteru
Session.Messenger.Send<InputBatchGroupChangedMessage>(new InputBatchGroupChangedMessage());
return mdata.IsMaster ? SGLMState.Handled | SGLMState.UpLevel : SGLMState.NotHandled;
}
s = base.ModuleChecker(mdata);
}
return s;
}
#endregion
#region pomocne funkce
private SGLMState HandleDockingCartData(string dockingCartCD)
{
SGLMState s = SGLMState.Handled;
if (SetError(Session.BomItemPreparer.DoDockingCart.CheckDockingCartExist(dockingCartCD), LogMsg.DockingCart_NotFound, dockingCartCD))
{
if (SetError(Session.BomItemPreparer.DoDockingCart.GetSlotsByInputBatchesFromDockingCart(dockingCartCD), LogMsg.DockingCart_IsEmpty, dockingCartCD))
{
if (Session.BomItemPreparer.DoDockingCart.IsForActualJobAndPosIndex)
{
//pokud se ma kontrolovat slot, tak se krome poslani productCD a InputBatch posle i ulozeny slot
if (m_checkSlot)
{
foreach (var item in Session.BomItemPreparer.DoDockingCart.SlotsByInputBatches)
{
Session.SetNextData(Session.Data.CreateReceivedData(SGDeviceType.Scanner, item.Key.ComponentCD + " " + item.Key.BatchCD, false)); //automaticke poslani productCD a inputbatche
Session.SetNextData(Session.Data.CreateReceivedData(SGDeviceType.Scanner, "**" + item.Value, false)); //automaticke poslani ulozene slotu u materialu ve voziku
}
}
//pokud se nema kontrolovat slot, tak se pouze podhodi productCD a inputbatch z voziku
else
{
foreach (var item in Session.BomItemPreparer.DoDockingCart.SlotsByInputBatches)
{
//z nacteneho materialu ve voziku se vezme ProductCD prida mezera a BatchCD a posle se to jako TerminalPort 1
string ibToBeSend = item.Key.ComponentCD + " " + item.Key.BatchCD;
Session.SetNextData(Session.Data.CreateReceivedData(SGDeviceType.Scanner, ibToBeSend, false));
}
}
s |= SGLMState.OK;
}
else
{
Message = Log(LogMsg.DockingCart_ForDifferentJobOrOperation,
Session.BomItemPreparer.DoDockingCart.DockingCartCD,
Session.Job.DoJob.JobID, Session.CycleContext.OperationOverride.RoutingPosIndex,
Session.BomItemPreparer.DoDockingCart.JobID, Session.BomItemPreparer.DoDockingCart.RoutingPosIndex);
s |= SGLMState.Fail;
}
}
}
else
{
s |= SGLMState.Fail;
}
return s;
}
public virtual void LoadComponents(bool clear)
{
if (clear)
{
m_globalContextComponents.Clear();
m_wholeContextComponents.Clear();
}
LoadGlobalContextComponents();
if (m_debugLogActive)
{
foreach (var item in m_globalContextComponents)
{
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"Tempova kolekce Kod materialu {item.ComponentCD}, reference {item.PositionCD}, mnozstvi {item.Quantity}");
}
foreach (var item in Session.GlobalContext.BOMComponents)
{
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"GlobalContext kolekce Kod materialu {item.ComponentCD}, reference {item.PositionCD}, mnozstvi {item.Quantity}");
}
foreach (var item in Session.CycleContext.Components)
{
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"CycleContext kolekce Kod materialu {item.ComponentCD}, sarze nacteneho materialu {item.InputBatchCD} reference {item.PositionCD}, mnozstvi {item.Quantity}");
}
}
FullyObservableCollection<BusItem> temp = new FullyObservableCollection<BusItem>();
//pokud je zapnuto automaticke odnacitani materialu pri zmene jobu
if (m_clearLoadedComponentsOnJobChanged)
{
ClearLoadedComponents();
foreach (var component in m_globalContextComponents)
{
temp.Add(component);
}
Session.GlobalContext.SetBOMComponents(temp);
}
else
{
if (CompareComponents(Session.GlobalContext.BOMComponents, m_globalContextComponents))
{
ClearLoadedComponents();
foreach (var component in m_globalContextComponents)
{
temp.Add(component);
}
Session.GlobalContext.SetBOMComponents(temp);
}
}
Session.Messenger.Send<GlobalCollectionBusItemCollectionChanged>(new GlobalCollectionBusItemCollectionChanged(Session.GlobalContext.BOMComponents));
m_lastJobID = Session.Job.GetEffectiveDOJob().JobID;
m_lastOperation = Session.CycleContext.OperationOverride;
//debugovaci logovani kusovniku
if (m_debugLogActive)
{
foreach (var item in Session.GlobalContext.BOMComponents)
{
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"Kod materialu {item.ComponentCD}, reference {item.PositionCD}, mnozstvi {item.Quantity}");
}
}
}
public void ClearLoadedComponents()
{
Session.GlobalContext.BOMComponents.Clear();
Session.CycleContext.Components.Clear();
Prepared = false;
if (m_debugLogActive)
Message = Log(LogMsg.CUSTOM_INFO_MSG, "Čistím kolekce v paměti");
}
/// <summary>
/// Nacte komponentu z kusovniku (original kusovnik co je na operaci)
/// </summary>
/// <param name="componentCD"></param>
/// <returns></returns>
public virtual BusItem GetComponentFromBom(string componentCD)
{
return Session.GlobalContext.BOMComponents.FirstOrDefault(x => x.ComponentCD == componentCD);
}
public virtual BusItem GetComponentFromBom(string componentCD, string machineID, string machineSideCD, string slot)
{
return Session.GlobalContext.BOMComponents.FirstOrDefault(x => x.ComponentCD == componentCD && x.MachineID == machineID && x.MachineSideCD == machineSideCD && x.RequestedSlot == slot);
}
public virtual BusItem GetComponentFromCycleContext(string componentCD, string machineID, string machineSideCD, string slot)
{
return Session.CycleContext.Components.FirstOrDefault(x => x.ComponentCD == componentCD && x.MachineID == machineID && x.MachineSideCD == machineSideCD && x.RequestedSlot == slot);
}
public virtual BusItem GetFirstUnMatchedComponentFromBom(string componentCD)
{
return Session.GlobalContext.BOMComponents.FirstOrDefault(x => x.ComponentCD == componentCD && !x.Matched);
}
public virtual List<BusItem> GetAllComponentsForCode(string componentCD)
{
return Session.GlobalContext.BOMComponents.Where(x => x.ComponentCD == componentCD && x.Matched == false).ToList();
}
public virtual List<long> GetAllPositionsForCode(string componentCD)
{
return Session.GlobalContext.BOMComponents.Where(x => x.ComponentCD == componentCD).Select(x => x.PositionID).ToList();
}
/// <summary>
///
/// </summary>
/// <param name="componentCD"></param>
/// <param name="machineID"></param>
/// <param name="side"></param>
/// <param name="slot"></param>
/// <returns></returns>
public virtual List<long> GetAllPositionsForCode(string componentCD, string machineID, string side, string slot)
{
return Session.GlobalContext.BOMComponents.Where(x => x.ComponentCD == componentCD && x.MachineID == machineID && x.MachineSideCD == side && x.RequestedSlot == slot).Select(x => x.PositionID).ToList();
}
/// <summary>
/// Porovnej dva seznamy komponent jestli jsou stejne
/// </summary>
/// <param name="sourceCollection"></param>
/// <param name="targetCollection"></param>
/// <returns>vrati true, pokud NEjsou kolekce stejne </returns>
public bool CompareComponents(ObservableCollection<BusItem> sourceCollection, ObservableCollection<BusItem> targetCollection, bool logit = false)
{
bool areCollectionDifferent = false;
if (targetCollection.Count() != sourceCollection.Count())
return areCollectionDifferent = true;
for (int i = 0; i < targetCollection.Count(); i++)
{
for (int j = 0; j < sourceCollection.Count(); j++)
{
if (sourceCollection[j].ComponentCD == targetCollection[i].ComponentCD && sourceCollection[j].InputBatchCD == targetCollection[i].InputBatchCD)
{
sourceCollection[j].CompareMatched = true;
targetCollection[j].CompareMatched = true;
}
}
}
//kolekce obsahuji jiny pocet zaznamu nebo v kolekcich existuje takovy nastroj, ktery neni v obou kolekcich
if ((sourceCollection.Any(x => x.CompareMatched == false) || targetCollection.Any(x => x.CompareMatched == false)))
areCollectionDifferent = true;
if (areCollectionDifferent && logit)
{
//BOM_ITEM_SAVE
//sourceCollection je posledni zalozena kolekce BusItem v nejake InputBatchGroup
Message = Log(LogMsg.CUSTOM_INFO_MSG, "Seznam komponent a jejich sarzi z puvodni kolekce, ktere nejsou v nove kolekci");
foreach (var item in sourceCollection.Where(x => x.CompareMatched == false))
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"Kod materialu: {item.ComponentCD} {item.InputBatchCD}");
//targetCollection je aktualni kolekce BusItem, u ktere musim zjistit, jestli neni odlisna od posledni ulozene kolekce
Message = Log(LogMsg.CUSTOM_INFO_MSG, "Seznam komponent a jejich sarzi z nove kolekce, ktere nejsou v puvodni kolekci");
foreach (var item in targetCollection.Where(x => x.CompareMatched == false))
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"Kod materialu: {item.ComponentCD} {item.InputBatchCD}");
}
return areCollectionDifferent;
}
public virtual bool IgnoreComponent(BusItem c)
{
if (c.ComponentID == 0) return true;
DOKatalogParams k = new DOKatalogParams(this, "Material");
k.Load(c.ComponentID);
return k.GetValue<bool>("IsPaste", false, true);
}
public bool IsComponentFromCurrentOp(BusItem component)
{
//TODO - Zeptat se Toma na porovnavani podle OID komponent
//porovnavat OID nebo ComponentID
return Session.GlobalContext.BOMComponents.Any(x => x.ComponentID == component.ComponentID);
}
public virtual SGLMState CheckComponent(BusItem component, ObservableCollection<BusItem> componentCollection)
{
bool addComponentToCollection = false;
return CheckComponent(component, componentCollection, out addComponentToCollection);
}
public virtual SGLMState CheckComponent(BusItem component, out bool addToCollection)
{
return CheckComponent(component, Session.CycleContext.Components, out addToCollection);
}
public virtual SGLMState CheckComponent(BusItem component, ObservableCollection<BusItem> componentCollection, out bool addComponentToCollection)
{
addComponentToCollection = false;
SGLMState s = SGLMState.NotHandled;
if (!IsComponentFromCurrentOp(component))
{
//preposlani na nejaky COM port
s = SGLMState.Handled | SGLMState.OK;
}
else if (IsComponentFromCurrentOp(component))
{
addComponentToCollection = true;
s = SGLMState.Handled | SGLMState.OK;
}
return s;
}
public virtual bool Recheck() { return true; }
private SGLMState HandleComponentData(string data)
{
SGLMState s = SGLMState.Handled | SGLMState.ResetIndex;
// tady se musi z barcode vyparsovat 3 group (P)MAT, (L)BATCH, (S)BATCHSN
SGCodeDef codeDef = Session.Data.GetCodeDef(data);
if (codeDef == null)
{
Message = Log(LogMsg.LOCALMANAGER_UnhandledData, data);
return s | SGLMState.Fail;
}
string regexText = codeDef.RegexText;
var regx = new Regex(regexText).Match(data);
if (regx.Success)
{
s = SGLMState.Handled;
// NVCZ kod se musi optimalizovat do lepsi podoby aby to bylo unoverzalni
string compCD = regx.Groups["MATCD"].Value.TrimEnd();
string batch = regx.Groups["BATCHCD"].Value.Trim();
string sn = regx.Groups["BATCHSN"].Value.Trim();
bool pbSnOnly = string.IsNullOrEmpty(batch) && !string.IsNullOrEmpty(sn);
bool pbBatchAndSn = !string.IsNullOrEmpty(batch) && !string.IsNullOrEmpty(sn);
bool pbCompAndBatch = !string.IsNullOrEmpty(compCD) && !string.IsNullOrEmpty(batch);
BusInputBatchSerial bibSn = null;
BusInputBatch bib = null;
// tady by se melo osetrit co nacitam za kod. pokud sn tak najdu prvni inputbatchsn a inputbatch abych vedel soucastku, pokud kod soucastku a sarze tak musim hledat prvni soucastku v kusovniku a pak dotahovat sarzi
// pokud by me dosla v kodu sarze a sn nebo sn sarze mel bych prvni hledat sarzi a sn a potom se divat na komponentu
// najdi soucastku v ciseliku
m_CurrentComponent = GetFirstUnMatchedComponentFromBom(compCD);
if (SetError(m_CurrentComponent != null, LogMsg.SMT_ComponentUnwanted, true, sn, batch, compCD))
{
if (m_loadReferenciesForSlot)
{
m_positionIDList = GetAllPositionsForCode(compCD, m_CurrentComponent.MachineID, m_CurrentComponent.MachineSideCD, m_CurrentComponent.RequestedSlot);
}
else
m_positionIDList = GetAllPositionsForCode(compCD);
bool addToCollection = false;
s = CheckComponent(m_CurrentComponent, out addToCollection);
if ((s & SGLMState.OK) == SGLMState.OK)
{
// najdi prvni komponentu co nema match
var cc = GetFirstUnMatchedComponentFromBom(compCD);
// mam neco?
if (cc != null)
m_CurrentComponent = cc.Clone();
else
{
Message = Log(LogMsg.SMT_ComponentAlreadyInList, compCD);
return SGLMState.Handled | SGLMState.Fail | SGLMState.ResetIndex;
}
// najdi inputbatch
bib = m_inputBatchService.GetInputBatch(m_dxSession, batch, m_CurrentComponent.ComponentID, true);
// pokud neexistuje a mam zalozit tak to udelej
if (bib == null && CreateInputBatch(batch, m_CurrentComponent.ComponentID))
bib = m_inputBatchService.GetInputBatch(m_dxSession, batch, m_CurrentComponent.ComponentID, true);
var inputBatchSN = new BusInputBatchSerial(m_inputBatchService);
if (SetError(bib != null, LogMsg.BATCH_BatchSnNotFound, true, data, batch, sn) && m_componentCheckSvc.CanUseComponent(this, m_dxSession, inputBatchSN, bib, SetError, Log, ref tmp_message))
{
if (bib.IsBlocked)
{
Message = Log(LogMsg.INPUTBATCH_IsBlocked, bib.BatchCD, bib.ComponentCD, bib.BlockedMessage);
m_CurrentComponent = null;
bib = null;
return SGLMState.Handled | SGLMState.Fail;
}
// nastav sarzi do komponenty
m_CurrentComponent.SetInputBatch(batch, sn);
if (!m_checkSlot || !m_CurrentComponent.IsSlotNeeded)
{
m_CurrentComponent.SetAsMatched();
}
// pokud se ma nacitat slot (feeder) pak jestli ho mas nacteny dej do seznamu a nastav IsMatch
else if (m_CurrentComponent.SlotMatched)
{
m_CurrentComponent.SetAsMatched();
}
else
m_waitingForSlot = true;
}
else
{
s = SGLMState.Handled | SGLMState.Fail;
Message = tmp_message;
}
}
if (m_CurrentComponent.Matched && addToCollection)
{
foreach (long position in m_positionIDList)
{
BusItem component;
if (!m_CurrentComponent.IsSlotNeeded)
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD).FirstOrDefault();
else
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD && x.FullRequestedSlot.Equals(m_CurrentComponent.FullRequestedSlot)).FirstOrDefault();
component.SetInputBatch(batch, sn);
component.SetInputBatchID(bib.OID);
component.SetAsMatched();
SetGlobalCollectionItem(m_CurrentComponent);
Session.CycleContext.Components.Add(component);
}
Message = Log(LogMsg.BOM_ITEM_ComponentLoaded, m_CurrentComponent.ComponentCD);
Session.Messenger.Send<GlobalCollectionBusItemCollectionChanged>(new GlobalCollectionBusItemCollectionChanged(Session.GlobalContext.BOMComponents));
//nutno este otestovat, jestli se to nekde nezhrouti
//m_CurrentComponent = null;
}
}
}
// jestli cekam na slot a mam komponentu
return s;
}
private SGLMState HandlePositionData(string data)
{
// slot bude v regexu
var slotRegx = new Regex(m_slotRegEx).Match(data);
string machineid = slotRegx.Groups["MachineNUM"].Value.TrimEnd();
string side = slotRegx.Groups["Side"].Value.TrimEnd();
string slot = slotRegx.Groups["PosNUM"].Value.TrimEnd();
return HandlePositionData(machineid, side, slot);
}
private SGLMState HandlePositionData(string machineid, string side, string slot)
{
SGLMState s = SGLMState.NotHandled;
if (m_waitingForSlot && m_CurrentComponent != null)
{
Message = Log(LogMsg.CUSTOM_INFO_MSG, "Zacinam zpracovavat slotove data");
s = SGLMState.Handled | SGLMState.ResetIndex;
// najdi komponentu na machineid, side a slotu
var c = GetComponentFromBom(m_CurrentComponent.ComponentCD, machineid, side, slot);
if (c != null)
{
var batch = m_CurrentComponent.InputBatchCD;
var sn = m_CurrentComponent.InputBatchSerialCD;
m_CurrentComponent = c;
m_CurrentComponent.SetInputBatch(batch, sn);
m_CurrentComponent.SetUsedSlot(slot);
if (m_CurrentComponent.SlotMatched)
{
foreach (var position in m_positionIDList)
{
BusItem component;
if (!m_CurrentComponent.IsSlotNeeded)
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD).FirstOrDefault();
else
component = Session.GlobalContext.BOMComponents.Where(x => x.PositionID == position && x.ComponentCD == m_CurrentComponent.ComponentCD && x.FullRequestedSlot.Equals(m_CurrentComponent.FullRequestedSlot)).FirstOrDefault();
if (component != null)
{
component.SetInputBatch(m_CurrentComponent.InputBatchCD, m_CurrentComponent.InputBatchSerialCD);
component.SetInputBatchID(m_CurrentComponent.InputBatchID);
component.SetAsMatched();
SetGlobalCollectionItem(m_CurrentComponent);
Session.CycleContext.Components.Add(component);
}
}
Message = Log(LogMsg.BOM_ITEM_SlotChecked, m_CurrentComponent.FullRequestedSlot);
Session.Messenger.Send<GlobalCollectionBusItemCollectionChanged>(new GlobalCollectionBusItemCollectionChanged(Session.GlobalContext.BOMComponents));
m_CurrentComponent = null;
m_waitingForSlot = false;
s |= SGLMState.OK;
}
else
{
Message = Log(LogMsg.BOM_ITEM_ComponentForIncorrectSlot, m_CurrentComponent.ComponentCD, machineid, side, slot);
s = SGLMState.Handled | SGLMState.Fail;
}
}
else
{
Message = Log(LogMsg.BOM_ITEM_ComponentForIncorrectSlot, m_CurrentComponent.ComponentCD, machineid, side, slot);
s = SGLMState.Handled | SGLMState.Fail;
}
}
return s;
}
private void LoadGlobalContextComponents()
{
if (Session.CycleContext.OperationOverride == null)
{
Log(LogMsg.CUSTOM_WARNING_MSG, "Není vybrána operace na modulu BOM_Item!");
return;
}
using (m_dxSession.GetLock())
{
var _BOMComponents = from j in new XPQuery<Job>(m_dxSession.Session)
join jpbi in new XPQuery<JobBomItem>(m_dxSession.Session) on j.JobBom equals jpbi.JobBom
where (j.OID == Session.Job.DoJob.JobID
&& jpbi.RoutingPosIndex == Session.CycleContext.OperationOverride.RoutingPosIndex
&& jpbi.Deleted == false && jpbi.IsRequested == true && jpbi.Quantity > 0)
group jpbi by new
{
jpbi.OID,
jpbi.RoutingPosIndex,
jpbi.PosIndex,
MaterialID = (jpbi.Material != null) ? jpbi.Material.OID : 0,
ProductID = (jpbi.Product != null) ? jpbi.Product.OID : 0,
MaterialCD = (jpbi.Material != null) ? jpbi.Material.ProductCD : string.Empty,
ProductCD = (jpbi.Product != null) ? jpbi.Product.ProductCD : string.Empty,
MaterialName = (jpbi.Material != null) ? jpbi.Material.Name : string.Empty,
ProductName = (jpbi.Product != null) ? jpbi.Product.Name : string.Empty,
PositionID = (jpbi.Position != null) ? jpbi.Position.OID : 0,
jpbi.Position.PositionCD,
jpbi.Quantity,
jpbi.BatchMustExist,
jpbi.CheckSameJob,
jpbi.CheckSameBatch,
jpbi.CheckSameLEDBinning
} into t
select BusItem.Create(t.Key.OID, t.Key.RoutingPosIndex, t.Key.PosIndex, t.Key.MaterialID,
t.Key.ProductID, t.Key.MaterialCD, t.Key.ProductCD, t.Key.MaterialName, t.Key.ProductName,
t.Key.PositionID, t.Key.PositionCD, t.Key.Quantity, t.Key.BatchMustExist,
t.Key.CheckSameJob, t.Key.CheckSameBatch, t.Key.CheckSameLEDBinning);
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"Zacinam dotahovat material z Jobu {Session.Job.DoJob.JobID} pro routingovou pozici {Session.CycleContext.OperationOverride.RoutingPosIndex}");
foreach (var component in _BOMComponents)
{
if (component.MaterialID != 0)
{
katalog.Load(component.MaterialID);
component.IsPaste = katalog.GetValue<bool>("IsPaste", false, true);
}
Message = Log(LogMsg.CUSTOM_INFO_MSG, $"Kod materialu {component.ComponentCD}, reference {component.PositionCD}, mnozstvi {component.Quantity}");
m_globalContextComponents.Add(component);
}
}
Message = Log(LogMsg.CUSTOM_INFO_MSG, "Dokoncil sem dotaz na material z jobu");
}
protected override void SendActualStep()
{
IEnumerable<BusItem> responseBusItemEnumerable;
if (m_sendOnlyOneComponent)
{
responseBusItemEnumerable = Session.GlobalContext.BOMComponents.Where(x => x.Matched == false).Take(1);
}
else
{
responseBusItemEnumerable = Session.GlobalContext.BOMComponents;
}
if (Session.GlobalContext.CurrentMachineProgram.IsSet)
{
Session.Messenger.Send(new HttpApiResponseMessage(new ApiResponseDataCheckActualStepComponents()
{
ActualStep = this.ModuleCD,
GlobalContextComponents = responseBusItemEnumerable,
CheckSlotActive = m_checkSlot,
Prepared = Prepared
}));
}
else
{
Session.Messenger.Send(new HttpApiResponseMessage(new ApiResponseDataCheckActualStepComponents()
{
ActualStep = this.ModuleCD,
GlobalContextComponents = responseBusItemEnumerable,
CheckSlotActive = m_checkSlot,
Prepared = Prepared
}));
}
}
/// <summary>
/// prepise index v kolekci GlobalContext.BOMComponents pokud v ni jiz existuje takovy zaznam
/// </summary>
/// <param name="item"></param>
public void SetGlobalCollectionItem(BusItem item)
{
if (item.IsSlotNeeded)
{
var compsToBeUpdated = Session.GlobalContext.BOMComponents.Where(x => x.ComponentID == item.ComponentID && x.FullRequestedSlot == item.FullRequestedSlot).Select(x => x).ToList();
for (int i = 0; i < compsToBeUpdated.Count; i++)
{
compsToBeUpdated[i].Matched = true;
}
}
else
{
var compsToBeUpdated = Session.GlobalContext.BOMComponents.Where(x => x.ComponentID == item.ComponentID).Select(x => x).ToList();
for (int i = 0; i < compsToBeUpdated.Count; i++)
{
compsToBeUpdated[i].Matched = true;
}
//Session.GlobalContext.BOMComponents.Where(x => x.ComponentID == item.ComponentID).Select(x => { x.Matched = item.Matched; return x; }).FirstOrDefault();
}
return;
}
#endregion
}
}