From b2b2922acf583a7121bbcb8fcbab3e11e793e1b8 Mon Sep 17 00:00:00 2001 From: devil_1nc Date: Sun, 23 Jun 2024 20:39:28 +0400 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=B8=D0=BC=D0=B0=D0=BD=20=D1=81=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D0=B9=20=D0=BF=D0=B6=20SupplyDoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BusinessLogic/BusinessLogic/SellLogic.cs | 69 +++++++++++++++++- Contracts/BindingModels/SellBindingModel.cs | 3 +- Contracts/Converters/SellConverter.cs | 17 ++++- Contracts/StorageContracts/ISellStorage.cs | 12 +-- Contracts/ViewModels/SellViewModel.cs | 2 +- DatabaseImplement/Database.cs | 3 +- DatabaseImplement/Implements/SellStorage.cs | 64 +++++++++++++--- .../Migrations/DatabaseModelSnapshot.cs | 22 +++--- DatabaseImplement/Models/Product.cs | 4 +- DatabaseImplement/Models/Purchase.cs | 10 +++ DatabaseImplement/Models/Sell.cs | 30 +++++++- DatabaseImplement/Models/SupplyDoc.cs | 18 +++++ WebApp/WebApp.csproj | 7 ++ WebApp/wwwroot/favicon.ico | Bin 5430 -> 67646 bytes 14 files changed, 221 insertions(+), 40 deletions(-) create mode 100644 DatabaseImplement/Models/SupplyDoc.cs diff --git a/BusinessLogic/BusinessLogic/SellLogic.cs b/BusinessLogic/BusinessLogic/SellLogic.cs index 9561f4f..aacd8e5 100644 --- a/BusinessLogic/BusinessLogic/SellLogic.cs +++ b/BusinessLogic/BusinessLogic/SellLogic.cs @@ -1,4 +1,11 @@ -using System; +using Contracts.BindingModels; +using Contracts.Converters; +using Contracts.SearchModels; +using Contracts.StorageContracts; +using Contracts.ViewModels; +using DatabaseImplement.Models; +using Microsoft.Extensions.Logging; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +13,65 @@ using System.Threading.Tasks; namespace BusinessLogic.BusinessLogic { - internal class SellLogic + public class SellLogic { + private readonly ISellStorage _sellStorage; + private readonly ILogger _logger; + + public SellLogic(ISellStorage sellStorage, ILogger logger) + { + _sellStorage = sellStorage; + _logger = logger; + } + public SellViewModel Create(SellBindingModel model) + { + ArgumentNullException.ThrowIfNull(model); + var sell = _sellStorage.Insert(model); + if (sell is null) + { + throw new Exception("Insert operation failed."); + } + return sell; + } + public SellViewModel GetElement(SellSearchModel model) + { + ArgumentNullException.ThrowIfNull(model); + var sell = _sellStorage.GetElement(model); + if (sell is null) + { + throw new Exception("Get element operation failed."); + } + return sell; + } + public IEnumerable GetElements(SellSearchModel? model) + { + var sell_list = _sellStorage.GetList(model); + if (sell_list is null || sell_list.Count() == 0) + { + _logger.LogWarning("ReadList return null list"); + return []; + } + return sell_list; + } + public SellViewModel Update(SellSearchModel model) + { + ArgumentNullException.ThrowIfNull(model); + var sell = _sellStorage.GetElement(model); + if (sell is null) + { + throw new Exception("Update operation failed."); + } + return sell; + } + public SellViewModel Delete(SellSearchModel model) + { + ArgumentNullException.ThrowIfNull(model); + var sell = _sellStorage.Delete(model); + if (sell is null) + { + throw new Exception("Update operation failed."); + } + return sell; + } } } diff --git a/Contracts/BindingModels/SellBindingModel.cs b/Contracts/BindingModels/SellBindingModel.cs index e0c32ed..0d93bcb 100644 --- a/Contracts/BindingModels/SellBindingModel.cs +++ b/Contracts/BindingModels/SellBindingModel.cs @@ -10,5 +10,6 @@ namespace Contracts.BindingModels { public Guid Id { get; set; } public DateTime DateSell { get; set; } - } + public Guid? SupplyDocId { get; set; } + } } diff --git a/Contracts/Converters/SellConverter.cs b/Contracts/Converters/SellConverter.cs index 556c9b1..0acd7fe 100644 --- a/Contracts/Converters/SellConverter.cs +++ b/Contracts/Converters/SellConverter.cs @@ -1,4 +1,7 @@ -using System; +using Contracts.BindingModels; +using Contracts.ViewModels; +using DataModels.Models; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,6 +11,18 @@ namespace Contracts.Converters { public class SellConverter { + public static SellViewModel ToView(SellBindingModel model) => new() + { + Id = model.Id, + DateSell = model.DateSell, + SupplyDocId = model.SupplyDocId + }; + public static SellBindingModel ToBinding(SellViewModel model) => new() + { + Id = model.Id, + DateSell = model.DateSell, + SupplyDocId = model.SupplyDocId + }; } } diff --git a/Contracts/StorageContracts/ISellStorage.cs b/Contracts/StorageContracts/ISellStorage.cs index ba31175..acf47f1 100644 --- a/Contracts/StorageContracts/ISellStorage.cs +++ b/Contracts/StorageContracts/ISellStorage.cs @@ -1,5 +1,6 @@ using Contracts.BindingModels; using Contracts.SearchModels; +using Contracts.ViewModels; using System; using System.Collections.Generic; using System.Linq; @@ -10,14 +11,15 @@ namespace Contracts.StorageContracts { public interface ISellStorage { - SellBindingModel? Insert(SellBindingModel model); + SellViewModel? Insert(SellBindingModel model); - IEnumerable GetList(SellSearchModel? model); + IEnumerable GetFullList(SellSearchModel? model); + IEnumerable GetFilteredList(SellSearchModel? model); - SellBindingModel? GetElement(SellSearchModel model); + SellViewModel? GetElement(SellSearchModel model); - SellBindingModel? Update(SellBindingModel model); + SellViewModel? Update(SellBindingModel model); - SellBindingModel? Delete(SellSearchModel model); + SellViewModel? Delete(SellSearchModel model); } } diff --git a/Contracts/ViewModels/SellViewModel.cs b/Contracts/ViewModels/SellViewModel.cs index 285d63f..3d09e5a 100644 --- a/Contracts/ViewModels/SellViewModel.cs +++ b/Contracts/ViewModels/SellViewModel.cs @@ -11,6 +11,6 @@ namespace Contracts.ViewModels { public Guid Id { get; set; } public DateTime DateSell { get; set; } - public ISupplyDoc? SupplyDoc { get; set; } + public Guid? SupplyDocId { get; set; } } } diff --git a/DatabaseImplement/Database.cs b/DatabaseImplement/Database.cs index 193acaf..c3284c4 100644 --- a/DatabaseImplement/Database.cs +++ b/DatabaseImplement/Database.cs @@ -30,5 +30,6 @@ namespace DatabaseImplement public virtual DbSet SupplierProducts { get; set; } = null!; public virtual DbSet MediaFiles { get; set; } = null!; public virtual DbSet PurchaseProducts { get; set; } = null!; - } + public virtual DbSet SupplyDocs { get; set; } = null!; + } } \ No newline at end of file diff --git a/DatabaseImplement/Implements/SellStorage.cs b/DatabaseImplement/Implements/SellStorage.cs index 533486d..090188f 100644 --- a/DatabaseImplement/Implements/SellStorage.cs +++ b/DatabaseImplement/Implements/SellStorage.cs @@ -1,6 +1,10 @@ using Contracts.BindingModels; +using Contracts.Converters; using Contracts.SearchModels; using Contracts.StorageContracts; +using Contracts.ViewModels; +using DatabaseImplement.Models; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -11,29 +15,65 @@ namespace DatabaseImplement.Implements { public class SellStorage : ISellStorage { - public SellBindingModel? Delete(SellSearchModel model) + public SellViewModel? Delete(SellSearchModel model) { throw new NotImplementedException(); } - public SellBindingModel? GetElement(SellSearchModel model) + public SellViewModel? GetElement(SellSearchModel model) { throw new NotImplementedException(); } - public IEnumerable GetList(SellSearchModel? model) + public IEnumerable GetFilteredList(SellSearchModel? model) + { + throw new NotImplementedException(); + } + + public IEnumerable GetFullList(SellSearchModel? model) { - throw new NotImplementedException(); + using var context = new Database(); + return context.Sells + .Include(x => x.SupplyDoc) + .ToList() + .Select((Sell sell, int index) => sell.GetViewModel()) + .ToList(); + } + + public SellViewModel? Insert(SellBindingModel model) + { + using var context = new Database(); + var sell = Sell.Create(context, model); + if (sell == null) + { + return null; + } + context.Sells.Add(sell); + context.SaveChanges(); + return sell.GetViewModel(); } - public SellBindingModel? Insert(SellBindingModel model) + public SellViewModel? Update(SellBindingModel model) { - throw new NotImplementedException(); - } - - public SellBindingModel? Update(SellBindingModel model) - { - throw new NotImplementedException(); - } + using var context = new Database(); + using var transaction = context.Database.BeginTransaction(); + try + { + var sell = context.Sells.FirstOrDefault(rec => rec.Id == model.Id); + if (sell == null) + { + return null; + } + sell.Update(model); + context.SaveChanges(); + transaction.Commit(); + return sell.GetViewModel(); + } + catch + { + transaction.Rollback(); + throw; + } + } } } diff --git a/DatabaseImplement/Migrations/DatabaseModelSnapshot.cs b/DatabaseImplement/Migrations/DatabaseModelSnapshot.cs index 0368a1c..b430445 100644 --- a/DatabaseImplement/Migrations/DatabaseModelSnapshot.cs +++ b/DatabaseImplement/Migrations/DatabaseModelSnapshot.cs @@ -41,7 +41,7 @@ namespace DatabaseImplement.Migrations b.HasKey("Id"); - b.ToTable("MediaFiles"); + b.ToTable("MediaFiles", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.Product", b => @@ -68,7 +68,7 @@ namespace DatabaseImplement.Migrations b.HasKey("Id"); - b.ToTable("Products"); + b.ToTable("Products", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.Purchase", b => @@ -90,7 +90,7 @@ namespace DatabaseImplement.Migrations b.HasIndex("UserId"); - b.ToTable("Purchases"); + b.ToTable("Purchases", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.PurchaseProducts", b => @@ -114,7 +114,7 @@ namespace DatabaseImplement.Migrations b.HasIndex("PurchaseId"); - b.ToTable("PurchaseProducts"); + b.ToTable("PurchaseProducts", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.Role", b => @@ -129,7 +129,7 @@ namespace DatabaseImplement.Migrations b.HasKey("Id"); - b.ToTable("Roles"); + b.ToTable("Roles", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.Sell", b => @@ -143,7 +143,7 @@ namespace DatabaseImplement.Migrations b.HasKey("Id"); - b.ToTable("Sells"); + b.ToTable("Sells", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.Supplier", b => @@ -161,7 +161,7 @@ namespace DatabaseImplement.Migrations b.HasKey("Id"); - b.ToTable("Suppliers"); + b.ToTable("Suppliers", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.SupplierProduct", b => @@ -185,7 +185,7 @@ namespace DatabaseImplement.Migrations b.HasIndex("SupplierId"); - b.ToTable("SupplierProducts"); + b.ToTable("SupplierProducts", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.Supply", b => @@ -214,7 +214,7 @@ namespace DatabaseImplement.Migrations b.HasIndex("SupplierId"); - b.ToTable("Supplies"); + b.ToTable("Supplies", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.SupplyProduct", b => @@ -238,7 +238,7 @@ namespace DatabaseImplement.Migrations b.HasIndex("SupplyId"); - b.ToTable("SupplyProducts"); + b.ToTable("SupplyProducts", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.User", b => @@ -276,7 +276,7 @@ namespace DatabaseImplement.Migrations b.HasIndex("RoleId"); - b.ToTable("Users"); + b.ToTable("Users", (string)null); }); modelBuilder.Entity("DatabaseImplement.Models.Purchase", b => diff --git a/DatabaseImplement/Models/Product.cs b/DatabaseImplement/Models/Product.cs index 70da3ba..fd8053e 100644 --- a/DatabaseImplement/Models/Product.cs +++ b/DatabaseImplement/Models/Product.cs @@ -43,7 +43,7 @@ namespace DatabaseImplement.Models Id = model.Id, Name = model.Name, Price = model.Price, - Rate = model.Rate, + Rate = model.Rating, IsBeingSold = model.IsBeingSold, Amount = model.Amount }; @@ -96,7 +96,7 @@ namespace DatabaseImplement.Models Name = Name, Price = Price, IsBeingSold = IsBeingSold, - Rate = Rate, + Rating = Rate, Amount = Amount }; } diff --git a/DatabaseImplement/Models/Purchase.cs b/DatabaseImplement/Models/Purchase.cs index 35e9041..a3e999e 100644 --- a/DatabaseImplement/Models/Purchase.cs +++ b/DatabaseImplement/Models/Purchase.cs @@ -41,6 +41,16 @@ namespace DatabaseImplement.Models } [ForeignKey("PurchaseId")] public virtual List Products { get; set; } = new(); + public static Purchase Create(Database context, SellBindingModel model) + { + return new Purchase() + { + DatePurchase = DateTime.Now, + UserId = Guid.NewGuid(), + Status = PurchaseStatus.Unknown, + + }; + } public PurchaseBindingModel GetBindingModel() => new() { Id = Id, diff --git a/DatabaseImplement/Models/Sell.cs b/DatabaseImplement/Models/Sell.cs index 03a7f26..74a441e 100644 --- a/DatabaseImplement/Models/Sell.cs +++ b/DatabaseImplement/Models/Sell.cs @@ -1,4 +1,5 @@ using Contracts.BindingModels; +using Contracts.Converters; using Contracts.ViewModels; using DataModels.Models; using System; @@ -13,13 +14,33 @@ namespace DatabaseImplement.Models { public Guid Id { get; set; } public DateTime DateSell { get; set; } + public Guid? SupplyDocId { get; set; } + + public virtual SupplyDoc? SupplyDoc { get; set; } + public static Sell Create(Database context, SellBindingModel model) + { + return new Sell() + { + Id = model.Id, + DateSell = model.DateSell, + SupplyDocId = model.SupplyDocId, + }; + } public SellBindingModel GetBindingModel() => new() { Id = Id, - DateSell = DateSell + DateSell = DateSell, + SupplyDocId = SupplyDocId, }; - public static Sell ToSellFromView(SellViewModel model, Sell sell) => new() + public SellViewModel GetViewModel() => new() + { + Id = Id, + DateSell = DateSell, + SupplyDocId = SupplyDocId, + + }; + public static Sell ToSellFromView(SellViewModel model, Sell sell) => new() { Id = model.Id, DateSell = model.DateSell @@ -31,14 +52,15 @@ namespace DatabaseImplement.Models DateSell = model.DateSell, }; - public void Update(SellBindingModel model, Sell sell) + public void Update(SellBindingModel model) { if (model is null) { throw new ArgumentNullException("Update user: binding model is null"); } - DateSell = sell.DateSell; + DateSell = model.DateSell; + SupplyDocId = model.SupplyDocId; } } } diff --git a/DatabaseImplement/Models/SupplyDoc.cs b/DatabaseImplement/Models/SupplyDoc.cs new file mode 100644 index 0000000..b4aed5a --- /dev/null +++ b/DatabaseImplement/Models/SupplyDoc.cs @@ -0,0 +1,18 @@ +using DataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DatabaseImplement.Models +{ + public class SupplyDoc : ISupplyDoc + { + public Guid Id { get; set; } + [Required] + public string Name { get; set; } = string.Empty; + public Guid SupplyId { get; set; } + } +} diff --git a/WebApp/WebApp.csproj b/WebApp/WebApp.csproj index 33e3dc7..8cc73e5 100644 --- a/WebApp/WebApp.csproj +++ b/WebApp/WebApp.csproj @@ -15,4 +15,11 @@ + + + true + PreserveNewest + + + diff --git a/WebApp/wwwroot/favicon.ico b/WebApp/wwwroot/favicon.ico index 63e859b476eff5055e0e557aaa151ca8223fbeef..f5a790500fb08b2faeb6fa22d4a0711f5cd65862 100644 GIT binary patch literal 67646 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 literal 5430 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