Compare commits

...

3 Commits
main ... Lab3

Author SHA1 Message Date
Владимир Данилов
df6647c3b4 -_- 2024-12-12 19:20:18 +04:00
Владимир Данилов
8b375b106e ... 2024-12-11 14:17:36 +04:00
Владимир Данилов
d9ce6d6a8e Добавление/удаление/отображение 2024-11-28 01:31:31 +04:00
39 changed files with 2585 additions and 0 deletions

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Contracts\Contracts.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,93 @@
using Contracts.BindingModels;
using Contracts.BusinessLogicContracts;
using Contracts.SearchModels;
using Contracts.StorageContracts;
using Contracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLogic.BusinessLogics
{
public class AccountLogic : IAccountLogic
{
private readonly IAccountStorage _accountStorage;
public AccountLogic(IAccountStorage accountStorage)
{
_accountStorage = accountStorage;
}
public bool Create(AccountBindingModel model)
{
CheckModel(model);
if (_accountStorage.Insert(model) == null)
{
return false;
}
return true;
}
public bool Delete(AccountBindingModel model)
{
CheckModel(model, false);
if (_accountStorage.Delete(model) == null)
{
return false;
}
return true;
}
public AccountViewModel? ReadElement(AccountSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
var element = _accountStorage.GetElement(model);
if (element == null)
{
return null;
}
return element;
}
public List<AccountViewModel>? ReadList(AccountSearchModel? model)
{
var list = model == null ? _accountStorage.GetFullList() : _accountStorage.GetFilteredList(model);
if (list == null)
{
return null;
}
return list;
}
public bool Update(AccountBindingModel model)
{
CheckModel(model);
if (_accountStorage.Update(model) == null)
{
return false;
}
return true;
}
private void CheckModel(AccountBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.Login))
{
throw new ArgumentNullException("Нет логина", nameof(model.Login));
}
}
}
}

View File

@ -0,0 +1,93 @@
using Contracts.BindingModels;
using Contracts.BusinessLogicContracts;
using Contracts.SearchModels;
using Contracts.StorageContracts;
using Contracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLogic.BusinessLogics
{
public class CityLogic : ICityLogic
{
private readonly ICityStorage _cityStorage;
public CityLogic(ICityStorage cityStorage)
{
_cityStorage = cityStorage;
}
public bool Create(CityBindingModel model)
{
CheckModel(model);
if (_cityStorage.Insert(model) == null)
{
return false;
}
return true;
}
public bool Delete(CityBindingModel model)
{
CheckModel(model, false);
if (_cityStorage.Delete(model) == null)
{
return false;
}
return true;
}
public CityViewModel? ReadElement(CitySearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
var element = _cityStorage.GetElement(model);
if (element == null)
{
return null;
}
return element;
}
public List<CityViewModel>? ReadList(CitySearchModel? model)
{
var list = model == null ? _cityStorage.GetFullList() : _cityStorage.GetFilteredList(model);
if (list == null)
{
return null;
}
return list;
}
public bool Update(CityBindingModel model)
{
CheckModel(model);
if (_cityStorage.Update(model) == null)
{
return false;
}
return true;
}
private void CheckModel(CityBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.Name))
{
throw new ArgumentNullException("Нет названия города", nameof(model.Name));
}
}
}
}

View File

