From 20fd6e399e99b9919180458d1e02349119587d33 Mon Sep 17 00:00:00 2001 From: xom9k Date: Sun, 20 Apr 2025 17:33:35 +0400 Subject: [PATCH] =?UTF-8?q?=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D1=83=D1=81=D0=BB=D0=BE=D0=B6=D0=BD=D0=B5=D0=BD=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SaleBusinessLogicContract.cs | 31 ++++++++++ .../SuppliesBusinessLogicContract.cs | 24 ++++++-- .../ISaleBusinessLogicContract.cs | 2 + .../ISuppliesBusinessLogicContract.cs | 1 + .../ISuppliesStorageContract.cs | 2 +- .../Implementations/AgencyStorageContract.cs | 46 +++++++++------ .../SuppliesStorageContract.cs | 9 ++- .../SaleBusinessLogicContractTests.cs | 33 +++++++++++ .../SuppliesBusinessLogicContractTests.cs | 58 ++++++++++++++++--- .../PostStorageContractTests.cs | 1 + 10 files changed, 174 insertions(+), 33 deletions(-) diff --git a/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SaleBusinessLogicContract.cs b/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SaleBusinessLogicContract.cs index 55e31d2..6a8524d 100644 --- a/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SaleBusinessLogicContract.cs +++ b/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SaleBusinessLogicContract.cs @@ -122,4 +122,35 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract, } _saleStorageContract.DelElement(id); } + //третье требование + public double CalculateSaleRevenue(DateTime fromDate, DateTime toDate) + { + _logger.LogInformation("CalculateSaleRevenue params: {fromDate}, {toDate}", fromDate, toDate); + if (fromDate.IsDateNotOlder(toDate)) + { + throw new IncorrectDatesException(fromDate, toDate); + } + var sales = GetAllSalesByPeriod(fromDate, toDate); + if (sales == null || !sales.Any()) + { + return 0; + } + + double totalRevenue = 0; + object lockObj = new object(); + + Parallel.ForEach(sales, sale => + { + if (sale.IsCancel) + return; + + lock (lockObj) + { + totalRevenue += sale.Sum; + } + }); + + _logger.LogInformation("Total revenue calculated: {totalRevenue}", totalRevenue); + return totalRevenue; + } } diff --git a/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SuppliesBusinessLogicContract.cs b/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SuppliesBusinessLogicContract.cs index 0f8ea0c..0315905 100644 --- a/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SuppliesBusinessLogicContract.cs +++ b/MagicCarpetProject/MagicCarpetBusinessLogic/Implementations/SuppliesBusinessLogicContract.cs @@ -23,8 +23,6 @@ public class SuppliesBusinessLogicContract(ISuppliesStorageContract suppliesStor { _logger.LogInformation("GetAllComponents"); return _suppliesStorageContract.GetList() ?? throw new NullListException(); - - return []; } public SuppliesDataModel GetComponentByData(string data) @@ -39,8 +37,6 @@ public class SuppliesBusinessLogicContract(ISuppliesStorageContract suppliesStor throw new ElementNotFoundException(data); } return _suppliesStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data); - - return new("", TourType.None, DateTime.UtcNow, 0, []); } public void InsertComponent(SuppliesDataModel suppliesDataModel) @@ -58,4 +54,24 @@ public class SuppliesBusinessLogicContract(ISuppliesStorageContract suppliesStor suppliesDataModel.Validate(); _suppliesStorageContract.UpdElement(suppliesDataModel); } + //первое требование + public int CalculateTourSupplies(DateTime? startDate, DateTime? endDate) + { + var supplies = _suppliesStorageContract.GetList(startDate, endDate); + if (supplies == null || supplies.Count == 0) + { + return 0; + } + int count = 0; + var lockObject = new object(); + Parallel.ForEach(supplies, supply => + { + int supplyCount = supply.Tours.Sum(component => component.Count); + lock (lockObject) + { + count += supplyCount; + } + }); + return count; + } } diff --git a/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISaleBusinessLogicContract.cs b/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISaleBusinessLogicContract.cs index 934d4fa..60ea15c 100644 --- a/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISaleBusinessLogicContract.cs +++ b/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISaleBusinessLogicContract.cs @@ -22,4 +22,6 @@ public interface ISaleBusinessLogicContract void InsertSale(SaleDataModel saleDataModel); void CancelSale(string id); + + public double CalculateSaleRevenue(DateTime fromDate, DateTime toDate); } diff --git a/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISuppliesBusinessLogicContract.cs b/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISuppliesBusinessLogicContract.cs index d5c0144..cc2f48f 100644 --- a/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISuppliesBusinessLogicContract.cs +++ b/MagicCarpetProject/MagicCarpetContracts/BusinessLogicContracts/ISuppliesBusinessLogicContract.cs @@ -13,4 +13,5 @@ public interface ISuppliesBusinessLogicContract SuppliesDataModel GetComponentByData(string data); void InsertComponent(SuppliesDataModel componentDataModel); void UpdateComponent(SuppliesDataModel componentDataModel); + int CalculateTourSupplies(DateTime? startDate, DateTime? endDate); } diff --git a/MagicCarpetProject/MagicCarpetContracts/StoragesContracts/ISuppliesStorageContract.cs b/MagicCarpetProject/MagicCarpetContracts/StoragesContracts/ISuppliesStorageContract.cs index 84ebf92..24a9031 100644 --- a/MagicCarpetProject/MagicCarpetContracts/StoragesContracts/ISuppliesStorageContract.cs +++ b/MagicCarpetProject/MagicCarpetContracts/StoragesContracts/ISuppliesStorageContract.cs @@ -9,7 +9,7 @@ namespace MagicCarpetContracts.StoragesContracts; public interface ISuppliesStorageContract { - List GetList(DateTime? startDate = null); + List GetList(DateTime? startDate = null, DateTime? endDate = null); SuppliesDataModel GetElementById(string id); void AddElement(SuppliesDataModel suppliesDataModel); void UpdElement(SuppliesDataModel suppliesDataModel); diff --git a/MagicCarpetProject/MagicCarpetDatabase/Implementations/AgencyStorageContract.cs b/MagicCarpetProject/MagicCarpetDatabase/Implementations/AgencyStorageContract.cs index fca854e..cc893a8 100644 --- a/MagicCarpetProject/MagicCarpetDatabase/Implementations/AgencyStorageContract.cs +++ b/MagicCarpetProject/MagicCarpetDatabase/Implementations/AgencyStorageContract.cs @@ -3,6 +3,7 @@ using MagicCarpetContracts.DataModels; using MagicCarpetContracts.Exceptions; using MagicCarpetContracts.StoragesContracts; using MagicCarpetDatabase.Models; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -106,30 +107,37 @@ public class AgencyStorageContract : IAgencyStorageContract throw new StorageException(ex); } } - + //второе требование public bool CheckComponents(SaleDataModel saleDataModel) { using (var transaction = _dbContext.Database.BeginTransaction()) { - foreach (SaleTourDataModel sale_tour in saleDataModel.Tours) - { - var tour = _dbContext.Tours.FirstOrDefault(x => x.Id == sale_tour.TourId); - var agency = _dbContext.Agencies.FirstOrDefault(x => x.TourType == tour.TourType && x.Count >= sale_tour.Count); + var componentTasks = saleDataModel.Tours + .AsParallel() + .Select(async saleComponent => + { + var component = await _dbContext.Tours.FirstOrDefaultAsync(x => x.Id == saleComponent.TourId); + var agency = await _dbContext.Agencies.FirstOrDefaultAsync(x => x.TourType == component.TourType && x.Count >= saleComponent.Count); + if (agency == null) + { + transaction.Rollback(); + return false; + } + if (agency.Count - saleComponent.Count == 0) + { + DelElement(agency.Id); + } + else + { + agency.Count -= saleComponent.Count; + _dbContext.Agencies.Update(agency); + } - if (agency == null) - { - transaction.Rollback(); - return false; - } - if (agency.Count - sale_tour.Count == 0) - { - DelElement(agency.Id); - } - else - { - agency.Count -= sale_tour.Count; - } - } + return true; + }) + .ToList(); + + Task.WaitAll(componentTasks.ToArray()); transaction.Commit(); _dbContext.SaveChanges(); return true; diff --git a/MagicCarpetProject/MagicCarpetDatabase/Implementations/SuppliesStorageContract.cs b/MagicCarpetProject/MagicCarpetDatabase/Implementations/SuppliesStorageContract.cs index cffeb4d..b09c1ad 100644 --- a/MagicCarpetProject/MagicCarpetDatabase/Implementations/SuppliesStorageContract.cs +++ b/MagicCarpetProject/MagicCarpetDatabase/Implementations/SuppliesStorageContract.cs @@ -36,11 +36,16 @@ public class SuppliesStorageContract : ISuppliesStorageContract _mapper = new Mapper(config); } - public List GetList(DateTime? startDate = null) + public List GetList(DateTime? startDate = null, DateTime? endDate = null) { try { - return [.. _dbContext.Supplieses.Select(x => _mapper.Map(x))]; + var query = _dbContext.Supplieses.AsQueryable(); + if (startDate is not null && endDate is not null) + { + query = query.Where(x => x.ProductuionDate >= startDate && x.ProductuionDate < endDate); + } + return [.. query.Select(x => _mapper.Map(x))]; } catch (Exception ex) { diff --git a/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SaleBusinessLogicContractTests.cs b/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SaleBusinessLogicContractTests.cs index 0c0cce9..37db1e2 100644 --- a/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SaleBusinessLogicContractTests.cs +++ b/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SaleBusinessLogicContractTests.cs @@ -523,4 +523,37 @@ internal class SaleBusinessLogicContractTests Assert.That(() => _saleBusinessLogicContract.CancelSale(Guid.NewGuid().ToString()), Throws.TypeOf()); _saleStorageContract.Verify(x => x.DelElement(It.IsAny()), Times.Once); } + + [Test] + public void CalculateSaleRevenue_ReturnsCorrectSum_Test() + { + // Arrange + var fromDate = DateTime.Now.AddDays(-10); + var toDate = DateTime.Now; + var listOriginal = new List() + { + new(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), null, DiscountType.None, false, + [new SaleTourDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 5, 1.2)]), + new(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), null, DiscountType.None, false, []), + new(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), null, DiscountType.None, false, []), + }; + _saleStorageContract.Setup(x => x.GetList(fromDate, toDate, It.IsAny(), It.IsAny(),It.IsAny())).Returns(listOriginal); + // Act + var result = _saleBusinessLogicContract.CalculateSaleRevenue(fromDate, toDate); + // Assert + Assert.That(result, Is.EqualTo(6.0)); + } + + [Test] + public void CalculateSaleRevenue_NoSales_ReturnsZero() + { + // Arrange + var fromDate = DateTime.Now.AddDays(-10); + var toDate = DateTime.Now; + _saleStorageContract.Setup(x => x.GetList(fromDate, toDate, null, null, null)).Returns([]); + // Act + double revenue = _saleBusinessLogicContract.CalculateSaleRevenue(fromDate, toDate); + // Assert + Assert.That(revenue, Is.EqualTo(0)); + } } diff --git a/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SuppliesBusinessLogicContractTests.cs b/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SuppliesBusinessLogicContractTests.cs index 130ed95..1de7889 100644 --- a/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SuppliesBusinessLogicContractTests.cs +++ b/MagicCarpetProject/MagicCarpetTests/BusinessLogicContractsTests/SuppliesBusinessLogicContractTests.cs @@ -42,7 +42,7 @@ internal class SuppliesBusinessLogicContractTests new(Guid.NewGuid().ToString(), TourType.Beach, DateTime.Now, 1, []), new(Guid.NewGuid().ToString(), TourType.Beach, DateTime.Now, 1, []), }; - _suppliesStorageContract.Setup(x => x.GetList(It.IsAny())).Returns(listOriginal); + _suppliesStorageContract.Setup(x => x.GetList(It.IsAny(), It.IsAny())).Returns(listOriginal); // Act var list = _suppliesBusinessLogicContract.GetAllComponents(); // Assert @@ -54,33 +54,33 @@ internal class SuppliesBusinessLogicContractTests public void GetAllSupplies_ReturnEmptyList_Test() { // Arrange - _suppliesStorageContract.Setup(x => x.GetList(It.IsAny())).Returns([]); + _suppliesStorageContract.Setup(x => x.GetList(It.IsAny(), It.IsAny())).Returns([]); // Act var list = _suppliesBusinessLogicContract.GetAllComponents(); // Assert Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(0)); - _suppliesStorageContract.Verify(x => x.GetList(It.IsAny()), Times.Once); + _suppliesStorageContract.Verify(x => x.GetList(It.IsAny(), It.IsAny()), Times.Once); } [Test] public void GetAllSupplies_ReturnNull_ThrowException_Test() { // Arrange - _suppliesStorageContract.Setup(x => x.GetList(It.IsAny())).Returns((List)null); + _suppliesStorageContract.Setup(x => x.GetList(It.IsAny(), It.IsAny())).Returns((List)null); // Act & Assert Assert.That(() => _suppliesBusinessLogicContract.GetAllComponents(), Throws.TypeOf()); - _suppliesStorageContract.Verify(x => x.GetList(It.IsAny()), Times.Once); + _suppliesStorageContract.Verify(x => x.GetList(It.IsAny(), It.IsAny()), Times.Once); } [Test] public void GetAllSupplies_StorageThrowError_ThrowException_Test() { // Arrange - _suppliesStorageContract.Setup(x => x.GetList(It.IsAny())).Throws(new StorageException(new InvalidOperationException())); + _suppliesStorageContract.Setup(x => x.GetList(It.IsAny(), It.IsAny())).Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _suppliesBusinessLogicContract.GetAllComponents(), Throws.TypeOf()); - _suppliesStorageContract.Verify(x => x.GetList(It.IsAny()), Times.Once); + _suppliesStorageContract.Verify(x => x.GetList(It.IsAny(), It.IsAny()), Times.Once); } [Test] @@ -239,4 +239,48 @@ internal class SuppliesBusinessLogicContractTests [new TourSuppliesDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 5)])), Throws.TypeOf()); _suppliesStorageContract.Verify(x => x.UpdElement(It.IsAny()), Times.Once); } + + [Test] + public void CalculateTour_ReturnInt_Test() + { + // Arrange + string id = Guid.NewGuid().ToString(); + var listOriginal = new List() + { + new(id, TourType.Beach, DateTime.UtcNow, 1, new List { new TourSuppliesDataModel(id, Guid.NewGuid().ToString(), 5), new TourSuppliesDataModel(id, Guid.NewGuid().ToString(), 6) }) + }; + _suppliesStorageContract.Setup(x => x.GetList(It.IsAny(), It.IsAny())).Returns(listOriginal); + // Act + var count = _suppliesBusinessLogicContract.CalculateTourSupplies(DateTime.UtcNow.AddDays(-5), DateTime.UtcNow.AddDays(5)); + // Assert + Assert.That(count, Is.EqualTo(11)); + } + + [Test] + public void CalculateTour_ReturnIntZero_Test() + { + // Arrange + string id1 = Guid.NewGuid().ToString(); + string id2 = Guid.NewGuid().ToString(); + string id3 = Guid.NewGuid().ToString(); + var listOriginal = new List() + { + new(id1, TourType.Beach, DateTime.UtcNow, 1, []) + }; + _suppliesStorageContract.Setup(x => x.GetList(It.IsAny(), It.IsAny())).Returns(listOriginal); + // Act + var count = _suppliesBusinessLogicContract.CalculateTourSupplies(DateTime.UtcNow.AddDays(-5), DateTime.UtcNow.AddDays(5)); + // Assert + Assert.That(count, Is.EqualTo(0)); + } + + [Test] + public void CalculateTour_StorageThrowError_ThrowException_Test() + { + // Arrange + _suppliesStorageContract.Setup(x => x.GetList(It.IsAny(), It.IsAny())).Throws(new StorageException(new InvalidOperationException())); + // Act & Assert + Assert.That(() => _suppliesBusinessLogicContract.CalculateTourSupplies(DateTime.UtcNow.AddDays(-5), DateTime.UtcNow.AddDays(5)), Throws.TypeOf()); + _suppliesStorageContract.Verify(x => x.GetList(It.IsAny(), It.IsAny()), Times.Once); + } } diff --git a/MagicCarpetProject/MagicCarpetTests/StoragesContractsTests/PostStorageContractTests.cs b/MagicCarpetProject/MagicCarpetTests/StoragesContractsTests/PostStorageContractTests.cs index 1f80bd5..1affe81 100644 --- a/MagicCarpetProject/MagicCarpetTests/StoragesContractsTests/PostStorageContractTests.cs +++ b/MagicCarpetProject/MagicCarpetTests/StoragesContractsTests/PostStorageContractTests.cs @@ -6,6 +6,7 @@ using MagicCarpetDatabase.Implementations; using MagicCarpetDatabase.Models; using MagicCarpetTests.Infrastructure; using MagicCarpetTests.StoragesContracts; +using MagicCarpetTests.StoragesContractsTests; using System; using System.Collections.Generic; using System.Linq;