Compare commits

...

28 Commits
main ... lab3

Author SHA1 Message Date
63668122c2 Начал реализацию логики форм;
Нужно доделать добавление продукта
2024-11-20 18:03:33 +04:00
de4a43be41 Добавил формы, нужно реализовать логику 2024-11-20 16:26:39 +04:00
d1b5b642ec Реализовал внедрение зависимостей 2024-11-20 16:14:23 +04:00
9b1c5ce5b9 Заменил модель на search в методе удаления из хранилища 2024-11-20 13:01:44 +04:00
fab697e3d6 Создал миграцию для инициализации БД 2024-11-20 12:42:08 +04:00
729df92e92 fix 2024-11-20 12:18:38 +04:00
1230cbb950 Реализовал хранилища БД 2024-11-20 12:14:16 +04:00
1814173da3 Реализовал подключение к БД и модели 2024-11-20 11:53:03 +04:00
f660eb0d47 Создал проект реализации хранения в БД 2024-11-20 10:38:20 +04:00
abd33d7f49 Реализовал логику доя товаров 2024-11-20 01:02:13 +04:00
4b21cfb004 Реализовал логику для заказов 2024-11-20 00:53:02 +04:00
3136067777 Создал классы логики, нужно реализовать 2024-11-20 00:27:36 +04:00
3140ab81a6 Обновил версию своего пакета 2024-11-20 00:07:46 +04:00
086eaa08cf Создал проект с реализацией логики 2024-11-19 22:48:09 +04:00
3b1a037e13 Добавил интерфейсы хранилищ 2024-11-19 22:41:03 +04:00
afc337a7ec Изменил структуру папки с логикой 2024-11-19 22:35:50 +04:00
677614a50e Добавил интерфейсы логики 2024-11-19 22:34:00 +04:00
3e356cb08e Добавил view модели 2024-11-19 22:23:42 +04:00
9f6b8ec085 Добавил search модели 2024-11-19 22:04:00 +04:00
fadc72399f Добавил биндинг модели 2024-11-19 21:40:30 +04:00
830442dfe1 Изменил поле продуктов в интерфейсе модели заказа 2024-11-19 21:40:12 +04:00
f838322500 Добавил проект контрактов 2024-11-19 21:19:25 +04:00
844d2d770b Добавил интерфейсы моделей данных 2024-11-19 21:09:33 +04:00
f00274367f Создал проект с моделями данных 2024-11-19 20:50:44 +04:00
b098bbc153 Поменял структуру папок проекта с формами 2024-11-19 20:45:29 +04:00
2ad53a08e5 Установил дополнительные компоненты 2024-11-19 20:43:39 +04:00
e7a62a55df Создал проект с формами 2024-11-19 20:39:03 +04:00
8d86e2b539 Создал решение 2024-11-19 20:33:11 +04:00
39 changed files with 1740 additions and 0 deletions

