Files
IHK-Projekt/03_Realisierung/Code Snippets/HostBooking/InterfaceWcsWms/MessageImplementation/AcknowledgeTransportCompleted.cs

111 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Gebhardt.Shared;
using Gebhardt.StoreWare.Wcs.Common.Application.LeHandling.Interfaces;
using Gebhardt.StoreWare.Wcs.Common.Application.LoopStrategy;
using Gebhardt.StoreWare.Wcs.Common.Application.StorageStrategies.Interfaces;
using Gebhardt.StoreWare.Wcs.Common.Application.TransportHandling.Interfaces;
using Gebhardt.StoreWare.Wcs.Common.DbAccess;
using Gebhardt.StoreWare.Wcs.Common.DbAccess.Model;
using Gebhardt.StoreWare.Wcs.Common.DbAccess.Model.Enums;
using Gebhardt.StoreWare.Wcs.Common.DbAccess.Queries;
using Gebhardt.StoreWare.Wcs.HostBooking.InterfaceWcsWms.Interfaces;
using Gebhardt.StoreWare.WcsWms.InterfaceWcsWms.Interfaces;
using static Gebhardt.StoreWare.Wcs.Common.Constants;
namespace Gebhardt.StoreWare.Wcs.HostBooking.InterfaceWcsWms.MessageImplementation
{
public class AcknowledgeTransportCompletedHandler : IHandleRecord<IAcknowledgeTransportCompleted>
{
private readonly IWcsDbContextFactory _dbContextFactory;
private readonly ITransportOrderService _transportOrderService;
private readonly ILeService _leService;
private readonly IDestinationService _destinationService;
private readonly ILoopSelectionService _loopSelectionService;
public AcknowledgeTransportCompletedHandler(IWcsDbContextFactory dbContextFactory, ITransportOrderService transportOrderService, ILeService leService, IDestinationService destinationService, ILoopSelectionService loopSelectionService)
{
_dbContextFactory = dbContextFactory;
_transportOrderService = transportOrderService;
_destinationService = destinationService;
_leService = leService;
_loopSelectionService = loopSelectionService;
}
public bool Handle(IAcknowledgeTransportCompleted message)
{
using (IWcsDbContext db = _dbContextFactory.GetDbContext())
{
List<int> ordersHostIds = db.OrdersHost.Where(o => o.IdOrderWms == message.IdOrderWms).Select(o => o.Id).ToList();
if (ordersHostIds.Any())
{
if (ordersHostIds.Count() > 1)
{
throw new InvalidOperationException($"Multiple OrdersHost found for same WMS id {message.IdOrderWms}");
}
_transportOrderService.FinishOrdersHost(ordersHostIds.Single(), "AcknowledgeTransportCompleted");
Log.Write(LogLevel.Info, $"{nameof(OrdersHost)} with Id {ordersHostIds.Single()} and WMS id {message.IdOrderWms} finished.");
//Other open OH for HU that must be cancelled?
List<OrdersHost> others = db.OrdersHost
.OpenByLeNo(message.LeNo).Where(oh => oh.Type == TransportOrderType.Transport).ToList();
foreach (var other in others)
{
_transportOrderService.CancelOrdersHost(other.Id, $"New destination {message.Destination}", $"OrderHost {ordersHostIds.Single()} was finished");
}
}
else
{
Log.Write(LogLevel.Error, $"{nameof(AcknowledgeTransportCompletedHandler)}: Cannot find OH for WMS id {message.IdOrderWms}");
}
db.SaveChanges();
}
// New DB Context since OrdersConveyorService changes data that we otherwise wouldn't notice
using (IWcsDbContext db = _dbContextFactory.GetDbContext())
{
// le empty?
Le le = db.Le.ByLeNo(message.LeNo);
// If there is no other order for this le, send it back to the storage
if (!db.OrdersHost.OpenByLeNo(message.LeNo).Any() && le != null)
{
DestinationProperty workStation = db.DestinationProperty.FirstOrDefault(d => d.Name == message.Destination && d.Property == nameof(IDestinationProperties.Level));
var workStationDest = _destinationService.Get(message.Destination);
List<VLoopOverview> availableLoops = _loopSelectionService.GetSuitableStorageLoops(message.LeNo);
// Choose a desired destination based on which is the closest to the workstation
string destination = MfcAllDestinations.StorageLoop2;
if (workStationDest != null)
{
destination = workStationDest.StorageArea == MfcAllDestinations.AKL02 ? MfcAllDestinationsOldSystem.LOOP3 : workStationDest.Level == ConveyorLevel.EtraBox.ToString() ? MfcAllDestinations.StorageLoop1 : MfcAllDestinations.StorageLoop2;
// If only one of the loops is available, choose this, no matter where the LE is located
if (availableLoops.Count == 1)
{
destination = availableLoops.First().PlcName;
}
else
{
// Prefer the destination closest connected to the pick station but select the other if this is full
string fallbackDestination = workStationDest.StorageArea == MfcAllDestinations.AKL02 ? MfcAllDestinationsOldSystem.LOOP3 : workStationDest.Level == ConveyorLevel.EtraBox.ToString() ? MfcAllDestinations.StorageLoop1 : MfcAllDestinations.StorageLoop2;
if (!_loopSelectionService.hasEnoughSpace(destination) && _loopSelectionService.hasEnoughSpace(fallbackDestination))
{
destination = fallbackDestination;
}
}
}
string source = message.Destination == MfcAllDestinationsOldSystem.TOPUP ? MfcAllDestinationsOldSystem.TOPUP : message.Source ?? "?";
int ordersHostId = _leService.CreateTransport(message.LeNo, source, destination);
Log.Write(LogLevel.Info, $"Loop selection in acknowledge transport handler for {le.LeNo}, set to {destination}");
LoopStrategy.ReserveForLoop(le.LeNo, ordersHostId, availableLoops.FirstOrDefault(l => l.PlcName == destination)?.Name);
}
}
return true;
}
}
}