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 { 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 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 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 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; } } }