@ -0,0 +1,22 @@
using DataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.BindingModels
{
public class AccountBindingModel : IAccountModel
{
public int Id { get; set; }
public string Login { get; set; } = string.Empty;
public List<DateTime> AuthorizationAttemptsHistory { get; set; } = new List<DateTime>();
public int ResidenceCityId { get; set; }
public DateTime AccountCreationDate { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using DataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.BindingModels
{
public class CityBindingModel : ICityModel
{
public int Id { get; set; }
public string Name { get; set; } = String.Empty;
}
}

View File

@ -0,0 +1,20 @@
using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.BusinessLogicContracts
{
public interface IAccountLogic
{
List<AccountViewModel>? ReadList(AccountSearchModel? model);
AccountViewModel? ReadElement(AccountSearchModel model);
bool Create(AccountBindingModel model);
bool Update(AccountBindingModel model);
bool Delete(AccountBindingModel model);
}
}

View File

@ -0,0 +1,20 @@
using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.BusinessLogicContracts
{
public interface ICityLogic
{
List<CityViewModel>? ReadList(CitySearchModel? model);
CityViewModel? ReadElement(CitySearchModel model);
bool Create(CityBindingModel model);
bool Update(CityBindingModel model);
bool Delete(CityBindingModel model);
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DataModels\DataModels.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.SearchModels
{
public class AccountSearchModel
{
public int? Id { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.SearchModels
{
public class CitySearchModel
{
public int? Id { get; set; }
}
}

View File

@ -0,0 +1,21 @@
using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.StorageContracts
{
public interface IAccountStorage
{
List<AccountViewModel> GetFullList();
List<AccountViewModel> GetFilteredList(AccountSearchModel model);
AccountViewModel? GetElement(AccountSearchModel model);
AccountViewModel? Insert(AccountBindingModel model);
AccountViewModel? Update(AccountBindingModel model);
AccountViewModel? Delete(AccountBindingModel model);
}
}

View File

@ -0,0 +1,21 @@
using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.StorageContracts
{
public interface ICityStorage
{
List<CityViewModel> GetFullList();
List<CityViewModel> GetFilteredList(CitySearchModel model);
CityViewModel? GetElement(CitySearchModel model);
CityViewModel? Insert(CityBindingModel model);
CityViewModel? Update(CityBindingModel model);
CityViewModel? Delete(CityBindingModel model);
}
}

View File

@ -0,0 +1,28 @@
using DataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.ViewModels
{
public class AccountViewModel : IAccountModel
{
[DisplayName("Логин")]
public string Login { get; set; } = string.Empty;
[DisplayName("История авторизаций")]
public List<DateTime> AuthorizationAttemptsHistory { get; set; }
[DisplayName("Город проживания")]
public string ResidenceCityName { get; set; }
public int ResidenceCityId { get; set; }
[DisplayName("Дата создания аккаунта")]
public DateTime AccountCreationDate { get; set; }
public int Id { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using DataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contracts.ViewModels
{
public class CityViewModel : ICityModel
{
public int Id { get; set; }
[DisplayName("Название")]
public string Name { get; set; } = string.Empty;
}
}

View File

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

7
Lab3/DataModels/IId.cs Normal file
View File

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

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataModels.Models
{
public interface IAccountModel: IId
{
// Логин
string Login { get; }
// Даты последних попыток авторизации
List<DateTime> AuthorizationAttemptsHistory { get; }
// Город проживания
int ResidenceCityId { get; }
// Дата создания аккаунта (последние 10 лет)
DateTime AccountCreationDate { get; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataModels.Models
{
public interface ICityModel : IId
{
string Name { get; }
}
}

View File

@ -0,0 +1,15 @@
using DatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
namespace DatabaseImplement
{
public class AccountsDatabase : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("Host=localhost;Port=5432;Database=COPAccountsBD;Username=postgres;Password=postgres");
public virtual DbSet<Accounts> Accounts { set; get; }
public virtual DbSet<Cities> Cities { set; get; }
}
}

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Contracts\Contracts.csproj" />
<ProjectReference Include="..\DataModels\DataModels.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,96 @@
using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.StorageContracts;
using Contracts.ViewModels;
using DatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DatabaseImplement.Implements
{
public class AccountStorage : IAccountStorage
{
public AccountViewModel? Delete(AccountBindingModel model)
{
using var context = new AccountsDatabase();
var element = context.Accounts
.Include(x => x.ResidenceCity)
.FirstOrDefault(rec => rec.Id == model.Id);
if (element != null)
{
context.Accounts.Remove(element);
context.SaveChanges();
return element.GetViewModel;
}
return null;
}
public AccountViewModel? GetElement(AccountSearchModel model)
{
if (!model.Id.HasValue)
{
return null;
}
using var context = new AccountsDatabase();
return context.Accounts
.Include(x => x.ResidenceCity)
.FirstOrDefault(x => x.Id == model.Id)
?.GetViewModel;
}
public List<AccountViewModel> GetFilteredList(AccountSearchModel model)
{
if (!model.Id.HasValue)
{
return new();
}
using var context = new AccountsDatabase();
return context.Accounts
.Include(x => x.ResidenceCity)
.Where(x => x.Id == model.Id)
.Select(x => x.GetViewModel)
.ToList();
}
public List<AccountViewModel> GetFullList()
{
using var context = new AccountsDatabase();
return context.Accounts
.Include(x => x.ResidenceCity)
.Select(x => x.GetViewModel)
.ToList();
}
public AccountViewModel? Insert(AccountBindingModel model)
{
using var context = new AccountsDatabase();
var newAccount = Accounts.Create(context, model);
if (newAccount == null)
{
return null;
}
context.Accounts.Add(newAccount);
context.SaveChanges();
return newAccount.GetViewModel;
}
public AccountViewModel? Update(AccountBindingModel model)
{
using var context = new AccountsDatabase();
var Account = context.Accounts.FirstOrDefault(x => x.Id == model.Id);
if (Account == null)
{
return null;
}
Account.Update(model, context);
context.SaveChanges();
return Account.GetViewModel;
}
}
}

View File

@ -0,0 +1,88 @@
using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.StorageContracts;
using Contracts.ViewModels;
using DatabaseImplement.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DatabaseImplement.Implements
{
public class CityStorage : ICityStorage
{
public CityViewModel? Delete(CityBindingModel model)
{
using var context = new AccountsDatabase();
var element = context.Cities.FirstOrDefault(rec => rec.Id == model.Id);
if (element != null)
{
context.Cities.Remove(element);
context.SaveChanges();
return element.GetViewModel;
}
return null;
}
public CityViewModel? GetElement(CitySearchModel model)
{
if (!model.Id.HasValue)
{
return null;
}
using var context = new AccountsDatabase();
return context.Cities
.FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)
?.GetViewModel;
}
public List<CityViewModel> GetFilteredList(CitySearchModel model)
{
if (!model.Id.HasValue)
{
return new();
}
using var context = new AccountsDatabase();
return context.Cities
.Where(x => x.Id == model.Id)
.Select(x => x.GetViewModel)
.ToList();
}
public List<CityViewModel> GetFullList()
{
using var context = new AccountsDatabase();
return context.Cities
.Select(x => x.GetViewModel)
.ToList();
}
public CityViewModel? Insert(CityBindingModel model)
{
var newcity = Cities.Create(model);
if (newcity == null)
{
return null;
}
using var context = new AccountsDatabase();
context.Cities.Add(newcity);
context.SaveChanges();
return newcity.GetViewModel;
}
public CityViewModel? Update(CityBindingModel model)
{
using var context = new AccountsDatabase();
var component = context.Cities.FirstOrDefault(x => x.Id == model.Id);
if (component == null)
{
return null;
}
component.Update(model);
context.SaveChanges();
return component.GetViewModel;
}
}
}

View File

@ -0,0 +1,88 @@
// <auto-generated />
using System;
using System.Collections.Generic;
using DatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace DatabaseImplement.Migrations
{
[DbContext(typeof(AccountsDatabase))]
[Migration("20241127202901_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("DatabaseImplement.Models.Accounts", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("AccountCreationDate")
.HasColumnType("timestamp with time zone");
b.PrimitiveCollection<List<DateTime>>("AuthorizationAttemptsHistory")
.IsRequired()
.HasColumnType("timestamp with time zone[]");
b.Property<string>("Login")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ResidenceCityId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ResidenceCityId");
b.ToTable("Accounts");
});
modelBuilder.Entity("DatabaseImplement.Models.Cities", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Cities");
});
modelBuilder.Entity("DatabaseImplement.Models.Accounts", b =>
{
b.HasOne("DatabaseImplement.Models.Cities", "ResidenceCity")
.WithMany()
.HasForeignKey("ResidenceCityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ResidenceCity");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace DatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Cities",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Name = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Cities", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Accounts",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Login = table.Column<string>(type: "text", nullable: false),
AuthorizationAttemptsHistory = table.Column<List<DateTime>>(type: "timestamp with time zone[]", nullable: false),
ResidenceCityId = table.Column<int>(type: "integer", nullable: false),
AccountCreationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Accounts", x => x.Id);
table.ForeignKey(
name: "FK_Accounts_Cities_ResidenceCityId",
column: x => x.ResidenceCityId,
principalTable: "Cities",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Accounts_ResidenceCityId",
table: "Accounts",
column: "ResidenceCityId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Accounts");
migrationBuilder.DropTable(
name: "Cities");
}
}
}

View File

@ -0,0 +1,85 @@
// <auto-generated />
using System;
using System.Collections.Generic;
using DatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace DatabaseImplement.Migrations
{
[DbContext(typeof(AccountsDatabase))]
partial class AccountsDatabaseModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("DatabaseImplement.Models.Accounts", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("AccountCreationDate")
.HasColumnType("timestamp with time zone");
b.PrimitiveCollection<List<DateTime>>("AuthorizationAttemptsHistory")
.IsRequired()
.HasColumnType("timestamp with time zone[]");
b.Property<string>("Login")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ResidenceCityId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ResidenceCityId");
b.ToTable("Accounts");
});
modelBuilder.Entity("DatabaseImplement.Models.Cities", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Cities");
});
modelBuilder.Entity("DatabaseImplement.Models.Accounts", b =>
{
b.HasOne("DatabaseImplement.Models.Cities", "ResidenceCity")
.WithMany()
.HasForeignKey("ResidenceCityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ResidenceCity");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,67 @@
using Contracts.BindingModels;
using Contracts.ViewModels;
using DataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DatabaseImplement.Models
{
public class Accounts : IAccountModel
{
[Required]
public string Login { get; set; } = string.Empty;
public List<DateTime> AuthorizationAttemptsHistory { get; set; } = new List<DateTime>();
public int ResidenceCityId { get; set; }
public virtual Cities ResidenceCity { get; set; } = new();
public DateTime AccountCreationDate { get; set; }
public int Id { get; private set; }
public static Accounts? Create(AccountsDatabase context, AccountBindingModel? model)
{
if (model == null)
{
return null;
}
return new Accounts()
{
Id = model.Id,
Login = model.Login,
ResidenceCityId = model.ResidenceCityId,
ResidenceCity = context.Cities.First(x => x.Id == model.ResidenceCityId),
AuthorizationAttemptsHistory = model.AuthorizationAttemptsHistory.Select(date => date.ToUniversalTime()).ToList(),
AccountCreationDate = model.AccountCreationDate.ToUniversalTime()
};
}
public void Update(AccountBindingModel? model, AccountsDatabase context)
{
if (model == null)
{
return;
}
Login = model.Login;
ResidenceCityId = model.ResidenceCityId;
ResidenceCity = context.Cities.First(x => x.Id == model.ResidenceCityId);
AuthorizationAttemptsHistory = model.AuthorizationAttemptsHistory.Select(date => date.ToUniversalTime()).ToList();
AccountCreationDate = model.AccountCreationDate.ToUniversalTime();
}
public AccountViewModel GetViewModel => new()
{
Id = Id,
Login = Login,
ResidenceCityId = ResidenceCity.Id,
ResidenceCityName = ResidenceCity.Name,
AuthorizationAttemptsHistory = AuthorizationAttemptsHistory,
AccountCreationDate = AccountCreationDate,
};
}
}

View File

@ -0,0 +1,54 @@
using Contracts.BindingModels;
using Contracts.ViewModels;
using DataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DatabaseImplement.Models
{
public class Cities : ICityModel
{
[Required]
public string Name { get; private set; } = string.Empty;
public int Id { get; private set; }
public static Cities? Create(CityBindingModel? model)
{
if (model == null)
{
return null;
}
return new Cities()
{
Id = model.Id,
Name = model.Name,
};
}
public static Cities? Create(CityViewModel? model)
{
return new Cities()
{
Id = model.Id,
Name = model.Name,
};
}
public void Update(CityBindingModel? model)
{
if (model == null)
{
return;
}
Name = model.Name;
}
public CityViewModel GetViewModel => new()
{
Id = Id,
Name = Name,
};
}
}

49
Lab3/Lab3.sln Normal file
View File

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataModels", "DataModels\DataModels.csproj", "{1A0D3060-AA07-4FE1-B35F-C50BDBD7DC11}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinForms", "WinForms\WinForms.csproj", "{41510F7C-2870-4639-A9C0-21B45A670051}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessLogic", "BusinessLogic\BusinessLogic.csproj", "{2F353788-82CB-41FB-9F30-0677595B324F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contracts", "Contracts\Contracts.csproj", "{4E33A514-74DF-4249-BC9A-577A9DE2428A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseImplement", "DatabaseImplement\DatabaseImplement.csproj", "{3E515C5F-ACF7-4980-B13F-4A2BC6E08D93}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1A0D3060-AA07-4FE1-B35F-C50BDBD7DC11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A0D3060-AA07-4FE1-B35F-C50BDBD7DC11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A0D3060-AA07-4FE1-B35F-C50BDBD7DC11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A0D3060-AA07-4FE1-B35F-C50BDBD7DC11}.Release|Any CPU.Build.0 = Release|Any CPU
{41510F7C-2870-4639-A9C0-21B45A670051}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{41510F7C-2870-4639-A9C0-21B45A670051}.Debug|Any CPU.Build.0 = Debug|Any CPU
{41510F7C-2870-4639-A9C0-21B45A670051}.Release|Any CPU.ActiveCfg = Release|Any CPU
{41510F7C-2870-4639-A9C0-21B45A670051}.Release|Any CPU.Build.0 = Release|Any CPU
{2F353788-82CB-41FB-9F30-0677595B324F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F353788-82CB-41FB-9F30-0677595B324F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F353788-82CB-41FB-9F30-0677595B324F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F353788-82CB-41FB-9F30-0677595B324F}.Release|Any CPU.Build.0 = Release|Any CPU
{4E33A514-74DF-4249-BC9A-577A9DE2428A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E33A514-74DF-4249-BC9A-577A9DE2428A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E33A514-74DF-4249-BC9A-577A9DE2428A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E33A514-74DF-4249-BC9A-577A9DE2428A}.Release|Any CPU.Build.0 = Release|Any CPU
{3E515C5F-ACF7-4980-B13F-4A2BC6E08D93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E515C5F-ACF7-4980-B13F-4A2BC6E08D93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E515C5F-ACF7-4980-B13F-4A2BC6E08D93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E515C5F-ACF7-4980-B13F-4A2BC6E08D93}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {76DCE003-B6A2-426C-87F2-C9C12FCB3691}
EndGlobalSection
EndGlobal

229
Lab3/WinForms/FormAccount.Designer.cs generated Normal file
View File

@ -0,0 +1,229 @@
using System.Windows.Forms;
namespace WinForms
{
partial class FormAccount
{
/// <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()
{
labelLogin = new Label();
textBoxLogin = new TextBox();
labelcity = new Label();
buttonCancel = new Button();
buttonSave = new Button();
openFileDialog = new OpenFileDialog();
label1 = new Label();
label2 = new Label();
listBoxDates = new ListBox();
dateTimePickerControl1 = new PutincevLibrary.DateTimePickerControl();
dateTimePicker1 = new DateTimePicker();
buttonAddDate = new Button();
checkedListBoxControl1 = new PutincevLibrary.CheckedListBoxControl();
buttonUpdateDate = new Button();
buttonDeleteDate = new Button();
SuspendLayout();
//
// labelLogin
//
labelLogin.AutoSize = true;
labelLogin.Location = new Point(10, 7);
labelLogin.Name = "labelLogin";
labelLogin.Size = new Size(41, 15);
labelLogin.TabIndex = 0;
labelLogin.Text = "Логин";
//
// textBoxLogin
//
textBoxLogin.Location = new Point(10, 24);
textBoxLogin.Margin = new Padding(3, 2, 3, 2);
textBoxLogin.Name = "textBoxLogin";
textBoxLogin.Size = new Size(241, 23);
textBoxLogin.TabIndex = 1;
//
// labelcity
//
labelcity.AutoSize = true;
labelcity.Location = new Point(10, 62);
labelcity.Name = "labelcity";
labelcity.Size = new Size(112, 15);
labelcity.TabIndex = 4;
labelcity.Text = "Город проживания";
//
// buttonCancel
//
buttonCancel.Location = new Point(162, 416);
buttonCancel.Margin = new Padding(3, 2, 3, 2);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(83, 21);
buttonCancel.TabIndex = 7;
buttonCancel.Text = "Отменить";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// buttonSave
//
buttonSave.Location = new Point(13, 416);
buttonSave.Margin = new Padding(3, 2, 3, 2);
buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(94, 21);
buttonSave.TabIndex = 8;
buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true;
buttonSave.Click += buttonSave_Click;
//
// openFileDialog
//
openFileDialog.FileName = "openFileDialog";
openFileDialog.Multiselect = true;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(13, 375);
label1.Name = "label1";
label1.Size = new Size(136, 15);
label1.TabIndex = 10;
label1.Text = "Дата создания аккаунта";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(13, 192);
label2.Name = "label2";
label2.Size = new Size(151, 15);
label2.TabIndex = 12;
label2.Text = "Даты ранних авторизаций";
//
// listBoxDates
//
listBoxDates.FormattingEnabled = true;
listBoxDates.ItemHeight = 15;
listBoxDates.Location = new Point(10, 210);
listBoxDates.Name = "listBoxDates";
listBoxDates.SelectionMode = SelectionMode.MultiExtended;
listBoxDates.Size = new Size(231, 94);
listBoxDates.TabIndex = 19;
//
// dateTimePickerControl1
//
dateTimePickerControl1.Location = new Point(13, 392);
dateTimePickerControl1.Margin = new Padding(3, 2, 3, 2);
dateTimePickerControl1.MaxValue = null;
dateTimePickerControl1.MinValue = null;
dateTimePickerControl1.Name = "dateTimePickerControl1";
dateTimePickerControl1.Size = new Size(228, 20);
dateTimePickerControl1.TabIndex = 20;
//
// dateTimePicker1
//
dateTimePicker1.Location = new Point(13, 310);
dateTimePicker1.Name = "dateTimePicker1";
dateTimePicker1.Size = new Size(228, 23);
dateTimePicker1.TabIndex = 22;
//
// buttonAddDate
//
buttonAddDate.Location = new Point(13, 339);
buttonAddDate.Name = "buttonAddDate";
buttonAddDate.Size = new Size(75, 23);
buttonAddDate.TabIndex = 23;
buttonAddDate.Text = "Добавить";
buttonAddDate.UseVisualStyleBackColor = true;
buttonAddDate.Click += buttonAddDate_Click;
//
// checkedListBoxControl1
//
checkedListBoxControl1.Location = new Point(10, 79);
checkedListBoxControl1.Margin = new Padding(3, 2, 3, 2);
checkedListBoxControl1.Name = "checkedListBoxControl1";
checkedListBoxControl1.Size = new Size(231, 102);
checkedListBoxControl1.TabIndex = 24;
//
// buttonUpdateDate
//
buttonUpdateDate.Location = new Point(89, 339);
buttonUpdateDate.Name = "buttonUpdateDate";
buttonUpdateDate.Size = new Size(75, 23);
buttonUpdateDate.TabIndex = 25;
buttonUpdateDate.Text = "Обновить";
buttonUpdateDate.UseVisualStyleBackColor = true;
buttonUpdateDate.Click += buttonUpdateDate_Click;
//
// buttonDeleteDate
//
buttonDeleteDate.Location = new Point(166, 339);
buttonDeleteDate.Name = "buttonDeleteDate";
buttonDeleteDate.Size = new Size(75, 23);
buttonDeleteDate.TabIndex = 26;
buttonDeleteDate.Text = "Удалить";
buttonDeleteDate.UseVisualStyleBackColor = true;
buttonDeleteDate.Click += buttonDeleteDate_Click;
//
// FormAccount
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(256, 449);
Controls.Add(buttonDeleteDate);
Controls.Add(buttonUpdateDate);
Controls.Add(checkedListBoxControl1);
Controls.Add(buttonAddDate);
Controls.Add(dateTimePicker1);
Controls.Add(dateTimePickerControl1);
Controls.Add(listBoxDates);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(buttonSave);
Controls.Add(buttonCancel);
Controls.Add(labelcity);
Controls.Add(textBoxLogin);
Controls.Add(labelLogin);
Margin = new Padding(3, 2, 3, 2);
Name = "FormAccount";
Text = "Аккаунт";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label labelLogin;
private TextBox textBoxLogin;
private Label labelcity;
private Button buttonCancel;
private Button buttonSave;
private OpenFileDialog openFileDialog;
private Label label1;
private Label label2;
private ListBox listBoxDates;
private PutincevLibrary.DateTimePickerControl dateTimePickerControl1;
private DateTimePicker dateTimePicker1;
private Button buttonAddDate;
private PutincevLibrary.CheckedListBoxControl checkedListBoxControl1;
private Button buttonUpdateDate;
private Button buttonDeleteDate;
}
}

View File

@ -0,0 +1,172 @@
using Contracts.BindingModels;
using Contracts.BusinessLogicContracts;
using Contracts.SearchModels;
using Contracts.ViewModels;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForms
{
public partial class FormAccount : Form
{
public int? _id;
private readonly IAccountLogic _logic;
//private readonly ICityLogic _cityLogic;
private List<CityViewModel> _Cities;
private bool hasUnsavedChanges = false;
public int Id { set { _id = value; } }
public FormAccount(IAccountLogic logic, ICityLogic cityLogic)
{
InitializeComponent();
_logic = logic;
_Cities = new List<CityViewModel>();
_Cities = cityLogic.ReadList(null);
var cityNames = _Cities.Select(city => city.Name).ToList();
checkedListBoxControl1.SetCheckedListBoxValues(cityNames);
DateTime now = DateTime.Now;
dateTimePickerControl1.MaxValue = now;
dateTimePickerControl1.MinValue = now.AddYears(-10);
this.Load += FormAccount_Load;
}
private void FormAccount_Load(object sender, EventArgs e)
{
if (_id.HasValue)
{
try
{
AccountViewModel accountViewModel = _logic.ReadElement(new AccountSearchModel { Id = _id.Value });
if (accountViewModel != null)
{
textBoxLogin.Text = accountViewModel.Login;
CityViewModel selectedCity = _Cities.FirstOrDefault(city => city.Id == accountViewModel.ResidenceCityId);
if (selectedCity != null)
{
checkedListBoxControl1.CheckedItem = selectedCity.Name;
}
dateTimePickerControl1.SelectedValue = accountViewModel.AccountCreationDate;
foreach (DateTime status in accountViewModel.AuthorizationAttemptsHistory)
{
listBoxDates.Items.Add(status);
}
}
else
{
MessageBox.Show("Аккаунт с указанным ID не найден.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void buttonSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBoxLogin.Text))
{
MessageBox.Show("Заполните логин", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if (checkedListBoxControl1.CheckedItem == null)
{
MessageBox.Show("Укажите город проживания", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
try
{
var model = new AccountBindingModel
{
Id = _id ?? 0,
Login = textBoxLogin.Text,
ResidenceCityId = _Cities.First(x => x.Name == checkedListBoxControl1.CheckedItem).Id,
AccountCreationDate = (DateTime)dateTimePickerControl1.SelectedValue,
AuthorizationAttemptsHistory = listBoxDates.Items
.Cast<DateTime>()
.Select(date => DateTime.SpecifyKind(date, DateTimeKind.Utc))
.ToList()
};
var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model);
if (!operationResult)
{
throw new Exception("Возникла ошибка при сохранении. Дополнительная информация в логах");
}
MessageBox.Show("Сохранение прошло успешно", "Успешное сохранение", MessageBoxButtons.OK, MessageBoxIcon.Information);
DialogResult = DialogResult.OK;
Close();
}
catch (DbUpdateException ex)
{
// Получение внутреннего исключения для более подробной информации
var innerException = ex.InnerException;
MessageBox.Show($"Ошибка при обновлении базы данных: {innerException?.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void buttonAddDate_Click(object sender, EventArgs e)
{
listBoxDates.Items.Add(dateTimePicker1.Value);
}
private void buttonUpdateDate_Click(object sender, EventArgs e)
{
if (listBoxDates.SelectedIndex != -1)
{
listBoxDates.Items[listBoxDates.SelectedIndex] = dateTimePicker1.Value;
}
else
{
MessageBox.Show("Выберите изменяемую дату", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void buttonDeleteDate_Click(object sender, EventArgs e)
{
if (listBoxDates.SelectedIndex != -1)
{
listBoxDates.Items.RemoveAt(listBoxDates.SelectedIndex);
}
else
{
MessageBox.Show("Выберите удаляемую дату", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
Close();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
// Проверка наличия несохраненных изменений
if (hasUnsavedChanges)
{
var result = MessageBox.Show("У вас есть несохраненные изменения. Вы действительно хотите закрыть форму?", "Предупреждение", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
// Если пользователь выбирает "Нет", отмена закрытия формы
if (result == DialogResult.No)
{
e.Cancel = true;
}
}
}
}
}

View File

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

86
Lab3/WinForms/FormCities.Designer.cs generated Normal file
View File

@ -0,0 +1,86 @@
using System.Windows.Forms;
namespace WinForms
{
partial class FormCities
{
/// <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();
NameCol = new DataGridViewTextBoxColumn();
Id = new DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Columns.AddRange(new DataGridViewColumn[] { NameCol, Id });
dataGridView.Location = new Point(0, 0);
dataGridView.Name = "dataGridView";
dataGridView.RowHeadersWidth = 47;
dataGridView.Size = new Size(800, 356);
dataGridView.TabIndex = 0;
dataGridView.CellValueChanged += dataGridView_CellValueChanged;
dataGridView.UserDeletingRow += dataGridView_UserDeletingRow;
dataGridView.KeyUp += dataGridView_KeyUp;
//
// NameCol
//
NameCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
NameCol.HeaderText = "Город проживания";
NameCol.MinimumWidth = 6;
NameCol.Name = "NameCol";
//
// Id
//
Id.HeaderText = "Id";
Id.MinimumWidth = 6;
Id.Name = "Id";
Id.Visible = false;
Id.Width = 125;
//
// Formcitys
//
AutoScaleDimensions = new SizeF(8F, 19F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 356);
Controls.Add(dataGridView);
Name = "Formcitys";
Text = "Города";
Load += Formcitys_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
private DataGridViewTextBoxColumn NameCol;
private DataGridViewTextBoxColumn Id;
}
}

105
Lab3/WinForms/FormCities.cs Normal file
View File

@ -0,0 +1,105 @@
using Contracts.BindingModels;
using Contracts.BusinessLogicContracts;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForms
{
public partial class FormCities : Form
{
private readonly ICityLogic _logic;
private bool loading = false;
public FormCities(ICityLogic logic)
{
InitializeComponent();
_logic = logic;
}
private void LoadData()
{
loading = true;
try
{
var list = _logic.ReadList(null);
if (list != null)
{
foreach (var city in list)
{
int rowIndex = dataGridView.Rows.Add();
dataGridView.Rows[rowIndex].Cells[0].Value = city.Name;
dataGridView.Rows[rowIndex].Cells[1].Value = city.Id;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
loading = false;
}
}
private void Formcitys_Load(object sender, EventArgs e)
{
LoadData();
}
private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (loading || e.RowIndex < 0 || e.ColumnIndex != 0) return;
if (dataGridView.Rows[e.RowIndex].Cells[1].Value != null && !string.IsNullOrEmpty(dataGridView.Rows[e.RowIndex].Cells[1].Value.ToString()))
{
var name = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (name is null) return;
_logic.Update(new CityBindingModel { Id = Convert.ToInt32(dataGridView.Rows[e.RowIndex].Cells[1].Value), Name = name.ToString() });
}
else
{
var name = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (name is null) return;
_logic.Create(new CityBindingModel { Id = 0, Name = name.ToString() });
int newInterestId = _logic.ReadList(null).ToList().Last().Id;
dataGridView.Rows[e.RowIndex].Cells[1].Value = newInterestId;
}
}
private void dataGridView_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Insert:
dataGridView.Rows.Add();
break;
}
}
private void deleteRows(DataGridViewSelectedRowCollection rows)
{
for (int i = 0; i < rows.Count; i++)
{
DataGridViewRow row = rows[i];
if (!_logic.Delete(new CityBindingModel { Id = Convert.ToInt32(row.Cells[1].Value) })) continue;
}
dataGridView.Rows.Clear();
LoadData();
}
private void dataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
e.Cancel = true;
if (dataGridView.SelectedRows == null) return;
if (MessageBox.Show("Удалить записи?", "Подтвердите действие", MessageBoxButtons.YesNo) == DialogResult.No) return;
deleteRows(dataGridView.SelectedRows);
}
}
}

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>

175
Lab3/WinForms/FormMain.Designer.cs generated Normal file
View File

@ -0,0 +1,175 @@
using System.Windows.Forms;
namespace WinForms
{
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()
{
components = new System.ComponentModel.Container();
menuStrip = new MenuStrip();
заказыToolStripMenuItem = new ToolStripMenuItem();
создатьToolStripMenuItem = new ToolStripMenuItem();
редактироватьToolStripMenuItem = new ToolStripMenuItem();
удалитьToolStripMenuItem = new ToolStripMenuItem();
отчётыToolStripMenuItem = new ToolStripMenuItem();
документToolStripMenuItem = new ToolStripMenuItem();
документСТаблицейToolStripMenuItem = new ToolStripMenuItem();
документСДиаграммойToolStripMenuItem = new ToolStripMenuItem();
выбранныеТоварыToolStripMenuItem = new ToolStripMenuItem();
controlDataTable = new ControlsLibraryNet60.Data.ControlDataTableTable();
tablepdf1 = new Components.NonVisual.TablePDF(components);
componentExcelWithTable1 = new PutincevLibrary.ComponentExcelWithTable(components);
componentDocumentWithChartLineWord1 = new ComponentsLibraryNet60.DocumentWithChart.ComponentDocumentWithChartLineWord(components);
menuStrip.SuspendLayout();
SuspendLayout();
//
// menuStrip
//
menuStrip.ImageScalingSize = new Size(18, 18);
menuStrip.Items.AddRange(new ToolStripItem[] { заказыToolStripMenuItem, отчётыToolStripMenuItem, выбранныеТоварыToolStripMenuItem });
menuStrip.Location = new Point(0, 0);
menuStrip.Name = "menuStrip";
menuStrip.Padding = new Padding(5, 2, 0, 2);
menuStrip.Size = new Size(853, 24);
menuStrip.TabIndex = 0;
menuStrip.Text = "menuStrip";
//
// заказыToolStripMenuItem
//
заказыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { создатьToolStripMenuItem, редактироватьToolStripMenuItem, удалитьToolStripMenuItem });
заказыToolStripMenuItem.Name = аказыToolStripMenuItem";
заказыToolStripMenuItem.Size = new Size(63, 20);
заказыToolStripMenuItem.Text = "Аккаунт";
//
// создатьToolStripMenuItem
//
создатьToolStripMenuItem.Name = "создатьToolStripMenuItem";
создатьToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.A;
создатьToolStripMenuItem.Size = new Size(196, 22);
создатьToolStripMenuItem.Text = "Создать";
создатьToolStripMenuItem.Click += создатьToolStripMenuItem_Click;
//
// редактироватьToolStripMenuItem
//
редактироватьToolStripMenuItem.Name = "редактироватьToolStripMenuItem";
редактироватьToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.U;
редактироватьToolStripMenuItem.Size = new Size(196, 22);
редактироватьToolStripMenuItem.Text = "Редактировать";
редактироватьToolStripMenuItem.Click += редактироватьToolStripMenuItem_Click;
//
// удалитьToolStripMenuItem
//
удалитьToolStripMenuItem.Name = "удалитьToolStripMenuItem";
удалитьToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.D;
удалитьToolStripMenuItem.Size = new Size(196, 22);
удалитьToolStripMenuItem.Text = "Удалить";
удалитьToolStripMenuItem.Click += удалитьToolStripMenuItem_Click;
//
// отчётыToolStripMenuItem
//
отчётыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { документToolStripMenuItem, документСТаблицейToolStripMenuItem, документСДиаграммойToolStripMenuItem });
отчётыToolStripMenuItem.Name = "отчётыToolStripMenuItem";
отчётыToolStripMenuItem.Size = new Size(60, 20);
отчётыToolStripMenuItem.Text = "Отчёты";
//
// документToolStripMenuItem
//
документToolStripMenuItem.Name = окументToolStripMenuItem";
документToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.S;
документToolStripMenuItem.Size = new Size(309, 22);
документToolStripMenuItem.Text = "Документ с простой таблицей";
документToolStripMenuItem.Click += GeneratePdfButton_Click;
//
// документСТаблицейToolStripMenuItem
//
документСТаблицейToolStripMenuItem.Name = окументСТаблицейToolStripMenuItem";
документСТаблицейToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.T;
документСТаблицейToolStripMenuItem.Size = new Size(309, 22);
документСТаблицейToolStripMenuItem.Text = "Отчет по всем аккаунтам Excel";
документСТаблицейToolStripMenuItem.Click += GenerateExelButton_Click;
//
// документСДиаграммойToolStripMenuItem
//
документСДиаграммойToolStripMenuItem.Name = окументСДиаграммойToolStripMenuItem";
документСДиаграммойToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.C;
документСДиаграммойToolStripMenuItem.Size = new Size(309, 22);
документСДиаграммойToolStripMenuItem.Text = "Документ с линейной диаграммой";
документСДиаграммойToolStripMenuItem.Click += GenerateWordButton_Click;
//
// выбранныеТоварыToolStripMenuItem
//
выбранныеТоварыToolStripMenuItem.Name = "выбранныеТоварыToolStripMenuItem";
выбранныеТоварыToolStripMenuItem.Size = new Size(130, 20);
выбранныеТоварыToolStripMenuItem.Text = "Города проживания";
выбранныеТоварыToolStripMenuItem.Click += выбранныеТоварыToolStripMenuItem_Click;
//
// controlDataTable
//
controlDataTable.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
controlDataTable.Location = new Point(13, 27);
controlDataTable.Margin = new Padding(4, 3, 4, 3);
controlDataTable.Name = "controlDataTable";
controlDataTable.SelectedRowIndex = -1;
controlDataTable.Size = new Size(827, 392);
controlDataTable.TabIndex = 1;
//
// FormMain
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(853, 431);
Controls.Add(controlDataTable);
Controls.Add(menuStrip);
MainMenuStrip = menuStrip;
Margin = new Padding(3, 2, 3, 2);
Name = "FormMain";
Text = "Аккаунты";
Load += FormMain_Load;
menuStrip.ResumeLayout(false);
menuStrip.PerformLayout();
ResumeLayout(false);
PerformLayout();
}
#endregion
private MenuStrip menuStrip;
private ToolStripMenuItem заказыToolStripMenuItem;
private ToolStripMenuItem создатьToolStripMenuItem;
private ToolStripMenuItem редактироватьToolStripMenuItem;
private ToolStripMenuItem удалитьToolStripMenuItem;
private ToolStripMenuItem отчётыToolStripMenuItem;
private ToolStripMenuItem документToolStripMenuItem;
private ToolStripMenuItem документСТаблицейToolStripMenuItem;
private ToolStripMenuItem выбранныеТоварыToolStripMenuItem;
private ToolStripMenuItem документСДиаграммойToolStripMenuItem;
private ControlsLibraryNet60.Data.ControlDataTableTable controlDataTable;
private Components.NonVisual.TablePDF tablepdf1;
private PutincevLibrary.ComponentExcelWithTable componentExcelWithTable1;
private ComponentsLibraryNet60.DocumentWithChart.ComponentDocumentWithChartLineWord componentDocumentWithChartLineWord1;
}
}

285
Lab3/WinForms/FormMain.cs Normal file
View File

@ -0,0 +1,285 @@
using Components.NonVisual;
using Components.SaveToPdfHelpers;
using Contracts.BindingModels;
using Contracts.BusinessLogicContracts;
using Contracts.SearchModels;
using Contracts.ViewModels;
using ControlsLibraryNet60.Core;
using ControlsLibraryNet60.Models;
using PutincevLibrary;
using PutincevLibrary.Info;
using System.Text;
using ComponentsLibraryNet60.DocumentWithChart;
using ComponentsLibraryNet60.Models;
namespace WinForms
{
public partial class FormMain : Form
{
private IAccountLogic _logic;
public FormMain(IAccountLogic logic)
{
InitializeComponent();
_logic = logic;
controlDataTable.LoadColumns(new List<DataTableColumnConfig>
{
new DataTableColumnConfig { ColumnHeader = "Идентификатор", PropertyName = "Id", Visible = true, Width = 100 },
new DataTableColumnConfig { ColumnHeader = "Логин", PropertyName = "Login", Visible = true, Width = 200 },
new DataTableColumnConfig { ColumnHeader = "Город проживания", PropertyName = "ResidenceCityName", Visible = true, Width = 150 },
new DataTableColumnConfig { ColumnHeader = "Последние попытки авторизации", PropertyName = "AccountStatusHistory", Visible = true, Width = 250 },
new DataTableColumnConfig { ColumnHeader = "Дата создания аккаунта", PropertyName = "AccountCreationDate", Visible = true, Width = 125 },
});
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
private void LoadData()
{
controlDataTable.Clear();
var accounts = _logic.ReadList(null);
if (accounts != null)
{
var displayAccounts = accounts.Select(account => new
{
account.Id,
account.Login,
account.ResidenceCityName,
AccountStatusHistory = string.Join(", \n", account.AuthorizationAttemptsHistory),
account.AccountCreationDate
}).ToList();
controlDataTable.AddTable(displayAccounts);
}
}
private void FormMain_Load(object sender, EventArgs e)
{
LoadData();
}
private void создатьToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormAccount));
if (service is FormAccount form)
{
form.ShowDialog();
LoadData();
}
}
private void редактироватьToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormAccount));
if (service is FormAccount form)
{
form._id = controlDataTable.GetSelectedObject<AccountViewModel>().Id;
if (form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
}
private void удалитьToolStripMenuItem_Click(object sender, EventArgs e)
{
var selectedAccount = controlDataTable.GetSelectedObject<AccountViewModel>();
if (selectedAccount == null)
{
MessageBox.Show("Не выбрана запись для удаления.");
return;
}
if (MessageBox.Show("Удалить запись?", "", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
if (_logic.Delete(new AccountBindingModel { Id = selectedAccount.Id }))
{
LoadData();
MessageBox.Show("Запись успешно удалена.");
}
else
{
MessageBox.Show("Ошибка при удалении записи.");
}
}
}
private void GeneratePdfButton_Click(object sender, EventArgs e)
{
try
{
var accounts = _logic.ReadList(null);
var accountTables = new List<string[,]>();
foreach (var account in accounts)
{
int rowCount = account.AuthorizationAttemptsHistory.Count;
string[,] accountTable = new string[rowCount + 1, 4];
accountTable[0, 0] = "Попытки авторизаций";
accountTable[0, 1] = "Идентификатор аккаунта";
accountTable[0, 2] = "Город проживания";
accountTable[0, 3] = "Дата создания";
for (int i = 0; i < rowCount; i++)
{
accountTable[i + 1, 0] = account.AuthorizationAttemptsHistory[i].ToString("dd-MM-yyyy");
accountTable[i + 1, 1] = account.Id.ToString();
accountTable[i + 1, 2] = account.ResidenceCityName;
accountTable[i + 1, 3] = account.AccountCreationDate.ToString("dd-MM-yyyy");
}
accountTables.Add(accountTable);
}
using (System.Windows.Forms.SaveFileDialog saveFileDialog = new System.Windows.Forms.SaveFileDialog())
{
saveFileDialog.Filter = "PDF files (*.pdf)|*.pdf|All files (*.*)|*.*";
saveFileDialog.Title = "Сохранить PDF-документ";
saveFileDialog.FileName = "Отчет1.pdf";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
var pdfData = new PdfDocumentData(
saveFileDialog.FileName,
"Отчет по попыткам авторизации аккаунтов",
accountTables
);
tablepdf1.GeneratePdf(pdfData);
MessageBox.Show("PDF-документ успешно создан!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Произошла ошибка: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void GenerateExelButton_Click(object sender, EventArgs e)
{
ComponentExcelWithTable table = new();
var accounts = _logic.ReadList(null);
if (accounts == null || accounts.Count == 0)
{
MessageBox.Show("Нет данных для отчета.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Dictionary<string, (List<(string, string)>, List<int>)> headers = new()
{
{ "Идентификатор аккаунта", (new List<(string, string)> { ("Id", "Идентификатор") }, new List<int> { 30 }) },
{ "Логин", (new List<(string, string)> { ("Login", "Логин") }, new List<int> { 30 }) },
{ "Информация", (new List<(string, string)> { ("ResidenceCityName", "Город проживания"), ("AccountCreationDate", "Дата создания") }, new List<int> { 25, 25 }) }
};
string path = AppDomain.CurrentDomain.BaseDirectory + "OrderReport.xlsx";
using (System.Windows.Forms.SaveFileDialog saveFileDialog = new System.Windows.Forms.SaveFileDialog())
{
saveFileDialog.Title = "Сохранить Excel-документ";
saveFileDialog.FileName = "Отчет2.xlsx";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
path = saveFileDialog.FileName;
}
}
ExcelTableInfo<Contracts.ViewModels.AccountViewModel> info = new(path, "Отчет по аккаунтам", accounts, headers);
try
{
table.GenerateDocument(info);
MessageBox.Show("Сохарнено успешно", "Результат", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void GenerateWordButton_Click(object sender, EventArgs e)
{
var accounts = _logic.ReadList(null).Cast<AccountViewModel>().ToList();
var chartData = new Dictionary<string, List<(DateTime Date, int Count)>>();
foreach (var order in accounts)
{
if (!chartData.ContainsKey(order.ResidenceCityName))
{
chartData[order.ResidenceCityName] = new List<(DateTime Date, int Count)>();
}
var existingData = chartData[order.ResidenceCityName]
.FirstOrDefault(d => d.Date.Date == order.AccountCreationDate.Date);
if (existingData.Date == default)
{
chartData[order.ResidenceCityName].Add((order.AccountCreationDate.Date, 1));
}
else
{
int index = chartData[order.ResidenceCityName].FindIndex(d => d.Date.Date == order.AccountCreationDate.Date);
var updatedValue = chartData[order.ResidenceCityName][index];
chartData[order.ResidenceCityName][index] = (updatedValue.Date, updatedValue.Count + 1);
}
}
string filePath = "Отчет3.docx";
using (System.Windows.Forms.SaveFileDialog saveFileDialog = new System.Windows.Forms.SaveFileDialog())
{
saveFileDialog.Title = "Сохранить Word-документ";
saveFileDialog.FileName = "Отчет3.docx";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
filePath = saveFileDialog.FileName;
MessageBox.Show("Docx-документ успешно создан!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
var config = new ComponentDocumentWithChartConfig
{
ChartTitle = "Отчет по аккаунтам",
LegendLocation = ComponentsLibraryNet60.Models.Location.Bottom,
Data = chartData.ToDictionary(
entry => entry.Key,
entry => entry.Value.Select(d => (DateTimeToInt(d.Date), (double)d.Count)).ToList()),
FilePath = filePath,
Header = "Заголовок аккаунта"
};
var documentComponent = new ComponentDocumentWithChartLineWord();
documentComponent.CreateDoc(config);
MessageBox.Show("Документ создан успешно!");
}
private int DateTimeToInt(DateTime date)
{
return date.Day;
}
private void выбранныеТоварыToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormCities));
if (service is FormCities form)
{
form.ShowDialog();
}
}
}
}

132
Lab3/WinForms/FormMain.resx Normal file
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="tablepdf1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>126, 17</value>
</metadata>
<metadata name="componentExcelWithTable1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>230, 17</value>
</metadata>
<metadata name="wordDiagramComponent1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>431, 17</value>
</metadata>
</root>

41
Lab3/WinForms/Program.cs Normal file
View File

@ -0,0 +1,41 @@
using Contracts.BusinessLogicContracts;
using Contracts.StorageContracts;
using DatabaseImplement.Implements;
using BusinessLogic.BusinessLogics;
using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection;
namespace WinForms
{
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<FormMain>());
}
private static void ConfigureServices(ServiceCollection services)
{
services.AddTransient<ICityStorage, CityStorage>();
services.AddTransient<IAccountStorage, AccountStorage>();
services.AddTransient<ICityLogic, CityLogic>();
services.AddTransient<IAccountLogic, AccountLogic>();
services.AddTransient<FormMain>();
services.AddTransient<FormAccount>();
services.AddTransient<FormCities>();
}
}
}

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.0" />
<PackageReference Include="ComponentsLibraryNet60" Version="1.0.0" />
<PackageReference Include="ControlsLibraryNet60" Version="1.0.0" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.1.1" />
<PackageReference Include="EPPlus" Version="7.4.1" />
<PackageReference Include="NPOI" Version="2.7.1" />
<PackageReference Include="PutincevLibrary" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BusinessLogic\BusinessLogic.csproj" />
<ProjectReference Include="..\Contracts\Contracts.csproj" />
<ProjectReference Include="..\DatabaseImplement\DatabaseImplement.csproj" />
</ItemGroup>
</Project>