diff --git a/Demo.sln b/Demo.sln new file mode 100644 index 0000000..ce1f93c --- /dev/null +++ b/Demo.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35312.102 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "Demo\Demo.csproj", "{983820F6-FF31-4B3A-8593-831BC3904E80}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {983820F6-FF31-4B3A-8593-831BC3904E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {983820F6-FF31-4B3A-8593-831BC3904E80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {983820F6-FF31-4B3A-8593-831BC3904E80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {983820F6-FF31-4B3A-8593-831BC3904E80}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4F43A963-447C-4FCB-BB78-8D315EC0F1D6} + EndGlobalSection +EndGlobal diff --git a/Demo/Data/Exceptions/GroupNotFoundException.cs b/Demo/Data/Exceptions/GroupNotFoundException.cs new file mode 100644 index 0000000..de2876b --- /dev/null +++ b/Demo/Data/Exceptions/GroupNotFoundException.cs @@ -0,0 +1,10 @@ +using System; + +namespace Demo.Data.Exceptions +{ + public class GroupNotFoundException : RepositoryException + { + public GroupNotFoundException(int userId) + : base($"Группа с ID {userId} не найдена.") { } + } +} \ No newline at end of file diff --git a/Demo/Data/Exceptions/PresenceNotFoundException.cs b/Demo/Data/Exceptions/PresenceNotFoundException.cs new file mode 100644 index 0000000..39ab821 --- /dev/null +++ b/Demo/Data/Exceptions/PresenceNotFoundException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Demo.Data.Exceptions +{ + public class PresenceNotFoundException : RepositoryException + { + public PresenceNotFoundException(int userId, DateOnly date, int firstLesson, int lastLesson) + : base($"Посещаемость для пользователя ID: {userId} на дату {date.ToShortDateString()}" + + $" с {firstLesson} по {lastLesson} уроки не найдена.") { } + } +} \ No newline at end of file diff --git a/Demo/Data/Exceptions/RepositoryException.cs b/Demo/Data/Exceptions/RepositoryException.cs new file mode 100644 index 0000000..5732bc4 --- /dev/null +++ b/Demo/Data/Exceptions/RepositoryException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Demo.Data.Exceptions +{ + public class RepositoryException : Exception + { + public RepositoryException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/Demo/Data/Exceptions/UserNotFoundException.cs b/Demo/Data/Exceptions/UserNotFoundException.cs new file mode 100644 index 0000000..c05fdea --- /dev/null +++ b/Demo/Data/Exceptions/UserNotFoundException.cs @@ -0,0 +1,10 @@ +using System; + +namespace Demo.Data.Exceptions +{ + public class UserNotFoundException : RepositoryException + { + public UserNotFoundException(int userId) + : base($"Пользователь с ID {userId} не найден.") { } + } +} \ No newline at end of file diff --git a/Demo/Data/LocalData/Entity/Group.cs b/Demo/Data/LocalData/Entity/Group.cs new file mode 100644 index 0000000..506833b --- /dev/null +++ b/Demo/Data/LocalData/Entity/Group.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.domain.Models +{ + public class GroupLocalEntity + { + public int Id { get; set; } + public required string Name { get; set; } + + + + } +} diff --git a/Demo/Data/LocalData/Entity/Presence.cs b/Demo/Data/LocalData/Entity/Presence.cs new file mode 100644 index 0000000..4c3a1c6 --- /dev/null +++ b/Demo/Data/LocalData/Entity/Presence.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.domain.Models +{ + public class PresenceLocalEntity + { + public required int UserId { get; set; } + public required int GroupId { get; set; } + public bool IsAttedance { get; set; } = true; + public required DateTime Date { get; set; } + + public required int LessonNumber { get; set; } + } +} diff --git a/Demo/Data/LocalData/Entity/User.cs b/Demo/Data/LocalData/Entity/User.cs new file mode 100644 index 0000000..ce8aebd --- /dev/null +++ b/Demo/Data/LocalData/Entity/User.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.domain.Models +{ + public class UserLocalEnity : IEquatable + { + + public required string FIO { get; set; } + public int ID { get; set; } + + public required int GroupID { get; set; } + + + + public bool Equals(UserLocalEnity? other) + { + if (other == null) return false; + return this.ID.Equals(other.ID); + } + } +} diff --git a/Demo/Data/LocalData/LocalStaticData.cs b/Demo/Data/LocalData/LocalStaticData.cs new file mode 100644 index 0000000..a1c741d --- /dev/null +++ b/Demo/Data/LocalData/LocalStaticData.cs @@ -0,0 +1,36 @@ +using Demo.domain.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.LocalData +{ + public static 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 UserLocalEnity{ID = 1, FIO = "RandomFio", GroupID = 1 }, + new UserLocalEnity{ID = 2, FIO = "RandomFio1", GroupID = 2 }, + new UserLocalEnity{ID = 3, FIO = "RandomFio2", GroupID = 3 }, + new UserLocalEnity{ID = 4, FIO = "RandomFio3", GroupID = 1 }, + new UserLocalEnity{ID = 5, FIO = "RandomFio4", GroupID = 2 }, + new UserLocalEnity{ID = 6, FIO = "RandomFio5", GroupID = 3 }, + }; + + public static List presences => new List + { + + }; + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/DAO/AttendanceRecord.cs b/Demo/Data/RemoteData/RemoteDataBase/DAO/AttendanceRecord.cs new file mode 100644 index 0000000..76a10ee --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/DAO/AttendanceRecord.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class AttendanceRecord + { + public int UserId { get; set; } + public string UserName { get; set; } + public string FullName { get; set; } + public DateOnly Date { get; set; } + public bool IsAttedance { get; set; } + public int LessonNumber { get; set; } + public string GroupName { get; set; } + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/DAO/Group.cs b/Demo/Data/RemoteData/RemoteDataBase/DAO/Group.cs new file mode 100644 index 0000000..33b8206 --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/DAO/Group.cs @@ -0,0 +1,16 @@ +using Demo.domain.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class GroupDao + { + public int Id { get; set; } + public string Name { get; set; } + public virtual List Users { get; set; } + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/DAO/GroupAttendanceStatistics.cs b/Demo/Data/RemoteData/RemoteDataBase/DAO/GroupAttendanceStatistics.cs new file mode 100644 index 0000000..93e39ab --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/DAO/GroupAttendanceStatistics.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class GroupAttendanceStatistics + { + public int UserCount { get; set; } + public int TotalLessons { get; set; } + public double AttendancePercentage { get; set; } + public List UserAttendanceDetails { get; set; } = new List(); + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/DAO/Presence.cs b/Demo/Data/RemoteData/RemoteDataBase/DAO/Presence.cs new file mode 100644 index 0000000..fbb977f --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/DAO/Presence.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class PresenceDao + { + public int PresenceId { get; set; } + public int UserId { get; set; } + public bool IsAttedance { get; set; } = true; + public DateOnly Date { get; set; } + public int LessonNumber { get; set; } + public int GroupId { get; set; } + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/DAO/User.cs b/Demo/Data/RemoteData/RemoteDataBase/DAO/User.cs new file mode 100644 index 0000000..bdf3616 --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/DAO/User.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class UserDao + { + public required string FIO { get; set; } + public required int UserId { get; set; } + public int GroupId { get; set; } + public GroupDao? Group { get; set; } + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/DAO/UserAttendance.cs b/Demo/Data/RemoteData/RemoteDataBase/DAO/UserAttendance.cs new file mode 100644 index 0000000..b26f69c --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/DAO/UserAttendance.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.RemoteData.RemoteDataBase.DAO +{ + public class UserAttendance + { + public int UserId { get; set; } + public double Attended { get; set; } + public double Missed { get; set; } + public double AttendanceRate { get; set; } + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/RemoteDatabase.cs b/Demo/Data/RemoteData/RemoteDataBase/RemoteDatabase.cs new file mode 100644 index 0000000..546b626 --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/RemoteDatabase.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.RemoteData.RemoteDataBase +{ + internal class RemoteDatabase + { + } +} diff --git a/Demo/Data/RemoteData/RemoteDataBase/RemoteDatabaseContext.cs b/Demo/Data/RemoteData/RemoteDataBase/RemoteDatabaseContext.cs new file mode 100644 index 0000000..31255d9 --- /dev/null +++ b/Demo/Data/RemoteData/RemoteDataBase/RemoteDatabaseContext.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +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=5432;Database=presencedb;Username=postgres;Password=123;Include Error Detail=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().HasKey(group=>group.Id); + modelBuilder.Entity().Property(group => group.Id).ValueGeneratedOnAdd(); + modelBuilder.Entity().HasKey(user=>user.UserId); + modelBuilder.Entity().Property(user=>user.UserId).ValueGeneratedOnAdd(); + modelBuilder.Entity().HasKey(presence =>presence.PresenceId); + modelBuilder.Entity().Property(presence=>presence.PresenceId).ValueGeneratedOnAdd(); + + } + } +} diff --git a/Demo/Data/Repository/GroupRepositoryImpl.cs b/Demo/Data/Repository/GroupRepositoryImpl.cs new file mode 100644 index 0000000..5f5a7fb --- /dev/null +++ b/Demo/Data/Repository/GroupRepositoryImpl.cs @@ -0,0 +1,60 @@ +using Demo.Data.Exceptions; +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.Data.Repository; +using Demo.domain.Models; +using System.Collections.Generic; +using System.Linq; + +public class GroupRepositoryImpl +{ + private List _groups = LocalStaticData.groups; + + + public GroupLocalEntity? GetGroupById(int groupId) + { + foreach (var group in _groups) + { + if (group.Id == groupId) + { + return group; + } + } + return null; + } + + + + + // Метод для получения всех групп + public List GetAllGroups() => _groups; + + // Метод для добавления новой группы + public void AddGroup(GroupLocalEntity group) + { + group.Id = _groups.Any() ? _groups.Max(g => g.Id) + 1 : 1; + _groups.Add(group); + } + + // Метод для обновления существующей группы + public void UpdateGroupById(int groupId, GroupLocalEntity updatedGroup) + { + var existingGroup = GetGroupById(groupId); + if (existingGroup == null) throw new GroupNotFoundException(groupId); + } + + public void RemoveGroupById(int groupId) + { + var existingGroup = GetGroupById(groupId); + if (existingGroup == null) throw new GroupNotFoundException(groupId); + if (_groups.Contains(existingGroup)) + { + _groups.Remove(existingGroup); + } + } + + public bool AddGroup(string Name) + { + throw new NotImplementedException(); + } +} diff --git a/Demo/Data/Repository/IGroupRepository.cs b/Demo/Data/Repository/IGroupRepository.cs new file mode 100644 index 0000000..d5f20ef --- /dev/null +++ b/Demo/Data/Repository/IGroupRepository.cs @@ -0,0 +1,18 @@ +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.Repository +{ + public interface IGroupRepository + { + List GetAllGroups(); + bool UpdateGroupById(int groupID, GroupDao updatedGroup); + GroupDao GetGroupById(int groupID); + bool AddGroup(string Name); + } +} \ No newline at end of file diff --git a/Demo/Data/Repository/IPresenceRepository.cs b/Demo/Data/Repository/IPresenceRepository.cs new file mode 100644 index 0000000..51ff137 --- /dev/null +++ b/Demo/Data/Repository/IPresenceRepository.cs @@ -0,0 +1,27 @@ + +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using Demo.Domain.UseCase; +using Microsoft.EntityFrameworkCore.Metadata; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Data.Repository +{ + public interface IPresenceRepository + { + List GetPresenceByDateAndGroup(DateTime date, int groupId); + void SavePresence(List presences); + List GetPresenceByGroup(int groupId); + DateOnly? GetLastDateByGroupId(int groupId); + List GetPresenceForAbsent(DateTime date, int GroupId); + GroupAttendanceStatistics GetGeneralPresenceForGroup(int groupId); + void UpdateAtt(int userId, int groupId, int firstLesson, int lastLesson, DateOnly date, bool isAttendance); + List GetAttendanceByGroup(int groupId); + } +} + diff --git a/Demo/Data/Repository/IUserRepository.cs b/Demo/Data/Repository/IUserRepository.cs new file mode 100644 index 0000000..7550e04 --- /dev/null +++ b/Demo/Data/Repository/IUserRepository.cs @@ -0,0 +1,14 @@ +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using System.Collections.Generic; + +namespace Demo.Data.Repository +{ + public interface IUserRepository + { + List GetAllUsers(); + bool RemoveUserById(int userId); + UserDao UpdateUser(int userId, string newFIO, int groupId); + List GetUserNames(); + } +} diff --git a/Demo/Data/Repository/PresenceRepositoryImpl.cs b/Demo/Data/Repository/PresenceRepositoryImpl.cs new file mode 100644 index 0000000..0f0b8df --- /dev/null +++ b/Demo/Data/Repository/PresenceRepositoryImpl.cs @@ -0,0 +1,53 @@ +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Demo.Data.Repository +{ + public class PresenceRepositoryImpl + { + private List _presences; + + public PresenceRepositoryImpl() + { + _presences = new List(); // Ваши реальные данные + } + + public void SavePresence(List presences) + { + foreach (var presence in presences) + { + var existingPresence = _presences.FirstOrDefault(p => + p.Date == presence.Date && + p.UserId == presence.UserId && + p.LessonNumber == presence.LessonNumber); + + if (existingPresence == null) + { + _presences.Add(presence); + } + else + { + existingPresence.IsAttedance = presence.IsAttedance; + } + } + } + + public List GetPresenceByDateAndGroup(DateTime date, int groupId) + { + return _presences.Where(p => p.Date.Date == date.Date && + LocalStaticData.users.Any(u => u.GroupID == groupId && u.ID == p.UserId)).ToList(); + } + + public List GetPresenceByGroup(int groupId) + { + return _presences.Where(p => p.GroupId == groupId).ToList(); + } + + + } +} diff --git a/Demo/Data/Repository/SQLGroupRepositoryImpl.cs b/Demo/Data/Repository/SQLGroupRepositoryImpl.cs new file mode 100644 index 0000000..d8de132 --- /dev/null +++ b/Demo/Data/Repository/SQLGroupRepositoryImpl.cs @@ -0,0 +1,116 @@ +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Demo.Data.Repository +{ + public class SQLGroupRepositoryImpl : IGroupRepository + { + private readonly RemoteDatabaseContext _remoteDatabaseContext; + + public SQLGroupRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext) + { + _remoteDatabaseContext = remoteDatabaseContext; + } + + // Метод для добавления новой группы + public bool AddGroup(GroupDao newGroup) + { + var groupDao = new GroupDao + { + Name = newGroup.Name + }; + _remoteDatabaseContext.Groups.Add(groupDao); + _remoteDatabaseContext.SaveChanges(); + return true; + } + + // Метод для получения группы по ID + public GroupDao GetGroupById(int groupId) + { + var groupDao = _remoteDatabaseContext.Groups + .Include(g => g.Users) + .FirstOrDefault(g => g.Id == groupId); + if (groupDao == null) return null; + + return new GroupDao + { + Id = groupDao.Id, + Name = groupDao.Name, + Users = groupDao.Users.Select(u => new UserDao + { + UserId = u.UserId, + FIO = u.FIO, + GroupId = u.GroupId + }).ToList() + }; + } + + // Метод для получения всех групп + public List GetAllGroups() + { + return _remoteDatabaseContext.Groups + .Include(g => g.Users) + .Select(g => new GroupDao + { + Id = g.Id, + Name = g.Name, + Users = g.Users.Select(u => new UserDao + { + UserId = u.UserId, + FIO = u.FIO, + GroupId = u.GroupId + }).ToList() + }) + .ToList(); + } + + // Метод для обновления группы по ID + public bool UpdateGroupById(int groupId, GroupDao updatedGroup) + { + var groupDao = _remoteDatabaseContext.Groups + .Include(g => g.Users) + .FirstOrDefault(g => g.Id == groupId); + if (groupDao == null) return false; + + groupDao.Name = updatedGroup.Name; + // Пример обновления списка пользователей + groupDao.Users = updatedGroup.Users.Select(user => new UserDao + { + UserId = user.UserId, + FIO = user.FIO, + GroupId = user.GroupId + }).ToList(); + + _remoteDatabaseContext.SaveChanges(); + return true; + } + + // Метод для удаления группы по ID + public bool RemoveGroupById(int groupId) + { + var groupDao = _remoteDatabaseContext.Groups.Find(groupId); + if (groupDao == null) return false; + + _remoteDatabaseContext.Groups.Remove(groupDao); + _remoteDatabaseContext.SaveChanges(); + return true; + } + + public bool AddGroup(string Name) + { + + var groupDao = new GroupDao + { + Name = Name + }; + _remoteDatabaseContext.Groups.Add(groupDao); + _remoteDatabaseContext.SaveChanges(); + return true; + } + } +} diff --git a/Demo/Data/Repository/SQLPresenceRepository.cs b/Demo/Data/Repository/SQLPresenceRepository.cs new file mode 100644 index 0000000..e70bfc0 --- /dev/null +++ b/Demo/Data/Repository/SQLPresenceRepository.cs @@ -0,0 +1,220 @@ +using Demo.Data.Exceptions; +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using DocumentFormat.OpenXml.InkML; +using DocumentFormat.OpenXml.Spreadsheet; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace Demo.Data.Repository +{ + public class SQLPresenceRepositoryImpl : IPresenceRepository + { + private readonly RemoteDatabaseContext _remoteDatabaseContext; + + public SQLPresenceRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext) + { + _remoteDatabaseContext = remoteDatabaseContext; + } + + + public List GetAttendanceByGroup(int groupId) + { + // Получаем записи посещаемости для указанной группы + return _remoteDatabaseContext.PresenceDaos + .Where(p => p.GroupId == groupId) + .Select(p => new PresenceDao + { + UserId = p.UserId, + GroupId = p.GroupId, + Date = p.Date, + LessonNumber = p.LessonNumber, + IsAttedance = p.IsAttedance + }) + .ToList(); + } + + + public List GetPresenceForAbsent(DateTime date, int GroupId) + { + return _remoteDatabaseContext.PresenceDaos.Where(p => p.GroupId == GroupId && p.Date == DateOnly.FromDateTime(date)).ToList(); + } + public List GetPresenceByDateAndGroup(DateTime date, int groupId) + { + return _remoteDatabaseContext.PresenceDaos.Where(p => p.Date == DateOnly.FromDateTime(date) && + _remoteDatabaseContext.Users.Any(u => u.GroupId == groupId && u.UserId == p.UserId)).ToList(); + } + + // Реализация метода для получения всех данных по группе + public List GetPresenceByGroup(int groupId) + { + return _remoteDatabaseContext.PresenceDaos.Where(p => p.GroupId == groupId) + .OrderBy(p => p.Date) + .ThenBy(p=>p.UserId).ToList(); + } + + public void SavePresence(List presences) + { + _remoteDatabaseContext.PresenceDaos.AddRange(presences.Select(it => new PresenceDao + { + Date = it.Date, + IsAttedance = it.IsAttedance, + LessonNumber = it.LessonNumber, + UserId = it.UserId, + GroupId = it.GroupId + })); + _remoteDatabaseContext.SaveChanges(); + } + + public void UpdateAtt(int userId, int groupId, int firstLesson, int lastLesson, DateOnly date, bool isAttendance) + { + // Находим все записи по UserId, GroupId, LessonNumber (в диапазоне) и дате + var presences = _remoteDatabaseContext.PresenceDaos + .Where(p => p.UserId == userId + && p.GroupId == groupId + && p.LessonNumber >= firstLesson + && p.LessonNumber <= lastLesson + && p.Date == date) + .ToList(); + + // Обновляем значение IsAttendance для всех найденных записей + foreach (var presence in presences) + { + presence.IsAttedance = isAttendance; + } + + _remoteDatabaseContext.SaveChanges(); // Сохраняем изменения в базе данных + } + + public DateOnly? GetLastDateByGroupId(int groupId) + { + // Проверяем наличие записей о посещаемости в базе данных для данной группы. + var lastDate = _remoteDatabaseContext.PresenceDaos + .Where(p => p.GroupId == groupId) + .OrderByDescending(p => p.Date) + .Select(p => p.Date) + .FirstOrDefault(); + + return lastDate == default ? (DateOnly?)null : lastDate; + } + + public List PresenceSort(List presences) + { + presences=_remoteDatabaseContext.PresenceDaos.OrderBy(p=>p.Date).ToList(); + return presences; + } + + + public GroupAttendanceStatistics GetGeneralPresenceForGroup(int groupId) + { + var presences = _remoteDatabaseContext.PresenceDaos.Where(p => p.GroupId == groupId).OrderBy(p => p.LessonNumber).ToList(); + var dates = _remoteDatabaseContext.PresenceDaos; + var distDates = dates.Select(p => p.Date).Distinct().ToList(); + int lesId = 0; + int lesNum = 1; + double att = 0; + int days = -1; + int countAllLes = 0; + DateOnly date = DateOnly.MinValue; + List usersId = new List(); + + foreach (var presence in presences) + { + if (!usersId.Contains(presence.UserId)) + { + usersId.Add(presence.UserId); + } + if (presence.Date != date) + { + date = presence.Date; + lesId++; + lesNum = presence.LessonNumber; + days++; + } + if (presence.LessonNumber != lesNum && date == presence.Date) + { + lesNum = presence.LessonNumber; + countAllLes++; + lesId++; + } + + + if (presence.IsAttedance) + { + att++; + } + + } + List a = new List(); + List ids = new List(); + double ok = 0; + double skip = 0; + int userId = 0; + foreach (var user in usersId) + { + var users = _remoteDatabaseContext.PresenceDaos.Where(p => p.UserId == user); + foreach (var usera in users) + { + userId = usera.UserId; + if (!ids.Contains(usera.UserId)) + { + skip = 0; + ok = 0; + ids.Add(userId); + a.Add(new UserAttendance { UserId = userId, Attended = ok, Missed = skip }); + userId = usera.UserId; + if (usera.IsAttedance) + { + a.First(a => a.UserId == usera.UserId).Attended = ok += 1; + } + else + { + a.First(a => a.UserId == usera.UserId).Missed = skip += 1; + } + } + else + { + if (usera.IsAttedance) + { + a.First(a => a.UserId == usera.UserId).Attended = ok += 1; + } + else + { + a.First(a => a.UserId == usera.UserId).Missed = skip += 1; + } + } + } + } + + var statistics = new GroupAttendanceStatistics + { + UserCount = usersId.Count, + TotalLessons = lesId, + AttendancePercentage = att / usersId.Count / lesNum / distDates.Count() * 100 + }; + + foreach (var user in a) + { + statistics.UserAttendanceDetails.Add(new UserAttendance + { + UserId = user.UserId, + Attended = user.Attended, + Missed = user.Missed, + AttendanceRate = user.Attended / (user.Missed + user.Attended) * 100 + }); + } + + return statistics; + } + } +} diff --git a/Demo/Data/Repository/SQLUserRepositoryImpl.cs b/Demo/Data/Repository/SQLUserRepositoryImpl.cs new file mode 100644 index 0000000..b726895 --- /dev/null +++ b/Demo/Data/Repository/SQLUserRepositoryImpl.cs @@ -0,0 +1,61 @@ +using Demo.Data.Exceptions; +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Demo.Data.Repository +{ + public class SQLUserRepositoryImpl : IUserRepository + { + private readonly RemoteDatabaseContext _remoteDatabaseContext; + + public SQLUserRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext) + { + _remoteDatabaseContext = remoteDatabaseContext; + } + + public bool RemoveUserById(int userId) + { + var user = _remoteDatabaseContext.Users.FirstOrDefault(u => u.UserId == userId); + if (user == null) throw new UserNotFoundException(userId); + + _remoteDatabaseContext.Users.Remove(user); + _remoteDatabaseContext.SaveChanges(); + return true; + } + + public UserDao UpdateUser(int userId, string newFio, int groupId) + { + var existingUser = _remoteDatabaseContext.Users.FirstOrDefault(u => u.UserId == userId); + if (existingUser == null) throw new UserNotFoundException(userId); + + // Обновляем поля существующего пользователя + existingUser.FIO = newFio; + existingUser.GroupId = groupId; + _remoteDatabaseContext.SaveChanges(); + + return existingUser; + } + + public List GetAllUsers() + { + // Возвращаем пользователей, отсортированных по UserId + return _remoteDatabaseContext.Users.OrderBy(u => u.UserId).ToList(); + } + + public List GetUserNames() + { + var users = GetAllUsers(); + List names = new List(); + foreach (var user in users) + { + names.Add(new UserDao{UserId=user.UserId, FIO=user.FIO }); + } + return names; + } + } +} diff --git a/Demo/Data/Repository/UserRepositoryImpl.cs b/Demo/Data/Repository/UserRepositoryImpl.cs new file mode 100644 index 0000000..e1d6e40 --- /dev/null +++ b/Demo/Data/Repository/UserRepositoryImpl.cs @@ -0,0 +1,37 @@ +using Demo.Data.Exceptions; +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Demo.Data.Repository +{ + public class UserRepositoryImpl + { + private List _users; + + public UserRepositoryImpl() + { + _users = LocalStaticData.users; + } + + public IEnumerable GetAllUsers => _users; + + + public bool RemoveUserById(int userId) + { + var user = _users.FirstOrDefault(u => u.ID == userId); + if (user == null) throw new UserNotFoundException(userId); + + _users.Remove(user); + return true; + } + + public UserDao? UpdateUser(UserDao user) + { + throw new NotImplementedException(); + } + } +} diff --git a/Demo/Demo.csproj b/Demo/Demo.csproj new file mode 100644 index 0000000..760f09a --- /dev/null +++ b/Demo/Demo.csproj @@ -0,0 +1,27 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + diff --git a/Demo/Domain/Models/Group.cs b/Demo/Domain/Models/Group.cs new file mode 100644 index 0000000..ce0914b --- /dev/null +++ b/Demo/Domain/Models/Group.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.domain.Models +{ + public class Group + { + public required int Id { get; set; } + public required string Name { get; set; } + } +} diff --git a/Demo/Domain/Models/Presence.cs b/Demo/Domain/Models/Presence.cs new file mode 100644 index 0000000..110a364 --- /dev/null +++ b/Demo/Domain/Models/Presence.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.domain.Models +{ + public class Presence + { + + public required User User { get; set; } + public required int GroupId { get; set; } + public bool IsAttedance { get; set; } = true; + public required DateTime Date { get; set; } + public required int LessonNumber { get; set; } + } +} diff --git a/Demo/Domain/Models/User.cs b/Demo/Domain/Models/User.cs new file mode 100644 index 0000000..8e09028 --- /dev/null +++ b/Demo/Domain/Models/User.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.domain.Models +{ + public class User + { + public required string FIO { get; set; } + public int ID { get; set; } + public required Group Group { get; set; } + } +} diff --git a/Demo/Domain/UseCase/GroupUseCase.cs b/Demo/Domain/UseCase/GroupUseCase.cs new file mode 100644 index 0000000..0f3492b --- /dev/null +++ b/Demo/Domain/UseCase/GroupUseCase.cs @@ -0,0 +1,88 @@ +using Demo.Data.LocalData; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.Data.Repository; +using Demo.domain.Models; + +namespace Demo.Domain.UseCase +{ + public class GroupUseCase + { + private readonly IGroupRepository _SQLGroupRepositoryImpl; + + public GroupUseCase(IGroupRepository SQlGroupRepositoryImpl) + { + _SQLGroupRepositoryImpl = SQlGroupRepositoryImpl; + } + + // Приватный метод для валидации имени группы + private void ValidateGroupName(string groupName) + { + if (string.IsNullOrWhiteSpace(groupName)) + { + throw new ArgumentException("Имя группы не может быть пустым."); + } + } + + private void ValidateGroupId(int GroupId) + { + if(GroupId < 1) + { + throw new ArgumentException("Введите корректный ID группы."); + } + } + + // Приватный метод для валидации существования группы по ID + private GroupDao ValidateGroupExistence(int groupId) + { + var existingGroup = _SQLGroupRepositoryImpl.GetAllGroups() + .FirstOrDefault(g => g.Id == groupId); + + if (existingGroup == null) + { + throw new ArgumentException("Группа не найдена."); + } + + return existingGroup; + } + + + // Метод для получения списка всех групп + public List GetAllGroups() + { + return [.. _SQLGroupRepositoryImpl.GetAllGroups() + .Select(it => new GroupDao { Id = it.Id, Name = it.Name })]; + } + + // Метод для получения группы по ID + public string FindGroupById(int IdGroup) + { + string groups = _SQLGroupRepositoryImpl.GetGroupById(IdGroup).Name; + + return groups; + } + + + // Метод для добавления новой группы + public void AddGroup(string groupName) + { + ValidateGroupName(groupName); + GroupDao newGroup = new GroupDao + { + Name = groupName + }; + + _SQLGroupRepositoryImpl.AddGroup(newGroup.Name); + } + + + // Метод для изменения названия группы + public void UpdateGroup(int groupId, string newGroupName) + { + ValidateGroupName(newGroupName); + var existingGroup = ValidateGroupExistence(groupId); + + existingGroup.Name = newGroupName; + _SQLGroupRepositoryImpl.UpdateGroupById(groupId,existingGroup); + } + } +} \ No newline at end of file diff --git a/Demo/Domain/UseCase/UseCaseGeneratePresence.cs b/Demo/Domain/UseCase/UseCaseGeneratePresence.cs new file mode 100644 index 0000000..71e0b64 --- /dev/null +++ b/Demo/Domain/UseCase/UseCaseGeneratePresence.cs @@ -0,0 +1,192 @@ +using ClosedXML.Excel; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.Data.Repository; +using Demo.domain.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Domain.UseCase +{ + public class UseCaseGeneratePresence + { + public readonly IUserRepository _userRepository; + public readonly IPresenceRepository _presenceRepository; + private readonly IGroupRepository _groupRepository; + + public UseCaseGeneratePresence(IUserRepository userRepository, IPresenceRepository presenceRepository, IGroupRepository groupRepository) + { + _userRepository = userRepository; + _presenceRepository = presenceRepository; + _groupRepository = groupRepository; + } + + public Dictionary> GetAllAttendanceByGroups() + { + var attendanceByGroup = new Dictionary>(); + var allGroups = _groupRepository.GetAllGroups(); + + foreach (var group in allGroups) + { + var groupAttendance = _presenceRepository.GetAttendanceByGroup(group.Id); + var attendanceRecords = new List(); + + foreach (var record in groupAttendance) + { + var names = _userRepository.GetUserNames().Where(u => u.UserId == record.UserId); + foreach (var name in names) + { + attendanceRecords.Add(new AttendanceRecord + { + UserName = name.FIO, + UserId = name.UserId, + Date = record.Date, + IsAttedance = record.IsAttedance, + LessonNumber = record.LessonNumber, + GroupName = group.Name + }); + } + } + + attendanceByGroup.Add(group.Name, attendanceRecords); + } + + return attendanceByGroup; + } + + public void ExportAttendanceToExcel() + { + var attendanceByGroup = GetAllAttendanceByGroups(); + string projectDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName; + string reportsFolderPath = Path.Combine(projectDirectory, "Reports"); + string filePath = Path.Combine(reportsFolderPath, "AttendanceReport.xlsx"); + + // Создаем папку, если она не существует + if (!Directory.Exists(reportsFolderPath)) + { + Directory.CreateDirectory(reportsFolderPath); + } + using (var workbook = new XLWorkbook()) + { + foreach (var group in attendanceByGroup) + { + var worksheet = workbook.Worksheets.Add($"{group.Key}"); + worksheet.Cell(1, 1).Value = "ФИО"; + worksheet.Cell(1, 2).Value = "Группа"; + worksheet.Cell(1, 3).Value = "Дата"; + worksheet.Cell(1, 4).Value = "Занятие"; + worksheet.Cell(1, 5).Value = "Статус"; + + int row = 2; + int lesNum = 1; + foreach (var record in group.Value.OrderBy(r => r.Date).ThenBy(r => r.LessonNumber).ThenBy(r => r.UserId)) + { + if (lesNum != record.LessonNumber) + { + row++; + } + worksheet.Cell(row, 1).Value = record.UserName; + worksheet.Cell(row, 2).Value = record.GroupName; + worksheet.Cell(row, 3).Value = record.Date.ToString("dd.MM.yyyy"); + worksheet.Cell(row, 4).Value = record.LessonNumber; + worksheet.Cell(row, 5).Value = record.IsAttedance ? "Присутствует" : "Отсутствует"; + row++; + + + + lesNum = record.LessonNumber; + } + + worksheet.Columns().AdjustToContents(); + } + + workbook.SaveAs(filePath); + } + } + + + + + public List GetPresenceByDateAndGroup(DateTime date, int groupId) + { + return _presenceRepository.GetPresenceByDateAndGroup(date, groupId); + } + + public void GeneratePresenceDaily(int firstLesson, int lastLesson, int groupId) + { + var users = _userRepository.GetAllUsers().Where(u => u.GroupId == groupId).ToList(); + + // Находим последнюю дату посещаемости для данной группы + DateOnly startDate = _presenceRepository.GetLastDateByGroupId(groupId)?.AddDays(1) + ?? DateOnly.FromDateTime(DateTime.Today); + + List presences = new List(); + for (int lessonNumber = firstLesson; lessonNumber <= lastLesson; lessonNumber++) + { + foreach (var user in users) + { + var presence = new PresenceDao + { + UserId = user.UserId, + GroupId = user.GroupId, + Date = startDate, + LessonNumber = lessonNumber, + IsAttedance = true + }; + _presenceRepository.SavePresence(new List { presence }); + } + } + } + + + + + public void GenerateWeeklyPresence(int firstLesson, int lastLesson, int groupId, DateTime startTime) + { + for (int i = 0; i < 7; i++) + { + DateTime currentTime = startTime.AddDays(i); + GeneratePresenceDaily(firstLesson, lastLesson, groupId); + } + } + + + + // Отметить пользователя как отсутствующего на диапазоне занятий + public bool MarkUserAbsentForLessons(int userId, int groupId, int firstLesson, int lastLesson, DateTime date) + { + List presences = _presenceRepository.GetPresenceForAbsent(date, groupId); + if (presences.Where(p => p.UserId == userId).Count() > 0) + { + // Обновляем состояние присутствия для указанных занятий + foreach (var presence in presences.Where(p => p.UserId == userId && p.LessonNumber >= firstLesson && p.LessonNumber <= lastLesson)) + { + presence.IsAttedance = false; // Устанавливаем отсутствие + } + // Сохраняем изменения в репозитории + _presenceRepository.UpdateAtt(userId, groupId, firstLesson, lastLesson, DateOnly.FromDateTime(date), false); + return true; + } + else + { + return false; + } + } + + public List GetAllPresenceByGroup(int groupId) + { + return _presenceRepository.GetPresenceByGroup(groupId); + } + + public GroupAttendanceStatistics GetGeneralPresence(int groupId) + { + return _presenceRepository.GetGeneralPresenceForGroup(groupId); + } + + + + } +} diff --git a/Demo/Domain/UseCase/UserUseCase.cs b/Demo/Domain/UseCase/UserUseCase.cs new file mode 100644 index 0000000..9a7bf71 --- /dev/null +++ b/Demo/Domain/UseCase/UserUseCase.cs @@ -0,0 +1,146 @@ +using Demo.Data.Exceptions; +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.Data.Repository; +using Demo.domain.Models; + +namespace Demo.Domain.UseCase +{ + public class UserUseCase + { + private readonly IUserRepository _repositoryUserImpl; + private readonly IGroupRepository _repositoryGroupImpl; + private readonly IPresenceRepository _repositoryPresenceImpl; + public UserUseCase(IUserRepository repositoryImpl, IGroupRepository repositoryGroupImpl, IPresenceRepository presenceRepository) + { + _repositoryUserImpl = repositoryImpl; + _repositoryGroupImpl = repositoryGroupImpl; + _repositoryPresenceImpl = presenceRepository; + } + + // Приватный метод для валидации ФИО пользователя + private void ValidateUserFIO(string fio) + { + if (string.IsNullOrWhiteSpace(fio)) + { + throw new ArgumentException("ФИО не может быть пустым."); + } + } + + public void RemovePresenceByUserId(int userId) + { + using (var context = new RemoteDatabaseContext()) + { + var presences = context.PresenceDaos.Where(p => p.UserId == userId).ToList(); + context.PresenceDaos.RemoveRange(presences); + context.SaveChanges(); + } + } + + // Приватный метод для валидации существования пользователя по ID + private UserDao ValidateUserExistence(int userId) + { + var user = _repositoryUserImpl.GetAllUsers() + .FirstOrDefault(u => u.UserId == userId); + + if (user == null) + { + throw new Exception("Пользователь не найден."); + } + + return user; + } + + // Приватный метод для валидации существования группы по ID + private GroupDao ValidateGroupExistence(int groupId) + { + var group = _repositoryGroupImpl.GetAllGroups() + .FirstOrDefault(g => g.Id == groupId); + + if (group == null) + { + throw new Exception("Группа не найдена."); + } + + return group; + } + + // Вывести всех пользователей + //упростить под ef + public List GetAllUsers() => _repositoryUserImpl.GetAllUsers() + .Join(_repositoryGroupImpl.GetAllGroups(), + user => user.GroupId, // Ключ для пользователей + group => group.Id, // Ключ для групп + (user, group) => // Результирующий объект + new UserDao + { + UserId = user.UserId, + FIO = user.FIO, + Group = new GroupDao { Id = group.Id, Name = group.Name } + }).ToList(); + + // Удалить пользователя по id + public bool RemoveUserById(int userId) + { + try + { + return _repositoryUserImpl.RemoveUserById(userId); + } + catch (UserNotFoundException ex) + { + Console.WriteLine($"Ошибка: {ex.Message}"); + return false; + } + catch (RepositoryException ex) + { + Console.WriteLine($"Ошибка в репозитории: {ex.Message}"); + return false; + } + } + + // Обновить пользователя по id + public UserDao UpdateUser(int userId, string newFio, int groupId) + { + ValidateUserFIO(newFio); + ValidateGroupExistence(groupId); + + UserDao userDao = new UserDao + { + UserId = userId, + FIO = newFio, + GroupId = groupId + }; + + UserDao? result = _repositoryUserImpl.UpdateUser(userId, newFio, groupId); + + if (result == null) + { + throw new Exception("Ошибка при обновлении пользователя."); + } + + var groupEntity = ValidateGroupExistence(result.GroupId); + + return new UserDao + { + UserId= userId, + FIO = newFio, + GroupId = groupId + }; + + } + + // Найти пользователя по id + public UserDao FindUserById(int userId) + { + var user = ValidateUserExistence(userId); + var group = ValidateGroupExistence(user.GroupId); + + return new UserDao + { + UserId = user.UserId, + FIO = user.FIO, + Group = new GroupDao { Id = group.Id, Name=group.Name } + }; + } + } +} diff --git a/Demo/Migrations/20241103105727_CreateDatabase.Designer.cs b/Demo/Migrations/20241103105727_CreateDatabase.Designer.cs new file mode 100644 index 0000000..d2f3403 --- /dev/null +++ b/Demo/Migrations/20241103105727_CreateDatabase.Designer.cs @@ -0,0 +1,113 @@ +// +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("20241103105727_CreateDatabase")] + partial class CreateDatabase + { + /// + 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("PresenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PresenceId")); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("GroupId") + .HasColumnType("integer"); + + b.Property("IsAttedance") + .HasColumnType("boolean"); + + b.Property("LessonNumber") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("PresenceId"); + + b.ToTable("PresenceDaos"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDao", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("FIO") + .IsRequired() + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("integer"); + + b.HasKey("UserId"); + + b.HasIndex("GroupId"); + + b.ToTable("Users"); + }); + + 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/Demo/Migrations/20241103105727_CreateDatabase.cs b/Demo/Migrations/20241103105727_CreateDatabase.cs new file mode 100644 index 0000000..7ec3b53 --- /dev/null +++ b/Demo/Migrations/20241103105727_CreateDatabase.cs @@ -0,0 +1,84 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Demo.Migrations +{ + /// + public partial class CreateDatabase : 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: "PresenceDaos", + columns: table => new + { + PresenceId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UserId = table.Column(type: "integer", nullable: false), + IsAttedance = table.Column(type: "boolean", nullable: false), + Date = table.Column(type: "date", nullable: false), + LessonNumber = table.Column(type: "integer", nullable: false), + GroupId = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PresenceDaos", x => x.PresenceId); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + UserId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + FIO = table.Column(type: "text", nullable: false), + GroupId = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.UserId); + table.ForeignKey( + name: "FK_Users_Groups_GroupId", + column: x => x.GroupId, + principalTable: "Groups", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + 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/Demo/Migrations/RemoteDatabaseContextModelSnapshot.cs b/Demo/Migrations/RemoteDatabaseContextModelSnapshot.cs new file mode 100644 index 0000000..3ee588f --- /dev/null +++ b/Demo/Migrations/RemoteDatabaseContextModelSnapshot.cs @@ -0,0 +1,110 @@ +// +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("PresenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PresenceId")); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("GroupId") + .HasColumnType("integer"); + + b.Property("IsAttedance") + .HasColumnType("boolean"); + + b.Property("LessonNumber") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("PresenceId"); + + b.ToTable("PresenceDaos"); + }); + + modelBuilder.Entity("Demo.Data.RemoteData.RemoteDataBase.DAO.UserDao", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("FIO") + .IsRequired() + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("integer"); + + b.HasKey("UserId"); + + b.HasIndex("GroupId"); + + b.ToTable("Users"); + }); + + 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/Demo/Program.cs b/Demo/Program.cs new file mode 100644 index 0000000..df70b1d --- /dev/null +++ b/Demo/Program.cs @@ -0,0 +1,28 @@ +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(); + + + +var serviceProvider = services.BuildServiceProvider(); +// Создаем пользовательский интерфейс +MainMenuUI mainMenuUI = serviceProvider.GetService(); + +// Выводим главное меню +mainMenuUI.DisplayMenu(); diff --git a/Demo/Reports/AttendanceReport.xlsx b/Demo/Reports/AttendanceReport.xlsx new file mode 100644 index 0000000..e032397 Binary files /dev/null and b/Demo/Reports/AttendanceReport.xlsx differ diff --git a/Demo/UI/GroupConsole.cs b/Demo/UI/GroupConsole.cs new file mode 100644 index 0000000..0e91f49 --- /dev/null +++ b/Demo/UI/GroupConsole.cs @@ -0,0 +1,58 @@ +using Demo.Domain.UseCase; +using System; +using System.Text; + +namespace Demo.UI +{ + public class GroupConsoleUI + { + private readonly GroupUseCase _groupUseCase; + + public GroupConsoleUI(GroupUseCase groupUseCase) + { + _groupUseCase = groupUseCase; + } + + public void FindGroupById(int IdGroup) + { + var groups = _groupUseCase.FindGroupById(IdGroup); + Console.WriteLine(groups); + } + + // Метод для отображения всех групп + public void DisplayAllGroups() + { + Console.WriteLine("\n=== Список всех групп ==="); + StringBuilder groupOutput = new StringBuilder(); + + foreach (var group in _groupUseCase.GetAllGroups()) + { + groupOutput.AppendLine($"{group.Id}\t{group.Name}"); + } + + Console.WriteLine(groupOutput); + Console.WriteLine("===========================\n"); + } + + // Метод для добавления новой группы + public void AddGroup(string groupName) + { + try + { + _groupUseCase.AddGroup(groupName); + Console.WriteLine($"\nГруппа {groupName} добавлена.\n"); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка: {ex.Message}\n"); + } + } + + // Метод для обновления названия группы + public void UpdateGroupName(int groupId, string newGroupName) + { + _groupUseCase.UpdateGroup(groupId, newGroupName); + Console.WriteLine($"\nНазвание группы с ID {groupId} изменено на {newGroupName}.\n"); + } + } +} diff --git a/Demo/UI/MainMenu.cs b/Demo/UI/MainMenu.cs new file mode 100644 index 0000000..6056da8 --- /dev/null +++ b/Demo/UI/MainMenu.cs @@ -0,0 +1,224 @@ +using Demo.domain.Models; +using Demo.Domain.UseCase; +using System; +using System.Globalization; + +namespace Demo.UI +{ + public class MainMenuUI + { + private readonly UserConsoleUI _userConsoleUI; + private readonly GroupConsoleUI _groupConsoleUI; + private readonly PresenceConsole _presenceConsoleUI; + + public MainMenuUI(UserUseCase userUseCase, GroupUseCase groupUseCase, UseCaseGeneratePresence presenceUseCase) + { + _userConsoleUI = new UserConsoleUI(userUseCase); + _groupConsoleUI = new GroupConsoleUI(groupUseCase); + _presenceConsoleUI = new PresenceConsole(presenceUseCase); + } + + public void DisplayMenu() + { + while (true) + { + Console.WriteLine("\n=-= Главное меню =-=\n"); + + Console.WriteLine("=-= Команды с Пользователями =-="); + Console.WriteLine("1. Вывести всех пользователей"); + Console.WriteLine("2. Удалить пользователя по id"); + Console.WriteLine("3. Обновить пользователя по id"); + Console.WriteLine("4. Найти пользователя по id"); + Console.WriteLine(); + + Console.WriteLine("=-= Команды с Группами =-="); + Console.WriteLine("5. Вывести все группы"); + Console.WriteLine("6. Добавить группу"); + Console.WriteLine("7. Изменить название группы"); + Console.WriteLine("8. Поиск группы по ID"); + Console.WriteLine(); + Console.WriteLine("=-= Команды Presence =-="); + Console.WriteLine("9. Сгенерировать посещаемость на день"); + Console.WriteLine("10. Сгенерировать посещаемость на неделю"); + Console.WriteLine("11. Показать посещаемость"); + Console.WriteLine("12. Отметить пользователя как отсутствующего"); + Console.WriteLine("13. Вывести всю посещаемость группы"); + Console.WriteLine("14. Вывести общую информацию об посещаемости по группе"); + Console.WriteLine("15. Вывести отчётв Excel"); + Console.WriteLine(); + Console.WriteLine("0. Выход"); + + Console.Write("\nВаш выбор: "); + string comand = Console.ReadLine(); + Console.WriteLine(); + + switch (comand) + { + case "1": + // Отображение всех пользователей + _userConsoleUI.DisplayAllUsers(); + break; + + case "2": + // Удаление пользователя по ID + Console.Write("Введите ID пользователя для удаления: "); + string inputId = Console.ReadLine(); + if (int.TryParse(inputId, out int userId)) + { + _userConsoleUI.RemoveUserById(userId); + } + else + { + Console.WriteLine("Неверный формат ID"); + } + break; + + case "3": + // Обновление пользователя по ID + Console.Write("Введите ID пользователя для обновления: "); + string updateIdInput = Console.ReadLine(); + if (int.TryParse(updateIdInput, out int updateUserId)) + { + _userConsoleUI.UpdateUserById(updateUserId); + } + else + { + Console.WriteLine("Неверный формат ID"); + } + break; + + case "4": + // Поиск пользователя по ID + Console.Write("Введите ID пользователя для поиска: "); + string findIdInput = Console.ReadLine(); + if (int.TryParse(findIdInput, out int findUserId)) + { + _userConsoleUI.FindUserById(findUserId); + } + else + { + Console.WriteLine("Неверный формат ID"); + } + break; + + case "5": + // Отображение всех групп + _groupConsoleUI.DisplayAllGroups(); + break; + + case "6": + // Добавление новой группы + Console.Write("Введите название новой группы: "); + string newGroupName = Console.ReadLine(); + _groupConsoleUI.AddGroup(newGroupName); + break; + + case "7": + // Изменение названия группы + Console.Write("Введите ID группы для изменения: "); + if (int.TryParse(Console.ReadLine(), out int groupId)) + { + Console.Write("Введите новое название группы: "); + string newName = Console.ReadLine(); + _groupConsoleUI.UpdateGroupName(groupId, newName); + } + else + { + Console.WriteLine("Неверный формат ID группы"); + } + break; + + case "8": + // Поиск группы + Console.Write("Введите ID группы для поиска : "); + if (int.TryParse(Console.ReadLine(), out int IdGroup)) + { + _groupConsoleUI.FindGroupById(IdGroup); + } + break; + + case "9": + // Генерация посещаемости на день + Console.Write("Введите номер первого занятия: "); + int firstLesson = int.Parse(Console.ReadLine()); + Console.Write("Введите номер последнего занятия: "); + int lastLesson = int.Parse(Console.ReadLine()); + Console.Write("Введите ID группы: "); + int groupIdForPresence = int.Parse(Console.ReadLine()); + + _presenceConsoleUI.GeneratePresenceForDay(DateTime.Now, groupIdForPresence, firstLesson, lastLesson); + Console.WriteLine("Посещаемость на день сгенерирована."); + break; + + case "10": + // Генерация посещаемости на неделю + Console.Write("Введите номер первого занятия: "); + int firstLessonForWeek = int.Parse(Console.ReadLine()); + Console.Write("Введите номер последнего занятия: "); + int lastLessonForWeek = int.Parse(Console.ReadLine()); + Console.Write("Введите ID группы: "); + int groupIdForWeekPresence = int.Parse(Console.ReadLine()); + + _presenceConsoleUI.GeneratePresenceForWeek(DateTime.Now, groupIdForWeekPresence, firstLessonForWeek, lastLessonForWeek); + Console.WriteLine("Посещаемость на неделю сгенерирована."); + break; + + case "11": + // Отображение посещаемости + Console.Write("Введите дату (гггг-мм-дд): "); + DateTime date = DateTime.Parse(Console.ReadLine()); + Console.Write("Введите ID группы: "); + int groupForPresenceView = int.Parse(Console.ReadLine()); + + _presenceConsoleUI.DisplayPresence(date, groupForPresenceView); + break; + + case "12": + // Отметить пользователя как отсутствующего + Console.Write("Введите ID пользователя: "); + userId = int.Parse(Console.ReadLine()); + Console.Write("Введите номер первого занятия: "); + int firstAbsLesson = int.Parse(Console.ReadLine()); + Console.Write("Введите номер последнего занятия: "); + int lastAbsLesson = int.Parse(Console.ReadLine()); + Console.Write("Введите ID группы: "); + int absGroupId = int.Parse(Console.ReadLine()); + + Console.Write("Введите дату (дд.мм.гггг): "); + string dateInput = Console.ReadLine(); + DateTime absenceDate; + + if (!DateTime.TryParseExact(dateInput, "d.M.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out absenceDate)) + { + Console.WriteLine("Ошибка: Введен некорректный формат даты. Пожалуйста, используйте формат дд.мм.гггг."); + return; // Завершает выполнение, если дата некорректна + } + _presenceConsoleUI.MarkUserAbsent(absenceDate, absGroupId, userId, firstAbsLesson, lastAbsLesson); + break; + case "13": + Console.Write("Введите ID группы: "); + int groupIdForAllPresence = int.Parse(Console.ReadLine()); + _presenceConsoleUI.DisplayAllPresenceByGroup(groupIdForAllPresence); + break; + + case "14": + Console.Write("Введите ID группы: "); + int searchGroupId= int.Parse(Console.ReadLine()); + _presenceConsoleUI.DisplayGeneralPresence(searchGroupId); + break; + case "15": + _presenceConsoleUI.ExportAttendanceToExcel(); + break; + case "0": + Console.WriteLine("Выход..."); + return; + + default: + Console.WriteLine("Неверный выбор, попробуйте снова."); + break; + } + Console.WriteLine(); + } + } + } +} \ No newline at end of file diff --git a/Demo/UI/PresenceConsole.cs b/Demo/UI/PresenceConsole.cs new file mode 100644 index 0000000..efa12d0 --- /dev/null +++ b/Demo/UI/PresenceConsole.cs @@ -0,0 +1,188 @@ +using Demo.Data.Exceptions; +using Demo.Data.RemoteData.RemoteDataBase.DAO; +using Demo.domain.Models; +using Demo.Domain.UseCase; +using System; +using System.Collections.Generic; + +namespace Demo.UI +{ + public class PresenceConsole + { + private readonly UseCaseGeneratePresence _presenceUseCase; + + public PresenceConsole(UseCaseGeneratePresence presenceUseCase) + { + _presenceUseCase = presenceUseCase; + } + + public void ExportAttendanceToExcel() + { + try + { + _presenceUseCase.ExportAttendanceToExcel(); + Console.WriteLine("Данные посещаемости успешно экспортированы в Excel."); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка при экспорте посещаемости: {ex.Message}"); + } + } + + + + // Метод для генерации посещаемости на день + public void GeneratePresenceForDay(DateTime date, int groupId, int firstLesson, int lastLesson) + { + try + { + _presenceUseCase.GeneratePresenceDaily(firstLesson, lastLesson, groupId); + Console.WriteLine("Посещаемость на день успешно сгенерирована."); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка при генерации посещаемости: {ex.Message}"); + } + } + + // Метод для генерации посещаемости на неделю + public void GeneratePresenceForWeek(DateTime date, int groupId, int firstLesson, int lastLesson) + { + try + { + _presenceUseCase.GenerateWeeklyPresence(firstLesson, lastLesson, groupId, date); + Console.WriteLine("Посещаемость на неделю успешно сгенерирована."); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка при генерации посещаемости: {ex.Message}"); + } + } + + // Метод для отображения посещаемости на конкретную дату и группу + public void DisplayPresence(DateTime date, int groupId) + { + try + { + List presences = _presenceUseCase.GetPresenceByDateAndGroup(date, groupId); + + if (presences == null || presences.Count == 0) + { + Console.WriteLine("Посещаемость на выбранную дату отсутствует."); + return; + } + + // Сортируем присутствия по номеру занятия и ID пользователя + var sortedPresences = presences.OrderBy(p => p.LessonNumber) + .ThenBy(p => p.UserId); + + Console.WriteLine($"\nПосещаемость на {date.ToShortDateString()} для группы с ID {groupId}:"); + Console.WriteLine("---------------------------------------------"); + + int previousLessonNumber = -1; // Инициализация для сравнения + foreach (var presence in sortedPresences) + { + if (previousLessonNumber != presence.LessonNumber) + { + Console.WriteLine("---------------------------------------------"); + previousLessonNumber = presence.LessonNumber; + } + string status = presence.IsAttedance ? "Присутствует" : "Отсутствует"; + Console.WriteLine($"Пользователь ID: {presence.UserId}, Занятие {presence.LessonNumber}: {status}"); + } + Console.WriteLine("---------------------------------------------"); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка при выводе посещаемости: {ex.Message}"); + } + + } + + public void MarkUserAbsent(DateTime date, int groupId, int userId, int firstLesson, int lastLesson) + { + bool check=_presenceUseCase.MarkUserAbsentForLessons(userId, groupId, firstLesson, lastLesson, date); + if (check) + { + Console.WriteLine("Пользователь отмечен как осутсвующий"); + } + else + { + Console.WriteLine($"Посещаемость для пользователя ID: {userId} на дату {date.ToShortDateString()}" + + $" с {firstLesson} по {lastLesson} уроки не найдена."); + } + } + + public void DisplayGeneralPresence(int groupId) + { + var statistics = _presenceUseCase.GetGeneralPresence(groupId); + Console.WriteLine($"Человек в группе: {statistics.UserCount}, " + + $"Количество проведённых занятий: {statistics.TotalLessons}, " + + $"Общий процент посещаемости группы: {statistics.AttendancePercentage}%"); + + foreach (var user in statistics.UserAttendanceDetails) + { + Console.ForegroundColor = user.AttendanceRate < 40 ? ConsoleColor.Red : ConsoleColor.White; + Console.WriteLine($"ID Пользователя: {user.UserId}, Посетил: {user.Attended}, " + + $"Пропустил: {user.Missed}, Процент посещаемости: {user.AttendanceRate}%"); + } + Console.ForegroundColor = ConsoleColor.White; + } + + + + public void DisplayAllPresenceByGroup(int groupId) + { + try + { + // Получаем все посещения для группы + var presences = _presenceUseCase.GetAllPresenceByGroup(groupId); + + if (presences == null || presences.Count == 0) + { + Console.WriteLine($"Посещаемость для группы с ID {groupId} отсутствует."); + return; + } + + // Группируем по дате + var groupedPresences = presences.GroupBy(p => p.Date); + + foreach (var group in groupedPresences) + { + Console.WriteLine("==================================================="); + Console.WriteLine($"Дата: {group.Key.ToString("dd.MM.yyyy")}"); + Console.WriteLine("==================================================="); + + // Группируем по занятию + var groupedByLesson = group.GroupBy(p => p.LessonNumber); + + foreach (var lessonGroup in groupedByLesson) + { + Console.WriteLine($"Занятие {lessonGroup.Key}:"); + + // Создаем HashSet для уникальных пользователей + var userIds = new HashSet(); + + foreach (var presence in lessonGroup) + { + // Проверяем, добавляется ли пользователь в HashSet + if (userIds.Add(presence.UserId)) + { + string status = presence.IsAttedance ? "Присутствует" : "Отсутствует"; + Console.WriteLine($"Пользователь ID: {presence.UserId}, Статус: {status}"); + } + } + + Console.WriteLine("---------------------------------------------------"); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка при выводе посещаемости: {ex.Message}"); + } + } + + + } +} diff --git a/Demo/UI/UserConsole.cs b/Demo/UI/UserConsole.cs new file mode 100644 index 0000000..b3b5c52 --- /dev/null +++ b/Demo/UI/UserConsole.cs @@ -0,0 +1,81 @@ +using Demo.Data.RemoteData.RemoteDataBase; +using Demo.Data.Repository; +using Demo.Domain.UseCase; +using System; +using System.Text; + +namespace Demo.UI +{ + public class UserConsoleUI + { + private readonly UserUseCase _userUseCase; + + public UserConsoleUI(UserUseCase userUseCase) + { + _userUseCase = userUseCase; + } + + // Метод для отображения всех пользователей + public void DisplayAllUsers() + { + Console.WriteLine("\n=== Список всех пользователей ==="); + StringBuilder userOutput = new StringBuilder(); + + foreach (var user in _userUseCase.GetAllUsers()) + { + userOutput.AppendLine($"{user.UserId}\t{user.FIO}\t{user.Group.Name}"); + } + + Console.WriteLine(userOutput); + Console.WriteLine("===============================\n"); + } + + // Метод для удаления пользователя по ID + public void RemoveUserById(int userId) + { + // Сначала удаляем все записи о присутствии пользователя + _userUseCase.RemovePresenceByUserId(userId); + + // Теперь удаляем пользователя + string output = _userUseCase.RemoveUserById(userId) ? "Пользователь удален" : "Пользователь не найден"; + Console.WriteLine($"\n{output}\n"); + } + + // Метод для обновления пользователя по ID + public void UpdateUserById(int userId) + { + try + { + var user = _userUseCase.FindUserById(userId); + + + Console.WriteLine($"Текущие данные: {user.FIO}"); + Console.Write("\nВведите новое ФИО: "); + string newFIO = Console.ReadLine(); + Console.Write("\nВведите новый ID группы (или оставьте такой же): "); + int GroupId = int.Parse(Console.ReadLine()); + _userUseCase.UpdateUser(userId, newFIO, GroupId); + + Console.WriteLine("\nПользователь обновлен.\n"); + } + catch (Exception ex) + { + Console.WriteLine($"Ошибка: {ex.Message}\n"); + } + } + + // Метод для поиска пользователя по ID + public void FindUserById(int userId) + { + var user = _userUseCase.FindUserById(userId); + if (user != null) + { + Console.WriteLine($"\nПользователь найден: {user.UserId}, {user.FIO}, {user.Group.Name}\n"); + } + else + { + Console.WriteLine("\nПользователь не найден.\n"); + } + } + } +} diff --git a/presence.sln b/presence.sln new file mode 100644 index 0000000..34ad780 --- /dev/null +++ b/presence.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35506.116 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "presence", "presence\presence.csproj", "{5DBB1FC4-E89F-4AC4-B5FD-D8A5321300CA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5DBB1FC4-E89F-4AC4-B5FD-D8A5321300CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DBB1FC4-E89F-4AC4-B5FD-D8A5321300CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DBB1FC4-E89F-4AC4-B5FD-D8A5321300CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DBB1FC4-E89F-4AC4-B5FD-D8A5321300CA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/presence/Class1.cs b/presence/Class1.cs new file mode 100644 index 0000000..22c197a --- /dev/null +++ b/presence/Class1.cs @@ -0,0 +1,7 @@ +namespace presence +{ + public class Class1 + { + + } +} diff --git a/presence/presence.csproj b/presence/presence.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/presence/presence.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + +