219 lines
8.2 KiB
C#
219 lines
8.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using AutoMapper.Configuration.Conventions;
|
|
using Gebhardt.Shared;
|
|
using Gebhardt.StoreWare.Wcs.Common.Application.TransportHandling.Interfaces;
|
|
using Gebhardt.StoreWare.Wcs.Common.DbAccess;
|
|
using Gebhardt.StoreWare.Wcs.Common.DbAccess.Factories;
|
|
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 Microsoft.EntityFrameworkCore;
|
|
using static Gebhardt.StoreWare.Wcs.Common.ConstantsCommon;
|
|
|
|
namespace Gebhardt.StoreWare.Wcs.HostBooking.InterfaceWcsWms.MessageImplementation
|
|
{
|
|
public class TransportOrderHandler : IHandleRecord<ITransportOrder>
|
|
{
|
|
private readonly IDestinationService _destinationService;
|
|
private readonly ITransportOrderService _transportOrderService;
|
|
private ITransportOrder _transportOrder;
|
|
private readonly LeFactory _leFactory = LeFactory.GetInstance();
|
|
private readonly List<string> _allStorageAndEmptyLeBufferDestinations;
|
|
|
|
public TransportOrderHandler(IDestinationService destinationService, ITransportOrderService transportOrderService)
|
|
{
|
|
_destinationService = destinationService;
|
|
_transportOrderService = transportOrderService;
|
|
_allStorageAndEmptyLeBufferDestinations = _destinationService.Where(d => d.IsStorage || d.IsStorageArea || d.BuffersEmptyLe).Select(d => d.Name).ToList();
|
|
}
|
|
|
|
public bool Handle(ITransportOrder message)
|
|
{
|
|
_transportOrder = message;
|
|
|
|
|
|
using WcsDbContext db = new();
|
|
string leNo = _transportOrder.LeNo;
|
|
Le le = db.Le.ByLeNo(leNo);
|
|
if (le == null)
|
|
{
|
|
Log.Write(LogLevel.Info, $"HU {leNo} is unknown. Create HU...");
|
|
LeTypeName type = LeType.GetLeTypeFromLeNo(leNo);
|
|
le = db.Add(_leFactory.RegularLe(leNo, type, preferredStorageArea: message.StorageArea)).Entity;
|
|
db.SaveChanges();
|
|
}
|
|
CheckTransportOrder();
|
|
|
|
IDestinationProperties destinationProperties = _destinationService.Get(_transportOrder.Destination);
|
|
if (destinationProperties == null)
|
|
{
|
|
throw new TransportDestinationInvalidException($"Unknown destination in {message}");
|
|
}
|
|
|
|
if (destinationProperties.IsStorage && !destinationProperties.IsSequencer && le.IsInStorage())
|
|
{
|
|
throw new LeAlreadyInStorageException($"{le} is in storage.");
|
|
}
|
|
|
|
CheckLeIsReachable(le);
|
|
//CheckActiveOrdersForLe();
|
|
if (_transportOrder.MovementType == TransportOrderType.Storage.ToString())
|
|
{
|
|
le.SetStatus(LeStatus.Created);
|
|
}
|
|
else
|
|
{
|
|
SetTransportStatus(le);
|
|
}
|
|
SetAbcArea(le);
|
|
// Le is in the old system, but no movement file has been created for it.
|
|
bool leNeedsMomFile = le.IsHuInOldSystem == true && le.L8OrderCreated == null;
|
|
CreateTransportOrder(leNeedsMomFile);
|
|
db.SaveChanges();
|
|
return true;
|
|
}
|
|
|
|
private void CheckTransportOrder()
|
|
{
|
|
if (_transportOrder.LeNo == null)
|
|
{
|
|
throw new LeNoMissingException("The HU number is is missing.");
|
|
}
|
|
if (_destinationService.Get(_transportOrder.Destination) == null)
|
|
{
|
|
throw new TransportDestinationInvalidException($"Destination {_transportOrder.Destination} is unknown. Order is confirmed negatively.");
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(_transportOrder.MovementType))
|
|
{
|
|
throw new FromWmsException($"Field {nameof(_transportOrder.MovementType)} is not set or not known.");
|
|
}
|
|
// TODO: Solche Prüfungen sollten in einem Plausiblitätsmodul für LE-Nummern erfolgen, damit sie leicht kundenspezifisch angepasst werden können
|
|
if (_transportOrder.LeNo.Length < ConstantsLE.LengthBarcodeWithType)
|
|
{
|
|
throw new LeNoTooShortException($"HU number '{_transportOrder.LeNo}' is too short. Should be {ConstantsLE.LengthBarcodeWithType} digits");
|
|
}
|
|
|
|
if (_transportOrder.LeNo.Length > ConstantsLE.LengthBarcodeWithType)
|
|
{
|
|
throw new LeNoTooLongException($"HU number '{_transportOrder.LeNo}' is too long. Should be {ConstantsLE.LengthBarcodeWithType} digits");
|
|
}
|
|
}
|
|
|
|
private void SetAbcArea(Le le)
|
|
{
|
|
//le.AbcArea = _transportOrder.AbcArea;
|
|
}
|
|
|
|
private void CreateTransportOrder(bool oldSystemBoxRequiringMomFile = false)
|
|
{
|
|
using WcsDbContext db = new();
|
|
string source = _transportOrder.Source;
|
|
OrderTypeWms? typeWmsForOrderHost;
|
|
if (!Enum.TryParse(_transportOrder.MovementType, true, out OrderTypeWms typeWms))
|
|
{
|
|
Log.Write(LogLevel.Error, $"could not parse '{_transportOrder.MovementType}'");
|
|
typeWmsForOrderHost = null;
|
|
}
|
|
else
|
|
{
|
|
typeWmsForOrderHost = typeWms;
|
|
}
|
|
|
|
OrdersHost ordersHost = OrdersHostFactory.GetInstance().InitialForLe(_transportOrder.LeNo, TransportOrderType.TransportHost, source == TestToolConstants.TestToolSource ? Common.Constants.MfcAllDestinations.AKL01 : source,
|
|
_transportOrder.Destination, idOrderWms: _transportOrder.IdOrderWms, idOrderWmsHead: _transportOrder.IdOrderWmsHead, idOrderWmsPos: _transportOrder.IdOrderWmsPos, typeWms: typeWmsForOrderHost);
|
|
|
|
IDestinationProperties destination = _destinationService.Get(_transportOrder.Destination);
|
|
if (destination != null && destination.IsAfterSequencer)
|
|
{
|
|
ordersHost.Destination = destination.ConnectedSequencer;
|
|
ordersHost.HostDestination = _transportOrder.Destination;
|
|
}
|
|
|
|
// TODO 15585
|
|
ordersHost.SequenceWms = _transportOrder.Sequence;
|
|
ordersHost.IsDirectPicking = _transportOrder.IsDirectPicking;
|
|
ordersHost.PriorityDate = _transportOrder.Priority;
|
|
db.Add(ordersHost);
|
|
|
|
if (source == TestToolConstants.TestToolSource)
|
|
{
|
|
ordersHost.Priority = TestToolConstants.TestToolPriority;
|
|
}
|
|
if (oldSystemBoxRequiringMomFile)
|
|
{
|
|
try
|
|
{
|
|
CreateMomFile(ordersHost.LeNo);
|
|
ordersHost.Le.L8OrderCreated = DateTime.Now;
|
|
Log.Write(LogLevel.Info, $"Mom file created and saved for HU {ordersHost.LeNo}.");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Write(LogLevel.Error, $"Error creating mom file for HU {ordersHost.LeNo}, Exception: {e}");
|
|
}
|
|
}
|
|
db.SaveChanges();
|
|
}
|
|
|
|
private void CreateMomFile(string huNumber)
|
|
{
|
|
// Hardcoded since very temporary
|
|
string filePath = $@"\\10.101.71.32\\InterfaceFiles\\ProdGB\\OrdersGB\\{huNumber}_{DateTime.Now:yyyyMMddHHmmss00}.mom";
|
|
File.WriteAllText(filePath, huNumber);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A Handling Unit that rests at a workplace is set to "On conveyer" when it receives a transport order
|
|
/// </summary>
|
|
private void SetTransportStatus(Le le)
|
|
{
|
|
if (le.Status != LeStatus.InStorage)
|
|
{
|
|
le.SetStatus(LeStatus.OnConveyor, le.LastWhere);
|
|
}
|
|
}
|
|
|
|
private void CheckLeIsReachable(Le le)
|
|
{
|
|
if (le.IsInStorage())
|
|
{
|
|
bool? storageDeviceHasCriticalFault = new WcsDbContext().AisleForLe.GetAisle(le.AisleName, le.StorageArea)?.StorageDevices.Any(s => s.HasCriticalFault);
|
|
if (storageDeviceHasCriticalFault == null)
|
|
{
|
|
Log.Write(LogLevel.Error, $"Unknown aisle {le.AisleName} LE: {le.LeNo}.");
|
|
}
|
|
else if (storageDeviceHasCriticalFault.Value)
|
|
{
|
|
// This throw causes, that the TransportOrder in FromWms will be frozen in status 'Failed'.
|
|
// Maybe the order gets then forgotten.
|
|
Log.Write(LogLevel.Error, $"Order for Le {le.LeNo} will be delayed: {le.AisleName} has a critical fault.");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckActiveOrdersForLe()
|
|
{
|
|
//is the an order to a storage location or EMB?
|
|
if (_allStorageAndEmptyLeBufferDestinations.Contains(_transportOrder.Destination))
|
|
{
|
|
using WcsDbContext db = new();
|
|
OrdersHost ordersHost = db.OrdersHost.AsNoTracking().
|
|
ByLeNo(_transportOrder.LeNo).
|
|
Open().
|
|
ByDestination(_allStorageAndEmptyLeBufferDestinations).FirstOrDefault();
|
|
if (ordersHost != null)
|
|
{
|
|
// Replace all open orders to storage or EMB with the new destination
|
|
_transportOrderService.CancelOrdersHost(ordersHost.Id, $"OH on the way to storage or EMB was ordered to a commisioning destination. This order is cancelled and replaced by this new host order with IdOrderWms {_transportOrder.IdOrderWms}.");
|
|
Log.Write(LogLevel.Info, $"HU {ordersHost.LeNo} with destination EMB or storage was ordered to a commisioning destination. The previous OH with IdOrderWms {ordersHost.IdOrderWms} was cancelled");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |