Compare commits

...

47 Commits
main ... lab4

Author SHA1 Message Date
5cd329c9bf Пофиксил документы, все работает 2024-12-15 02:36:18 +04:00
27bae95eaa Работают плагины, нужно разобраться с документами 2024-12-15 02:09:41 +04:00
858b0bc76b Реализовал класс для подключения плагина 2024-12-15 01:39:07 +04:00
b8f938b6e6 Добавил классы для работы плагинов в проект с формами 2024-12-15 00:45:51 +04:00
354d5f180d Реализовал форму для плагинов 2024-12-15 00:38:14 +04:00
71ff67396e Добавил форму для плагинов и настроил проект 2024-12-15 00:24:09 +04:00
b8ae78940c Добавил папку с плагинами в .gitignore 2024-12-15 00:17:47 +04:00
4fd4259f69 Создал классы для работы плагинов 2024-12-15 00:15:02 +04:00
e0b8f7eb2f Добавил проекты для классов плагинов 2024-12-15 00:02:44 +04:00
c7254999b0 Поправил экспорт отчета в ворд под новую версию библиотеки 2024-12-06 20:15:06 +04:00
08a481d8e6 Правка экспорта диаграммы в PDF
Теперь в диаграмме показаны все товары
2024-12-06 15:52:23 +04:00
9a85314694 Реализовал сохранение отчета в PDF 2024-12-06 15:34:00 +04:00
4144f645ad Реализовал отчет в word 2024-12-06 15:14:50 +04:00
29e97447b1 Начал реализацию отчета word 2024-12-04 18:02:24 +04:00
be8383f5b2 Реализовал отчет с фотографиями 2024-12-04 17:59:16 +04:00
0f80c8fa43 Работает добавление, редактирование и удаление заказов 2024-12-04 17:38:21 +04:00
e396435644 Реализовал отслеживание изменений на форме редактирования заказа 2024-12-04 16:36:07 +04:00
dbf68b6614 Начал реализацию логики основной формы 2024-12-04 15:54:03 +04:00
dbb2838638 Поправил баг при двойном нажатии Insert в списке продуктов 2024-12-04 12:10:03 +04:00
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
51 changed files with 3457 additions and 0 deletions

1
.gitignore vendored
View File

@ -398,3 +398,4 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
InternetShop/PluginApp/plugins/

View File

@ -0,0 +1,61 @@

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("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InternetShopDatabase", "InternetShopDatabase\InternetShopDatabase.csproj", "{255BBE50-71EE-4E41-BDC8-4280CFB93D5D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginApp", "PluginApp\PluginApp.csproj", "{EB4BEC60-76CF-49DA-B11A-14AB5E78A217}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginConventions", "PluginConventions\PluginConventions.csproj", "{49E41741-AEBC-4675-852A-9AE3836AAD01}"
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
{EB4BEC60-76CF-49DA-B11A-14AB5E78A217}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB4BEC60-76CF-49DA-B11A-14AB5E78A217}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB4BEC60-76CF-49DA-B11A-14AB5E78A217}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB4BEC60-76CF-49DA-B11A-14AB5E78A217}.Release|Any CPU.Build.0 = Release|Any CPU
{49E41741-AEBC-4675-852A-9AE3836AAD01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{49E41741-AEBC-4675-852A-9AE3836AAD01}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49E41741-AEBC-4675-852A-9AE3836AAD01}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49E41741-AEBC-4675-852A-9AE3836AAD01}.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,25 @@
using InternetShopContracts.DataViewModels;
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; }
public static OrderBindingModel FromViewModel(OrderViewModel viewModel)
{
OrderBindingModel model = new OrderBindingModel();
model.Id = viewModel.Id;
model.CustomerFIO = viewModel.CustomerFIO;
model.CustomerEmail = viewModel.CustomerEmail;
model.ImagePath = viewModel.ImagePath;
model.ProductNames = viewModel.ProductNames;
return model;
}
}
}

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,30 @@
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; }
public string ProductsString
{
get
{
return string.Join(", ", ProductNames);
}
set
{
ProductNames = value.Split(',').Select(x => x.ToString().Trim()).ToList();
}
}
}
}

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,28 @@
<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.6" />
<PackageReference Include="FixedWinFormsLibrary1" Version="1.0.2" />
<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.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\InternetShopContracts\InternetShopContracts.csproj" />
<ProjectReference Include="..\InternetShopDatabase\InternetShopDatabase.csproj" />
<ProjectReference Include="..\InternetShopLogics\InternetShopLogics.csproj" />
<ProjectReference Include="..\PluginConventions\PluginConventions.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,192 @@
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()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormOrderEdit));
textBoxCustomerFIO = new TextBox();
labelCustomerFIO = new Label();
writeComponentCustomerEmail = new UserComponentsOption19.WriteComponent();
labelCustomerEmail = new Label();
labelOrderImage = new Label();
textBoxImagePath = new TextBox();
buttonSelectImage = new Button();
labelOrderProducts = new Label();
buttonAccept = new Button();
buttonCancel = new Button();
productsList = new Components.UserControlCheckedList();
SuspendLayout();
//
// textBoxCustomerFIO
//
textBoxCustomerFIO.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
textBoxCustomerFIO.Location = new Point(133, 6);
textBoxCustomerFIO.Name = "textBoxCustomerFIO";
textBoxCustomerFIO.PlaceholderText = "Иванов Иван Иванович";
textBoxCustomerFIO.Size = new Size(741, 27);
textBoxCustomerFIO.TabIndex = 0;
textBoxCustomerFIO.TextChanged += textBoxCustomerFIO_TextChanged;
//
// labelCustomerFIO
//
labelCustomerFIO.AutoSize = true;
labelCustomerFIO.Location = new Point(12, 9);
labelCustomerFIO.Name = "labelCustomerFIO";
labelCustomerFIO.Size = new Size(118, 20);
labelCustomerFIO.TabIndex = 1;
labelCustomerFIO.Text = "ФИО заказчика:";
//
// writeComponentCustomerEmail
//
writeComponentCustomerEmail.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
writeComponentCustomerEmail.Location = new Point(133, 39);
writeComponentCustomerEmail.Name = "writeComponentCustomerEmail";
writeComponentCustomerEmail.Size = new Size(741, 44);
writeComponentCustomerEmail.TabIndex = 2;
writeComponentCustomerEmail.Template = null;
//
// labelCustomerEmail
//
labelCustomerEmail.AutoSize = true;
labelCustomerEmail.Location = new Point(12, 46);
labelCustomerEmail.Name = "labelCustomerEmail";
labelCustomerEmail.Size = new Size(122, 20);
labelCustomerEmail.TabIndex = 3;
labelCustomerEmail.Text = "Email заказчика:";
//
// labelOrderImage
//
labelOrderImage.AutoSize = true;
labelOrderImage.Location = new Point(12, 86);
labelOrderImage.Name = "labelOrderImage";
labelOrderImage.Size = new Size(159, 20);
labelOrderImage.TabIndex = 4;
labelOrderImage.Text = "Изображение заказа:";
//
// textBoxImagePath
//
textBoxImagePath.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
textBoxImagePath.Location = new Point(177, 83);
textBoxImagePath.Name = "textBoxImagePath";
textBoxImagePath.Size = new Size(597, 27);
textBoxImagePath.TabIndex = 5;
textBoxImagePath.TextChanged += textBoxImagePath_TextChanged;
//
// buttonSelectImage
//
buttonSelectImage.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonSelectImage.Location = new Point(777, 82);
buttonSelectImage.Name = "buttonSelectImage";
buttonSelectImage.Size = new Size(97, 29);
buttonSelectImage.TabIndex = 6;
buttonSelectImage.Text = "Выбрать";
buttonSelectImage.UseVisualStyleBackColor = true;
buttonSelectImage.Click += buttonSelectImage_Click;
//
// labelOrderProducts
//
labelOrderProducts.AutoSize = true;
labelOrderProducts.Location = new Point(12, 131);
labelOrderProducts.Name = "labelOrderProducts";
labelOrderProducts.Size = new Size(138, 20);
labelOrderProducts.TabIndex = 8;
labelOrderProducts.Text = "Продукты в заказе";
//
// buttonAccept
//
buttonAccept.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonAccept.Location = new Point(777, 382);
buttonAccept.Name = "buttonAccept";
buttonAccept.Size = new Size(94, 29);
buttonAccept.TabIndex = 9;
buttonAccept.Text = "Сохранить";
buttonAccept.UseVisualStyleBackColor = true;
buttonAccept.Click += buttonAccept_Click;
//
// buttonCancel
//
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonCancel.Location = new Point(677, 382);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(94, 29);
buttonCancel.TabIndex = 10;
buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// productsList
//
productsList.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
productsList.BackColor = Color.Transparent;
productsList.CheckedItems = (List<string>)resources.GetObject("productsList.CheckedItems");
productsList.Location = new Point(12, 155);
productsList.Margin = new Padding(3, 4, 3, 4);
productsList.MaxCheckedItemsCount = 1;
productsList.Name = "productsList";
productsList.Size = new Size(557, 255);
productsList.TabIndex = 11;
//
// FormOrderEdit
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(886, 423);
Controls.Add(productsList);
Controls.Add(buttonCancel);
Controls.Add(buttonAccept);
Controls.Add(labelOrderProducts);
Controls.Add(buttonSelectImage);
Controls.Add(textBoxImagePath);
Controls.Add(labelOrderImage);
Controls.Add(labelCustomerEmail);
Controls.Add(writeComponentCustomerEmail);
Controls.Add(labelCustomerFIO);
Controls.Add(textBoxCustomerFIO);
Name = "FormOrderEdit";
Text = "Заказ";
FormClosing += FormOrderEdit_FormClosing;
Load += FormOrderEdit_Load;
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox textBoxCustomerFIO;
private Label labelCustomerFIO;
private UserComponentsOption19.WriteComponent writeComponentCustomerEmail;
private Label labelCustomerEmail;
private Label labelOrderImage;
private TextBox textBoxImagePath;
private Button buttonSelectImage;
private Label labelOrderProducts;
private Button buttonAccept;
private Button buttonCancel;
private Components.UserControlCheckedList productsList;
}
}

