d
dunknown
csharp
2 years ago
15 kB
2
Indexable
Never
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Bastian.Exacta.Automation.Core; using Bastian.Exacta.Automation.Core.Models; using Bastian.Exacta.Business.Core.Entities; using Bastian.Exacta.Business.Core.Interfaces; using Bastian.Exacta.Business.Persistance.QueryExtensions; using Bastian.Exacta.Core.PlugIn; namespace Bastian.Exacta.Puma.PackRoutingScanner { [ProcessType("SCANNER_TYPE_1003")] public class PumaPackRoutingScanner : BaseScanner { #region Constants private const string VasDestination = "VAS"; private const string LidderDestination = "LID"; private const string StraightRecircDestination = "REC"; #endregion #region Instance Methods public override bool CheckForAndQueueUpScan(TagInfo[] readTagList, ref List<WriteTag> clearReadTags) { if (readTagList[this.ScannerInfo.OPCTriggerIndex].LongVal != 0 && readTagList[this.ScannerInfo.OPCTriggerIndex + 1].StringVal.Trim() != string.Empty) { long trackId = readTagList[this.ScannerInfo.OPCTriggerIndex].LongVal; string barcode = SanitizeString(readTagList[this.ScannerInfo.OPCTriggerIndex + 1].StringVal.Trim()); var vasLane = this.ScannerInfo.LaneInfoList.Where(x => x.OpcFullIndex > 0 && x.Description.ToUpper().Contains(VasDestination)) .FirstOrDefault(); if (vasLane != null) { var fullVal = readTagList[(int)vasLane.OpcFullIndex].LongVal; var laneStatus = fullVal > 0; Log.Debug($" vas Lane OpcFullIndex tag value [{fullVal}] at {ScannerInfo.ScannerDesc}"); vasLane.Full = laneStatus; } PackageInfo laneAssignInfo = new PackageInfo { PkgBarCode = barcode, TrackID = trackId, ScaleData = string.Empty, ScannerID = this.ScannerInfo.ScannerNum, ScannerIndex = this.ScannerInfo.ScannerIndex, ScanDateTime = DateTime.Now }; this.StartProcessingCarton(laneAssignInfo); // Tell controls to clear the track id clearReadTags = new WriteTagBuilder() .AddTag(this.ScannerInfo.OPCTriggerIndex, 0) .GetTags(); readTagList[this.ScannerInfo.OPCTriggerIndex].LongVal = 0; // Set scan values as last values readTagList[this.ScannerInfo.OPCTriggerIndex].LastLongVal = trackId; readTagList[this.ScannerInfo.OPCTriggerIndex + 1].LastStringVal = barcode; if (IsContainerNoRead(barcode)) { this.ScannerInfo.NumberOfNoReads++; } else { this.ScannerInfo.NumberOfReads++; } this.ScannerInfo.CurrentScanValue = barcode; this.ScannerInfo.OldScanValue = barcode; this.ScannerInfo.TrackingID = (int)trackId; return true; } // Handle manual input for no reads if (!string.IsNullOrWhiteSpace(this.ManualScan) && this.ScannerInfo.TrackingID != 0) { readTagList[this.ScannerInfo.OPCTriggerIndex].LastLongVal = 0; readTagList[this.ScannerInfo.OPCTriggerIndex].LongVal = this.ScannerInfo.TrackingID; readTagList[this.ScannerInfo.OPCTriggerIndex + 1].StringVal = this.ManualScan; this.ManualScan = string.Empty; return this.CheckForAndQueueUpScan(readTagList, ref clearReadTags); } return false; } protected override bool ProcessCarton(ref IQueueInfo qInfo) { PackageInfo laneAssignInfo = (PackageInfo)qInfo; string containerName = laneAssignInfo.PkgBarCode; int trackingId = (int)laneAssignInfo.TrackID; ZoneInfo assignedRoute = ScannerInfo.GetBestRoutingDestination(new object[] { DefaultZone }); if (IsContainerNoRead(containerName)) { PostGeneralSystemMessage($"Detected no read at {ScannerInfo.ScannerDesc.Trim()}."); assignedRoute = ScannerInfo.GetBestRoutingDestination(new object[] { NoReadZone }); } else if (IsContainerMultiRead(containerName)) { PostGeneralSystemMessage($"Detected multi read at {ScannerInfo.ScannerDesc.Trim()}."); assignedRoute = ScannerInfo.GetBestRoutingDestination(new object[] { NoReadZone }); } else { PostGeneralSystemMessage($"Ready to Process Package {containerName} Tracking ID {trackingId} at {ScannerInfo.ScannerDesc.Trim()}"); using (var unitOfWork = this.UnitOfWorkFactory.Create()) { //Does Container Exist and Have Work var containerWorkModel = GetRemainingWorkForContainer(unitOfWork, containerName); laneAssignInfo.GuidValList.AddRange(containerWorkModel.OrderIds.Select(o => (Guid?)o)); if (containerWorkModel?.DoesContainerExist != true) { PostGeneralSystemMessage($"Container does not exist! {containerName} Tracking ID {trackingId} at {ScannerInfo.ScannerDesc.Trim()}"); assignedRoute = ScannerInfo.GetBestRoutingDestination(new object[] { NoContainerFoundZone }); } else if (containerWorkModel.QcRequired) { PostGeneralSystemMessage($"Container QC Required!! {containerName} Tracking ID {trackingId} at {ScannerInfo.ScannerDesc.Trim()}"); assignedRoute = ScannerInfo.GetBestRoutingDestination(new object[] { ExceptionZone }); } else if (CheckForRecircMax(unitOfWork, laneAssignInfo)) { PostGeneralSystemMessage(msg: $"Carton {laneAssignInfo.PkgBarCode} Has Reached its Recirc Max ({ScannerInfo.RecircMax}) at this scanner ({ScannerInfo.ScannerDesc}) and will be sent to exception."); assignedRoute = ScannerInfo.GetBestRoutingDestination(new object[] { ExceptionZone }); } else if (this.ContainerHasOpenOrShortedPicks(unitOfWork, containerWorkModel)) { this.PostGeneralSystemMessage($"Container [{containerName}] has open or shorted picks, routing to QC"); assignedRoute = this.ScannerInfo.GetBestRoutingDestination(new object[] { ScannerInfo.DefaultZone }); } else if(this.ContainerHasMultipleOrdersOrVas(unitOfWork, containerWorkModel)) { this.PostGeneralSystemMessage($"Container [{containerName}] has multiple orders or an order that requires VAS."); assignedRoute = this.ScannerInfo.GetBestRoutingDestination(new object[] { VasDestination }); var vasLane = this.ScannerInfo.LaneInfoList.FirstOrDefault(x => x.ControlsDestination == assignedRoute.ControlsDestination); if (vasLane.Full) { this.PostGeneralSystemMessage($"VAS lane is full. Sending Container [{containerName}] to recirc."); assignedRoute = this.ScannerInfo.GetBestRoutingDestination(new object[] { StraightRecircDestination }); } } else { var bestRoutingDestination = this.ScannerInfo.GetBestRoutingDestination(new object[] { LidderDestination }); if (bestRoutingDestination != null) { assignedRoute = bestRoutingDestination; LaneInfo divertLane = ScannerInfo.LaneInfoList.FirstOrDefault(x => x.ControlsDestination == assignedRoute.ControlsDestination); if (divertLane == null || divertLane.OpcDivertIndex == 0) { CompleteRoutingInstructionsForDestination(unitOfWork, assignedRoute.ControlsDestination, laneAssignInfo.PkgBarCode); } PostGeneralSystemMessage($"Container Still has Work! {containerName} Tracking ID {trackingId} at {ScannerInfo.ScannerDesc.Trim()}"); } } } } laneAssignInfo.DestinationID = assignedRoute.ControlsDestination; ScannerInfo.DefaultDestination = laneAssignInfo.DestinationID; laneAssignInfo.AssignedLane = assignedRoute.DestinationDescription; ScannerInfo.Destination = laneAssignInfo.AssignedLane; //Write Destination to PLC laneAssignInfo.DestinationTags = new WriteTagBuilder() .AddTag(ScannerInfo.OPCDestinationIndex + 1, laneAssignInfo.DestinationID) .AddTag(ScannerInfo.OPCDestinationIndex, laneAssignInfo.TrackID) .GetTags(); PostGeneralSystemMessage($"Route Container {containerName} at {ScannerInfo.ScannerDesc.Trim()} to {laneAssignInfo.AssignedLane}"); if (ScannerInfo.LaneInfoList.Any(l => l.ControlsDestination == laneAssignInfo.DestinationID) || assignedRoute?.InsertPreScan == true && assignedRoute?.WorkArea != null) { InsertPrescanRecord(TaskQueue, assignedRoute?.WorkArea ?? ScannerInfo.WorkAreaID, laneAssignInfo); } return true; } /// <summary> /// Determines if a container has multiple orders or lines in VAS /// </summary> /// <param name="unitOfWork">The unit of work</param> /// <param name="containerWorkModel">The container work model</param> /// <returns></returns> private bool ContainerHasMultipleOrdersOrVas(IUnitOfWork unitOfWork, ContainerWorkModel containerWorkModel) { this.PostGeneralSystemMessage($"Checking if container has multiple orders or VAS..."); var container = this.RepositoryFactory.Create<Container>(unitOfWork) .Query() .FirstOrDefault(cntnr => cntnr.Name == containerWorkModel.Name); var orderSubLineRepo = this.RepositoryFactory.Create<OrderSubLine>(unitOfWork); var containerOrderCount = orderSubLineRepo .Query() .Where(osl => osl.TransportContainer.Name == containerWorkModel.Name) .Select(osl => osl.OrderLine.Order.Id) .Distinct() .Count(); this.PostGeneralSystemMessage($"Container [{containerWorkModel.Name}] has [{containerOrderCount}] order and is container type [{container?.Type.Type}]"); var containerHasMultipleOrders = containerOrderCount > 1 || container?.Type.Type == (decimal)ContainerCategory.MANUFACTURING_TOTE; var orderLinesInContainer = orderSubLineRepo.Query() .Where(osl => osl.TransportContainer.Name == containerWorkModel.Name) .Select(osl => osl.OrderLine.Id) .ToList(); var ordersInContainer = this.RepositoryFactory.Create<OrderLine>(unitOfWork) .Query() .Where(line => orderLinesInContainer.Contains(line.Id)) .Select(line => line.Order.Id) .Distinct() .ToList(); var containerHasVas = this.RepositoryFactory.Create<Vas>(unitOfWork) .Query() .Any(vas => ordersInContainer.Contains(vas.Order.Id) || orderLinesInContainer.Contains(vas.OrderLine.Id) || vas.Container.Id == containerWorkModel.Id); this.PostGeneralSystemMessage(containerHasVas ? $"Container [{containerWorkModel.Name}] DOES have VAS" : $"Container [{containerWorkModel.Name}] DOES NOT have VAS"); return containerHasMultipleOrders || containerHasVas; } /// <summary> /// Determines if the order has open or shorted picks /// </summary> /// <param name="unitOfWork">The unit of work</param> /// <param name="containerWorkModel">The container work model</param> /// <returns></returns> private bool ContainerHasOpenOrShortedPicks(IUnitOfWork unitOfWork, ContainerWorkModel containerWorkModel) { bool openPicks = containerWorkModel.PickOrderIds.Any(); bool shortedPicks = this.RepositoryFactory.Create<OrderSubLine>(unitOfWork) .Query() .Any(subLine => containerWorkModel.OrderIds.Contains(subLine.OrderLine.Order.Id) && subLine.Status == OrderSubLineStatus.NEEDS_REALLOCATION); return openPicks || shortedPicks; } #endregion } }