View File

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.11.35312.102
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InternetShopForms", "InternetShopForms\InternetShopForms.csproj", "{45D39595-B9F2-4F61-ADA5-ED4611FA5D0E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InternetShopDataModels", "InternetShopDataModels\InternetShopDataModels.csproj", "{FF513D7D-CB26-42A5-9BD8-A41CEEEC9076}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InternetShopContracts", "InternetShopContracts\InternetShopContracts.csproj", "{D9242FC8-6F64-4768-8966-218D2A0836C5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InternetShopLogics", "InternetShopLogics\InternetShopLogics.csproj", "{580875F9-D1E3-4BCE-9B91-5AE6DD10BD07}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InternetShopDatabase", "InternetShopDatabase\InternetShopDatabase.csproj", "{255BBE50-71EE-4E41-BDC8-4280CFB93D5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{45D39595-B9F2-4F61-ADA5-ED4611FA5D0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{45D39595-B9F2-4F61-ADA5-ED4611FA5D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45D39595-B9F2-4F61-ADA5-ED4611FA5D0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45D39595-B9F2-4F61-ADA5-ED4611FA5D0E}.Release|Any CPU.Build.0 = Release|Any CPU
{FF513D7D-CB26-42A5-9BD8-A41CEEEC9076}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF513D7D-CB26-42A5-9BD8-A41CEEEC9076}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF513D7D-CB26-42A5-9BD8-A41CEEEC9076}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF513D7D-CB26-42A5-9BD8-A41CEEEC9076}.Release|Any CPU.Build.0 = Release|Any CPU
{D9242FC8-6F64-4768-8966-218D2A0836C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9242FC8-6F64-4768-8966-218D2A0836C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9242FC8-6F64-4768-8966-218D2A0836C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9242FC8-6F64-4768-8966-218D2A0836C5}.Release|Any CPU.Build.0 = Release|Any CPU
{580875F9-D1E3-4BCE-9B91-5AE6DD10BD07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{580875F9-D1E3-4BCE-9B91-5AE6DD10BD07}.Debug|Any CPU.Build.0 = Debug|Any CPU
{580875F9-D1E3-4BCE-9B91-5AE6DD10BD07}.Release|Any CPU.ActiveCfg = Release|Any CPU
{580875F9-D1E3-4BCE-9B91-5AE6DD10BD07}.Release|Any CPU.Build.0 = Release|Any CPU
{255BBE50-71EE-4E41-BDC8-4280CFB93D5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{255BBE50-71EE-4E41-BDC8-4280CFB93D5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{255BBE50-71EE-4E41-BDC8-4280CFB93D5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{255BBE50-71EE-4E41-BDC8-4280CFB93D5D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2F5EC10C-8E7C-4B63-9AB3-39AA90257731}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,13 @@
using InternetShopDataModels.Models;
namespace InternetShopContracts.DataBindingModels
{
public class OrderBindingModel : IOrderModel
{
public string CustomerFIO { get; set; } = string.Empty;
public string CustomerEmail { get; set; } = string.Empty;
public string ImagePath { get; set; } = string.Empty;
public List<string> ProductNames { get; set; } = new List<string>();
public int Id { get; set; }
}
}

View File

@ -0,0 +1,10 @@
using InternetShopDataModels.Models;
namespace InternetShopContracts.DataBindingModels
{
public class ProductBindingModel : IProductModel
{
public string Name { get; set; } = string.Empty;
public int Id { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace InternetShopContracts.DataSearchModels
{
public class OrderSearchModel
{
public string? CustomerFIO { get; set; }
public string? CustomerEmail { get; set; }
public int? Id { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace InternetShopContracts.DataSearchModels
{
public class ProductSearchModel
{
public string? Name { get; set; }
public int? Id { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using InternetShopDataModels.Models;
using System.ComponentModel;
namespace InternetShopContracts.DataViewModels
{
public class OrderViewModel : IOrderModel
{
[DisplayName("ФИО заказчика")]
public string CustomerFIO { get; set; } = string.Empty;
[DisplayName("Email заказчика")]
public string CustomerEmail { get; set; } = string.Empty;
[DisplayName("Изображение")]
public string ImagePath { get; set; } = string.Empty;
[DisplayName("Товары")]
public List<string> ProductNames { get; set; } = new List<string>();
[DisplayName("ID")]
public int Id { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using InternetShopDataModels.Models;
using System.ComponentModel;
namespace InternetShopContracts.DataViewModels
{
public class ProductViewModel : IProductModel
{
[DisplayName("Название")]
public string Name { get; set; } = string.Empty;
[DisplayName("ID")]
public int Id { get; set; }
}
}

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\InternetShopDataModels\InternetShopDataModels.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,15 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
namespace InternetShopContracts.LogicsContracts
{
public interface IOrderLogic
{
List<OrderViewModel> ReadList(OrderSearchModel? model = null);
OrderViewModel? ReadElement(OrderSearchModel model);
bool Create(OrderBindingModel model);
bool Update(OrderBindingModel model);
bool Delete(OrderSearchModel model);
}
}

View File

@ -0,0 +1,15 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
namespace InternetShopContracts.LogicsContracts
{
public interface IProductLogic
{
List<ProductViewModel> ReadList(ProductSearchModel? model = null);
ProductViewModel? ReadElement(ProductSearchModel model);
bool Create(ProductBindingModel model);
bool Update(ProductBindingModel model);
bool Delete(ProductSearchModel model);
}
}

View File

@ -0,0 +1,16 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
namespace InternetShopContracts.StorageContracts
{
public interface IOrderStorage
{
List<OrderViewModel> GetFullList();
List<OrderViewModel> GetFilteredList(OrderSearchModel model);
OrderViewModel? GetElement(OrderSearchModel model);
OrderViewModel? Insert(OrderBindingModel model);
OrderViewModel? Update(OrderBindingModel model);
OrderViewModel? Delete(OrderSearchModel model);
}
}

View File

@ -0,0 +1,16 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
namespace InternetShopContracts.StorageContracts
{
public interface IProductStorage
{
List<ProductViewModel> GetFullList();
List<ProductViewModel> GetFilteredList(ProductSearchModel model);
ProductViewModel? GetElement(ProductSearchModel model);
ProductViewModel? Insert(ProductBindingModel model);
ProductViewModel? Update(ProductBindingModel model);
ProductViewModel? Delete(ProductSearchModel model);
}
}

View File

@ -0,0 +1,7 @@
namespace InternetShopDataModels
{
public interface IId
{
int Id { get; }
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,10 @@
namespace InternetShopDataModels.Models
{
public interface IOrderModel : IId
{
string CustomerFIO { get; }
string CustomerEmail { get; }
string ImagePath { get; }
List<string> ProductNames { get; }
}
}

View File

@ -0,0 +1,7 @@
namespace InternetShopDataModels.Models
{
public interface IProductModel : IId
{
string Name { get; }
}
}

View File

@ -0,0 +1,19 @@
using InternetShopDatabase.Models;
using Microsoft.EntityFrameworkCore;
namespace InternetShopDatabase
{
public class InternetShopDatabase : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (optionsBuilder.IsConfigured == false)
{
optionsBuilder.UseSqlServer(@"Data Source=tcp:127.0.0.1;Initial Catalog=internetShopBase;User ID=SA;Password=87cbn9y48392nu32;TrustServerCertificate=true;");
}
base.OnConfiguring(optionsBuilder);
}
public virtual DbSet<Order> Orders { set; get; }
public virtual DbSet<Product> Products { set; get; }
}
}

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\InternetShopContracts\InternetShopContracts.csproj" />
<ProjectReference Include="..\InternetShopDataModels\InternetShopDataModels.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,75 @@
// <auto-generated />
using InternetShopDatabase;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace InternetShopDatabase.Migrations
{
[DbContext(typeof(InternetShopDatabase))]
[Migration("20241120083224_InitialMigration")]
partial class InitialMigration
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("InternetShopDatabase.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("CustomerEmail")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("CustomerFIO")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ImagePath")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.PrimitiveCollection<string>("ProductNames")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Orders");
});
modelBuilder.Entity("InternetShopDatabase.Models.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Products");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace InternetShopDatabase.Migrations
{
/// <inheritdoc />
public partial class InitialMigration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Orders",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
CustomerFIO = table.Column<string>(type: "nvarchar(max)", nullable: false),
CustomerEmail = table.Column<string>(type: "nvarchar(max)", nullable: false),
ImagePath = table.Column<string>(type: "nvarchar(max)", nullable: false),
ProductNames = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Orders", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Orders");
migrationBuilder.DropTable(
name: "Products");
}
}
}

View File

@ -0,0 +1,72 @@
// <auto-generated />
using InternetShopDatabase;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace InternetShopDatabase.Migrations
{
[DbContext(typeof(InternetShopDatabase))]
partial class InternetShopDatabaseModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("InternetShopDatabase.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("CustomerEmail")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("CustomerFIO")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ImagePath")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.PrimitiveCollection<string>("ProductNames")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Orders");
});
modelBuilder.Entity("InternetShopDatabase.Models.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Products");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,45 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataViewModels;
using InternetShopDataModels.Models;
using System.ComponentModel.DataAnnotations;
namespace InternetShopDatabase.Models
{
public class Order : IOrderModel
{
[Required]
public string CustomerFIO { get; set; } = string.Empty;
[Required]
public string CustomerEmail { get; set; } = string.Empty;
[Required]
public string ImagePath { get; set; } = string.Empty;
public List<string> ProductNames { get; set; } = new List<string>();
public int Id { get; set; }
public OrderViewModel GetViewModel => new()
{
Id = Id,
CustomerFIO = CustomerFIO,
CustomerEmail = CustomerEmail,
ImagePath = ImagePath,
ProductNames = ProductNames,
};
public static Order Create(OrderBindingModel model)
{
return new Order()
{
Id = model.Id,
CustomerFIO = model.CustomerFIO,
CustomerEmail = model.CustomerEmail,
ImagePath = model.ImagePath,
ProductNames = model.ProductNames,
};
}
public void Update(OrderBindingModel model)
{
CustomerFIO = model.CustomerFIO;
CustomerEmail = model.CustomerEmail;
ImagePath = model.ImagePath;
ProductNames = model.ProductNames;
}
}
}

View File

@ -0,0 +1,31 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataViewModels;
using InternetShopDataModels.Models;
using System.ComponentModel.DataAnnotations;
namespace InternetShopDatabase.Models
{
public class Product : IProductModel
{
[Required]
public string Name { get; set; } = string.Empty;
public int Id { get; set; }
public ProductViewModel GetViewModel => new()
{
Id = Id,
Name = Name,
};
public static Product Create(ProductBindingModel model)
{
return new Product()
{
Id = model.Id,
Name = model.Name,
};
}
public void Update(ProductBindingModel model)
{
Name = model.Name;
}
}
}

View File

@ -0,0 +1,75 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.StorageContracts;
using InternetShopDatabase.Models;
namespace InternetShopDatabase.Storages
{
public class OrderStorage : IOrderStorage
{
public OrderViewModel? Delete(OrderSearchModel model)
{
using var context = new InternetShopDatabase();
var item = context.Orders.FirstOrDefault(rec => rec.Id == model.Id);
if (item != null)
{
context.Orders.Remove(item);
context.SaveChanges();
return item.GetViewModel;
}
return null;
}
public OrderViewModel? GetElement(OrderSearchModel model)
{
return GetFilteredList(model).FirstOrDefault();
}
public List<OrderViewModel> GetFilteredList(OrderSearchModel model)
{
var elements = GetFullList();
if (model.Id != null)
{
elements = elements.Where(x => x.Id == model.Id).ToList();
}
if (model.CustomerFIO != null)
{
elements = elements.Where(x => x.CustomerFIO.Contains(model.CustomerFIO)).ToList();
}
if (model.CustomerEmail != null)
{
elements = elements.Where(x => x.CustomerEmail.Contains(model.CustomerEmail)).ToList();
}
return elements;
}
public List<OrderViewModel> GetFullList()
{
using var context = new InternetShopDatabase();
return context.Orders.Select(x => x.GetViewModel).ToList();
}
public OrderViewModel? Insert(OrderBindingModel model)
{
using var context = new InternetShopDatabase();
var item = Order.Create(model);
context.Orders.Add(item);
context.SaveChanges();
return item.GetViewModel;
}
public OrderViewModel? Update(OrderBindingModel model)
{
using var context = new InternetShopDatabase();
var item = context.Orders.FirstOrDefault(x => x.Id == model.Id);
if (item == null)
{
return null;
}
item.Update(model);
context.SaveChanges();
return item.GetViewModel;
}
}
}

View File

@ -0,0 +1,71 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.StorageContracts;
using InternetShopDatabase.Models;
namespace InternetShopDatabase.Storages
{
public class ProductStorage : IProductStorage
{
public ProductViewModel? Delete(ProductSearchModel model)
{
using var context = new InternetShopDatabase();
var item = context.Products.FirstOrDefault(rec => rec.Id == model.Id);
if (item != null)
{
context.Products.Remove(item);
context.SaveChanges();
return item.GetViewModel;
}
return null;
}
public ProductViewModel? GetElement(ProductSearchModel model)
{
return GetFilteredList(model).FirstOrDefault();
}
public List<ProductViewModel> GetFilteredList(ProductSearchModel model)
{
var elements = GetFullList();
if (model.Id != null)
{
elements = elements.Where(x => x.Id == model.Id).ToList();
}
if (model.Name != null)
{
elements = elements.Where(x => x.Name.Contains(model.Name)).ToList();
}
return elements;
}
public List<ProductViewModel> GetFullList()
{
using var context = new InternetShopDatabase();
return context.Products.Select(x => x.GetViewModel).ToList();
}
public ProductViewModel Insert(ProductBindingModel model)
{
using var context = new InternetShopDatabase();
var item = Product.Create(model);
context.Products.Add(item);
context.SaveChanges();
return item.GetViewModel;
}
public ProductViewModel? Update(ProductBindingModel model)
{
using var context = new InternetShopDatabase();
var item = context.Products.FirstOrDefault(x => x.Id == model.Id);
if (item == null)
{
return null;
}
item.Update(model);
context.SaveChanges();
return item.GetViewModel;
}
}
}

View File

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Components" Version="1.0.1" />
<PackageReference Include="FixedWinFormsLibrary1" Version="1.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="UserComponentsOption19" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\InternetShopContracts\InternetShopContracts.csproj" />
<ProjectReference Include="..\InternetShopDatabase\InternetShopDatabase.csproj" />
<ProjectReference Include="..\InternetShopLogics\InternetShopLogics.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,45 @@
namespace InternetShopForms.Orders
{
partial class FormOrderEdit
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
SuspendLayout();
//
// FormOrderEdit
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Name = "FormOrderEdit";
Text = "Заказ";
ResumeLayout(false);
}
#endregion
}
}

View File

@ -0,0 +1,14 @@
using InternetShopContracts.LogicsContracts;
namespace InternetShopForms.Orders
{
public partial class FormOrderEdit : Form
{
private IOrderLogic _orderLogic;
public FormOrderEdit(IOrderLogic orderLogic)
{
InitializeComponent();
_orderLogic = orderLogic;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,117 @@
namespace InternetShopForms
{
partial class FormOrdersList
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
tableComponent = new WinFormsLibrary1.TableComponent();
menuStrip = new MenuStrip();
productsToolStripMenuItem = new ToolStripMenuItem();
reportsToolStripMenuItem = new ToolStripMenuItem();
reportOrderImagesExcelToolStripMenuItem = new ToolStripMenuItem();
reportOrdersWordToolStripMenuItem = new ToolStripMenuItem();
reportProductsPDFToolStripMenuItem = new ToolStripMenuItem();
menuStrip.SuspendLayout();
SuspendLayout();
//
// tableComponent
//
tableComponent.Dock = DockStyle.Fill;
tableComponent.Location = new Point(0, 28);
tableComponent.Margin = new Padding(3, 4, 3, 4);
tableComponent.Name = "tableComponent";
tableComponent.Size = new Size(887, 361);
tableComponent.TabIndex = 1;
//
// menuStrip
//
menuStrip.ImageScalingSize = new Size(20, 20);
menuStrip.Items.AddRange(new ToolStripItem[] { productsToolStripMenuItem, reportsToolStripMenuItem });
menuStrip.Location = new Point(0, 0);
menuStrip.Name = "menuStrip";
menuStrip.Size = new Size(887, 28);
menuStrip.TabIndex = 2;
menuStrip.Text = "menuStrip1";
//
// productsToolStripMenuItem
//
productsToolStripMenuItem.Name = "productsToolStripMenuItem";
productsToolStripMenuItem.Size = new Size(134, 24);
productsToolStripMenuItem.Text = "Список товаров";
productsToolStripMenuItem.Click += productsToolStripMenuItem_Click;
//
// reportsToolStripMenuItem
//
reportsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { reportOrderImagesExcelToolStripMenuItem, reportOrdersWordToolStripMenuItem, reportProductsPDFToolStripMenuItem });
reportsToolStripMenuItem.Name = "reportsToolStripMenuItem";
reportsToolStripMenuItem.Size = new Size(73, 24);
reportsToolStripMenuItem.Text = "Отчеты";
//
// reportOrderImagesExcelToolStripMenuItem
//
reportOrderImagesExcelToolStripMenuItem.Name = "reportOrderImagesExcelToolStripMenuItem";
reportOrderImagesExcelToolStripMenuItem.Size = new Size(296, 26);
reportOrderImagesExcelToolStripMenuItem.Text = "Изображения заказов (Excel)";
//
// reportOrdersWordToolStripMenuItem
//
reportOrdersWordToolStripMenuItem.Name = "reportOrdersWordToolStripMenuItem";
reportOrdersWordToolStripMenuItem.Size = new Size(296, 26);
reportOrdersWordToolStripMenuItem.Text = "Отчет по заказам (Word)";
//
// reportProductsPDFToolStripMenuItem
//
reportProductsPDFToolStripMenuItem.Name = "reportProductsPDFToolStripMenuItem";
reportProductsPDFToolStripMenuItem.Size = new Size(296, 26);
reportProductsPDFToolStripMenuItem.Text = "Отчет по товарам (PDF)";
//
// FormOrdersList
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(887, 389);
Controls.Add(tableComponent);
Controls.Add(menuStrip);
MainMenuStrip = menuStrip;
Name = "FormOrdersList";
Text = "Заказы";
menuStrip.ResumeLayout(false);
menuStrip.PerformLayout();
ResumeLayout(false);
PerformLayout();
}
#endregion
private WinFormsLibrary1.TableComponent tableComponent;
private MenuStrip menuStrip;
private ToolStripMenuItem productsToolStripMenuItem;
private ToolStripMenuItem reportsToolStripMenuItem;
private ToolStripMenuItem reportOrderImagesExcelToolStripMenuItem;
private ToolStripMenuItem reportOrdersWordToolStripMenuItem;
private ToolStripMenuItem reportProductsPDFToolStripMenuItem;
}
}

View File

@ -0,0 +1,24 @@
using InternetShopContracts.LogicsContracts;
using InternetShopForms.Products;
namespace InternetShopForms
{
public partial class FormOrdersList : Form
{
private IOrderLogic _orderLogic;
public FormOrdersList(IOrderLogic orderLogic)
{
InitializeComponent();
_orderLogic = orderLogic;
}
private void productsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormProductsList));
if (service is FormProductsList form)
{
form.ShowDialog();
}
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,73 @@
namespace InternetShopForms.Products
{
partial class FormProductsList
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
dataGridView = new DataGridView();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToResizeColumns = false;
dataGridView.AllowUserToResizeRows = false;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(0, 0);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.RowHeadersVisible = false;
dataGridView.RowHeadersWidth = 51;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(310, 450);
dataGridView.TabIndex = 0;
dataGridView.CellEndEdit += dataGridView_CellEndEdit;
dataGridView.CellValidating += dataGridView_CellValidating;
//
// FormProductsList
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(310, 450);
Controls.Add(dataGridView);
Name = "FormProductsList";
Text = "Список товаров";
Load += FormProductsList_Load;
KeyDown += FormProductsList_KeyDown;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
}
}

View File

@ -0,0 +1,137 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.LogicsContracts;
namespace InternetShopForms.Products
{
public partial class FormProductsList : Form
{
private IProductLogic _productLogic;
private List<ProductViewModel> _products;
public FormProductsList(IProductLogic productLogic)
{
InitializeComponent();
_productLogic = productLogic;
KeyPreview = true;
}
private void FormProductsList_Load(object sender, EventArgs e)
{
var idColumn = new DataGridViewColumn();
var nameColumn = new DataGridViewColumn();
var dataGridViewCell = new DataGridViewTextBoxCell();
idColumn.Visible = false;
idColumn.DataPropertyName = "Id";
idColumn.Name = "Id";
idColumn.CellTemplate = dataGridViewCell;
nameColumn.DataPropertyName = "Name";
nameColumn.HeaderText = "Название";
nameColumn.Name = "Name";
nameColumn.CellTemplate = dataGridViewCell;
dataGridView.Columns.Add(idColumn);
dataGridView.Columns.Add(nameColumn);
LoadData();
}
private void LoadData()
{
try
{
_products = _productLogic.ReadList();
dataGridView.Rows.Clear();
foreach (var product in _products)
{
dataGridView.Rows.Add(product);
}
}
catch (Exception ex)
{
MessageBox.Show("Произошла ошибка при загрузке данных:\n" + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormProductsList_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Insert)
{
dataGridView.Rows.Add();
dataGridView.CurrentCell = dataGridView.Rows[dataGridView.RowCount - 1].Cells[1];
e.Handled = true;
}
else if (e.KeyCode == Keys.Delete)
{
if (dataGridView.SelectedRows.Count == 1)
{
DataGridViewRow selectedRow = dataGridView.SelectedRows[0];
var selectedItemIdValue = selectedRow.Cells["Id"].Value;
if (selectedItemIdValue == null)
{
dataGridView.Rows.Remove(selectedRow);
return;
}
int selectedItemId = Convert.ToInt32(selectedItemIdValue);
string selectedItemName = (string)selectedRow.Cells["Name"].Value;
var result = MessageBox.Show(
$"Удалить товар \"{selectedRow.Cells["Id"].Value}\"?",
"Подтверждение",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question
);
if (result == DialogResult.Yes)
{
if (_productLogic.Delete(new ProductSearchModel { Id = selectedItemId }))
{
MessageBox.Show($"Товар \"{selectedItemName}\" удален");
LoadData();
}
else
{
MessageBox.Show("Ошибка удаления", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
try
{
DataGridViewRow currentRow = dataGridView.Rows[e.RowIndex];
if (currentRow.Cells["Id"].Value == null || Convert.ToInt32(currentRow.Cells["Id"].Value) == 0)
{
_productLogic.Create(new ProductBindingModel
{
Name = currentRow.Cells["Name"].Value.ToString()!,
});
}
else
{
_productLogic.Update(new ProductBindingModel
{
Id = Convert.ToInt32(currentRow.Cells["Id"].Value),
Name = currentRow.Cells["Name"].Value.ToString(),
});
}
MessageBox.Show("Запись сохранена");
}
catch (Exception ex)
{
MessageBox.Show("Ошибка сохранения:\n" + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
string? userInput = e.FormattedValue.ToString();
if (string.IsNullOrWhiteSpace(userInput))
{
MessageBox.Show("Нельзя сохранить пустую строку", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
e.Cancel = true;
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,42 @@
using InternetShopContracts.LogicsContracts;
using InternetShopContracts.StorageContracts;
using InternetShopDatabase.Storages;
using InternetShopForms.Orders;
using InternetShopForms.Products;
using InternetShopLogics.Logics;
using Microsoft.Extensions.DependencyInjection;
namespace InternetShopForms
{
internal static class Program
{
private static ServiceProvider? _serviceProvider;
public static ServiceProvider? ServiceProvider => _serviceProvider;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
var services = new ServiceCollection();
ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider();
Application.Run(_serviceProvider.GetRequiredService<FormOrdersList>());
}
private static void ConfigureServices(ServiceCollection services)
{
services.AddTransient<IOrderStorage, OrderStorage>();
services.AddTransient<IProductStorage, ProductStorage>();
services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<IProductLogic, ProductLogic>();
services.AddTransient<FormOrdersList>();
services.AddTransient<FormOrderEdit>();
services.AddTransient<FormProductsList>();
}
}
}

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\InternetShopContracts\InternetShopContracts.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,100 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.LogicsContracts;
using InternetShopContracts.StorageContracts;
namespace InternetShopLogics.Logics
{
public class OrderLogic : IOrderLogic
{
private IOrderStorage _orderStorage;
public OrderLogic(IOrderStorage orderStorage)
{
_orderStorage = orderStorage;
}
public bool Create(OrderBindingModel model)
{
CheckModel(model);
if (_orderStorage.Insert(model) == null)
{
return false;
}
return true;
}
public bool Delete(OrderSearchModel model)
{
if (_orderStorage.Delete(model) == null)
{
return false;
}
return true;
}
public OrderViewModel? ReadElement(OrderSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
return _orderStorage.GetElement(model);
}
public List<OrderViewModel> ReadList(OrderSearchModel? model = null)
{
List<OrderViewModel>? list = null;
if (model == null)
{
list = _orderStorage.GetFullList();
}
else
{
list = _orderStorage.GetFilteredList(model);
}
if (list == null)
{
return new List<OrderViewModel>();
}
return list;
}
public bool Update(OrderBindingModel model)
{
CheckModel(model);
if (_orderStorage.Update(model) == null)
{
return false;
}
return true;
}
private void CheckModel(OrderBindingModel model, bool checkParams = true)
{
if (model == null) throw new ArgumentNullException(nameof(model));
if (!checkParams) return;
if (string.IsNullOrEmpty(model.CustomerFIO))
{
throw new ArgumentNullException("Нет фио заказчика", nameof(model.CustomerFIO));
}
if (string.IsNullOrEmpty(model.CustomerEmail))
{
throw new ArgumentNullException("Нет email заказчика", nameof(model.CustomerEmail));
}
if (string.IsNullOrEmpty(model.ImagePath))
{
throw new ArgumentNullException("Нет фото заказа", nameof(model.ImagePath));
}
if (model.ProductNames == null)
{
throw new ArgumentNullException("Список товаров не инициализирован", nameof(model.ProductNames));
}
else if (model.ProductNames.Count == 0)
{
throw new ArgumentException("Список товаров пуст", nameof(model.ProductNames));
}
}
}
}

View File

@ -0,0 +1,92 @@
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.LogicsContracts;
using InternetShopContracts.StorageContracts;
namespace InternetShopLogics.Logics
{
public class ProductLogic : IProductLogic
{
private IProductStorage _productStorage;
public ProductLogic(IProductStorage productStorage)
{
_productStorage = productStorage;
}
public bool Create(ProductBindingModel model)
{
CheckModel(model);
if (_productStorage.Insert(model) == null)
{
return false;
}
return true;
}
public bool Delete(ProductSearchModel model)
{
if (_productStorage.Delete(model) == null)
{
return false;
}
return true;
}
public ProductViewModel? ReadElement(ProductSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
return _productStorage.GetElement(model);
}
public List<ProductViewModel> ReadList(ProductSearchModel? model = null)
{
List<ProductViewModel>? list = null;
if (model == null)
{
list = _productStorage.GetFullList();
}
else
{
list = _productStorage.GetFilteredList(model);
}
if (list == null)
{
return new List<ProductViewModel>();
}
return list;
}
public bool Update(ProductBindingModel model)
{
CheckModel(model);
if (_productStorage.Update(model) == null)
{
return false;
}
return true;
}
private void CheckModel(ProductBindingModel model, bool checkParams = true)
{
if (model == null) throw new ArgumentNullException(nameof(model));
if (!checkParams) return;
if (string.IsNullOrEmpty(model.Name))
{
throw new ArgumentNullException("Нет названия товара", nameof(model.Name));
}
var item = _productStorage.GetElement(new ProductSearchModel
{
Name = model.Name
});
if (item != null && item.Id != model.Id)
{
throw new InvalidOperationException("Товар с таким названием уже есть");
}
}
}
}