View File

@ -0,0 +1,191 @@
using DocumentFormat.OpenXml.Bibliography;
using InternetShopContracts.DataBindingModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.LogicsContracts;
using System.Text.RegularExpressions;
namespace InternetShopForms.Orders
{
public partial class FormOrderEdit : Form
{
private IOrderLogic _orderLogic;
private IProductLogic _productLogic;
public int? OrderId;
private bool IsFieldsChanged = false;
private bool IsFieldsSaved = false;
private string OriginalTitle;
private bool IsFormLoaded = false;
public FormOrderEdit(IOrderLogic orderLogic, IProductLogic productLogic)
{
InitializeComponent();
_orderLogic = orderLogic;
OriginalTitle = Text;
writeComponentCustomerEmail.ChangeText += textBoxCustomerEmail_Changed;
productsList.CheckedItemChanged += listBoxProductsList_Changed;
_productLogic = productLogic;
productsList.MaxCheckedItemsCount = 1000;
writeComponentCustomerEmail.Template = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
}
private void FieldChanged()
{
if (IsFormLoaded)
{
if (!IsFieldsChanged)
{
Text = OriginalTitle + "*";
}
IsFieldsChanged = true;
}
}
private void buttonSelectImage_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = "d:\\tmp";
openFileDialog.Filter = "Image files (*.jpg;*.png)|*.jpg;*.png|All files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string prevText = textBoxImagePath.Text;
textBoxImagePath.Text = openFileDialog.FileName;
if (prevText != textBoxImagePath.Text)
{
FieldChanged();
}
}
}
}
private void FormOrderEdit_Load(object sender, EventArgs e)
{
LoadProductsList();
if (OrderId != null)
{
LoadOrderData();
}
IsFormLoaded = true;
}
private void LoadProductsList()
{
var products = _productLogic.ReadList();
productsList.SetCheckedListBoxValues(products.Select(x => x.Name).ToList());
}
private void LoadOrderData()
{
OrderViewModel? orderViewModel = _orderLogic.ReadElement(
new InternetShopContracts.DataSearchModels.OrderSearchModel { Id = OrderId }
);
if (orderViewModel == null)
{
MessageBox.Show("Заказ не найден", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
textBoxCustomerFIO.Text = orderViewModel.CustomerFIO;
textBoxImagePath.Text = orderViewModel.ImagePath;
writeComponentCustomerEmail.WriteTextInTextBox = orderViewModel.CustomerEmail;
productsList.CheckedItems = orderViewModel.ProductNames;
}
private void FormOrderEdit_FormClosing(object sender, FormClosingEventArgs e)
{
if (IsFieldsChanged && !IsFieldsSaved)
{
DialogResult result = MessageBox.Show("Изменения не сохранятся, вы хотите выйти?",
"Предупреждение", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No)
{
e.Cancel = true;
}
}
}
private void textBoxCustomerFIO_TextChanged(object sender, EventArgs e)
{
FieldChanged();
}
private void textBoxImagePath_TextChanged(object sender, EventArgs e)
{
FieldChanged();
}
private void listBoxProductsList_Changed(object sender, EventArgs e)
{
FieldChanged();
}
private void textBoxCustomerEmail_Changed(object sender, EventArgs e)
{
FieldChanged();
}
private void buttonAccept_Click(object sender, EventArgs e)
{
OrderBindingModel? orderBindingModel = new OrderBindingModel();
if (OrderId == null)
{
orderBindingModel = new OrderBindingModel();
}
else
{
var viewModel = _orderLogic.ReadElement(new InternetShopContracts.DataSearchModels.OrderSearchModel { Id = OrderId });
if (viewModel == null)
{
throw new Exception("Заказ не найден");
}
orderBindingModel = OrderBindingModel.FromViewModel(viewModel);
}
orderBindingModel.CustomerFIO = textBoxCustomerFIO.Text;
try
{
orderBindingModel.CustomerEmail = writeComponentCustomerEmail.WriteTextInTextBox;
}
catch (Exception ex)
{
MessageBox.Show("Проверьте поле \"Email заказчика\":\n" + ex.Message);
return;
}
orderBindingModel.ImagePath = textBoxImagePath.Text;
orderBindingModel.ProductNames = productsList.CheckedItems;
try
{
bool savedOK;
if (OrderId == null)
{
savedOK = _orderLogic.Create(orderBindingModel);
}
else
{
savedOK = _orderLogic.Update(orderBindingModel);
}
if (savedOK)
{
DialogResult = DialogResult.OK;
IsFieldsSaved = true;
Close();
}
else
{
throw new Exception("Не удалось сохранить заказ");
}
}
catch (Exception ex)
{
MessageBox.Show("Произошла ошибка при сохранении:\n" + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
Close();
}
}
}

View File

@ -0,0 +1,128 @@
<?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>
<data name="productsList.CheckedItems" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAEAQAAAH9TeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5
c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVi
bGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dAwAAAAZfaXRlbXMFX3NpemUIX3ZlcnNpb24GAAAI
CAkCAAAAAAAAAAAAAAARAgAAAAAAAAAL
</value>
</data>
</root>

View File

@ -0,0 +1,129 @@
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()
{
components = new System.ComponentModel.Container();
tableComponent = new WinFormsLibrary1.TableComponent();
menuStrip = new MenuStrip();
productsToolStripMenuItem = new ToolStripMenuItem();
reportsToolStripMenuItem = new ToolStripMenuItem();
reportOrderImagesExcelToolStripMenuItem = new ToolStripMenuItem();
reportOrdersWordToolStripMenuItem = new ToolStripMenuItem();
reportProductsPDFToolStripMenuItem = new ToolStripMenuItem();
componentExcelWithImage = new Components.ComponentExcelWithImage(components);
pdfHistogram = new WinFormsLibrary1.PDFHistogram(components);
tableWordNoVisibleComponent = new UserComponentsOption19.TableWordNoVisibleComponent(components);
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)";
reportOrderImagesExcelToolStripMenuItem.Click += reportOrderImagesExcelToolStripMenuItem_Click;
//
// reportOrdersWordToolStripMenuItem
//
reportOrdersWordToolStripMenuItem.Name = "reportOrdersWordToolStripMenuItem";
reportOrdersWordToolStripMenuItem.Size = new Size(296, 26);
reportOrdersWordToolStripMenuItem.Text = "Отчет по заказам (Word)";
reportOrdersWordToolStripMenuItem.Click += reportOrdersWordToolStripMenuItem_Click;
//
// reportProductsPDFToolStripMenuItem
//
reportProductsPDFToolStripMenuItem.Name = "reportProductsPDFToolStripMenuItem";
reportProductsPDFToolStripMenuItem.Size = new Size(296, 26);
reportProductsPDFToolStripMenuItem.Text = "Отчет по товарам (PDF)";
reportProductsPDFToolStripMenuItem.Click += reportProductsPDFToolStripMenuItem_Click;
//
// 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 = "Заказы";
Load += FormOrdersList_Load;
KeyDown += FormOrdersList_KeyDown;
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;
private Components.ComponentExcelWithImage componentExcelWithImage;
private WinFormsLibrary1.PDFHistogram pdfHistogram;
private UserComponentsOption19.TableWordNoVisibleComponent tableWordNoVisibleComponent;
}
}

