From 28d492421bb92c7d546b358f6124b7d3eabc0717 Mon Sep 17 00:00:00 2001 From: 1billy17 Date: Fri, 1 Nov 2024 22:07:13 +0300 Subject: [PATCH] first (projects) --- .gitignore | 363 ++++++++++++++++++ .../20241028031712_InitialCreate.Designer.cs | 118 ++++++ Migrations/20241028031712_InitialCreate.cs | 92 +++++ .../RemoteDatabaseContextModelSnapshot.cs | 115 ++++++ console_ui/Program.cs | 26 ++ console_ui/console_ui.csproj | 20 + data/Entity/Group.cs | 8 + data/Entity/Presence.cs | 9 + data/Entity/User.cs | 13 + data/LocalData/LocalStaticData.cs | 24 ++ data/RemoteData/RemoteDataBase/DAO/Group.cs | 9 + .../RemoteData/RemoteDataBase/DAO/Presence.cs | 11 + data/RemoteData/RemoteDataBase/DAO/User.cs | 12 + .../RemoteDataBase/RemoteDatabaseContext.cs | 30 ++ data/Repository/AdminRepositoryImpl.cs | 17 + data/Repository/GroupRepositoryImpl.cs | 55 +++ data/Repository/IAdminRepository.cs | 9 + data/Repository/IGroupRepository.cs | 13 + data/Repository/IPresenceRepository.cs | 11 + data/Repository/IUserRepository.cs | 13 + data/Repository/PresenceRepositoryImpl.cs | 55 +++ data/Repository/UserRepositoryImpl.cs | 60 +++ data/data.csproj | 18 + domain/Models/Group.cs | 13 + domain/Models/Presence.cs | 11 + domain/Models/User.cs | 38 ++ domain/UseCase/AdminUseCase.cs | 123 ++++++ domain/UseCase/GroupUseCase.cs | 54 +++ domain/UseCase/IAdminUseCase.cs | 10 + domain/UseCase/IGroupUseCase.cs | 13 + domain/UseCase/IPresenceUseCase.cs | 16 + domain/UseCase/IUserUseCase.cs | 13 + domain/UseCase/PresenceUseCase.cs | 188 +++++++++ domain/UseCase/UserUseCase.cs | 94 +++++ domain/domain.csproj | 17 + presence.sln | 40 ++ ui/AdminConsole.cs | 18 + ui/MainMenu.cs | 105 +++++ ui/UserConsole.cs | 172 +++++++++ ui/ui.csproj | 13 + 40 files changed, 2039 insertions(+) create mode 100644 .gitignore create mode 100644 Migrations/20241028031712_InitialCreate.Designer.cs create mode 100644 Migrations/20241028031712_InitialCreate.cs create mode 100644 Migrations/RemoteDatabaseContextModelSnapshot.cs create mode 100644 console_ui/Program.cs create mode 100644 console_ui/console_ui.csproj create mode 100644 data/Entity/Group.cs create mode 100644 data/Entity/Presence.cs create mode 100644 data/Entity/User.cs create mode 100644 data/LocalData/LocalStaticData.cs create mode 100644 data/RemoteData/RemoteDataBase/DAO/Group.cs create mode 100644 data/RemoteData/RemoteDataBase/DAO/Presence.cs create mode 100644 data/RemoteData/RemoteDataBase/DAO/User.cs create mode 100644 data/RemoteData/RemoteDataBase/RemoteDatabaseContext.cs create mode 100644 data/Repository/AdminRepositoryImpl.cs create mode 100644 data/Repository/GroupRepositoryImpl.cs create mode 100644 data/Repository/IAdminRepository.cs create mode 100644 data/Repository/IGroupRepository.cs create mode 100644 data/Repository/IPresenceRepository.cs create mode 100644 data/Repository/IUserRepository.cs create mode 100644 data/Repository/PresenceRepositoryImpl.cs create mode 100644 data/Repository/UserRepositoryImpl.cs create mode 100644 data/data.csproj create mode 100644 domain/Models/Group.cs create mode 100644 domain/Models/Presence.cs create mode 100644 domain/Models/User.cs create mode 100644 domain/UseCase/AdminUseCase.cs create mode 100644 domain/UseCase/GroupUseCase.cs create mode 100644 domain/UseCase/IAdminUseCase.cs create mode 100644 domain/UseCase/IGroupUseCase.cs create mode 100644 domain/UseCase/IPresenceUseCase.cs create mode 100644 domain/UseCase/IUserUseCase.cs create mode 100644 domain/UseCase/PresenceUseCase.cs create mode 100644 domain/UseCase/UserUseCase.cs create mode 100644 domain/domain.csproj create mode 100644 presence.sln create mode 100644 ui/AdminConsole.cs create mode 100644 ui/MainMenu.cs create mode 100644 ui/UserConsole.cs create mode 100644 ui/ui.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/Migrations/20241028031712_InitialCreate.Designer.cs b/Migrations/20241028031712_InitialCreate.Designer.cs new file mode 100644 index 0000000..4edcf56 --- /dev/null +++ b/Migrations/20241028031712_InitialCreate.Designer.cs @@ -0,0 +1,118 @@ +// +using System; +using Demo.Data.RemoteData.RemoteDataBase; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Demo.Migrations +{ + [DbContext(typeof(RemoteDatabaseContext))] + [Migration("20241028031712_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.GroupDAO", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ID")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ID"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.PresenceDAO", b => + { + b.Property("UserGuid") + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("LessonNumber") + .HasColumnType("integer"); + + b.Property("IsAttedance") + .HasColumnType("boolean"); + + b.Property("userDAOGuid") + .HasColumnType("uuid"); + + b.HasKey("UserGuid", "Date", "LessonNumber"); + + b.HasIndex("userDAOGuid"); + + b.ToTable("PresenceDaos"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDAO", b => + { + b.Property("Guid") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("FIO") + .IsRequired() + .HasColumnType("text"); + + b.Property("GroupID") + .HasColumnType("integer"); + + b.HasKey("Guid"); + + b.HasIndex("GroupID"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.PresenceDAO", b => + { + b.HasOne("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDAO", "userDAO") + .WithMany() + .HasForeignKey("userDAOGuid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("userDAO"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDAO", b => + { + b.HasOne("Demo.Data.RemoteData.RemoteDataBase.DAO.GroupDAO", "Group") + .WithMany("Users") + .HasForeignKey("GroupID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.GroupDAO", b => + { + b.Navigation("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20241028031712_InitialCreate.cs b/Migrations/20241028031712_InitialCreate.cs new file mode 100644 index 0000000..b76e162 --- /dev/null +++ b/Migrations/20241028031712_InitialCreate.cs @@ -0,0 +1,92 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Demo.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Groups", + columns: table => new + { + ID = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Groups", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Guid = table.Column(type: "uuid", nullable: false), + FIO = table.Column(type: "text", nullable: false), + GroupID = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Guid); + table.ForeignKey( + name: "FK_Users_Groups_GroupID", + column: x => x.GroupID, + principalTable: "Groups", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PresenceDaos", + columns: table => new + { + UserGuid = table.Column(type: "uuid", nullable: false), + Date = table.Column(type: "date", nullable: false), + LessonNumber = table.Column(type: "integer", nullable: false), + IsAttedance = table.Column(type: "boolean", nullable: false), + userDAOGuid = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PresenceDaos", x => new { x.UserGuid, x.Date, x.LessonNumber }); + table.ForeignKey( + name: "FK_PresenceDaos_Users_userDAOGuid", + column: x => x.userDAOGuid, + principalTable: "Users", + principalColumn: "Guid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_PresenceDaos_userDAOGuid", + table: "PresenceDaos", + column: "userDAOGuid"); + + migrationBuilder.CreateIndex( + name: "IX_Users_GroupID", + table: "Users", + column: "GroupID"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PresenceDaos"); + + migrationBuilder.DropTable( + name: "Users"); + + migrationBuilder.DropTable( + name: "Groups"); + } + } +} diff --git a/Migrations/RemoteDatabaseContextModelSnapshot.cs b/Migrations/RemoteDatabaseContextModelSnapshot.cs new file mode 100644 index 0000000..4d73666 --- /dev/null +++ b/Migrations/RemoteDatabaseContextModelSnapshot.cs @@ -0,0 +1,115 @@ +// +using System; +using Demo.Data.RemoteData.RemoteDataBase; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Demo.Migrations +{ + [DbContext(typeof(RemoteDatabaseContext))] + partial class RemoteDatabaseContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.GroupDAO", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ID")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("ID"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.PresenceDAO", b => + { + b.Property("UserGuid") + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("LessonNumber") + .HasColumnType("integer"); + + b.Property("IsAttedance") + .HasColumnType("boolean"); + + b.Property("userDAOGuid") + .HasColumnType("uuid"); + + b.HasKey("UserGuid", "Date", "LessonNumber"); + + b.HasIndex("userDAOGuid"); + + b.ToTable("PresenceDaos"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDAO", b => + { + b.Property("Guid") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("FIO") + .IsRequired() + .HasColumnType("text"); + + b.Property("GroupID") + .HasColumnType("integer"); + + b.HasKey("Guid"); + + b.HasIndex("GroupID"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.PresenceDAO", b => + { + b.HasOne("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDAO", "userDAO") + .WithMany() + .HasForeignKey("userDAOGuid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("userDAO"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDAO", b => + { + b.HasOne("Demo.Data.RemoteData.RemoteDataBase.DAO.GroupDAO", "Group") + .WithMany("Users") + .HasForeignKey("GroupID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.GroupDAO", b => + { + b.Navigation("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/console_ui/Program.cs b/console_ui/Program.cs new file mode 100644 index 0000000..b6e25ab --- /dev/null +++ b/console_ui/Program.cs @@ -0,0 +1,26 @@ +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.Repository; +using Demo.Domain.UseCase; +using Demo.UI; +using Microsoft.Extensions.DependencyInjection; + +IServiceCollection services = new ServiceCollection(); + + services + + .AddDbContext() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(); + + var serviceProvider = services.BuildServiceProvider(); + + MainMenuUI? mainMenuUI = serviceProvider.GetService(); diff --git a/console_ui/console_ui.csproj b/console_ui/console_ui.csproj new file mode 100644 index 0000000..6197270 --- /dev/null +++ b/console_ui/console_ui.csproj @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + Exe + net8.0 + enable + enable + + + diff --git a/data/Entity/Group.cs b/data/Entity/Group.cs new file mode 100644 index 0000000..e0b05ad --- /dev/null +++ b/data/Entity/Group.cs @@ -0,0 +1,8 @@ +namespace Demo.Domain.Models +{ + public class GroupLocalEntity + { + public required int ID {get; set; } + public required string Name{get; set; } + } +} \ No newline at end of file diff --git a/data/Entity/Presence.cs b/data/Entity/Presence.cs new file mode 100644 index 0000000..29995e7 --- /dev/null +++ b/data/Entity/Presence.cs @@ -0,0 +1,9 @@ +namespace Demo.Domain.Models{ + public class PresenceLocalEntity{ + public required Guid UserGuid{get; set; } + public bool IsAttedance { get; set; } = true; + public required DateOnly Date { get; set; } + + public required int LessonNumber { get; set; } + } +} \ No newline at end of file diff --git a/data/Entity/User.cs b/data/Entity/User.cs new file mode 100644 index 0000000..1d14a68 --- /dev/null +++ b/data/Entity/User.cs @@ -0,0 +1,13 @@ +namespace Demo.Domain.Models{ + public class UserLocalEntity :IEquatable{ + public required string FIO{get; set; } + public Guid Guid {get; set; } + public required int GroupID{get; set; } + + public bool Equals(UserLocalEntity? other) + { + if (other == null) return false; + return this.Guid.Equals(other.Guid); + } +} +} \ No newline at end of file diff --git a/data/LocalData/LocalStaticData.cs b/data/LocalData/LocalStaticData.cs new file mode 100644 index 0000000..4d26fdd --- /dev/null +++ b/data/LocalData/LocalStaticData.cs @@ -0,0 +1,24 @@ +using Demo.Domain.Models; + +namespace Demo.Data.LocalData +{ + public class LocalStaticData + { + public static List groups => new List + { + new GroupLocalEntity{ID = 1, Name = "ИП1-21"}, + new GroupLocalEntity{ID = 2, Name = "ИП1-22"}, + new GroupLocalEntity{ID = 3, Name = "ИП1-23"}, + }; + + public static List users => new List + { + new UserLocalEntity{Guid=Guid.Parse("e6b9964d-ea9f-420a-84b9-af9633bbfab9"), FIO = "RandomFio", GroupID = 1 }, + new UserLocalEntity{Guid=Guid.Parse("8388d931-5bef-41be-a152-78f1aca980ed"), FIO = "RandomFio1", GroupID = 2 }, + new UserLocalEntity{Guid=Guid.Parse("ed174548-49ed-4503-a902-c970cbf27173"), FIO = "RandomFio2", GroupID = 3 }, + new UserLocalEntity{Guid=Guid.Parse("614c0a23-5bd5-43ae-b48e-d5750afbc282"), FIO = "RandomFio3", GroupID = 1 }, + new UserLocalEntity{Guid=Guid.Parse("efcc1473-c116-4244-b3f7-f2341a5c3003"), FIO = "RandomFio4", GroupID = 2 }, + new UserLocalEntity{Guid=Guid.Parse("60640fb3-ace2-4cad-81d5-a0a58bc2dbbd"), FIO = "RandomFio5", GroupID = 3 }, + }; + } +} \ No newline at end of file diff --git a/data/RemoteData/RemoteDataBase/DAO/Group.cs b/data/RemoteData/RemoteDataBase/DAO/Group.cs new file mode 100644 index 0000000..dc1f561 --- /dev/null +++ b/data/RemoteData/RemoteDataBase/DAO/Group.cs @@ -0,0 +1,9 @@ +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class GroupDAO + { + public int ID {get; set; } + public string Name{get; set; } + public IEnumerable Users {get; set; } + } +} \ No newline at end of file diff --git a/data/RemoteData/RemoteDataBase/DAO/Presence.cs b/data/RemoteData/RemoteDataBase/DAO/Presence.cs new file mode 100644 index 0000000..c7d9622 --- /dev/null +++ b/data/RemoteData/RemoteDataBase/DAO/Presence.cs @@ -0,0 +1,11 @@ +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class PresenceDAO + { + public Guid UserGuid {get; set; } + public bool IsAttedance {get; set; } + public DateOnly Date {get; set; } + public int LessonNumber {get; set; } + public UserDAO userDAO {get; set; } + } +} \ No newline at end of file diff --git a/data/RemoteData/RemoteDataBase/DAO/User.cs b/data/RemoteData/RemoteDataBase/DAO/User.cs new file mode 100644 index 0000000..5c042d2 --- /dev/null +++ b/data/RemoteData/RemoteDataBase/DAO/User.cs @@ -0,0 +1,12 @@ +using System.Text.RegularExpressions; + +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class UserDAO + { + public string FIO { get; set; } + public Guid Guid {get; set; } + public int GroupID {get; set;} + public GroupDAO Group {get; set; } + } +} \ No newline at end of file diff --git a/data/RemoteData/RemoteDataBase/RemoteDatabaseContext.cs b/data/RemoteData/RemoteDataBase/RemoteDatabaseContext.cs new file mode 100644 index 0000000..b043a5e --- /dev/null +++ b/data/RemoteData/RemoteDataBase/RemoteDatabaseContext.cs @@ -0,0 +1,30 @@ +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Microsoft.EntityFrameworkCore; + +namespace Demo.Data.RemoteData.RemoteDataBase +{ + public class RemoteDatabaseContext: DbContext + { + public DbSet Groups {get; set; } + public DbSet Users {get; set;} + public DbSet PresenceDaos{get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseNpgsql("Host=localhost;Port=5433;Username=myuser;Password=mypassword;Database=mydatabase"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().HasKey(group => group.ID); + modelBuilder.Entity().Property(group => group.ID).ValueGeneratedOnAdd(); + modelBuilder.Entity().HasKey(user => user.Guid); + modelBuilder.Entity().Property(user => user.Guid).ValueGeneratedOnAdd(); + modelBuilder.Entity().HasKey(presence => new { + presence.UserGuid, + presence.Date, + presence.LessonNumber + }); + } + } +} \ No newline at end of file diff --git a/data/Repository/AdminRepositoryImpl.cs b/data/Repository/AdminRepositoryImpl.cs new file mode 100644 index 0000000..6a14738 --- /dev/null +++ b/data/Repository/AdminRepositoryImpl.cs @@ -0,0 +1,17 @@ +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Domain.Models; + +namespace Demo.Data.Repository +{ + public class SQLAdminRepositoryImpl : IAdminRepository{ + private readonly RemoteDatabaseContext _remoteDatabaseContext; + public SQLAdminRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext){ + _remoteDatabaseContext = remoteDatabaseContext; + } + + public List GetAllGroup() + { + return _remoteDatabaseContext.Groups.Select(x => new GroupLocalEntity{Name = x.Name, ID = x.ID}).ToList(); + } + } +} \ No newline at end of file diff --git a/data/Repository/GroupRepositoryImpl.cs b/data/Repository/GroupRepositoryImpl.cs new file mode 100644 index 0000000..d1a9d4b --- /dev/null +++ b/data/Repository/GroupRepositoryImpl.cs @@ -0,0 +1,55 @@ +using Demo.Domain.Models; +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.RemoteData.RemoteDataBase.DAO; + +namespace Demo.Data.Repository +{ + public class SQLGroupRepositoryImpl : IGroupRepository + { + private readonly RemoteDatabaseContext _remoteDatabaseContext; + + public SQLGroupRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext){ + _remoteDatabaseContext = remoteDatabaseContext; + GetAllGroups = _remoteDatabaseContext.Groups.Select(x => new GroupLocalEntity{Name = x.Name, ID = x.ID}).ToList(); + } + + public List GetAllGroups + { get; set; } + + public List GetAllGroup() + { + return _remoteDatabaseContext.Groups.Select(x => new GroupLocalEntity{Name = x.Name, ID = x.ID}).ToList(); + } + + public GroupLocalEntity? GetGroupById(int ID){ + var groupDAO = _remoteDatabaseContext.Groups.FirstOrDefault(x => x.ID == ID); + return new GroupLocalEntity{Name = groupDAO.Name, ID = groupDAO.ID}; + } + + public GroupLocalEntity? CreateGroup(string Name) { + GroupDAO groupDAO = new GroupDAO{Name = Name}; + var result = _remoteDatabaseContext.Groups.Add(groupDAO); + _remoteDatabaseContext.SaveChanges(); + return new GroupLocalEntity{Name = groupDAO.Name, ID = groupDAO.ID}; + } + + public GroupLocalEntity? UpdateGroup(GroupLocalEntity updatedGroup){ + var group = _remoteDatabaseContext.Groups.FirstOrDefault(x => x.ID == updatedGroup.ID); + if (group == null){ + return null; + } + + group.Name = updatedGroup.Name; + _remoteDatabaseContext.SaveChanges(); + return new GroupLocalEntity{Name = group.Name, ID = group.ID}; + } + + public bool RemoveGroupByID(int ID){ + var groupDAO = _remoteDatabaseContext.Groups.FirstOrDefault(x => x.ID == ID); + _remoteDatabaseContext.Groups.Remove(groupDAO); + _remoteDatabaseContext.SaveChanges(); + return true; + } + } +} \ No newline at end of file diff --git a/data/Repository/IAdminRepository.cs b/data/Repository/IAdminRepository.cs new file mode 100644 index 0000000..3455b25 --- /dev/null +++ b/data/Repository/IAdminRepository.cs @@ -0,0 +1,9 @@ +using Demo.Domain.Models; + +namespace Demo.Data.Repository +{ + public interface IAdminRepository + { + List GetAllGroup(); + } +} \ No newline at end of file diff --git a/data/Repository/IGroupRepository.cs b/data/Repository/IGroupRepository.cs new file mode 100644 index 0000000..b48d1da --- /dev/null +++ b/data/Repository/IGroupRepository.cs @@ -0,0 +1,13 @@ +using Demo.Domain.Models; + +namespace Demo.Data.Repository +{ + public interface IGroupRepository + { + List GetAllGroup(); + GroupLocalEntity? GetGroupById(int ID); + bool RemoveGroupByID(int groupId); + GroupLocalEntity? UpdateGroup(GroupLocalEntity updatedGroup); + GroupLocalEntity? CreateGroup(string Name); + } +} \ No newline at end of file diff --git a/data/Repository/IPresenceRepository.cs b/data/Repository/IPresenceRepository.cs new file mode 100644 index 0000000..bce6080 --- /dev/null +++ b/data/Repository/IPresenceRepository.cs @@ -0,0 +1,11 @@ +using Demo.Domain.Models; + +namespace Demo.Data.Repository +{ + public interface IPresenceRepository + { + List GetAllPresences(); + void IsAttedance(int firstLesson, int lastLesson, DateOnly date, Guid UserGuid); + List GeneratePresence(List presenceLocalEntities); + } +} \ No newline at end of file diff --git a/data/Repository/IUserRepository.cs b/data/Repository/IUserRepository.cs new file mode 100644 index 0000000..16629e7 --- /dev/null +++ b/data/Repository/IUserRepository.cs @@ -0,0 +1,13 @@ +using Demo.Domain.Models; + +namespace Demo.Data.Repository +{ + public interface IUserRepository + { + List GetAllUser(); + UserLocalEntity? GetUserByGuid(Guid guid); + List GetUsersByGroupID(int groupID); + bool RemoveUserByGuid(Guid guid); + UserLocalEntity? UpdateUser(UserLocalEntity updatedUser); + } +} \ No newline at end of file diff --git a/data/Repository/PresenceRepositoryImpl.cs b/data/Repository/PresenceRepositoryImpl.cs new file mode 100644 index 0000000..1b00299 --- /dev/null +++ b/data/Repository/PresenceRepositoryImpl.cs @@ -0,0 +1,55 @@ +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.Domain.Models; + +namespace Demo.Data.Repository +{ + public class SQLPresenceRepositoryImpl : IPresenceRepository + { + private readonly RemoteDatabaseContext _remoteDatabaseContext; + + public SQLPresenceRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext){ + _remoteDatabaseContext = remoteDatabaseContext; + GetAllPresence = _remoteDatabaseContext.PresenceDaos.Select(x => new PresenceLocalEntity{UserGuid = x.UserGuid, Date = x.Date, LessonNumber = x.LessonNumber, IsAttedance = x.IsAttedance}).ToList(); + } + public List GetAllPresence = new List{}; + + public List GetAllPresences(){ + return _remoteDatabaseContext.PresenceDaos.Select(x => new PresenceLocalEntity{UserGuid = x.UserGuid, Date = x.Date, LessonNumber = x.LessonNumber, IsAttedance = x.IsAttedance}).ToList(); + } + + public List GeneratePresence(List presenceLocalEntities) + { + var presences = presenceLocalEntities.Select(x => new PresenceDAO + { + UserGuid = x.UserGuid, + IsAttedance = x.IsAttedance, + LessonNumber = x.LessonNumber, + Date = x.Date, + userDAO = _remoteDatabaseContext.Users.FirstOrDefault(u => u.Guid == x.UserGuid) + }).ToList(); + + _remoteDatabaseContext.PresenceDaos.AddRange(presences); + _remoteDatabaseContext.SaveChanges(); + + return presenceLocalEntities; + } + + public void IsAttedance(int firstLesson, int lastLesson, DateOnly date, Guid UserGuid){ + var presencesToUpdate = _remoteDatabaseContext.PresenceDaos + .Where(x => x.LessonNumber >= firstLesson + && x.LessonNumber <= lastLesson + && x.Date == date + && x.UserGuid == UserGuid) + .ToList(); + + foreach(var presence in presencesToUpdate){ + presence.IsAttedance = false; + } + + _remoteDatabaseContext.SaveChanges(); + } + + } +} \ No newline at end of file diff --git a/data/Repository/UserRepositoryImpl.cs b/data/Repository/UserRepositoryImpl.cs new file mode 100644 index 0000000..af195e3 --- /dev/null +++ b/data/Repository/UserRepositoryImpl.cs @@ -0,0 +1,60 @@ +using Demo.Domain.Models; +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase; + +namespace Demo.Data.Repository +{ + public class SQLUserRepositoryImpl : IUserRepository + { + private readonly RemoteDatabaseContext _remoteDatabaseContext; + + public SQLUserRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext){ + _remoteDatabaseContext = remoteDatabaseContext; + GetAllUsers = _remoteDatabaseContext.Users.Select(x => new UserLocalEntity{FIO = x.FIO, Guid = x.Guid, GroupID = x.GroupID}).ToList(); + } + + public List GetAllUsers + { get; set; } + + public List GetAllUser(){ + return _remoteDatabaseContext.Users.Select(x => new UserLocalEntity{FIO = x.FIO, Guid = x.Guid, GroupID = x.GroupID}).ToList(); + } + + public UserLocalEntity? GetUserByGuid(Guid guid){ + var userDAO = _remoteDatabaseContext.Users.FirstOrDefault(x => x.Guid == guid); + return new UserLocalEntity{FIO = userDAO.FIO, GroupID = userDAO.GroupID, Guid = guid}; + } + + public List GetUsersByGroupID(int groupID) + { + return _remoteDatabaseContext.Users + .Where(x => x.GroupID == groupID) + .Select(x => new UserLocalEntity + { + FIO = x.FIO, + Guid = x.Guid, + GroupID = x.GroupID + }) + .ToList(); + } + + public bool RemoveUserByGuid(Guid guid){ + var userDAO = _remoteDatabaseContext.Users.FirstOrDefault(x => x.Guid == guid); + _remoteDatabaseContext.Users.Remove(userDAO); + _remoteDatabaseContext.SaveChanges(); + return true; + } + + public UserLocalEntity? UpdateUser(UserLocalEntity updatedUser){ + var user = _remoteDatabaseContext.Users.FirstOrDefault(x => x.Guid == updatedUser.Guid); + if (user == null){ + return null; + } + + user.FIO = updatedUser.FIO; + user.GroupID = updatedUser.GroupID; + _remoteDatabaseContext.SaveChanges(); + return new UserLocalEntity{FIO = user.FIO, Guid = user.Guid, GroupID = user.GroupID}; + } + } +} \ No newline at end of file diff --git a/data/data.csproj b/data/data.csproj new file mode 100644 index 0000000..bf69493 --- /dev/null +++ b/data/data.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + diff --git a/domain/Models/Group.cs b/domain/Models/Group.cs new file mode 100644 index 0000000..ef15cfd --- /dev/null +++ b/domain/Models/Group.cs @@ -0,0 +1,13 @@ +namespace Demo.Domain.Models +{ + public class Group + { + public required int ID{get; set; } + public required string Name{get; set; } + + public static Group Parse(string input){ + string[] words = input.Split(" "); + return new Group{ID = Convert.ToInt32(words[0]), Name = words[1]}; + } + } +} \ No newline at end of file diff --git a/domain/Models/Presence.cs b/domain/Models/Presence.cs new file mode 100644 index 0000000..8fddb96 --- /dev/null +++ b/domain/Models/Presence.cs @@ -0,0 +1,11 @@ +namespace Demo.Domain.Models +{ + public class Presence + { + public required User User{get; set; } + public bool IsAttedance { get; set; } = true; + public required DateOnly Date { get; set; } + + public required int LessonNumber { get; set; } + } +} \ No newline at end of file diff --git a/domain/Models/User.cs b/domain/Models/User.cs new file mode 100644 index 0000000..d1f6626 --- /dev/null +++ b/domain/Models/User.cs @@ -0,0 +1,38 @@ +namespace Demo.Domain.Models +{ + public class User + { + public required string FIO{get; set; } + public Guid Guid{get; set; } + public required Group Group{get; set; } + + public static User Parse(string input) + { + string[] words = input.Split(" "); + + if (words.Length < 4) + { + throw new FormatException("Input string does not have the expected number of elements."); + } + + try + { + return new User + { + FIO = words[0], + Guid = Guid.Parse(words[1]), + Group = new Group + { + ID = Convert.ToInt32(words[2]), + Name = words[3] + } + }; + } + catch (FormatException ex) + { + Console.WriteLine("Error parsing input: " + ex.Message); + throw; + } + } + } +} \ No newline at end of file diff --git a/domain/UseCase/AdminUseCase.cs b/domain/UseCase/AdminUseCase.cs new file mode 100644 index 0000000..c24f2e7 --- /dev/null +++ b/domain/UseCase/AdminUseCase.cs @@ -0,0 +1,123 @@ +using ClosedXML.Excel; +using Demo.Data.Repository; +using Demo.Domain.Models; +using DocumentFormat.OpenXml.Office.Word; +using DocumentFormat.OpenXml.Wordprocessing; + +namespace Demo.Domain.UseCase +{ + public class AdminUseCase : IAdminUseCase + { + private readonly IAdminRepository _repositoryAdminImpl; + private readonly IUserRepository _repositoryUserImpl; + private readonly IPresenceRepository _repositoryPresenceImpl; + public AdminUseCase(IAdminRepository repositoryAdminImpl, IUserRepository repositoryUserImpl, IPresenceRepository repositoryPresenceImpl) + { + _repositoryAdminImpl = repositoryAdminImpl; + _repositoryUserImpl = repositoryUserImpl; + _repositoryPresenceImpl = repositoryPresenceImpl; + } + + public bool ExcelExport(int groupID){ + var users = _repositoryUserImpl.GetUsersByGroupID(groupID); + var groupPresences = GetPresenceByGroup(groupID); + var dates = new List(); + foreach(var presence in groupPresences){ + if (!dates.Contains(presence.Date)){ + dates.Add(presence.Date); + } + } + using (var workbook = new XLWorkbook()){ + var worksheet = workbook.Worksheets.Add(groupID); + worksheet.Cell(1, 1).Value = "FIO"; + worksheet.Range(1, 1, 2, 1).Merge(); + + var colIndex = 2; + foreach (var date in dates) { + worksheet.Cell(1, colIndex).Value = date.ToString("dd.MM.yy"); + worksheet.Range(1, colIndex, 1, colIndex + 8).Merge(); + colIndex += 9; + } + + var k = 2; + foreach(var date in dates){ + for (int lesson = 1; lesson <= 9; lesson++){ + worksheet.Cell(2, k).Value = lesson; + k++; + } + } + + var lessonColIndex = 2; + var rowIndex = 3; + foreach(var user in users){ + worksheet.Cell(rowIndex, 1).Value = user.FIO; + + var userPresences = GetPresenceByUser(user.Guid); + + foreach(var date in dates){ + for (int lesson = 1; lesson <= 9; lesson++){ + var presence = userPresences.FirstOrDefault(p => p.Date == date && p.LessonNumber == lesson); + if (presence != null){ + worksheet.Cell(rowIndex, lessonColIndex).Value = presence.IsAttedance ? "Истина" : "Ложь"; + } else{ + worksheet.Cell(rowIndex, lessonColIndex).Value = "-"; + } + lessonColIndex++; + } + } + + rowIndex++; + lessonColIndex = 2; + } + + workbook.SaveAs($"gruop_{groupID}.xlsx"); + } + return true; + } + + public List GetPresenceByUser(Guid userGuid){ + var user = _repositoryUserImpl.GetUserByGuid(userGuid); + + var presenceByUser = _repositoryPresenceImpl.GetAllPresences() + .Where(user => userGuid == user.UserGuid) + .Select(presence => new Presence{ + User = new User{ + Guid = user.Guid, + Group = new Group{ + ID = user.GroupID, + Name = _repositoryAdminImpl.GetAllGroup().First(group => group.ID == user.GroupID).Name + }, + FIO = user.FIO + }, + LessonNumber = presence.LessonNumber, + Date = presence.Date, + IsAttedance = presence.IsAttedance + }).ToList(); + + return presenceByUser; + } + + public List GetPresenceByGroup(int groupID){ + var usersByGroup = _repositoryUserImpl.GetAllUser() + .Where(user => user.GroupID == groupID).ToList(); + + var presenceByGroup = _repositoryPresenceImpl.GetAllPresences() + .Where(x => usersByGroup.Any(user => user.Guid == x.UserGuid)) + .Select(presence => new Presence{ + User = new User{ + Guid = presence.UserGuid, + Group = new Group{ + ID = groupID, + Name = _repositoryAdminImpl.GetAllGroup().First(group => group.ID == groupID).Name + }, + FIO = usersByGroup.First(user => user.Guid == presence.UserGuid).FIO, + }, + LessonNumber = presence.LessonNumber, + Date = presence.Date, + IsAttedance = presence.IsAttedance + }).ToList(); + + return presenceByGroup; + } + } +} \ No newline at end of file diff --git a/domain/UseCase/GroupUseCase.cs b/domain/UseCase/GroupUseCase.cs new file mode 100644 index 0000000..8c2efc5 --- /dev/null +++ b/domain/UseCase/GroupUseCase.cs @@ -0,0 +1,54 @@ +using Demo.Domain.Models; +using Demo.Data.Repository; + +namespace Demo.Domain.UseCase +{ + public class GroupUseCase : IGroupUseCase + { + private readonly IUserRepository _repositoryUserImpl; + private readonly IGroupRepository _repositoryGroupImpl; + public GroupUseCase(IGroupRepository repositoryGroupImpl, IUserRepository repositoryUserImpl) + { + _repositoryGroupImpl = repositoryGroupImpl; + _repositoryUserImpl = repositoryUserImpl; + } + + public List GetAllGroups() => _repositoryGroupImpl.GetAllGroup() + .Select(it => new Group{ID = it.ID, Name = it.Name}).ToList(); + + public Group GetGroupById(int groupID) + { + GroupLocalEntity? groupLocalEntity = _repositoryGroupImpl.GetGroupById(groupID); + if (groupLocalEntity == null) throw new Exception("bello"); + return new Group{ID = groupID, Name = groupLocalEntity.Name}; + } + + public bool CreateGroup(string Name){ + _repositoryGroupImpl.CreateGroup(Name); + return true; + } + + public Group UpdateGroup(Group group) + { + GroupLocalEntity groupLocalEntity = new GroupLocalEntity + { + ID = group.ID, + Name = group.Name + }; + GroupLocalEntity? result = _repositoryGroupImpl.UpdateGroup(groupLocalEntity); + if (result == null) + { + throw new Exception("Не удалось обновить пользователя: пользователь не найден."); + } + return new Group + { + ID = result.ID, + Name = result.Name + }; + } + + public bool RemoveGroupByID(int userID) { + return _repositoryGroupImpl.RemoveGroupByID(userID); + } + } +} \ No newline at end of file diff --git a/domain/UseCase/IAdminUseCase.cs b/domain/UseCase/IAdminUseCase.cs new file mode 100644 index 0000000..fadf483 --- /dev/null +++ b/domain/UseCase/IAdminUseCase.cs @@ -0,0 +1,10 @@ +using Demo.Domain.Models; + +namespace Demo.Domain.UseCase +{ + public interface IAdminUseCase{ + bool ExcelExport(int groupID); + List GetPresenceByUser(Guid userGuid); + List GetPresenceByGroup(int groupID); + } +} \ No newline at end of file diff --git a/domain/UseCase/IGroupUseCase.cs b/domain/UseCase/IGroupUseCase.cs new file mode 100644 index 0000000..c6d2d49 --- /dev/null +++ b/domain/UseCase/IGroupUseCase.cs @@ -0,0 +1,13 @@ +using Demo.Domain.Models; + +namespace Demo.Domain.UseCase +{ + public interface IGroupUseCase + { + List GetAllGroups(); + bool RemoveGroupByID(int groupID); + Group UpdateGroup(Group group); + Group GetGroupById(int groupID); + bool CreateGroup(string Name); + } +} \ No newline at end of file diff --git a/domain/UseCase/IPresenceUseCase.cs b/domain/UseCase/IPresenceUseCase.cs new file mode 100644 index 0000000..8a1d588 --- /dev/null +++ b/domain/UseCase/IPresenceUseCase.cs @@ -0,0 +1,16 @@ +using Demo.Domain.Models; + +namespace Demo.Domain.UseCase +{ + public interface IPresenceUseCase + { + List GetPresenceByGroup(int groupID); + List GetPresenceByGroupByTime(int groupID, DateOnly date); + List GetPresenceByUser(Guid userGuid); + List GetFalsePresenceByUser(Guid userGuid); + List GetFalsePresenceByGroup(int groupID); + bool IsAttedance(int firstLesson, int lastLesson, DateOnly date, Guid UserGuid); + bool GeneratePresence(int firstLesson, int lastLesson, int groupID, DateOnly date); + bool GeneratePresenceWeek(int firstLesson, int lastLesson, int groupID, DateOnly date); + } +} \ No newline at end of file diff --git a/domain/UseCase/IUserUseCase.cs b/domain/UseCase/IUserUseCase.cs new file mode 100644 index 0000000..96a00b1 --- /dev/null +++ b/domain/UseCase/IUserUseCase.cs @@ -0,0 +1,13 @@ +using Demo.Domain.Models; + +namespace Demo.Domain.UseCase +{ + public interface IUserUseCase + { + List GetAllUsers(); + bool RemoveUserByGuid(Guid userGuid); + User UpdateUser(User user); + User GetUserByGuid(Guid userGuid); + List GetUsersByGroupID(int groupID); + } +} \ No newline at end of file diff --git a/domain/UseCase/PresenceUseCase.cs b/domain/UseCase/PresenceUseCase.cs new file mode 100644 index 0000000..7170fd6 --- /dev/null +++ b/domain/UseCase/PresenceUseCase.cs @@ -0,0 +1,188 @@ +using System.Security.Cryptography.X509Certificates; +using Demo.Data.Repository; +using Demo.Domain.Models; + +namespace Demo.Domain.UseCase +{ + public class PresenceUseCase : IPresenceUseCase + { + private readonly IUserRepository _repositoryUserImpl; + private readonly IPresenceRepository _repositoryPresenceImpl; + private readonly IGroupRepository _repositoryGroupImpl; + + public PresenceUseCase(IPresenceRepository repositoryPresenceImpl, IUserRepository repositoryUserImpl, IGroupRepository repositoryGroupImpl) + { + _repositoryPresenceImpl = repositoryPresenceImpl; + _repositoryUserImpl = repositoryUserImpl; + _repositoryGroupImpl = repositoryGroupImpl; + } + + public List GetPresenceByGroup(int groupID){ + var usersByGroup = _repositoryUserImpl.GetAllUser() + .Where(user => user.GroupID == groupID).ToList(); + + var presenceByGroup = _repositoryPresenceImpl.GetAllPresences() + .Where(x => usersByGroup.Any(user => user.Guid == x.UserGuid)) + .Select(presence => new Presence{ + User = new User{ + Guid = presence.UserGuid, + Group = new Group{ + ID = groupID, + Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name + }, + FIO = usersByGroup.First(user => user.Guid == presence.UserGuid).FIO, + }, + LessonNumber = presence.LessonNumber, + Date = presence.Date, + IsAttedance = presence.IsAttedance + }).ToList(); + + return presenceByGroup; + } + + public List GetFalsePresenceByGroup(int groupID){ + var usersByGroup = _repositoryUserImpl.GetAllUser() + .Where(user => user.GroupID == groupID).ToList(); + + var presenceByGroup = _repositoryPresenceImpl.GetAllPresences() + .Where(x => usersByGroup.Any(user => user.Guid == x.UserGuid) && x.IsAttedance == false) + .Select(presence => new Presence{ + User = new User{ + Guid = presence.UserGuid, + Group = new Group{ + ID = groupID, + Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name + }, + FIO = usersByGroup.First(user => user.Guid == presence.UserGuid).FIO, + }, + LessonNumber = presence.LessonNumber, + Date = presence.Date, + IsAttedance = presence.IsAttedance + }).ToList(); + + return presenceByGroup; + } + + public List GetPresenceByUser(Guid userGuid){ + var user = _repositoryUserImpl.GetUserByGuid(userGuid); + + var presenceByUser = _repositoryPresenceImpl.GetAllPresences() + .Where(user => userGuid == user.UserGuid) + .Select(presence => new Presence{ + User = new User{ + Guid = user.Guid, + Group = new Group{ + ID = user.GroupID, + Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == user.GroupID).Name + }, + FIO = user.FIO + }, + LessonNumber = presence.LessonNumber, + Date = presence.Date, + IsAttedance = presence.IsAttedance + }).ToList(); + + return presenceByUser; + } + + public List GetFalsePresenceByUser(Guid userGuid){ + var user = _repositoryUserImpl.GetUserByGuid(userGuid); + + var presenceByUser = _repositoryPresenceImpl.GetAllPresences() + .Where(user => userGuid == user.UserGuid && user.IsAttedance == false) + .Select(presence => new Presence{ + User = new User{ + Guid = user.Guid, + Group = new Group{ + ID = user.GroupID, + Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == user.GroupID).Name + }, + FIO = user.FIO + }, + LessonNumber = presence.LessonNumber, + Date = presence.Date, + IsAttedance = presence.IsAttedance + }).ToList(); + + return presenceByUser; + } + + public List GetPresenceByGroupByTime(int groupID, DateOnly date){ + var usersByGroup = _repositoryUserImpl.GetAllUser() + .Where(user => user.GroupID == groupID).ToList(); + + var presenceByGroup = _repositoryPresenceImpl.GetAllPresences() + .Where(x => usersByGroup.Any(user => user.Guid == x.UserGuid && x.Date == date)) + .Select(presence => new Presence{ + User = new User{ + Guid = presence.UserGuid, + Group = new Group{ + ID = groupID, + Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name + }, + FIO = usersByGroup.First(user => user.Guid == presence.UserGuid).FIO, + }, + LessonNumber = presence.LessonNumber, + Date = presence.Date, + IsAttedance = presence.IsAttedance + }).ToList(); + + return presenceByGroup; + } + + public bool IsAttedance(int firstLesson, int lastLesson, DateOnly date, Guid UserGuid){ + _repositoryPresenceImpl.IsAttedance(firstLesson, lastLesson, date, UserGuid); + return true; + } + + public bool GeneratePresence(int firstLesson, int lastLesson, int groupID, DateOnly date) + { + var usersByGroup = _repositoryUserImpl.GetAllUser().Where(x => x.GroupID == groupID).ToList(); + var groupName = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name; + + List presenceList = new List(); + + for (int i = firstLesson; i <= lastLesson; i++) + { + foreach (UserLocalEntity user in usersByGroup) + { + presenceList.Add(new Presence + { + User = new User + { + Group = new Group + { + ID = groupID, + Name = groupName + }, + FIO = user.FIO, + Guid = user.Guid + }, + IsAttedance = true, + Date = date, + LessonNumber = i + }); + } + } + + var presenceLocalEntity = presenceList.Select(x => new PresenceLocalEntity + { + UserGuid = x.User.Guid, + IsAttedance = x.IsAttedance, + LessonNumber = x.LessonNumber, + Date = x.Date + }).ToList(); + + _repositoryPresenceImpl.GeneratePresence(presenceLocalEntity); + + return true; + } + + public bool GeneratePresenceWeek(int firstLesson, int lastLesson, int groupID, DateOnly date){ + for (int i = 0; i < 8; i++){ + GeneratePresence(firstLesson, lastLesson, groupID, date.AddDays(i)); + } + return true; + } + } +} \ No newline at end of file diff --git a/domain/UseCase/UserUseCase.cs b/domain/UseCase/UserUseCase.cs new file mode 100644 index 0000000..c42523e --- /dev/null +++ b/domain/UseCase/UserUseCase.cs @@ -0,0 +1,94 @@ +using Demo.Domain.Models; +using Demo.Data.Repository; + +namespace Demo.Domain.UseCase +{ + public class UserUseCase : IUserUseCase + { + private readonly IUserRepository _repositoryUserImpl; + private readonly IGroupRepository _repositoryGroupImpl; + + public UserUseCase(IGroupRepository repositoryGroupImpl, IUserRepository repositoryUserImpl) + { + _repositoryGroupImpl = repositoryGroupImpl; + _repositoryUserImpl = repositoryUserImpl; + } + + public List GetAllGroups() => _repositoryGroupImpl.GetAllGroup() + .Select(it => new Group{ID = it.ID, Name = it.Name}).ToList(); + + public List GetAllUsers() => _repositoryUserImpl.GetAllUser() + .Join(_repositoryGroupImpl.GetAllGroup(), + user => user.GroupID, + group => group.ID, + (user, group) => new User{ + FIO = user.FIO, + Guid = user.Guid, + Group = new Group{ + ID = group.ID, + Name = group.Name} + } + ).ToList(); + + public User GetUserByGuid(Guid userGuid){ + UserLocalEntity? userLocalEntity = _repositoryUserImpl.GetUserByGuid(userGuid); + if (userLocalEntity == null) throw new Exception("bello"); + Group? group = GetAllGroups().FirstOrDefault(it => userLocalEntity.GroupID == it.ID); + if (group == null) throw new Exception("bello"); + return new User{ + FIO = userLocalEntity.FIO, + Guid = userLocalEntity.Guid, + Group = new Group{ + ID = group.ID, + Name = group.Name} + }; + } + + public List GetUsersByGroupID(int groupID){ + List localUsers = _repositoryUserImpl.GetUsersByGroupID(groupID); + if (localUsers == null) throw new Exception("bello"); + Group? group = GetAllGroups().FirstOrDefault(it => groupID == it.ID); + if (group == null) throw new Exception("bello"); + List users = localUsers.Select(userLocal => new User{ + FIO = userLocal.FIO, + Guid = userLocal.Guid, + Group = new Group{ + Name = group.Name, + ID = group.ID + } + }).ToList(); + + return users; + } + + public bool RemoveUserByGuid(Guid userGuid) { + return _repositoryUserImpl.RemoveUserByGuid(userGuid); + } + + public User UpdateUser(User user) + { + UserLocalEntity userLocalEntity = new UserLocalEntity + { + FIO = user.FIO, + Guid = user.Guid, + GroupID = user.Group.ID + }; + UserLocalEntity? result = _repositoryUserImpl.UpdateUser(userLocalEntity); + if (result == null) + { + throw new Exception("Не удалось обновить пользователя: пользователь не найден."); + } + Group? group = GetAllGroups().FirstOrDefault(it => result.GroupID == it.ID); + if (group == null) + { + throw new Exception("Не удалось обновить пользователя: группа не найдена."); + } + return new User + { + FIO = result.FIO, + Guid = result.Guid, + Group = group + }; + } + } +} \ No newline at end of file diff --git a/domain/domain.csproj b/domain/domain.csproj new file mode 100644 index 0000000..985e4a7 --- /dev/null +++ b/domain/domain.csproj @@ -0,0 +1,17 @@ + + + + + + + + + + + + net8.0 + enable + enable + + + diff --git a/presence.sln b/presence.sln new file mode 100644 index 0000000..314432d --- /dev/null +++ b/presence.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "domain", "domain\domain.csproj", "{90F2D7E7-4D8A-40E6-87A0-2417E32C98C7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ui", "ui\ui.csproj", "{4E82627C-4A8E-4372-99D3-2FB5414F556B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "console_ui", "console_ui\console_ui.csproj", "{314AB1A4-CD9E-47D3-BDDB-5829803ADFB7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "data", "data\data.csproj", "{7FD5C1C4-6DF8-42BD-AD74-6D33CDE48894}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {90F2D7E7-4D8A-40E6-87A0-2417E32C98C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90F2D7E7-4D8A-40E6-87A0-2417E32C98C7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90F2D7E7-4D8A-40E6-87A0-2417E32C98C7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90F2D7E7-4D8A-40E6-87A0-2417E32C98C7}.Release|Any CPU.Build.0 = Release|Any CPU + {4E82627C-4A8E-4372-99D3-2FB5414F556B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E82627C-4A8E-4372-99D3-2FB5414F556B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E82627C-4A8E-4372-99D3-2FB5414F556B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E82627C-4A8E-4372-99D3-2FB5414F556B}.Release|Any CPU.Build.0 = Release|Any CPU + {314AB1A4-CD9E-47D3-BDDB-5829803ADFB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {314AB1A4-CD9E-47D3-BDDB-5829803ADFB7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {314AB1A4-CD9E-47D3-BDDB-5829803ADFB7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {314AB1A4-CD9E-47D3-BDDB-5829803ADFB7}.Release|Any CPU.Build.0 = Release|Any CPU + {7FD5C1C4-6DF8-42BD-AD74-6D33CDE48894}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FD5C1C4-6DF8-42BD-AD74-6D33CDE48894}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FD5C1C4-6DF8-42BD-AD74-6D33CDE48894}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FD5C1C4-6DF8-42BD-AD74-6D33CDE48894}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/ui/AdminConsole.cs b/ui/AdminConsole.cs new file mode 100644 index 0000000..fba8608 --- /dev/null +++ b/ui/AdminConsole.cs @@ -0,0 +1,18 @@ +using Demo.Domain.UseCase; + +namespace Demo.UI +{ + public class AdminConsoleUI + { + IAdminUseCase _adminUseCase; + public AdminConsoleUI(IAdminUseCase adminUseCase) { + _adminUseCase = adminUseCase; + } + + public void ExcelExport(int groupID) { + + string output = _adminUseCase.ExcelExport(groupID) ? "Таблица создана" : "Таблица не создана"; + Console.WriteLine(output); + } + } +} \ No newline at end of file diff --git a/ui/MainMenu.cs b/ui/MainMenu.cs new file mode 100644 index 0000000..cb7a39d --- /dev/null +++ b/ui/MainMenu.cs @@ -0,0 +1,105 @@ +using Demo.Domain.Models; +using Demo.Domain.UseCase; + +namespace Demo.UI +{ + public class MainMenuUI + { + + UserConsoleUI _userConsoleUI; + GroupConsoleUI _groupConsoleUI; + PresenceConsoleUI _presenceConsoleUI; + AdminConsoleUI _adminConsoleUI; + + public MainMenuUI(IUserUseCase userUseCase, IGroupUseCase groupUseCase, IPresenceUseCase presenceUseCase, IAdminUseCase adminUseCase) { + _userConsoleUI = new UserConsoleUI(userUseCase); + _groupConsoleUI = new GroupConsoleUI(groupUseCase, userUseCase, presenceUseCase); + _presenceConsoleUI = new PresenceConsoleUI(presenceUseCase); + _adminConsoleUI = new AdminConsoleUI(adminUseCase); + SelectRole(); + + } + + private void SelectRole() + { + Console.WriteLine("Выберите роль:\n1: user\n2: admin"); + string role = Console.ReadLine(); + + if (role == "1") + { + DisplayMenu(); + } + else if (role == "2") + { + DisplayAdminMenu(); + } + else + { + Console.WriteLine("Неверная роль. Попробуйте еще раз."); + SelectRole(); + } + } + + private void DisplayAdminMenu() + { + Console.WriteLine("0) Создать таблицу посещаемости для группы"); + while(true) + { + switch (Console.ReadLine()) + { + case "0": Console.WriteLine("Введите номер группы"); + _adminConsoleUI.ExcelExport(Convert.ToInt32(Console.ReadLine())); break; + + default: DisplayAdminMenu(); + break; + } + } + } + + private void DisplayMenu() { + Console.WriteLine("0) Вывести всё о группе\n1) Вывести все группы\n2) Cоздать новую группу\n3) Обновить имя группы\n4) Вывести группу по ID\n5) Удалить группу по ID\n6) Вывести всех юзеров\n7) Вывести юзера по GUID\n8) Обновить юзера по GUID\n9) Удалить юзера по GUID\n10) Тебе этого не надо\n11) Вывести посещаемость по группе\n12) Вывести посещаемость по группе и времени\n13) Генерация посещаемости\n14) Генерация посещаемости на неделю\n15) Смена посещаемости юзера"); + while (true) + { + switch (Console.ReadLine()) + { + + case "0": Console.WriteLine("Введите номер группы"); + _groupConsoleUI.DisplayAllBoutGroup(Convert.ToInt32(Console.ReadLine())); break; + case "1": _groupConsoleUI.DisplayAllGroups(); break; + case "2": Console.WriteLine("Введите имя группы"); + _groupConsoleUI.CreateNewGroup(Console.ReadLine()); break; + case "3": Console.WriteLine("Введите номер и имя группы"); + _groupConsoleUI.UpdateGroupName(Group.Parse(Console.ReadLine())); break; + case "4": Console.WriteLine("Введите номер группы"); + _groupConsoleUI.DisplayGroupByID(Convert.ToInt32(Console.ReadLine())); break; + case "5": Console.WriteLine("Введите номер группы"); + _groupConsoleUI.RemoveGroupByID(Convert.ToInt32(Console.ReadLine())); break; + + case "6": _userConsoleUI.DisplayAllUsers(); break; + case "7": Console.WriteLine("Введите Guid юзера"); + _userConsoleUI.DisplayUserByGuid(Guid.Parse(Console.ReadLine())); break; + case "8": Console.WriteLine("Введите Guid юзера"); + _userConsoleUI.UpdateUserByGuid(User.Parse(Console.ReadLine())); break; + case "9": Console.WriteLine("Введите Guid юзера"); + _userConsoleUI.RemoveUserByGuid(Guid.Parse(Console.ReadLine())); break; + + case "10": Console.WriteLine("писяпопакака"); break; + + case "11": Console.WriteLine("Введите номер группы"); + _presenceConsoleUI.DisplayPresenceByGroup(Convert.ToInt32(Console.ReadLine())); break; + case "12": Console.WriteLine("Введите номер группы и дату"); + _presenceConsoleUI.DisplayPresenceByGroupByTime(Convert.ToInt32(Console.ReadLine()), DateOnly.FromDateTime(Convert.ToDateTime(Console.ReadLine()))); break; + case "13": Console.WriteLine("Введите первый и последний урок, номер группы и дату"); + _presenceConsoleUI.GeneratePresence(Convert.ToInt32(Console.ReadLine()), Convert.ToInt32(Console.ReadLine()), Convert.ToInt32(Console.ReadLine()), DateOnly.FromDateTime(Convert.ToDateTime(Console.ReadLine()))); break; + case "14": Console.WriteLine("Введите первый и последний урок, номер группы и дату"); + _presenceConsoleUI.GeneratePresenceWeek(Convert.ToInt32(Console.ReadLine()), Convert.ToInt32(Console.ReadLine()), Convert.ToInt32(Console.ReadLine()), DateOnly.FromDateTime(Convert.ToDateTime(Console.ReadLine()))); break; + case "15": Console.WriteLine("Введите первый и последний урок, дату и Guid юзера"); + _presenceConsoleUI.IsAttedance(Convert.ToInt32(Console.ReadLine()), Convert.ToInt32(Console.ReadLine()), DateOnly.FromDateTime(Convert.ToDateTime(Console.ReadLine())), Guid.Parse(Console.ReadLine())); break; + + default: DisplayMenu(); + break; + } + } + } + } +} \ No newline at end of file diff --git a/ui/UserConsole.cs b/ui/UserConsole.cs new file mode 100644 index 0000000..0fac04f --- /dev/null +++ b/ui/UserConsole.cs @@ -0,0 +1,172 @@ +using System.ComponentModel.DataAnnotations; +using System.Text; +using Demo.Domain.Models; +using Demo.Domain.UseCase; + +namespace Demo.UI +{ + public class UserConsoleUI + { + IUserUseCase _userUseCase; + public UserConsoleUI(IUserUseCase userUseCase) { + _userUseCase = userUseCase; + } + + public void DisplayAllUsers() + { + StringBuilder userOutput = new StringBuilder(); + foreach (var user in _userUseCase.GetAllUsers()) + { + userOutput.AppendLine($"{user.Guid}\t{user.FIO}\t{user.Group.Name}"); + } + Console.WriteLine(userOutput); + } + + public void RemoveUserByGuid(Guid guidUser) { + + string output = _userUseCase.RemoveUserByGuid(guidUser) ? "Пользователь удален" : "Пользователь не удален"; + Console.WriteLine(output); + } + + public void UpdateUserByGuid(User user) + { + try + { + User output = _userUseCase.UpdateUser(user); + StringBuilder userOutput = new StringBuilder(); + userOutput.AppendLine($"Обновленный пользователь: {output.Guid}\t{output.FIO}\t{output.Group.Name}"); + Console.WriteLine(userOutput); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка при обновлении пользователя: {ex.Message}"); + } + } + + public void DisplayUserByGuid(Guid guid){ + User output = _userUseCase.GetUserByGuid(guid); + StringBuilder userOutput = new StringBuilder(); + userOutput.AppendLine($"{output.Guid}\t{output.FIO}\t{output.Group.Name}"); + Console.WriteLine(userOutput); + } + } + + public class GroupConsoleUI + { + IGroupUseCase _groupUseCase; + IUserUseCase _userUseCase; + IPresenceUseCase _presenceUseCase; + public GroupConsoleUI(IGroupUseCase groupUseCase, IUserUseCase userUseCase, IPresenceUseCase presenceUseCase){ + _groupUseCase = groupUseCase; + _userUseCase = userUseCase; + _presenceUseCase = presenceUseCase; + } + + public void DisplayAllGroups(){ + StringBuilder userOutput = new StringBuilder(); + foreach (var group in _groupUseCase.GetAllGroups()) + { + userOutput.AppendLine($"{group.ID}\t{group.Name}"); + } + Console.WriteLine(userOutput); + } + + public void DisplayGroupByID(int ID){ + StringBuilder userOutput = new StringBuilder(); + var group = _groupUseCase.GetGroupById(ID); + { + userOutput.AppendLine($"{group.ID}\t{group.Name}"); + } + Console.WriteLine(userOutput); + } + + public void CreateNewGroup(string Name){ + string output = _groupUseCase.CreateGroup(Name) ? "Группа создана" : "Группа не создана"; + Console.WriteLine(output); + } + + public void UpdateGroupName(Group group) + { + try + { + Group output = _groupUseCase.UpdateGroup(group); + StringBuilder groupOutput = new StringBuilder(); + groupOutput.AppendLine($"Обновленная группа: {output.ID}\t{output.Name}"); + Console.WriteLine(groupOutput); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка при обновлении группы: {ex.Message}"); + } + } + + public void RemoveGroupByID(int ID){ + string output = _groupUseCase.RemoveGroupByID(ID) ? "Группа удалена" : "Группа не удалена"; + Console.WriteLine(output); + } + + public void DisplayAllBoutGroup(int groupID){ + var users = _userUseCase.GetUsersByGroupID(groupID); + Console.WriteLine($"Группа: {groupID}\tКоличество учеников: {users.Count}"); + + var presencesByGroup = _presenceUseCase.GetPresenceByGroup(groupID); + var presenceFalseByGroup = _presenceUseCase.GetFalsePresenceByGroup(groupID); + var precentePresenceGroup = 100 - Math.Round((double)presenceFalseByGroup.Count / presencesByGroup.Count * 100); + Console.WriteLine($"Количество занятий: {presencesByGroup.Count}\tОбщий процент посещаемости: {precentePresenceGroup}"); + + foreach(var user in _userUseCase.GetUsersByGroupID(groupID)){ + var countPresences = _presenceUseCase.GetPresenceByUser(user.Guid); + var countFalsePresences = _presenceUseCase.GetFalsePresenceByUser(user.Guid); + var precentePresenceUser = 100 - Math.Round((double)countFalsePresences.Count / countPresences.Count * 100); + if (precentePresenceUser < 40) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"FIO: {user.FIO}\tКоличество посещённых занятий: {countPresences.Count - countFalsePresences.Count}\tКоличество пропущенных занятий: {countFalsePresences.Count}\tПроцент посещаемости: {precentePresenceUser}"); + Console.ResetColor(); + } + else + { + Console.WriteLine($"FIO: {user.FIO}\tКоличество посещённых занятий: {countPresences.Count - countFalsePresences.Count}\tКоличество пропущенных занятий: {countFalsePresences.Count}\tПроцент посещаемости: {precentePresenceUser}"); + } + } + } + } + + public class PresenceConsoleUI{ + IPresenceUseCase _presenceUseCase; + public PresenceConsoleUI (IPresenceUseCase presenceUseCase){ + _presenceUseCase = presenceUseCase; + } + + public void DisplayPresenceByGroup(int groupID){ + StringBuilder stringBuilder = new StringBuilder(); + foreach(Presence presence in _presenceUseCase.GetPresenceByGroup(groupID)){ + stringBuilder.AppendLine($"{presence.User.FIO}, {presence.User.Group.Name}, {presence.IsAttedance}, {presence.Date}, {presence.LessonNumber}"); + } + Console.WriteLine(stringBuilder); + } + + public void DisplayPresenceByGroupByTime(int groupID, DateOnly date){ + StringBuilder stringBuilder = new StringBuilder(); + foreach(Presence presence in _presenceUseCase.GetPresenceByGroupByTime(groupID, date)){ + stringBuilder.AppendLine($"{presence.User.FIO}, {presence.User.Group.Name}, {presence.IsAttedance}, {presence.Date}, {presence.LessonNumber}"); + } + Console.WriteLine(stringBuilder); + } + + public void GeneratePresence(int firstLesson, int lastLesson, int groupID, DateOnly date){ + string output = _presenceUseCase.GeneratePresence(firstLesson, lastLesson, groupID, date) ? "Сгенерированно" : "Не сгенерированно"; + Console.WriteLine(output); + } + + public void GeneratePresenceWeek(int firstLesson, int lastLesson, int groupID, DateOnly date){ + string output = _presenceUseCase.GeneratePresenceWeek(firstLesson, lastLesson, groupID, date) ? "Сгенерированно" : "Не сгенерированно"; + Console.WriteLine(output); + } + + public void IsAttedance(int firstLesson, int lastLesson, DateOnly date, Guid UserGuid){ + string output = _presenceUseCase.IsAttedance(firstLesson, lastLesson, date, UserGuid) ? "Обновлено" : "Не обновлено"; + Console.WriteLine(output); + } + } +} \ No newline at end of file diff --git a/ui/ui.csproj b/ui/ui.csproj new file mode 100644 index 0000000..3760ee8 --- /dev/null +++ b/ui/ui.csproj @@ -0,0 +1,13 @@ + + + + + + + + net8.0 + enable + enable + + +