diff --git a/ClothShop/ClothShopBusinessLogic/BusinessLogics/ClientLogic.cs b/ClothShop/ClothShopBusinessLogic/BusinessLogics/ClientLogic.cs new file mode 100644 index 0000000..c798b3a --- /dev/null +++ b/ClothShop/ClothShopBusinessLogic/BusinessLogics/ClientLogic.cs @@ -0,0 +1,123 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.BusinessLogicContracts; +using ClothShopContracts.SearchModels; +using ClothShopContracts.StoragesContracts; +using ClothShopContracts.ViewModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopBusinessLogic.BusinessLogics +{ + public class ClientLogic : IClientLogic + { + private readonly ILogger _logger; + private readonly IClientStorage _clientStorage; + public ClientLogic(ILogger logger, IClientStorage + componentStorage) + { + _logger = logger; + _clientStorage = componentStorage; + } + public List? ReadList(ClientSearchModel? model) + { + _logger.LogInformation("ReadList. ClientFIO:{ClientFIO}. Id:{ Id}", model?.ClientFIO, model?.Id); + var list = model == null ? _clientStorage.GetFullList() : + _clientStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + public ClientViewModel? ReadElement(ClientSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. ClientFIO:{ClientFIO}.Id:{ Id}", model.ClientFIO, model.Id); + var element = _clientStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + public bool Create(ClientBindingModel model) + { + CheckModel(model); + if (_clientStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + public bool Update(ClientBindingModel model) + { + CheckModel(model); + if (_clientStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + public bool Delete(ClientBindingModel model) + { + CheckModel(model, false); + _logger.LogInformation("Delete. Id:{Id}", model.Id); + if (_clientStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; + } + private void CheckModel(ClientBindingModel model, bool withParams = + true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.ClientFIO)) + { + throw new ArgumentNullException("Нет ФИО клиента", + nameof(model.ClientFIO)); + } + if (string.IsNullOrEmpty(model.Email)) + { + throw new ArgumentNullException("Нет Email клиента", + nameof(model.ClientFIO)); + } + if (string.IsNullOrEmpty(model.Password)) + { + throw new ArgumentNullException("Нет пароля клиента", + nameof(model.ClientFIO)); + } + _logger.LogInformation("Client. ClientFIO:{ClientFIO}." + + "Email:{ Email}. Password:{ Password}. Id: { Id} ", model.ClientFIO, model.Email, model.Password, model.Id); + var element = _clientStorage.GetElement(new ClientSearchModel + { + Email = model.Email, + }); + if (element != null && element.Id != model.Id) + { + throw new InvalidOperationException("Клиент с таким лоигном уже есть"); + } + } + } +} diff --git a/ClothShop/ClothShopContracts/BindingModels/ClientBindingModel.cs b/ClothShop/ClothShopContracts/BindingModels/ClientBindingModel.cs new file mode 100644 index 0000000..626ad91 --- /dev/null +++ b/ClothShop/ClothShopContracts/BindingModels/ClientBindingModel.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ClothShopDataModels.Models; + +namespace ClothShopContracts.BindingModels +{ + public class ClientBindingModel : IClientModel + { + public int Id { get; set; } + public string ClientFIO { get; set; } = string.Empty; + public string Email { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + } +} diff --git a/ClothShop/ClothShopContracts/BindingModels/OrderBindingModel.cs b/ClothShop/ClothShopContracts/BindingModels/OrderBindingModel.cs index 64fa12d..11c14d3 100644 --- a/ClothShop/ClothShopContracts/BindingModels/OrderBindingModel.cs +++ b/ClothShop/ClothShopContracts/BindingModels/OrderBindingModel.cs @@ -12,6 +12,7 @@ namespace ClothShopContracts.BindingModels { public int Id { get; set; } public int TextileId { get; set; } + public int ClientId { get; set; } public int Count { get; set; } public double Sum { get; set; } public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; diff --git a/ClothShop/ClothShopContracts/BusinessLogicContracts/IClientLogic.cs b/ClothShop/ClothShopContracts/BusinessLogicContracts/IClientLogic.cs new file mode 100644 index 0000000..177197e --- /dev/null +++ b/ClothShop/ClothShopContracts/BusinessLogicContracts/IClientLogic.cs @@ -0,0 +1,21 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.SearchModels; +using ClothShopContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopContracts.BusinessLogicContracts +{ + public interface IClientLogic + { + List? ReadList(ClientSearchModel? model); + ClientViewModel? ReadElement(ClientSearchModel model); + bool Create(ClientBindingModel model); + bool Update(ClientBindingModel model); + bool Delete(ClientBindingModel model); + } + +} diff --git a/ClothShop/ClothShopContracts/SearchModels/ClientSearchModel.cs b/ClothShop/ClothShopContracts/SearchModels/ClientSearchModel.cs new file mode 100644 index 0000000..30c8dc6 --- /dev/null +++ b/ClothShop/ClothShopContracts/SearchModels/ClientSearchModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopContracts.SearchModels +{ + public class ClientSearchModel + { + public int? Id { get; set; } + public string? ClientFIO { get; set; } + public string? Email { get; set; } + public string? Password { get; set; } + } +} diff --git a/ClothShop/ClothShopContracts/SearchModels/OrderSearchModel.cs b/ClothShop/ClothShopContracts/SearchModels/OrderSearchModel.cs index 207176d..3cc0322 100644 --- a/ClothShop/ClothShopContracts/SearchModels/OrderSearchModel.cs +++ b/ClothShop/ClothShopContracts/SearchModels/OrderSearchModel.cs @@ -9,6 +9,7 @@ namespace ClothShopContracts.SearchModels public class OrderSearchModel { public int? Id { get; set; } + public int? ClientId { get; set; } public DateTime? DateFrom { get; set; } public DateTime? DateTo { get; set; } } diff --git a/ClothShop/ClothShopContracts/StoragesContracts/IClientStorage.cs b/ClothShop/ClothShopContracts/StoragesContracts/IClientStorage.cs new file mode 100644 index 0000000..df92ba0 --- /dev/null +++ b/ClothShop/ClothShopContracts/StoragesContracts/IClientStorage.cs @@ -0,0 +1,21 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.SearchModels; +using ClothShopContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopContracts.StoragesContracts +{ + public interface IClientStorage + { + List GetFullList(); + List GetFilteredList(ClientSearchModel model); + ClientViewModel? GetElement(ClientSearchModel model); + ClientViewModel? Insert(ClientBindingModel model); + ClientViewModel? Update(ClientBindingModel model); + ClientViewModel? Delete(ClientBindingModel model); + } +} diff --git a/ClothShop/ClothShopContracts/ViewModels/ClientViewModel.cs b/ClothShop/ClothShopContracts/ViewModels/ClientViewModel.cs new file mode 100644 index 0000000..42e4840 --- /dev/null +++ b/ClothShop/ClothShopContracts/ViewModels/ClientViewModel.cs @@ -0,0 +1,22 @@ +using ClothShopDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopContracts.ViewModels +{ + public class ClientViewModel : IClientModel + { + public int Id { get; set; } + [DisplayName("ФИО клиента")] + public string ClientFIO { get; set; } = string.Empty; + [DisplayName("Логин (эл. почта)")] + public string Email { get; set; } = string.Empty; + [DisplayName("Пароль")] + public string Password { get; set; } = string.Empty; + } + +} diff --git a/ClothShop/ClothShopContracts/ViewModels/OrderViewModel.cs b/ClothShop/ClothShopContracts/ViewModels/OrderViewModel.cs index 817114c..f623cfe 100644 --- a/ClothShop/ClothShopContracts/ViewModels/OrderViewModel.cs +++ b/ClothShop/ClothShopContracts/ViewModels/OrderViewModel.cs @@ -16,6 +16,9 @@ namespace ClothShopContracts.ViewModels public int TextileId { get; set; } [DisplayName("Изделие")] public string TextileName { get; set; } = string.Empty; + public int ClientId { get; set; } + [DisplayName("Клиент")] + public string ClientFIO { get; set; } = string.Empty; [DisplayName("Количество")] public int Count { get; set; } [DisplayName("Сумма")] diff --git a/ClothShop/ClothShopDataModels/Models/IClientModel.cs b/ClothShop/ClothShopDataModels/Models/IClientModel.cs new file mode 100644 index 0000000..b2e3c19 --- /dev/null +++ b/ClothShop/ClothShopDataModels/Models/IClientModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopDataModels.Models +{ + public class IClientModel + { + string ClientFIO { get; } + string Email { get; } + string Password { get; } + } +} diff --git a/ClothShop/ClothShopDataModels/Models/IOrderModel.cs b/ClothShop/ClothShopDataModels/Models/IOrderModel.cs index 105ad5e..6f3995d 100644 --- a/ClothShop/ClothShopDataModels/Models/IOrderModel.cs +++ b/ClothShop/ClothShopDataModels/Models/IOrderModel.cs @@ -10,6 +10,7 @@ namespace ClothShopDataModels.Models public interface IOrderModel : IId { int TextileId { get; } + int ClientId { get; } int Count { get; } double Sum { get; } OrderStatus Status { get; } diff --git a/ClothShop/ClothShopDatabaseImplement/ClothShopDatabase.cs b/ClothShop/ClothShopDatabaseImplement/ClothShopDatabase.cs index dcfa406..c7fa78f 100644 --- a/ClothShop/ClothShopDatabaseImplement/ClothShopDatabase.cs +++ b/ClothShop/ClothShopDatabaseImplement/ClothShopDatabase.cs @@ -18,5 +18,6 @@ namespace ClothShopDatabaseImplement public virtual DbSet Textiles { set; get; } public virtual DbSet TextileComponents { set; get; } public virtual DbSet Orders { set; get; } + public virtual DbSet Clients { set; get; } } } \ No newline at end of file diff --git a/ClothShop/ClothShopDatabaseImplement/Implements/ClientStorage.cs b/ClothShop/ClothShopDatabaseImplement/Implements/ClientStorage.cs new file mode 100644 index 0000000..6f90f46 --- /dev/null +++ b/ClothShop/ClothShopDatabaseImplement/Implements/ClientStorage.cs @@ -0,0 +1,88 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.SearchModels; +using ClothShopContracts.StoragesContracts; +using ClothShopContracts.ViewModels; +using ClothShopDatabaseImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopDatabaseImplement.Implements +{ + public class ClientStorage : IClientStorage + { + public List GetFullList() + { + using var context = new ClothShopDatabase(); + return context.Clients + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(ClientSearchModel model) + { + if (string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email) && string.IsNullOrEmpty(model.Password)) + { + return new(); + } + using var context = new ClothShopDatabase(); + return context.Clients + .Where(x => (string.IsNullOrEmpty(model.ClientFIO) || x.ClientFIO.Contains(model.ClientFIO) && + (string.IsNullOrEmpty(model.Email) || x.Email.Contains(model.Email)) && + (string.IsNullOrEmpty(model.Password) || x.Password.Contains(model.Password)))) + .Select(x => x.GetViewModel) + .ToList(); + } + public ClientViewModel? GetElement(ClientSearchModel model) + { + if (string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email) && + !model.Id.HasValue) + { + return null; + } + using var context = new ClothShopDatabase(); + return context.Clients + .FirstOrDefault(x => (string.IsNullOrEmpty(model.ClientFIO) || x.ClientFIO == model.ClientFIO) && + (!model.Id.HasValue || x.Id == model.Id) && (string.IsNullOrEmpty(model.Email) || x.Email == model.Email) && + (string.IsNullOrEmpty(model.Password) || x.Password == model.Password)) + ?.GetViewModel; + } + public ClientViewModel? Insert(ClientBindingModel model) + { + var newClient = Client.Create(model); + if (newClient == null) + { + return null; + } + using var context = new ClothShopDatabase(); + context.Clients.Add(newClient); + context.SaveChanges(); + return newClient.GetViewModel; + } + public ClientViewModel? Update(ClientBindingModel model) + { + using var context = new ClothShopDatabase(); + var client = context.Clients.FirstOrDefault(x => x.Id == model.Id); + if (client == null) + { + return null; + } + client.Update(model); + context.SaveChanges(); + return client.GetViewModel; + } + public ClientViewModel? Delete(ClientBindingModel model) + { + using var context = new ClothShopDatabase(); + var element = context.Clients.FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + context.Clients.Remove(element); + context.SaveChanges(); + return element.GetViewModel; + } + return null; + } + } +} diff --git a/ClothShop/ClothShopDatabaseImplement/Implements/OrderStorage.cs b/ClothShop/ClothShopDatabaseImplement/Implements/OrderStorage.cs index 134f1df..055d927 100644 --- a/ClothShop/ClothShopDatabaseImplement/Implements/OrderStorage.cs +++ b/ClothShop/ClothShopDatabaseImplement/Implements/OrderStorage.cs @@ -17,30 +17,23 @@ namespace ClothShopDatabaseImplement.Implements public List GetFullList() { using var context = new ClothShopDatabase(); - return context.Orders.Include(x => x.Textiles) + return context.Orders.Include(x => x.Textiles).Include(x => x.Client) .Select(x => x.GetViewModel) .ToList(); } public List GetFilteredList(OrderSearchModel model) { - if (!model.Id.HasValue && !model.DateFrom.HasValue) - { - return new(); - } using var context = new ClothShopDatabase(); - if (model.DateFrom.HasValue) - { - return context.Orders - .Include(x => x.Textiles) - .Where(x => x.DateCreate >= model.DateFrom && x.DateCreate <= model.DateTo) - .Select(x => x.GetViewModel) - .ToList(); - } - return context.Orders - .Include(x => x.Textiles) - .Where(x => x.Id == model.Id) - .Select(x => x.GetViewModel) - .ToList(); + return context.Orders.Include(x => x.Textiles).Include(x => x.Client) + .Where(x => ( + (!model.Id.HasValue || x.Id == model.Id) && + (!model.DateFrom.HasValue || x.DateCreate >= model.DateFrom) && + (!model.DateTo.HasValue || x.DateCreate <= model.DateTo) && + (!model.ClientId.HasValue || x.ClientId == model.ClientId) + ) + ) + .Select(x => x.GetViewModel) + .ToList(); } public OrderViewModel? GetElement(OrderSearchModel model) { @@ -49,7 +42,7 @@ namespace ClothShopDatabaseImplement.Implements return null; } using var context = new ClothShopDatabase(); - return context.Orders.Include(x => x.Textiles).FirstOrDefault(x => x.Id == model.Id)?.GetViewModel; + return context.Orders.Include(x => x.Textiles).Include(x => x.Client).FirstOrDefault(x => x.Id == model.Id)?.GetViewModel; } public OrderViewModel? Insert(OrderBindingModel model) { @@ -66,7 +59,7 @@ namespace ClothShopDatabaseImplement.Implements public OrderViewModel? Update(OrderBindingModel model) { using var context = new ClothShopDatabase(); - var order = context.Orders.Include(x => x.Textiles).FirstOrDefault(x => x.Id == model.Id); + var order = context.Orders.Include(x => x.Textiles).Include(x => x.Client).FirstOrDefault(x => x.Id == model.Id); if (order == null) { return null; @@ -78,7 +71,7 @@ namespace ClothShopDatabaseImplement.Implements public OrderViewModel? Delete(OrderBindingModel model) { using var context = new ClothShopDatabase(); - var element = context.Orders.Include(x => x.Textiles).FirstOrDefault(rec => rec.Id == model.Id); + var element = context.Orders.Include(x => x.Textiles).Include(x => x.Client).FirstOrDefault(rec => rec.Id == model.Id); if (element != null) { context.Orders.Remove(element); diff --git a/ClothShop/ClothShopDatabaseImplement/Migrations/20240407194221_InitMigration.Designer.cs b/ClothShop/ClothShopDatabaseImplement/Migrations/20240518182542_InitialCreate.Designer.cs similarity index 78% rename from ClothShop/ClothShopDatabaseImplement/Migrations/20240407194221_InitMigration.Designer.cs rename to ClothShop/ClothShopDatabaseImplement/Migrations/20240518182542_InitialCreate.Designer.cs index be774e4..1e6b9d4 100644 --- a/ClothShop/ClothShopDatabaseImplement/Migrations/20240407194221_InitMigration.Designer.cs +++ b/ClothShop/ClothShopDatabaseImplement/Migrations/20240518182542_InitialCreate.Designer.cs @@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace ClothShopDatabaseImplement.Migrations { [DbContext(typeof(ClothShopDatabase))] - [Migration("20240407194221_InitMigration")] - partial class InitMigration + [Migration("20240518182542_InitialCreate")] + partial class InitialCreate { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -24,6 +24,31 @@ namespace ClothShopDatabaseImplement.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ClientFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Clients"); + }); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Component", b => { b.Property("Id") @@ -52,6 +77,9 @@ namespace ClothShopDatabaseImplement.Migrations SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + b.Property("ClientId") + .HasColumnType("int"); + b.Property("Count") .HasColumnType("int"); @@ -72,6 +100,8 @@ namespace ClothShopDatabaseImplement.Migrations b.HasKey("Id"); + b.HasIndex("ClientId"); + b.HasIndex("TextileId"); b.ToTable("Orders"); @@ -125,12 +155,20 @@ namespace ClothShopDatabaseImplement.Migrations modelBuilder.Entity("ClothShopDatabaseImplement.Models.Order", b => { + b.HasOne("ClothShopDatabaseImplement.Models.Client", "Client") + .WithMany("Orders") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("ClothShopDatabaseImplement.Models.Textile", "Textiles") .WithMany("Orders") .HasForeignKey("TextileId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.Navigation("Client"); + b.Navigation("Textiles"); }); @@ -153,6 +191,11 @@ namespace ClothShopDatabaseImplement.Migrations b.Navigation("Textile"); }); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Client", b => + { + b.Navigation("Orders"); + }); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Component", b => { b.Navigation("TextileComponents"); diff --git a/ClothShop/ClothShopDatabaseImplement/Migrations/20240407194221_InitMigration.cs b/ClothShop/ClothShopDatabaseImplement/Migrations/20240518182542_InitialCreate.cs similarity index 78% rename from ClothShop/ClothShopDatabaseImplement/Migrations/20240407194221_InitMigration.cs rename to ClothShop/ClothShopDatabaseImplement/Migrations/20240518182542_InitialCreate.cs index 7639bf4..4d5880d 100644 --- a/ClothShop/ClothShopDatabaseImplement/Migrations/20240407194221_InitMigration.cs +++ b/ClothShop/ClothShopDatabaseImplement/Migrations/20240518182542_InitialCreate.cs @@ -5,10 +5,25 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace ClothShopDatabaseImplement.Migrations { - public partial class InitMigration : Migration + public partial class InitialCreate : Migration { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "Clients", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ClientFIO = table.Column(type: "nvarchar(max)", nullable: false), + Email = table.Column(type: "nvarchar(max)", nullable: false), + Password = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Clients", x => x.Id); + }); + migrationBuilder.CreateTable( name: "Components", columns: table => new @@ -48,11 +63,18 @@ namespace ClothShopDatabaseImplement.Migrations Status = table.Column(type: "int", nullable: false), DateCreate = table.Column(type: "datetime2", nullable: false), DateImplement = table.Column(type: "datetime2", nullable: true), - TextileId = table.Column(type: "int", nullable: false) + TextileId = table.Column(type: "int", nullable: false), + ClientId = table.Column(type: "int", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); table.ForeignKey( name: "FK_Orders_Textiles_TextileId", column: x => x.TextileId, @@ -88,6 +110,11 @@ namespace ClothShopDatabaseImplement.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateIndex( + name: "IX_Orders_ClientId", + table: "Orders", + column: "ClientId"); + migrationBuilder.CreateIndex( name: "IX_Orders_TextileId", table: "Orders", @@ -112,6 +139,9 @@ namespace ClothShopDatabaseImplement.Migrations migrationBuilder.DropTable( name: "TextileComponents"); + migrationBuilder.DropTable( + name: "Clients"); + migrationBuilder.DropTable( name: "Components"); diff --git a/ClothShop/ClothShopDatabaseImplement/Migrations/ClothShopDatabaseModelSnapshot.cs b/ClothShop/ClothShopDatabaseImplement/Migrations/ClothShopDatabaseModelSnapshot.cs index bcd8fb9..c395b97 100644 --- a/ClothShop/ClothShopDatabaseImplement/Migrations/ClothShopDatabaseModelSnapshot.cs +++ b/ClothShop/ClothShopDatabaseImplement/Migrations/ClothShopDatabaseModelSnapshot.cs @@ -22,6 +22,31 @@ namespace ClothShopDatabaseImplement.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ClientFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Clients"); + }); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Component", b => { b.Property("Id") @@ -50,6 +75,9 @@ namespace ClothShopDatabaseImplement.Migrations SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + b.Property("ClientId") + .HasColumnType("int"); + b.Property("Count") .HasColumnType("int"); @@ -70,6 +98,8 @@ namespace ClothShopDatabaseImplement.Migrations b.HasKey("Id"); + b.HasIndex("ClientId"); + b.HasIndex("TextileId"); b.ToTable("Orders"); @@ -123,12 +153,20 @@ namespace ClothShopDatabaseImplement.Migrations modelBuilder.Entity("ClothShopDatabaseImplement.Models.Order", b => { + b.HasOne("ClothShopDatabaseImplement.Models.Client", "Client") + .WithMany("Orders") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("ClothShopDatabaseImplement.Models.Textile", "Textiles") .WithMany("Orders") .HasForeignKey("TextileId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.Navigation("Client"); + b.Navigation("Textiles"); }); @@ -151,6 +189,11 @@ namespace ClothShopDatabaseImplement.Migrations b.Navigation("Textile"); }); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Client", b => + { + b.Navigation("Orders"); + }); + modelBuilder.Entity("ClothShopDatabaseImplement.Models.Component", b => { b.Navigation("TextileComponents"); diff --git a/ClothShop/ClothShopDatabaseImplement/Models/Client.cs b/ClothShop/ClothShopDatabaseImplement/Models/Client.cs new file mode 100644 index 0000000..161b728 --- /dev/null +++ b/ClothShop/ClothShopDatabaseImplement/Models/Client.cs @@ -0,0 +1,68 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.ViewModels; +using ClothShopDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopDatabaseImplement.Models +{ + public class Client : IClientModel + { + public int Id { get; private set; } + [Required] + public string ClientFIO { get; private set; } = string.Empty; + [Required] + public string Email { get; set; } = string.Empty; + [Required] + public string Password { get; set; } = string.Empty; + [ForeignKey("ClientId")] + public virtual List Orders { get; set; } = + new(); + public static Client? Create(ClientBindingModel model) + { + if (model == null) + { + return null; + } + return new Client() + { + Id = model.Id, + ClientFIO = model.ClientFIO, + Email = model.Email, + Password = model.Password + }; + } + public static Client Create(ClientViewModel model) + { + return new Client() + { + Id = model.Id, + ClientFIO = model.ClientFIO, + Email = model.Email, + Password = model.Password + }; + } + public void Update(ClientBindingModel model) + { + if (model == null) + { + return; + } + ClientFIO = model.ClientFIO; + Email = model.Email; + Password = model.Password; + } + public ClientViewModel GetViewModel => new() + { + Id = Id, + ClientFIO = ClientFIO, + Email = Email, + Password = Password + }; + } +} diff --git a/ClothShop/ClothShopDatabaseImplement/Models/Order.cs b/ClothShop/ClothShopDatabaseImplement/Models/Order.cs index 0c561dd..c306f83 100644 --- a/ClothShop/ClothShopDatabaseImplement/Models/Order.cs +++ b/ClothShop/ClothShopDatabaseImplement/Models/Order.cs @@ -21,6 +21,9 @@ namespace ClothShopDatabaseImplement.Models [Required] public int TextileId { get; private set; } public virtual Textile? Textiles { get; private set; } + [Required] + public int ClientId { get; private set; } + public virtual Client? Client { get; private set; } public static Order? Create(OrderBindingModel model) { @@ -37,6 +40,7 @@ namespace ClothShopDatabaseImplement.Models DateCreate = model.DateCreate, DateImplement = model.DateImplement, TextileId = model.TextileId, + ClientId = model.ClientId, }; } @@ -53,13 +57,15 @@ namespace ClothShopDatabaseImplement.Models public OrderViewModel GetViewModel => new() { TextileId = TextileId, + ClientId = ClientId, Count = Count, Sum = Sum, Status = Status, DateCreate = DateCreate, DateImplement = DateImplement, Id = Id, - TextileName = Textiles?.TextileName ?? string.Empty + TextileName = Textiles?.TextileName ?? string.Empty, + ClientFIO = Client?.ClientFIO ?? string.Empty }; } } diff --git a/ClothShop/ClothShopFileImplement/DataFileSingleton.cs b/ClothShop/ClothShopFileImplement/DataFileSingleton.cs index 434c29a..903ab5b 100644 --- a/ClothShop/ClothShopFileImplement/DataFileSingleton.cs +++ b/ClothShop/ClothShopFileImplement/DataFileSingleton.cs @@ -8,9 +8,12 @@ namespace ClothShopFileImplement private readonly string ComponentFileName = "Component.xml"; private readonly string OrderFileName = "Order.xml"; private readonly string TextileFileName = "Textile.xml"; + private readonly string ClientFileName = "Client.xml"; + public List Components { get; private set; } public List Orders { get; private set; } public List Textiles { get; private set; } + public List Clients { get; private set; } public static DataFileSingleton GetInstance() { if (instance == null) @@ -19,37 +22,32 @@ namespace ClothShopFileImplement } return instance; } - public void SaveComponents() => SaveData(Components, ComponentFileName, - "Components", x => x.GetXElement); - public void SaveTextiles() => SaveData(Textiles, TextileFileName, - "Textiles", x => x.GetXElement); + public void SaveComponents() => SaveData(Components, ComponentFileName, "Components", x => x.GetXElement); + public void SaveTextiles() => SaveData(Textiles, TextileFileName, "Textiles", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); + public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement); private DataFileSingleton() { - Components = LoadData(ComponentFileName, "Component", x => - Component.Create(x)!)!; - Textiles = LoadData(TextileFileName, "Textile", x => - Textile.Create(x)!)!; + Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!; + Textiles = LoadData(TextileFileName, "Textile", x => Textile.Create(x)!)!; Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; + Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!; } - private static List? LoadData(string filename, string xmlNodeName, - Func selectFunction) + private static List? LoadData(string filename, string xmlNodeName, Func selectFunction) { if (File.Exists(filename)) { - return - XDocument.Load(filename)?.Root?.Elements(xmlNodeName)?.Select(selectFunction)?.ToList(); + return XDocument.Load(filename)?.Root?.Elements(xmlNodeName)?.Select(selectFunction)?.ToList(); } return new List(); } - private static void SaveData(List data, string filename, string - xmlNodeName, Func selectFunction) + private static void SaveData(List data, string filename, string xmlNodeName, Func selectFunction) { if (data != null) { - new XDocument(new XElement(xmlNodeName, - data.Select(selectFunction).ToArray())).Save(filename); + new XDocument(new XElement(xmlNodeName, data.Select(selectFunction).ToArray())).Save(filename); } } + } } diff --git a/ClothShop/ClothShopFileImplement/Implements/ClientStorage.cs b/ClothShop/ClothShopFileImplement/Implements/ClientStorage.cs new file mode 100644 index 0000000..785c13b --- /dev/null +++ b/ClothShop/ClothShopFileImplement/Implements/ClientStorage.cs @@ -0,0 +1,85 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.SearchModels; +using ClothShopContracts.StoragesContracts; +using ClothShopContracts.ViewModels; +using ClothShopFileImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopFileImplement.Implements +{ + public class ClientStorage : IClientStorage + { + private readonly DataFileSingleton source; + public ClientStorage() + { + source = DataFileSingleton.GetInstance(); + } + public List GetFullList() + { + return source.Clients + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(ClientSearchModel + model) + { + if (string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email) && string.IsNullOrEmpty(model.Password)) + { + return new(); + } + return source.Clients + .Where(x => (string.IsNullOrEmpty(model.ClientFIO) || x.ClientFIO.Contains(model.ClientFIO) && + (string.IsNullOrEmpty(model.Email) || x.Email.Contains(model.Email)) && + (string.IsNullOrEmpty(model.Password) || x.Password.Contains(model.Password)))) + .Select(x => x.GetViewModel) + .ToList(); + } + public ClientViewModel? GetElement(ClientSearchModel model) + { + return source.Clients + .FirstOrDefault(x => (string.IsNullOrEmpty(model.ClientFIO) || x.ClientFIO == model.ClientFIO) && + (!model.Id.HasValue || x.Id == model.Id) && (string.IsNullOrEmpty(model.Email) || x.Email == model.Email) && + (string.IsNullOrEmpty(model.Password) || x.Password == model.Password)) + ?.GetViewModel; + } + public ClientViewModel? Insert(ClientBindingModel model) + { + model.Id = source.Clients.Count > 0 ? source.Clients.Max(x => + x.Id) + 1 : 1; + var newClient = Client.Create(model); + if (newClient == null) + { + return null; + } + source.Clients.Add(newClient); + source.SaveClients(); + return newClient.GetViewModel; + } + public ClientViewModel? Update(ClientBindingModel model) + { + var client = source.Clients.FirstOrDefault(x => x.Id == model.Id); + if (client == null) + { + return null; + } + client.Update(model); + source.SaveClients(); + return client.GetViewModel; + } + public ClientViewModel? Delete(ClientBindingModel model) + { + var element = source.Clients.FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + source.Clients.Remove(element); + source.SaveClients(); + return element.GetViewModel; + } + return null; + } + } +} diff --git a/ClothShop/ClothShopFileImplement/Models/Client.cs b/ClothShop/ClothShopFileImplement/Models/Client.cs new file mode 100644 index 0000000..3626388 --- /dev/null +++ b/ClothShop/ClothShopFileImplement/Models/Client.cs @@ -0,0 +1,72 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.ViewModels; +using ClothShopDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace ClothShopFileImplement.Models +{ + public class Client : IClientModel + { + public int Id { get; private set; } + public string ClientFIO { get; private set; } = string.Empty; + public string Email { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + public static Client? Create(ClientBindingModel model) + { + if (model == null) + { + return null; + } + return new Client() + { + Id = model.Id, + ClientFIO = model.ClientFIO, + Email = model.Email, + Password = model.Password + }; + } + public static Client? Create(XElement element) + { + if (element == null) + { + return null; + } + return new Client() + { + Id = Convert.ToInt32(element.Attribute("Id")!.Value), + ClientFIO = element.Element("ClientFIO")!.Value, + Email = element.Element("Email")!.Value, + Password = element.Element("Password")!.Value + }; + } + public void Update(ClientBindingModel model) + { + if (model == null) + { + return; + } + ClientFIO = model.ClientFIO; + Email = model.Email; + Password = model.Password; + } + public ClientViewModel GetViewModel => new() + { + Id = Id, + ClientFIO = ClientFIO, + Email = Email, + Password = Password + }; + + public XElement GetXElement => new("Client", + new XAttribute("Id", Id), + new XElement("ClientFIO", ClientFIO), + new XElement("Email", Email.ToString()), + new XElement("Password", Password.ToString()) + ); + } +} diff --git a/ClothShop/ClothShopFileImplement/Models/Order.cs b/ClothShop/ClothShopFileImplement/Models/Order.cs index f94ff2b..b4d7107 100644 --- a/ClothShop/ClothShopFileImplement/Models/Order.cs +++ b/ClothShop/ClothShopFileImplement/Models/Order.cs @@ -9,6 +9,7 @@ namespace ClothShopFileImplement.Models { public int Id { get; private set; } public int TextileId { get; private set; } + public int ClientId { get; private set; } public int Count { get; private set; } public double Sum { get; private set; } public OrderStatus Status { get; private set; } @@ -25,6 +26,7 @@ namespace ClothShopFileImplement.Models { Id = model.Id, TextileId = model.TextileId, + ClientId = model.ClientId, Count = model.Count, Sum = model.Sum, Status = model.Status, @@ -42,6 +44,7 @@ namespace ClothShopFileImplement.Models { Id = Convert.ToInt32(element.Attribute("Id")!.Value), TextileId = Convert.ToInt32(element.Element("TextileId")!.Value), + ClientId = Convert.ToInt32(element.Element("ClientId")!.Value), Count = Convert.ToInt32(element.Element("Count")!.Value), Sum = Convert.ToDouble(element.Element("Sum")!.Value), Status = (OrderStatus)Enum.Parse(typeof(OrderStatus), element.Element("Status")!.Value.ToString()), @@ -62,6 +65,7 @@ namespace ClothShopFileImplement.Models { Id = Id, TextileId = TextileId, + ClientId = ClientId, Count = Count, Sum = Sum, Status = Status, @@ -71,6 +75,7 @@ namespace ClothShopFileImplement.Models public XElement GetXElement => new("Order", new XAttribute("Id", Id), new XElement("TextileId", TextileId), + new XElement("ClientId", ClientId), new XElement("Sum", Sum.ToString()), new XElement("Count", Count), new XElement("Status", Status.ToString()), diff --git a/ClothShop/ClothShopListImplement/DataListSingleton.cs b/ClothShop/ClothShopListImplement/DataListSingleton.cs new file mode 100644 index 0000000..11d980f --- /dev/null +++ b/ClothShop/ClothShopListImplement/DataListSingleton.cs @@ -0,0 +1,35 @@ +using ClothShopListImplement.Models; +using System; +using System.Collections.Generic; + +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopListImplement +{ + public class DataListSingleton + { + private static DataListSingleton? _instance; + public List Components { get; set; } + public List Orders { get; set; } + public List Textiles { get; set; } + public List Clients { get; set; } + + private DataListSingleton() + { + Components = new List(); + Orders = new List(); + Textiles = new List(); + Clients = new List(); + } + public static DataListSingleton GetInstance() + { + if (_instance == null) + { + _instance = new DataListSingleton(); + } + return _instance; + } + } +} diff --git a/ClothShop/ClothShopListImplement/Implements/ClientStorage.cs b/ClothShop/ClothShopListImplement/Implements/ClientStorage.cs new file mode 100644 index 0000000..79b8bda --- /dev/null +++ b/ClothShop/ClothShopListImplement/Implements/ClientStorage.cs @@ -0,0 +1,104 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.SearchModels; +using ClothShopContracts.StoragesContracts; +using ClothShopContracts.ViewModels; +using ClothShopListImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopListImplement.Implements +{ + public class ClientStorage : IClientStorage + { + private readonly DataListSingleton _source; + public ClientStorage() + { + _source = DataListSingleton.GetInstance(); + } + public List GetFullList() + { + var result = new List(); + foreach (var client in _source.Clients) + { + result.Add(client.GetViewModel); + } + return result; + } + public List GetFilteredList(ClientSearchModel + model) + { + var result = new List(); + if (string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email) && string.IsNullOrEmpty(model.Password)) + { + return result; + } + foreach (var client in _source.Clients) + { + if (client.ClientFIO.Contains(model.ClientFIO)) + { + result.Add(client.GetViewModel); + } + } + return result; + } + public ClientViewModel? GetElement(ClientSearchModel model) + { + foreach (var client in _source.Clients) + { + if ((string.IsNullOrEmpty(model.ClientFIO) || client.ClientFIO == model.ClientFIO) && + (!model.Id.HasValue || client.Id == model.Id) && (string.IsNullOrEmpty(model.Email) || client.Email == model.Email) && + (string.IsNullOrEmpty(model.Password) || client.Password == model.Password)) + { + return client.GetViewModel; + } + } + return null; + } + public ClientViewModel? Insert(ClientBindingModel model) + { + model.Id = 1; + foreach (var client in _source.Clients) + { + if (model.Id <= client.Id) + { + model.Id = client.Id + 1; + } + } + var newClient = Client.Create(model); + if (newClient == null) + { + return null; + } + _source.Clients.Add(newClient); + return newClient.GetViewModel; + } + public ClientViewModel? Update(ClientBindingModel model) + { + foreach (var client in _source.Clients) + { + if (client.Id == model.Id) + { + client.Update(model); + return client.GetViewModel; + } + } + return null; + } + public ClientViewModel? Delete(ClientBindingModel model) + { + for (int i = 0; i < _source.Clients.Count; ++i) + { + if (_source.Clients[i].Id == model.Id) + { + var element = _source.Clients[i]; + _source.Clients.RemoveAt(i); + return element.GetViewModel; + } + } + return null; + } + } +} diff --git a/ClothShop/ClothShopListImplement/Implements/OrderStorage.cs b/ClothShop/ClothShopListImplement/Implements/OrderStorage.cs index 4f8b9aa..9b8c138 100644 --- a/ClothShop/ClothShopListImplement/Implements/OrderStorage.cs +++ b/ClothShop/ClothShopListImplement/Implements/OrderStorage.cs @@ -23,19 +23,21 @@ namespace ClothShopListImplement.Implements var result = new List(); foreach (var order in _source.Orders) { - result.Add(AcessDressesStorage(order.GetViewModel)); + result.Add(AccessTextileStorage(order.GetViewModel)); } return result; } public List GetFilteredList(OrderSearchModel model) { var result = new List(); - foreach (var order in _source.Orders) { - if (order.Id == model.Id) + if ((!model.Id.HasValue || order.Id == model.Id) && + (!model.DateFrom.HasValue || order.DateCreate >= model.DateFrom) && + (!model.DateTo.HasValue || order.DateCreate <= model.DateTo) && + (!model.ClientId.HasValue || order.ClientId == model.ClientId)) { - result.Add(AcessDressesStorage(order.GetViewModel)); + result.Add(AccessTextileStorage(order.GetViewModel)); } } return result; @@ -87,7 +89,7 @@ namespace ClothShopListImplement.Implements } public OrderViewModel? Delete(OrderBindingModel model) { - for (int i = 0; i < _source.Orders.Count; i++) + for (int i = 0; i < _source.Orders.Count; ++i) { if (_source.Orders[i].Id == model.Id) { @@ -98,17 +100,26 @@ namespace ClothShopListImplement.Implements } return null; } - public OrderViewModel AcessDressesStorage(OrderViewModel model) + + public OrderViewModel AccessTextileStorage(OrderViewModel model) { - foreach (var dress in _source.Textiles) + foreach (var Textile in _source.Textiles) { - if (dress.Id == model.TextileId) + if (Textile.Id == model.TextileId) { - model.TextileName = dress.TextileName; + model.TextileName = Textile.TextileName; break; } } return model; } + + public OrderViewModel AccessClientStorage(OrderViewModel model) + { + var client = _source.Clients.FirstOrDefault(x => x.Id == model.ClientId); + if (client != null) + model.ClientFIO = client.ClientFIO; + return model; + } } } diff --git a/ClothShop/ClothShopListImplement/Models/Client.cs b/ClothShop/ClothShopListImplement/Models/Client.cs new file mode 100644 index 0000000..d50a86e --- /dev/null +++ b/ClothShop/ClothShopListImplement/Models/Client.cs @@ -0,0 +1,50 @@ +using ClothShopContracts.BindingModels; +using ClothShopContracts.ViewModels; +using ClothShopDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClothShopListImplement.Models +{ + public class Client : IClientModel + { + public int Id { get; private set; } + public string ClientFIO { get; private set; } = string.Empty; + public string Email { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + public static Client? Create(ClientBindingModel model) + { + if (model == null) + { + return null; + } + return new Client() + { + Id = model.Id, + ClientFIO = model.ClientFIO, + Email = model.Email, + Password = model.Password + }; + } + public void Update(ClientBindingModel model) + { + if (model == null) + { + return; + } + ClientFIO = model.ClientFIO; + Email = model.Email; + Password = model.Password; + } + public ClientViewModel GetViewModel => new() + { + Id = Id, + ClientFIO = ClientFIO, + Email = Email, + Password = Password + }; + } +} diff --git a/ClothShop/ClothShopListImplement/Models/Order.cs b/ClothShop/ClothShopListImplement/Models/Order.cs index 31dd21b..a6c3bc0 100644 --- a/ClothShop/ClothShopListImplement/Models/Order.cs +++ b/ClothShop/ClothShopListImplement/Models/Order.cs @@ -13,6 +13,7 @@ namespace ClothShopListImplement.Models public class Order : IOrderModel { public int TextileId { get; private set; } + public int ClientId { get; private set; } public int Count { get; private set; } public double Sum { get; private set; } public OrderStatus Status { get; private set; } = OrderStatus.Неизвестен; @@ -28,6 +29,7 @@ namespace ClothShopListImplement.Models return new Order { TextileId = model.TextileId, + ClientId = model.ClientId, Count = model.Count, Sum = model.Sum, Status = model.Status, @@ -48,6 +50,7 @@ namespace ClothShopListImplement.Models public OrderViewModel GetViewModel => new() { TextileId = TextileId, + ClientId = ClientId, Count = Count, Sum = Sum, DateCreate = DateCreate, diff --git a/ClothShop/ClothShopView/Program.cs b/ClothShop/ClothShopView/Program.cs index 101db26..e0ec753 100644 --- a/ClothShop/ClothShopView/Program.cs +++ b/ClothShop/ClothShopView/Program.cs @@ -46,6 +46,8 @@ namespace ClothShopView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient();