2024-05-21 21:24:17 +04:00

214 lines
6.8 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 TravelCompanyContracts.BindingModels;
using TravelCompanyContracts.BusinessLogicsContracts;
using TravelCompanyContracts.SearchModels;
using TravelCompanyContracts.StoragesContracts;
using TravelCompanyContracts.ViewModels;
using TravelCompanyDataModels.Enums;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TravelCompanyContracts.BusinessLogicContracts;
using TravelCompanyDataModels.Models;
namespace TravelCompanyBusinessLogic.BusinessLogic
{
public class OrderLogic : IOrderLogic
{
//Класс с логикой для заказов будет отвечать за получение списка заказов,
//создания заказа и смены его статусов. Следует учитывать, что у заказа можно
//менять статус на новый, если его текущий статус предшествует новому
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly ITravelStorage _travelStorage;
private readonly IShopStorage _shopStorage;
private readonly IShopLogic _shopLogic;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, ITravelStorage travelStorage, IShopStorage shopStorage, IShopLogic shopLogic)
{
_logger = logger;
_orderStorage = orderStorage;
_travelStorage = travelStorage;
_shopStorage = shopStorage;
_shopLogic = shopLogic;
}
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 CreateOrder(OrderBindingModel model)
{
CheckModel(model);
if (model.Status != OrderStatus.Неизвестен)
return false;
model.Status = OrderStatus.Принят;
if (_orderStorage.Insert(model) == null)
{
model.Status = OrderStatus.Неизвестен;
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool TakeOrderInWork(OrderBindingModel model)
{
return ToNextStatus(model, OrderStatus.Выполняется);
}
public bool FinishOrder(OrderBindingModel model)
{
return ToNextStatus(model, OrderStatus.Готов);
}
public bool DeliveryOrder(OrderBindingModel model)
{
return ToNextStatus(model, OrderStatus.Выдан);
}
public bool ToNextStatus(OrderBindingModel model, OrderStatus orderStatus)
{
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 != orderStatus)
{
_logger.LogWarning("Change status operation failed. Incorrect new status: {orderStatus}. Current status: {currStatus}",
orderStatus, order.Status);
return false;
}
if (orderStatus == OrderStatus.Выдан)
{
var iceCream = _travelStorage.GetElement(new TravelSearchModel() { Id = order.TravelId });
if (iceCream == null)
{
_logger.LogWarning("Change status operation failed. Travel not found");
return false;
}
if (!DeliverTravels(iceCream, order.Count))
{
_logger.LogWarning("Change status operation failed. Travels delivery operation failed");
return false;
}
}
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 bool DeliverTravels(ITravelModel travel, int count)
{
if (count <= 0)
{
_logger.LogWarning("Travels delivery operation failed. Travel count <= 0");
return false;
}
var shopList = _shopStorage.GetFullList();
int shopsCapacity = shopList.Sum(x => x.TravelsMaximum);
int currentTravels = shopList.Select(x => x.ShopTravels.Sum(y => y.Value.Item2)).Sum();
int freePlaces = shopsCapacity - currentTravels;
if (freePlaces < count)
{
_logger.LogWarning("Travels delivery operation failed. No space for new travels");
return false;
}
foreach (var shop in shopList)
{
freePlaces = shop.TravelsMaximum - shop.ShopTravels.Sum(x => x.Value.Item2);
if (freePlaces == 0)
{
continue;
}
if (freePlaces >= count)
{
if (_shopLogic.MakeDelivery(new() { Id = shop.Id }, travel, count))
{
count = 0;
}
else
{
_logger.LogWarning("Travels delivery operation failed");
return false;
}
}
else
{
if (_shopLogic.MakeDelivery(new() { Id = shop.Id }, travel, freePlaces))
{
count -= freePlaces;
}
else
{
_logger.LogWarning("Travels delivery operation failed");
return false;
}
}
if (count == 0)
{
return true;
}
}
return false;
}
private void CheckModel(OrderBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (model.Count <= 0)
{
throw new ArgumentNullException("Количество изделий должно быть больше 0", nameof(model.Count));
}
if (model.Sum <= 0)
{
throw new ArgumentNullException("Цена заказа должна быть больше 0", nameof(model.Sum));
}
if (model.DateImplement.HasValue && model.DateImplement < model.DateCreate)
{
throw new ArithmeticException($"Дата выдачи заказа {model.DateImplement} должна быть позже даты его создания {model.DateCreate}");
}
_logger.LogInformation("Travel. TravelId:{TravelId}.Count:{Count}.Sum:{Sum}Id:{Id}", model.TravelId, model.Count, model.Sum, model.Id);
}
}
}