|
|
|
|
using Connected.Collections.Queues;
|
|
|
|
|
using Connected.Logistics.Types.WarehouseLocations;
|
|
|
|
|
using Connected.Middleware;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
|
|
|
|
|
namespace Connected.Logistics.Stock.Services;
|
|
|
|
|
internal sealed class StockAggregator : MiddlewareComponent, IQueueClient<PrimaryKeyQueueArgs<long>>
|
|
|
|
|
{
|
|
|
|
|
public StockAggregator(ILogger<StockAggregator> logger, IWarehouseLocationService locations, IStockService stock)
|
|
|
|
|
{
|
|
|
|
|
Logger = logger;
|
|
|
|
|
Locations = locations;
|
|
|
|
|
Stock = stock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ILogger<StockAggregator> Logger { get; }
|
|
|
|
|
private IWarehouseLocationService Locations { get; }
|
|
|
|
|
private IStockService Stock { get; }
|
|
|
|
|
|
|
|
|
|
public async Task Invoke(IQueueMessage message, PrimaryKeyQueueArgs<long> args)
|
|
|
|
|
{
|
|
|
|
|
if (await Stock.SelectItem(args.Id) is not IStockItem stock)
|
|
|
|
|
{
|
|
|
|
|
Logger.LogWarning("IStockItem not found {id}", args.Id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await Calculate(stock, stock.Location);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task Calculate(IStockItem stock, int locationId)
|
|
|
|
|
{
|
|
|
|
|
if (await Locations.Select(locationId) is not IWarehouseLocation location)
|
|
|
|
|
{
|
|
|
|
|
Logger.LogWarning("IWarehouseLocation not found {id}", locationId);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (location.Parent is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var parent = (int)location.Parent;
|
|
|
|
|
|
|
|
|
|
var sum = (await Stock.QueryItems(new QueryStockItemsArgs
|
|
|
|
|
{
|
|
|
|
|
Id = stock.Id,
|
|
|
|
|
Location = parent,
|
|
|
|
|
Serial = stock.Serial
|
|
|
|
|
})).Sum(f => f.Quantity);
|
|
|
|
|
|
|
|
|
|
await Stock.Update(new UpdateStockArgs
|
|
|
|
|
{
|
|
|
|
|
Location = parent,
|
|
|
|
|
Quantity = sum,
|
|
|
|
|
Serial = stock.Serial
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await Calculate(stock, parent);
|
|
|
|
|
}
|
|
|
|
|
}
|