PIbd-21_Bakalskaya_E.D._Sus.../SushiBarBusinessLogic/OrderLogic.cs

211 lines
7.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using SushiBarContracts.BindingModel;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModel;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
using Microsoft.Extensions.Logging;
using SushiBarDataModels.Enums;
using SushiBarDataModels.Models;
using System.Xml.Linq;
namespace SushiBarBusinessLogic.BusinessLogic
{
public class OrderLogic : IOrderLogic
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly IShopStorage _shopStorage;
private readonly IShopLogic _shopLogic;
private readonly ISushiStorage _sushiStorage;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage,
IShopLogic shopLogic, IShopStorage shopStorage, ISushiStorage sushiStorage)
{
_logger = logger;
_orderStorage = orderStorage;
_shopStorage = shopStorage;
_shopLogic = shopLogic;
_sushiStorage = sushiStorage;
}
public List<OrderViewModel>? ReadList(OrderSearchModel? model)
{
_logger.LogInformation("ReadList. Id:{ Id}", model?.Id);
var list = model == null ? _orderStorage.GetFullList() : _orderStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool CreateOrder(OrderBindingModel model)
{
CheckModel(model);
if (model.Status != OrderStatus.Неизвестен) return false;
model.Status = OrderStatus.Принят;
if (_orderStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool TakeOrderInWork(OrderBindingModel model)
{
return ChangeStatus(model, OrderStatus.Выполняется);
}
public bool FinishOrder(OrderBindingModel model)
{
return ChangeStatus(model, OrderStatus.Готов);
}
public bool DeliveryOrder(OrderBindingModel model)
{
return ChangeStatus(model, OrderStatus.Выдан);
}
private bool ChangeStatus(OrderBindingModel model, OrderStatus orderStatus)
{
var order = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id });
if (order == null)
{
_logger.LogWarning("Change status operation failed. Order not found");
throw new ArgumentNullException("Не найден заказ... ");
}
if (order.Status + 1 != orderStatus)
{
_logger.LogWarning("Change status operation failed. Incorrect new status: {orderStatus}. Current status: {Status}",
orderStatus, order.Status);
throw new ArgumentException("Вы не можете перевести заказ в статус ", nameof(orderStatus));
}
if(order.Status == OrderStatus.Готов)
{
var sushi = _sushiStorage.GetElement(new SushiSearchModel { Id = order.SushiId });
if (sushi == null)
{
_logger.LogWarning("Status change error. Sushi not found");
throw new ArgumentNullException("Суши не нашлись такие... ");
}
if (!CheckSupply(sushi, order.Count))
{
_logger.LogWarning("Status change error. Shop is overflowed");
throw new ArgumentOutOfRangeException("Вы не можете выдать заказ, амбары переполнены ");
}
}
model.Status = orderStatus;
if (model.Status == OrderStatus.Готов)
{
model.DateImplement = DateTime.Now;
}
else
{
model.DateImplement = order.DateImplement;
}
if (_orderStorage.Update(model) == null)
{
_logger.LogWarning("Change status operation failed");
return false;
}
return true;
}
private void CheckModel(OrderBindingModel model, bool withParams = true)
{
if (model == null)
throw new ArgumentNullException(nameof(model));
if (!withParams) return;
if (model.SushiId <= 0)
throw new ArgumentNullException("Неверный идентификатор суши", nameof(model.SushiId));
if (model.Count <= 0)
throw new ArgumentNullException("Количество суш в заказе не может быть меньше нуля или равно нулю", nameof(model.Count));
if (model.Sum <= 0)
throw new ArgumentNullException("Стоимость заказа не может быть меньше нуля", nameof(model.Sum));
if (model.DateImplement.HasValue && model.DateImplement < model.DateCreate)
throw new ArithmeticException("Заказ должен быть выдан позже, чем был создан");
_logger.LogInformation("Sushi. SushiId:{SushiId}. Count:{ Count}. Sum:{ Sum}. Id: { Id}",
model.SushiId, model.Count, model.Sum, model.Id);
}
public bool CheckSupply(ISushiModel model, int count)
{
if (count <= 0)
{
_logger.LogWarning("Check supply operation error. Planes count < 0");
return false;
}
int sumCapacity = _shopStorage.GetFullList().Select(x => x.MaxCountSushis).Sum();
int sumCount = _shopStorage.GetFullList().Select(x => x.ShopSushis.Select(y => y.Value.Item2).Sum()).Sum();
int free = sumCapacity - sumCount;
if (free < count)
{
_logger.LogWarning("Check supply error. No place for new sushis");
return false;
}
foreach (var shop in _shopStorage.GetFullList())
{
free = shop.MaxCountSushis;
foreach (var sushi in shop.ShopSushis)
{
free -= sushi.Value.Item2;
}
if (free == 0)
{
continue;
}
if (free >= count)
{
if (_shopLogic.AddSushiInShop(new()
{
Id = shop.Id
}, model, count))
{
count = 0;
}
else
{
_logger.LogWarning("Supply error");
return false;
}
}
else
{
if (_shopLogic.AddSushiInShop(new()
{
Id = shop.Id
}, model, free))
{
count -= free;
}
else
{
_logger.LogWarning("Supply error");
return false;
}
}
if (count <= 0)
{
return true;
}
}
return false;
}
}
}