d
dunknown
csharp
3 years ago
15 kB
10
Indexable
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
}
}
Editor is loading...