View File

@ -0,0 +1,367 @@
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.LogicsContracts;
using InternetShopForms.Orders;
using InternetShopForms.Products;
using WinFormsLibrary1.HelperClasses;
namespace InternetShopForms
{
public partial class FormOrdersList : Form
{
private IOrderLogic _orderLogic;
private IProductLogic _productLogic;
public FormOrdersList(IOrderLogic orderLogic, IProductLogic productLogic)
{
InitializeComponent();
_orderLogic = orderLogic;
_productLogic = productLogic;
List<(string, string, float)> configureColumns = [
("ID", "Id", 1.0f),
("ÔÈÎ çàêàç÷èêà", "CustomerFIO", 1.0f),
("Ïðîäóêòû", "ProductsString", 1.0f),
("Email çàêàç÷èêà", "CustomerEmail", 1.0f),
];
tableComponent.ConfigureColumns(configureColumns);
tableComponent.dataGridView1.AllowUserToDeleteRows = false;
tableComponent.dataGridView1.Columns[0].Visible = false;
KeyPreview = true;
}
private void productsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormProductsList));
if (service is FormProductsList form)
{
form.ShowDialog();
}
}
private void FormOrdersList_Load(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
try
{
var orders = _orderLogic.ReadList();
tableComponent.FillData(orders);
}
catch (Exception ex)
{
MessageBox.Show("Ïðîèçîøëà îøèáêà ïðè çàãðóçêå äàííûõ:\n" + ex.Message, "Îøèáêà", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormOrdersList_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control)
{
switch (e.KeyCode)
{
case Keys.A:
CreateOrder();
e.SuppressKeyPress = true;
break;
case Keys.U:
EditOrder();
e.SuppressKeyPress = true;
break;
case Keys.D:
DeleteOrder();
e.SuppressKeyPress = true;
break;
case Keys.S:
CreateWord();
e.SuppressKeyPress = true;
break;
case Keys.C:
CreateExcel();
e.SuppressKeyPress = true;
break;
case Keys.T:
CreatePDF();
e.SuppressKeyPress = true;
break;
}
}
}
private void CreateOrder()
{
var service = Program.ServiceProvider?.GetService(typeof(FormOrderEdit));
if (!(service is FormOrderEdit form))
{
return;
}
if (form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
private void EditOrder()
{
OrderViewModel? selectedOrder = null;
try
{
selectedOrder = tableComponent.GetSelectedObject<OrderViewModel>();
}
catch (Exception ex)
{
MessageBox.Show("Âûáåðèòå ñòðîêó");
return;
}
var service = Program.ServiceProvider?.GetService(typeof(FormOrderEdit));
if (!(service is FormOrderEdit form))
{
return;
}
form.OrderId = Convert.ToInt32(selectedOrder.Id);
if (form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
private void DeleteOrder()
{
try
{
OrderViewModel? selectedOrder = null;
try
{
selectedOrder = tableComponent.GetSelectedObject<OrderViewModel>();
}
catch (Exception ex)
{
MessageBox.Show("Âûáåðèòå ñòðîêó");
return;
}
var result = MessageBox.Show(
"Âû õîòèòå óäàëèòü çàêàç?",
"Ïðåäóïðåæäåíèå",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question
);
if (result == DialogResult.Yes)
{
if (_orderLogic.Delete(new OrderSearchModel { Id = selectedOrder.Id }))
{
MessageBox.Show("Çàêàç óäàëåí");
}
else
{
throw new Exception("Îøèáêà óäàëåíèÿ");
}
LoadData();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private enum ReportType
{
Word = 0,
Excel = 1,
PDF = 2
}
private string GetFileFilter(ReportType reportType)
{
if (reportType == ReportType.Excel)
{
return "Excel files (*.xlsx)|*.xlsx";
}
else if (reportType == ReportType.PDF)
{
return "PDF files (*.pdf)|*.pdf";
}
else
{
return "Word files (*.docx)|*.docx";
}
}
private string? GetExportFileName(ReportType reportType)
{
using (SaveFileDialog openFileDialog = new SaveFileDialog())
{
openFileDialog.InitialDirectory = "d:\\tmp";
openFileDialog.Filter = GetFileFilter(reportType) + "|All files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
return openFileDialog.FileName;
}
}
return null;
}
private void CreateWord()
{
string? exportFileName = GetExportFileName(ReportType.Word);
if (string.IsNullOrEmpty(exportFileName))
{
return;
}
var orders = _orderLogic.ReadList();
try
{
string[] headerRow1 = {
"ID",
"Ëè÷íûå äàííûå",
"Ëè÷íûå äàííûå",
"Òîâàðû",
};
string[] headerRow2 = {
"ID",
"ÔÈÎ",
"Email",
"Òîâàðû",
};
List<(float columnWidth, string headerRowCell1, string headerRowCell2, string property)> columnWidths =
[ (3.0f, "ID", "ID", "Id"),
(5.0f, "Ëè÷íûå äàííûå", "ÔÈÎ", "CustomerFIO"),
(5.0f, "Ëè÷íûå äàííûå", "Email", "CustomerEmail"),
(5.0f, "Òîâàðû", "Òîâàðû", "ProductsString"),
];
var mergeColumns = new List<(int StartColumn, int EndColumn)> { (1, 2) };
var columnPropertyMapping = new Dictionary<int, string>
{
{ 0, "Id" },
{ 1, "CustomerFIO" },
{ 2, "CustomerEmail" },
{ 3, "ProductsString" },
};
tableWordNoVisibleComponent.CreateTableInWordDocument(
exportFileName,
"Îò÷åò ïî çàêàçàì",
mergeColumns,
columnWidths,
orders
);
MessageBox.Show("Îò÷åò óñïåøíî ñôîðìèðîâàí", "Ñîçäàíèå îò÷åòà", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Ïðîèçîøëà îøèáêà ïðè ñîçäàíèè îò÷åòà:\n" + ex.Message, "Ñîçäàíèå îò÷åòà", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CreateExcel()
{
string? exportFileName = GetExportFileName(ReportType.Excel);
if (string.IsNullOrEmpty(exportFileName))
{
return;
}
var orders = _orderLogic.ReadList();
try
{
componentExcelWithImage.CreateExcelWithImages(exportFileName, "Çàêàçû", orders.Select(x => x.ImagePath).ToArray());
MessageBox.Show("Îò÷åò óñïåøíî ñôîðìèðîâàí", "Ñîçäàíèå îò÷åòà", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Ïðîèçîøëà îøèáêà ïðè ñîçäàíèè îò÷åòà:\n" + ex.Message, "Ñîçäàíèå îò÷åòà", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CreatePDF()
{
string? exportFileName = GetExportFileName(ReportType.PDF);
if (string.IsNullOrEmpty(exportFileName))
{
return;
}
var orders = _orderLogic.ReadList();
var products = _productLogic.ReadList();
Dictionary<string, double> productsStat = new Dictionary<string, double>();
foreach (var order in orders)
{
foreach (var product in order.ProductNames)
{
if (productsStat.ContainsKey(product))
{
productsStat[product]++;
}
else
{
productsStat.Add(product, 1);
}
}
}
foreach (var product in products)
{
if (!productsStat.ContainsKey(product.Name))
{
productsStat.Add(product.Name, 0);
}
}
List<ChartData> charts = new List<ChartData>();
foreach (var product in productsStat.Keys)
{
ChartData chartData = new ChartData();
Dictionary<string, double> data = new Dictionary<string, double>();
data.Add(product, productsStat[product]);
chartData.SeriesName = product;
chartData.Data = data;
charts.Add(chartData);
}
try
{
pdfHistogram.CreateHistogramPdf(
exportFileName,
"Îò÷åò ïî òîâàðàì",
"Êîëè÷åñòâî çàêàçîâ",
OxyPlot.Legends.LegendPosition.RightTop,
charts
);
MessageBox.Show("Îò÷åò óñïåøíî ñôîðìèðîâàí", "Ñîçäàíèå îò÷åòà", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Ïðîèçîøëà îøèáêà ïðè ñîçäàíèè îò÷åòà:\n" + ex.Message, "Ñîçäàíèå îò÷åòà", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void reportOrderImagesExcelToolStripMenuItem_Click(object sender, EventArgs e)
{
CreateExcel();
}
private void reportOrdersWordToolStripMenuItem_Click(object sender, EventArgs e)
{
CreateWord();
}
private void reportProductsPDFToolStripMenuItem_Click(object sender, EventArgs e)
{
CreatePDF();
}
}
}

View File

@ -0,0 +1,132 @@
<?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>
<metadata name="componentExcelWithImage.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>145, 17</value>
</metadata>
<metadata name="pdfHistogram.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>667, 17</value>
</metadata>
<metadata name="tableWordNoVisibleComponent.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>816, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,231 @@
using Components;
using InternetShopContracts.DataSearchModels;
using InternetShopContracts.DataViewModels;
using InternetShopContracts.LogicsContracts;
using InternetShopDatabase.Storages;
using InternetShopForms.Orders;
using InternetShopForms.Products;
using InternetShopLogics.Logics;
using PluginConventions;
using UserComponentsOption19;
using WinFormsLibrary1;
using WinFormsLibrary1.HelperClasses;
namespace InternetShopForms.Plugins
{
public class PluginsConvention : IPluginsConvention
{
private readonly IOrderLogic _orderLogic;
private readonly IProductLogic _productLogic;
private readonly TableComponent _componentTable = new();
private readonly PDFHistogram _componentPDF = new();
private readonly ComponentExcelWithImage _componentExcel = new();
private readonly TableWordNoVisibleComponent _componentWord = new();
public string PluginName => "PluginLab3";
public UserControl GetControl => _componentTable;
public PluginsConvention()
{
_orderLogic = new OrderLogic(new OrderStorage());
_productLogic = new ProductLogic(new ProductStorage());
ReloadData();
}
public PluginsConventionElement GetElement
{
get
{
var selected = _componentTable.GetSelectedObject<OrderViewModel>();
if (selected == null) throw new Exception("Не удалось получить выбранный элемент");
byte[] bytes = new byte[16];
BitConverter.GetBytes(selected.Id).CopyTo(bytes, 0);
return new PluginsConventionOrder()
{
Id = new Guid(bytes),
CustomerFIO = selected.CustomerFIO,
CustomerEmail = selected.CustomerEmail,
ProductNames = selected.ProductNames,
};
}
}
public bool CreateChartDocument(PluginsConventionSaveDocument saveDocument)
{
string? exportFileName = saveDocument.FileName;
var orders = _orderLogic.ReadList();
var products = _productLogic.ReadList();
Dictionary<string, double> productsStat = new Dictionary<string, double>();
foreach (var order in orders)
{
foreach (var product in order.ProductNames)
{
if (productsStat.ContainsKey(product))
{
productsStat[product]++;
}
else
{
productsStat.Add(product, 1);
}
}
}
foreach (var product in products)
{
if (!productsStat.ContainsKey(product.Name))
{
productsStat.Add(product.Name, 0);
}
}
List<ChartData> charts = new List<ChartData>();
foreach (var product in productsStat.Keys)
{
ChartData chartData = new ChartData();
Dictionary<string, double> data = new Dictionary<string, double>();
data.Add(product, productsStat[product]);
chartData.SeriesName = product;
chartData.Data = data;
charts.Add(chartData);
}
try
{
_componentPDF.CreateHistogramPdf(
exportFileName,
"Отчет по товарам",
"Количество заказов",
OxyPlot.Legends.LegendPosition.RightTop,
charts
);
//MessageBox.Show("Отчет успешно сформирован", "Создание отчета", MessageBoxButtons.OK, MessageBoxIcon.Information);
return true;
}
catch (Exception ex)
{
//MessageBox.Show("Произошла ошибка при создании отчета:\n" + ex.Message, "Создание отчета", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
public bool CreateSimpleDocument(PluginsConventionSaveDocument saveDocument)
{
string? exportFileName = saveDocument.FileName;
var orders = _orderLogic.ReadList();
try
{
string[] headerRow1 = {
"ID",
"Личные данные",
"Личные данные",
"Товары",
};
string[] headerRow2 = {
"ID",
"ФИО",
"Email",
"Товары",
};
List<(float columnWidth, string headerRowCell1, string headerRowCell2, string property)> columnWidths =
[ (3.0f, "ID", "ID", "Id"),
(5.0f, "Личные данные", "ФИО", "CustomerFIO"),
(5.0f, "Личные данные", "Email", "CustomerEmail"),
(5.0f, "Товары", "Товары", "ProductsString"),
];
var mergeColumns = new List<(int StartColumn, int EndColumn)> { (1, 2) };
var columnPropertyMapping = new Dictionary<int, string>
{
{ 0, "Id" },
{ 1, "CustomerFIO" },
{ 2, "CustomerEmail" },
{ 3, "ProductsString" },
};
_componentWord.CreateTableInWordDocument(
exportFileName,
"Отчет по заказам",
mergeColumns,
columnWidths,
orders
);
//MessageBox.Show("Отчет успешно сформирован", "Создание отчета", MessageBoxButtons.OK, MessageBoxIcon.Information);
return true;
}
catch (Exception ex)
{
//MessageBox.Show("Произошла ошибка при создании отчета:\n" + ex.Message, "Создание отчета", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
public bool CreateTableDocument(PluginsConventionSaveDocument saveDocument)
{
string? exportFileName = saveDocument.FileName;
var orders = _orderLogic.ReadList();
try
{
_componentExcel.CreateExcelWithImages(exportFileName, "Заказы", orders.Select(x => x.ImagePath).ToArray());
//MessageBox.Show("Отчет успешно сформирован", "Создание отчета", MessageBoxButtons.OK, MessageBoxIcon.Information);
return true;
}
catch (Exception ex)
{
//MessageBox.Show("Произошла ошибка при создании отчета:\n" + ex.Message, "Создание отчета", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
public bool DeleteElement(PluginsConventionElement element)
{
return _orderLogic.Delete(new OrderSearchModel
{
Id = element.Id.GetHashCode()
});
}
public Form GetForm(PluginsConventionElement element)
{
var form = new FormOrderEdit(_orderLogic, _productLogic);
if (element != null)
{
form.OrderId = element.Id.GetHashCode();
}
return form;
}
public Form GetThesaurus()
{
return new FormProductsList(_productLogic);
}
public void ReloadData()
{
List<(string, string, float)> configureColumns = [
("ID", "Id", 1.0f),
("ФИО заказчика", "CustomerFIO", 1.0f),
("Продукты", "ProductsString", 1.0f),
("Email заказчика", "CustomerEmail", 1.0f),
];
_componentTable.ConfigureColumns(configureColumns);
_componentTable.dataGridView1.AllowUserToDeleteRows = false;
_componentTable.dataGridView1.Columns[0].Visible = false;
try
{
var orders = _orderLogic.ReadList();
_componentTable.FillData(orders);
}
catch (Exception ex)
{
MessageBox.Show("Произошла ошибка при загрузке данных:\n" + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

View File

@ -0,0 +1,12 @@
using PluginConventions;
namespace InternetShopForms.Plugins
{
public class PluginsConventionOrder : PluginsConventionElement
{
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>();
}
}

View File

@ -0,0 +1,95 @@
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();
ColumnId = new DataGridViewTextBoxColumn();
ColumnName = new DataGridViewTextBoxColumn();
((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.Columns.AddRange(new DataGridViewColumn[] { ColumnId, ColumnName });
dataGridView.Dock = DockStyle.Fill;
dataGridView.EditMode = DataGridViewEditMode.EditOnF2;
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;
//
// ColumnId
//
ColumnId.DataPropertyName = "Id";
ColumnId.HeaderText = "Id";
ColumnId.MinimumWidth = 6;
ColumnId.Name = "ColumnId";
ColumnId.ReadOnly = true;
ColumnId.Visible = false;
//
// ColumnName
//
ColumnName.DataPropertyName = "Name";
ColumnName.HeaderText = "Name";
ColumnName.MinimumWidth = 6;
ColumnName.Name = "ColumnName";
//
// 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;
private DataGridViewTextBoxColumn ColumnId;
private DataGridViewTextBoxColumn ColumnName;
}
}

View File

@ -0,0 +1,131 @@
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 = new List<ProductViewModel>();
public FormProductsList(IProductLogic productLogic)
{
InitializeComponent();
_productLogic = productLogic;
KeyPreview = true;
}
private void FormProductsList_Load(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
try
{
_products = _productLogic.ReadList();
dataGridView.Rows.Clear();
foreach (var product in _products)
{
dataGridView.Rows.Add(product.Id, product.Name);
}
}
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)
{
try
{
dataGridView.Rows.Add();
dataGridView.CurrentCell = dataGridView.Rows[dataGridView.RowCount - 1].Cells[1];
}
catch (Exception ex)
{
dataGridView.Rows.RemoveAt(dataGridView.RowCount - 1);
}
e.Handled = true;
}
else if (e.KeyCode == Keys.Delete)
{
if (dataGridView.SelectedRows.Count == 1)
{
DataGridViewRow selectedRow = dataGridView.SelectedRows[0];
var selectedItemIdValue = selectedRow.Cells["ColumnId"].Value;
if (selectedItemIdValue == null)
{
dataGridView.Rows.Remove(selectedRow);
return;
}
int selectedItemId = Convert.ToInt32(selectedItemIdValue);
string selectedItemName = (string)selectedRow.Cells["ColumnName"].Value;
var result = MessageBox.Show(
$"Удалить товар \"{selectedRow.Cells["ColumnId"].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["ColumnId"].Value == null || Convert.ToInt32(currentRow.Cells["ColumnId"].Value) == 0)
{
_productLogic.Create(new ProductBindingModel
{
Name = currentRow.Cells["ColumnName"].Value.ToString()!,
});
}
else
{
_productLogic.Update(new ProductBindingModel
{
Id = Convert.ToInt32(currentRow.Cells["ColumnId"].Value),
Name = currentRow.Cells["ColumnName"].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,126 @@
<?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="ColumnId.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnName.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</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("Товар с таким названием уже есть");
}
}
}
}

View File

@ -0,0 +1,252 @@
namespace PluginApp
{
partial class FormMain
{
/// <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()
{
this.menuStrip = new System.Windows.Forms.MenuStrip();
this.ControlsStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.ActionsToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.DocsToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.SimpleDocToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.TableDocToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.ChartDocToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.panelControl = new System.Windows.Forms.Panel();
this.ThesaurusToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.AddElementToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.UpdElementToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.DelElementToolStripMenuItem = new
System.Windows.Forms.ToolStripMenuItem();
this.menuStrip.SuspendLayout();
this.SuspendLayout();
//
// menuStrip
//
this.menuStrip.Items.AddRange(new
System.Windows.Forms.ToolStripItem[] {
this.ControlsStripMenuItem,
this.ActionsToolStripMenuItem,
this.DocsToolStripMenuItem});
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.Name = "menuStrip";
this.menuStrip.Size = new System.Drawing.Size(800, 24);
this.menuStrip.TabIndex = 0;
this.menuStrip.Text = "Меню";
//
// ControlsStripMenuItem
//
this.ControlsStripMenuItem.Name = "ControlsStripMenuItem";
this.ControlsStripMenuItem.Size = new System.Drawing.Size(94,
20);
this.ControlsStripMenuItem.Text = "Компоненты";
//
// ActionsToolStripMenuItem
//
this.ActionsToolStripMenuItem.DropDownItems.AddRange(new
System.Windows.Forms.ToolStripItem[] {
this.ThesaurusToolStripMenuItem,
this.AddElementToolStripMenuItem,
this.UpdElementToolStripMenuItem,
this.DelElementToolStripMenuItem});
this.ActionsToolStripMenuItem.Name =
"ActionsToolStripMenuItem";
this.ActionsToolStripMenuItem.Size = new
System.Drawing.Size(70, 20);
this.ActionsToolStripMenuItem.Text = "Действия";
//
// DocsToolStripMenuItem
//
this.DocsToolStripMenuItem.DropDownItems.AddRange(new
System.Windows.Forms.ToolStripItem[] {
this.SimpleDocToolStripMenuItem,
this.TableDocToolStripMenuItem,
this.ChartDocToolStripMenuItem});
this.DocsToolStripMenuItem.Name = "DocsToolStripMenuItem";
this.DocsToolStripMenuItem.Size = new System.Drawing.Size(82,
20);
this.DocsToolStripMenuItem.Text = "Документы";
//
// SimpleDocToolStripMenuItem
//
this.SimpleDocToolStripMenuItem.Name =
"SimpleDocToolStripMenuItem";
this.SimpleDocToolStripMenuItem.ShortcutKeys =
((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control |
System.Windows.Forms.Keys.S)));
this.SimpleDocToolStripMenuItem.Size = new
System.Drawing.Size(233, 22);
this.SimpleDocToolStripMenuItem.Text = "Простой документ";
this.SimpleDocToolStripMenuItem.Click += new
System.EventHandler(this.SimpleDocToolStripMenuItem_Click);
//
// TableDocToolStripMenuItem
//
this.TableDocToolStripMenuItem.Name =
"TableDocToolStripMenuItem";
this.TableDocToolStripMenuItem.ShortcutKeys =
((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control |
System.Windows.Forms.Keys.T)));
this.TableDocToolStripMenuItem.Size = new
System.Drawing.Size(233, 22);
this.TableDocToolStripMenuItem.Text = "Документ с таблицой";
this.TableDocToolStripMenuItem.Click += new
System.EventHandler(this.TableDocToolStripMenuItem_Click);
//
// ChartDocToolStripMenuItem
//
this.ChartDocToolStripMenuItem.Name =
"ChartDocToolStripMenuItem";
this.ChartDocToolStripMenuItem.ShortcutKeys =
((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control |
System.Windows.Forms.Keys.C)));
this.ChartDocToolStripMenuItem.Size = new
System.Drawing.Size(233, 22);
this.ChartDocToolStripMenuItem.Text = "Диаграмма";
this.ChartDocToolStripMenuItem.Click += new
System.EventHandler(this.ChartDocToolStripMenuItem_Click);
//
// panelControl
//
this.panelControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.panelControl.Location = new System.Drawing.Point(0, 24);
this.panelControl.Name = "panelControl";
this.panelControl.Size = new System.Drawing.Size(800, 426);
this.panelControl.TabIndex = 1;
//
// ThesaurusToolStripMenuItem
//
this.ThesaurusToolStripMenuItem.Name =
"ThesaurusToolStripMenuItem";
this.ThesaurusToolStripMenuItem.ShortcutKeys =
((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control |
System.Windows.Forms.Keys.I)));
this.ThesaurusToolStripMenuItem.Size = new
System.Drawing.Size(180, 22);
this.ThesaurusToolStripMenuItem.Text = "Справочник";
this.ThesaurusToolStripMenuItem.Click += new
System.EventHandler(this.ThesaurusToolStripMenuItem_Click);
//
// AddElementToolStripMenuItem
//
this.AddElementToolStripMenuItem.Name =
"AddElementToolStripMenuItem";
this.AddElementToolStripMenuItem.ShortcutKeys =
((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control |
System.Windows.Forms.Keys.A)));
this.AddElementToolStripMenuItem.Size = new
System.Drawing.Size(180, 22);
this.AddElementToolStripMenuItem.Text = "Добавить";
this.AddElementToolStripMenuItem.Click += new
System.EventHandler(this.AddElementToolStripMenuItem_Click);
// UpdElementToolStripMenuItem
//
this.UpdElementToolStripMenuItem.Name =
"UpdElementToolStripMenuItem";
this.UpdElementToolStripMenuItem.ShortcutKeys =
((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control |
System.Windows.Forms.Keys.U)));
this.UpdElementToolStripMenuItem.Size = new
System.Drawing.Size(180, 22);
this.UpdElementToolStripMenuItem.Text = "Изменить";
this.UpdElementToolStripMenuItem.Click += new
System.EventHandler(this.UpdElementToolStripMenuItem_Click);
//
// DelElementToolStripMenuItem
//
this.DelElementToolStripMenuItem.Name =
"DelElementToolStripMenuItem";
this.DelElementToolStripMenuItem.ShortcutKeys =
((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control |
System.Windows.Forms.Keys.D)));
this.DelElementToolStripMenuItem.Size = new
System.Drawing.Size(180, 22);
this.DelElementToolStripMenuItem.Text = "Удалить";
this.DelElementToolStripMenuItem.Click += new
System.EventHandler(this.DelElementToolStripMenuItem_Click);
//
// FormMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.panelControl);
this.Controls.Add(this.menuStrip);
this.MainMenuStrip = this.menuStrip;
this.Name = "FormMain";
this.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Главная форма";
this.WindowState =
System.Windows.Forms.FormWindowState.Maximized;
this.KeyDown += new
System.Windows.Forms.KeyEventHandler(this.FormMain_KeyDown);
this.menuStrip.ResumeLayout(false);
this.menuStrip.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.MenuStrip menuStrip;
private System.Windows.Forms.ToolStripMenuItem ControlsStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem DocsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem
SimpleDocToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem
TableDocToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem
ChartDocToolStripMenuItem;
private System.Windows.Forms.Panel panelControl;
private System.Windows.Forms.ToolStripMenuItem
ActionsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem
ThesaurusToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem
AddElementToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem
UpdElementToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem
DelElementToolStripMenuItem;
}
}

View File

@ -0,0 +1,220 @@
using PluginConventions;
using System.Reflection;
namespace PluginApp
{
public partial class FormMain : Form
{
private readonly Dictionary<string, IPluginsConvention> _plugins;
private string _selectedPlugin;
public FormMain()
{
InitializeComponent();
_selectedPlugin = string.Empty;
_plugins = LoadPlugins();
}
private Dictionary<string, IPluginsConvention> LoadPlugins()
{
var plugins = new Dictionary<string, IPluginsConvention>();
string pluginsPath = Directory.GetParent(Directory.GetCurrentDirectory())!.Parent!.Parent!.FullName + "\\plugins";
string[] dllFiles = Directory.GetFiles(pluginsPath, "*.dll", SearchOption.AllDirectories);
if (!Directory.Exists(pluginsPath))
{
MessageBox.Show($"Ошибка получения плагинов", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return plugins;
}
foreach (var dll in dllFiles)
{
try
{
Assembly asmbly = Assembly.LoadFrom(dll);
Type[] types = asmbly.GetTypes();
foreach (var type in types)
{
if (typeof(IPluginsConvention).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
{
var plugin = (IPluginsConvention)Activator.CreateInstance(type)!;
plugins.Add(plugin.PluginName, plugin);
CreateStripMenuItem(plugin.PluginName);
}
}
}
catch (Exception ex)
{
// MessageBox.Show("Неудалось загрузить плагины:\n" + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
return plugins;
}
private void CreateStripMenuItem(string pluginName)
{
var menuItem = new ToolStripMenuItem(pluginName);
menuItem.Click += (s, e) =>
{
_selectedPlugin = pluginName;
IPluginsConvention plugin = _plugins![pluginName];
if (plugin?.GetControl == null) throw new Exception("Неудалось получить контрол");
UserControl userControl = plugin.GetControl;
panelControl.Controls.Clear();
plugin.ReloadData();
userControl.Dock = DockStyle.Fill;
panelControl.Controls.Add(userControl);
};
ControlsStripMenuItem.DropDownItems.Add(menuItem);
}
private void FormMain_KeyDown(object sender, KeyEventArgs e)
{
if (string.IsNullOrEmpty(_selectedPlugin) || !_plugins.ContainsKey(_selectedPlugin))
{
return;
}
if (!e.Control)
{
return;
}
switch (e.KeyCode)
{
case Keys.I:
ShowThesaurus();
break;
case Keys.A:
AddNewElement();
break;
case Keys.U:
UpdateElement();
break;
case Keys.D:
DeleteElement();
break;
case Keys.S:
CreateSimpleDoc();
break;
case Keys.T:
CreateTableDoc();
break;
case Keys.C:
CreateChartDoc();
break;
}
}
private void ShowThesaurus()
{
_plugins[_selectedPlugin].GetThesaurus().Show();
}
private void AddNewElement()
{
var form = _plugins[_selectedPlugin].GetForm(null);
if (form != null && form.ShowDialog() == DialogResult.OK)
{
_plugins[_selectedPlugin].ReloadData();
}
}
private void UpdateElement()
{
var element = _plugins[_selectedPlugin].GetElement;
if (element == null)
{
MessageBox.Show("Нет выбранного элемента", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var form = _plugins[_selectedPlugin].GetForm(element);
if (form != null && form.ShowDialog() == DialogResult.OK)
{
_plugins[_selectedPlugin].ReloadData();
}
}
private void DeleteElement()
{
if (MessageBox.Show("Удалить выбранный элемент", "Удаление", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
{
return;
}
var element = _plugins[_selectedPlugin].GetElement;
if (element == null)
{
MessageBox.Show("Нет выбранного элемента", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (_plugins[_selectedPlugin].DeleteElement(element))
{
_plugins[_selectedPlugin].ReloadData();
}
}
private void CreateTableDoc()
{
using var dialog = new SaveFileDialog
{
Filter = "Word Files|*.docx"
};
if (dialog.ShowDialog() == DialogResult.OK)
{
if (_plugins[_selectedPlugin].CreateSimpleDocument(new PluginsConventionSaveDocument() { FileName = dialog.FileName }))
{
MessageBox.Show("Документ сохранен", "Создание документа", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Ошибка при создании документа",
"Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void CreateSimpleDoc()
{
using var dialog = new SaveFileDialog
{
Filter = "Excel Files|*.xlsx"
};
if (dialog.ShowDialog() == DialogResult.OK)
{
if (_plugins[_selectedPlugin].CreateTableDocument(new PluginsConventionSaveDocument() { FileName = dialog.FileName }))
{
MessageBox.Show("Документ сохранен", "Создание документа", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Ошибка при создании документа",
"Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public void CreateChartDoc()
{
using var dialog = new SaveFileDialog
{
Filter = "PDF Files|*.pdf"
};
if (dialog.ShowDialog() == DialogResult.OK)
{
if (_plugins[_selectedPlugin].CreateChartDocument(new PluginsConventionSaveDocument() { FileName = dialog.FileName }))
{
MessageBox.Show("Документ сохранен", "Создание документа", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Ошибка при создании документа",
"Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void ThesaurusToolStripMenuItem_Click(object sender, EventArgs e) => ShowThesaurus();
private void AddElementToolStripMenuItem_Click(object sender, EventArgs e) => AddNewElement();
private void UpdElementToolStripMenuItem_Click(object sender, EventArgs e) => UpdateElement();
private void DelElementToolStripMenuItem_Click(object sender, EventArgs e) => DeleteElement();
private void SimpleDocToolStripMenuItem_Click(object sender, EventArgs e) => CreateSimpleDoc();
private void TableDocToolStripMenuItem_Click(object sender, EventArgs e) => CreateTableDoc();
private void ChartDocToolStripMenuItem_Click(object sender, EventArgs e) => CreateChartDoc();
}
}

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,29 @@
<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="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>
<ProjectReference Include="..\PluginConventions\PluginConventions.csproj" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Folder Include="plugins\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,17 @@
namespace PluginApp
{
internal static class Program
{
/// <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();
Application.Run(new FormMain());
}
}
}

View File

@ -0,0 +1,57 @@
namespace PluginConventions
{
public interface IPluginsConvention
{
/// <summary>
/// Название плагина
/// </summary>
string PluginName { get; }
/// <summary>
/// Получение контрола для вывода набора данных
/// </summary>
UserControl GetControl { get; }
/// <summary>
/// Получение элемента, выбранного в контроле
/// </summary>
PluginsConventionElement GetElement { get; }
/// <summary>
/// Получение формы для создания/редактирования объекта
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
Form GetForm(PluginsConventionElement element);
/// <summary>
/// Получение формы для работы со справочником
/// </summary>
/// <returns></returns>
Form GetThesaurus();
/// <summary>
/// Удаление элемента
/// /// </summary>
/// <param name="element"></param>
/// <returns></returns>
bool DeleteElement(PluginsConventionElement element);
/// <summary>
/// Обновление набора данных в контроле
/// </summary>
void ReloadData();
/// <summary>
/// Создание простого документа
/// </summary>
/// <param name="saveDocument"></param>
/// <returns></returns>
bool CreateSimpleDocument(PluginsConventionSaveDocument saveDocument);
/// <summary>
/// Создание простого документа
/// </summary>
/// <param name="saveDocument"></param>
/// <returns></returns>
bool CreateTableDocument(PluginsConventionSaveDocument saveDocument);
/// <summary>
/// Создание документа с диаграммой
/// </summary>
/// <param name="saveDocument"></param>
/// <returns></returns>
bool CreateChartDocument(PluginsConventionSaveDocument saveDocument);
}
}

View File

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

View File

@ -0,0 +1,7 @@
namespace PluginConventions
{
public class PluginsConventionElement
{
public Guid Id { get; set; }
}
}

View File

@ -0,0 +1,7 @@
namespace PluginConventions
{
public class PluginsConventionSaveDocument
{
public string FileName { get; set; } = string.Empty;
}
}