214 lines
7.4 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ConfectioneryDataModels.Models;
using ConfectioneryContracts.BindingModels;
using ConfectioneryContracts.SearchModels;
using ConfectioneryContracts.ViewModels;
using ConfectioneryContracts.BusinessLogicsContracts;
using ConfectioneryContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
using ConfectioneryDataModels.Enums;
namespace ConfectioneryBusinessLogic.BusinessLogics
{
public class OrderLogic : IOrderLogic
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly IPastryStorage _pastryStorage;
private readonly IShopStorage _shopStorage;
private readonly IShopLogic _shopLogic;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, IPastryStorage pastryStorage,
IShopStorage shopStorage, IShopLogic shopLogic)
{
_logger = logger;
_orderStorage = orderStorage;
_pastryStorage = pastryStorage;
_shopStorage = shopStorage;
_shopLogic = shopLogic;
}
public bool CreateOrder(OrderBindingModel model)
{
CheckModel(model);
if (model.Status != OrderStatus.Неизвестен)
{
_logger.LogWarning("Invalid order status");
return false;
}
model.Status = OrderStatus.Принят;
if (_orderStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public List<OrderViewModel>? ReadList(OrderSearchModel? model)
{
_logger.LogInformation("ReadList. OrderId: {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 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 void CheckModel(OrderBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (model.PastryId <= 0)
{
throw new ArgumentNullException("Некорректный идентификатор выпечки", nameof(model.PastryId));
}
if (model.Count <= 0)
{
throw new ArgumentNullException("В заказе должно быть хотя бы одна выпечка", nameof(model.Count));
}
if (model.Sum <= 0)
{
throw new ArgumentNullException("Стоимость заказа должна быть больше 0", nameof(model.Sum));
}
_logger.LogInformation("Order. Id: {Id}. Sum: {Sum}. PastryId: {PastryId}. PastryCount: {Count}", model.Id, model.Sum,
model.PastryId, model.Count);
}
private bool ChangeStatus(OrderBindingModel model, OrderStatus newStatus)
{
CheckModel(model, false);
var order = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id });
if (order == null)
{
_logger.LogWarning("Change status operation failed. Order not found");
return false;
}
if (order.Status + 1 != newStatus)
{
_logger.LogWarning("Change status operation failed. Incorrect new status: {newStatus}. Current status: {currStatus}",
newStatus, order.Status);
return false;
}
if (newStatus == OrderStatus.Выдан)
{
var pastry = _pastryStorage.GetElement(new PastrySearchModel() { Id = order.PastryId });
if (pastry == null)
{
_logger.LogWarning("Change status operation failed. Pastry not found");
return false;
}
if (!DeliverPastries(pastry, order.Count))
{
_logger.LogWarning("Change status operation failed. Pastries delivery operation failed");
return false;
}
}
model.Status = newStatus;
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 bool DeliverPastries(IPastryModel pastry, int count)
{
if (count <= 0)
{
_logger.LogWarning("Pastries delivery operation failed. Pastry count <= 0");
return false;
}
var shopList = _shopStorage.GetFullList();
int shopsCapacity = shopList.Sum(x => x.PastriesMaximum);
int currentPastrys = shopList.Select(x => x.ShopPastries.Sum(y => y.Value.Item2)).Sum();
int freePlaces = shopsCapacity - currentPastrys;
if (freePlaces < count)
{
_logger.LogWarning("Pastries delivery operation failed. No space for new pastries");
return false;
}
foreach (var shop in shopList)
{
freePlaces = shop.PastriesMaximum - shop.ShopPastries.Sum(x => x.Value.Item2);
if (freePlaces == 0)
{
continue;
}
if (freePlaces >= count)
{
if (_shopLogic.Supply(new() { Id = shop.Id }, pastry, count))
{
count = 0;
}
else
{
_logger.LogWarning("Pastries delivery operation failed");
return false;
}
}
else
{
if (_shopLogic.Supply(new() { Id = shop.Id }, pastry, freePlaces))
{
count -= freePlaces;
}
else
{
_logger.LogWarning("Pastries delivery operation failed");
return false;
}
}
if (count == 0)
{
return true;
}
}
return false;
}
}
}