From 2b8621489422169c3e84f2e102a83fc73b479012 Mon Sep 17 00:00:00 2001 From: Timourka Date: Sun, 10 Mar 2024 18:53:43 +0400 Subject: [PATCH] LC3 done --- .../AutomobilePlantDatabase.cs | 2 + .../Implements/ShopStorage.cs | 143 ++++++++++ .../20240310130521_HardMbINeedIt.Designer.cs | 248 ++++++++++++++++++ .../20240310130521_HardMbINeedIt.cs | 78 ++++++ .../AutomobilePlantDatabaseModelSnapshot.cs | 77 ++++++ .../Models/Shop.cs | 114 ++++++++ .../Models/ShopCar.cs | 22 ++ 7 files changed, 684 insertions(+) create mode 100644 AutomobilePlant/AutomobilePlantDatabaseImplement/Implements/ShopStorage.cs create mode 100644 AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.Designer.cs create mode 100644 AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.cs create mode 100644 AutomobilePlant/AutomobilePlantDatabaseImplement/Models/Shop.cs create mode 100644 AutomobilePlant/AutomobilePlantDatabaseImplement/Models/ShopCar.cs diff --git a/AutomobilePlant/AutomobilePlantDatabaseImplement/AutomobilePlantDatabase.cs b/AutomobilePlant/AutomobilePlantDatabaseImplement/AutomobilePlantDatabase.cs index 1c1a8b5..8b38532 100644 --- a/AutomobilePlant/AutomobilePlantDatabaseImplement/AutomobilePlantDatabase.cs +++ b/AutomobilePlant/AutomobilePlantDatabaseImplement/AutomobilePlantDatabase.cs @@ -17,5 +17,7 @@ namespace AutomobilePlantDatabaseImplement public virtual DbSet Cars { set; get; } public virtual DbSet CarComponents { set; get; } public virtual DbSet Orders { set; get; } + public virtual DbSet Shops { set; get; } + public virtual DbSet ShopCars { set; get; } } } diff --git a/AutomobilePlant/AutomobilePlantDatabaseImplement/Implements/ShopStorage.cs b/AutomobilePlant/AutomobilePlantDatabaseImplement/Implements/ShopStorage.cs new file mode 100644 index 0000000..bb23a76 --- /dev/null +++ b/AutomobilePlant/AutomobilePlantDatabaseImplement/Implements/ShopStorage.cs @@ -0,0 +1,143 @@ +using AutomobilePlantContracts.BindingModels; +using AutomobilePlantContracts.SearchModels; +using AutomobilePlantContracts.StoragesContracts; +using AutomobilePlantContracts.ViewModels; +using AutomobilePlantDatabaseImplement.Models; +using AutomobilePlantDataModels.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AutomobilePlantDatabaseImplement.Implements +{ + public class ShopStorage : IShopStorage + { + public ShopViewModel? GetElement(ShopSearchModel model) + { + if (string.IsNullOrEmpty(model.Name) && !model.Id.HasValue) + { + return new(); + } + using var context = new AutomobilePlantDatabase(); + return context.Shops.Include(x => x.Cars).ThenInclude(x => x.Car).FirstOrDefault(x => + (!string.IsNullOrEmpty(model.Name) && x.Name == model.Name) || + (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; + } + + public List GetFilteredList(ShopSearchModel model) + { + if (string.IsNullOrEmpty(model.Name)) + { + return new(); + } + using var context = new AutomobilePlantDatabase(); + return context.Shops.Include(x => x.Cars).ThenInclude(x => x.Car).Where(x => x.Name.Contains(model.Name)).ToList().Select(x => x.GetViewModel).ToList(); + } + + public List GetFullList() + { + using var context = new AutomobilePlantDatabase(); + return context.Shops.Include(x => x.Cars).ThenInclude(x => x.Car).ToList().Select(x => x.GetViewModel).ToList(); + } + + public ShopViewModel? Insert(ShopBindingModel model) + { + using var context = new AutomobilePlantDatabase(); + using var transaction = context.Database.BeginTransaction(); + try + { + var newShop = Shop.Create(context, model); + if (newShop == null) + { + return null; + } + if (context.Shops.Any(x => x.Name == newShop.Name)) + { + throw new Exception("Название магазина уже занято"); + } + + context.Shops.Add(newShop); + context.SaveChanges(); + transaction.Commit(); + return newShop.GetViewModel; + } + catch + { + transaction.Rollback(); + throw; + } + } + + public ShopViewModel? Update(ShopBindingModel model) + { + using var context = new AutomobilePlantDatabase(); + using var transaction = context.Database.BeginTransaction(); + try + { + var shop = context.Shops.Include(x => x.Cars).FirstOrDefault(x => x.Id == model.Id); + if (shop == null) + { + return null; + } + shop.Update(model); + context.SaveChanges(); + if (model.ShopCars.Count > 0) + { + shop.UpdateCars(context, model); + } + transaction.Commit(); + return shop.GetViewModel; + } + catch + { + transaction.Rollback(); + throw; + } + } + public ShopViewModel? Delete(ShopBindingModel model) + { + using var context = new AutomobilePlantDatabase(); + var shop = context.Shops.Include(x => x.Cars).FirstOrDefault(x => x.Id == model.Id); + if (shop != null) + { + context.Shops.Remove(shop); + context.SaveChanges(); + return shop.GetViewModel; + } + return null; + } + + public bool SellCar(ICarModel model, int count) + { + using var context = new AutomobilePlantDatabase(); + using var transaction = context.Database.BeginTransaction(); + + foreach (var shopCars in context.ShopCars.Where(x => x.CarId == model.Id)) + { + var min = Math.Min(count, shopCars.Count); + shopCars.Count -= min; + count -= min; + if (count <= 0) + { + break; + } + } + + if (count == 0) + { + context.SaveChanges(); + transaction.Commit(); + } + else + transaction.Rollback(); + + if (count > 0) + return false; + + return true; + } + } +} diff --git a/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.Designer.cs b/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.Designer.cs new file mode 100644 index 0000000..df2c9e6 --- /dev/null +++ b/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.Designer.cs @@ -0,0 +1,248 @@ +// +using System; +using AutomobilePlantDatabaseImplement; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace AutomobilePlantDatabaseImplement.Migrations +{ + [DbContext(typeof(AutomobilePlantDatabase))] + [Migration("20240310130521_HardMbINeedIt")] + partial class HardMbINeedIt + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.16") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Car", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CarName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Cars"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.CarComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CarId") + .HasColumnType("int"); + + b.Property("ComponentId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CarId"); + + b.HasIndex("ComponentId"); + + b.ToTable("CarComponents"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ComponentName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Components"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CarId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateImplement") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Sum") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("CarId"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Shop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("MaxCountCars") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OpeningDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Shops"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.ShopCar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CarId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("ShopId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CarId"); + + b.HasIndex("ShopId"); + + b.ToTable("ShopCars"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.CarComponent", b => + { + b.HasOne("AutomobilePlantDatabaseImplement.Models.Car", "Car") + .WithMany("Components") + .HasForeignKey("CarId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AutomobilePlantDatabaseImplement.Models.Component", "Component") + .WithMany("ProductComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Car"); + + b.Navigation("Component"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Order", b => + { + b.HasOne("AutomobilePlantDatabaseImplement.Models.Car", "Car") + .WithMany("Orders") + .HasForeignKey("CarId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Car"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.ShopCar", b => + { + b.HasOne("AutomobilePlantDatabaseImplement.Models.Car", "Car") + .WithMany() + .HasForeignKey("CarId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AutomobilePlantDatabaseImplement.Models.Shop", "Shop") + .WithMany("Cars") + .HasForeignKey("ShopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Car"); + + b.Navigation("Shop"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Car", b => + { + b.Navigation("Components"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Component", b => + { + b.Navigation("ProductComponents"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Shop", b => + { + b.Navigation("Cars"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.cs b/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.cs new file mode 100644 index 0000000..33af8a9 --- /dev/null +++ b/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/20240310130521_HardMbINeedIt.cs @@ -0,0 +1,78 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AutomobilePlantDatabaseImplement.Migrations +{ + /// + public partial class HardMbINeedIt : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Shops", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: false), + Address = table.Column(type: "nvarchar(max)", nullable: false), + OpeningDate = table.Column(type: "datetime2", nullable: false), + MaxCountCars = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Shops", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ShopCars", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CarId = table.Column(type: "int", nullable: false), + ShopId = table.Column(type: "int", nullable: false), + Count = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ShopCars", x => x.Id); + table.ForeignKey( + name: "FK_ShopCars_Cars_CarId", + column: x => x.CarId, + principalTable: "Cars", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ShopCars_Shops_ShopId", + column: x => x.ShopId, + principalTable: "Shops", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ShopCars_CarId", + table: "ShopCars", + column: "CarId"); + + migrationBuilder.CreateIndex( + name: "IX_ShopCars_ShopId", + table: "ShopCars", + column: "ShopId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ShopCars"); + + migrationBuilder.DropTable( + name: "Shops"); + } + } +} diff --git a/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/AutomobilePlantDatabaseModelSnapshot.cs b/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/AutomobilePlantDatabaseModelSnapshot.cs index 9530642..9083828 100644 --- a/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/AutomobilePlantDatabaseModelSnapshot.cs +++ b/AutomobilePlant/AutomobilePlantDatabaseImplement/Migrations/AutomobilePlantDatabaseModelSnapshot.cs @@ -121,6 +121,59 @@ namespace AutomobilePlantDatabaseImplement.Migrations b.ToTable("Orders"); }); + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Shop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("MaxCountCars") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OpeningDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Shops"); + }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.ShopCar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CarId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("ShopId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CarId"); + + b.HasIndex("ShopId"); + + b.ToTable("ShopCars"); + }); + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.CarComponent", b => { b.HasOne("AutomobilePlantDatabaseImplement.Models.Car", "Car") @@ -151,6 +204,25 @@ namespace AutomobilePlantDatabaseImplement.Migrations b.Navigation("Car"); }); + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.ShopCar", b => + { + b.HasOne("AutomobilePlantDatabaseImplement.Models.Car", "Car") + .WithMany() + .HasForeignKey("CarId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AutomobilePlantDatabaseImplement.Models.Shop", "Shop") + .WithMany("Cars") + .HasForeignKey("ShopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Car"); + + b.Navigation("Shop"); + }); + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Car", b => { b.Navigation("Components"); @@ -162,6 +234,11 @@ namespace AutomobilePlantDatabaseImplement.Migrations { b.Navigation("ProductComponents"); }); + + modelBuilder.Entity("AutomobilePlantDatabaseImplement.Models.Shop", b => + { + b.Navigation("Cars"); + }); #pragma warning restore 612, 618 } } diff --git a/AutomobilePlant/AutomobilePlantDatabaseImplement/Models/Shop.cs b/AutomobilePlant/AutomobilePlantDatabaseImplement/Models/Shop.cs new file mode 100644 index 0000000..c37fc3f --- /dev/null +++ b/AutomobilePlant/AutomobilePlantDatabaseImplement/Models/Shop.cs @@ -0,0 +1,114 @@ +using AutomobilePlantContracts.BindingModels; +using AutomobilePlantContracts.ViewModels; +using AutomobilePlantDataModels.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 AutomobilePlantDatabaseImplement.Models +{ + public class Shop : IShopModel + { + public int Id { get; set; } + + [Required] + public string Name { get; set; } = string.Empty; + + [Required] + public string Address { get; set; } = string.Empty; + + [Required] + public DateTime OpeningDate { get; set; } + + [ForeignKey("ShopId")] + public List Cars { get; set; } = new(); + + private Dictionary? _shopCars = null; + + [NotMapped] + public Dictionary ShopCars + { + get + { + if (_shopCars == null) + { + _shopCars = Cars.ToDictionary(recPC => recPC.CarId, recPC => (recPC.Car as ICarModel, recPC.Count)); + } + return _shopCars; + } + } + + [Required] + public int MaxCountCars { get; set; } + + public static Shop Create(AutomobilePlantDatabase context, ShopBindingModel model) + { + return new Shop() + { + Id = model.Id, + Name = model.Name, + Address = model.Address, + OpeningDate = model.OpeningDate, + Cars = model.ShopCars.Select(x => new ShopCar + { + Car = context.Cars.First(y => y.Id == x.Key), + Count = x.Value.Item2 + }).ToList(), + MaxCountCars = model.MaxCountCars + }; + } + + public void Update(ShopBindingModel model) + { + Name = model.Name; + Address = model.Address; + OpeningDate = model.OpeningDate; + MaxCountCars = model.MaxCountCars; + } + + public ShopViewModel GetViewModel => new() + { + Id = Id, + Name = Name, + Address = Address, + OpeningDate = OpeningDate, + ShopCars = ShopCars, + MaxCountCars = MaxCountCars + }; + + public void UpdateCars(AutomobilePlantDatabase context, ShopBindingModel model) + { + var ShopCars = context.ShopCars.Where(rec => rec.ShopId == model.Id).ToList(); + if (ShopCars != null && ShopCars.Count > 0) + { + // удалили те, которых нет в модели + context.ShopCars.RemoveRange(ShopCars.Where(rec => !model.ShopCars.ContainsKey(rec.CarId))); + context.SaveChanges(); + ShopCars = context.ShopCars.Where(rec => rec.ShopId == model.Id).ToList(); + // обновили количество у существующих записей + foreach (var updateCar in ShopCars) + { + updateCar.Count = model.ShopCars[updateCar.CarId].Item2; + model.ShopCars.Remove(updateCar.CarId); + } + context.SaveChanges(); + } + var shop = context.Shops.First(x => x.Id == Id); + foreach (var elem in model.ShopCars) + { + context.ShopCars.Add(new ShopCar + { + Shop = shop, + Car = context.Cars.First(x => x.Id == elem.Key), + Count = elem.Value.Item2 + }); + context.SaveChanges(); + } + _shopCars = null; + } + } +} diff --git a/AutomobilePlant/AutomobilePlantDatabaseImplement/Models/ShopCar.cs b/AutomobilePlant/AutomobilePlantDatabaseImplement/Models/ShopCar.cs new file mode 100644 index 0000000..3170589 --- /dev/null +++ b/AutomobilePlant/AutomobilePlantDatabaseImplement/Models/ShopCar.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace AutomobilePlantDatabaseImplement.Models +{ + public class ShopCar + { + public int Id { get; set; } + + [Required] + public int CarId { get; set; } + + [Required] + public int ShopId { get; set; } + + [Required] + public int Count { get; set; } + + public virtual Shop Shop { get; set; } = new(); + + public virtual Car Car { get; set; } = new(); + } +}