Compare commits

..

4 Commits

Author SHA1 Message Date
3ca477dd51 last-commit 2024-12-13 10:34:58 +03:00
8648e3efaf addDataGrid 2024-12-13 08:47:52 +03:00
908715ff15 regular-commit 2024-12-12 22:47:32 +03:00
b84da3b29a right-version 2024-12-12 21:16:01 +03:00
57 changed files with 1099 additions and 1684 deletions

View File

@ -1,45 +0,0 @@
using domain.Service;
using domain.UseCase;
using domain.Request;
using domain.Service;
using Microsoft.AspNetCore.Mvc;
using Presence.Api.Response;
namespace Presence.Api.Controllers
{
[ApiController]
[Route("[controller]/api")]
public class GroupController: ControllerBase
{
private readonly IGroupUseCase _groupService;
public GroupController(IGroupUseCase groupService)
{
_groupService = groupService;
}
[HttpGet("/group")]
public async Task<ActionResult<GroupResponse>> GetAllGroups()
{
var result = _groupService
.GetGroupsWithStudents();
var response = result
.Select(group => new GroupResponse {
Id = group.Id,
Name = group.Name,
Users = group.Users.Select(user => new UserResponse {
Guid = user.Guid,
Name = user.Name
}).ToList(),
}).ToList();
return Ok(new GroupResponse());
}
[HttpPost("/admin/{groupId}/students")]
public void AddGroup(int groupId, [FromBody] AddGroupRequest addGroupRequest)
{
Console.WriteLine(groupId);
_groupService.AddGroup(addGroupRequest);
}
}
}

View File

@ -1,33 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace Presence.Api.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View File

@ -1,20 +0,0 @@
using data;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Presence.Api.Controllers;
namespace Presence.Api.Extensions
{
public static class ServiceCollectionsExtension
{
public static void AddCommomService(this IServiceCollection services)
{
services
.AddDbContext<RemoteDatabaseContext>()
.AddScoped<IGroupRepository, SQLGroupRepository>()
.AddScoped<IGroupUseCase, GroupService>()
.AddScoped<GroupController>();
}
}
}

View File

@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\domain\domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Request\" />
<Folder Include="ServiceCollectionsExtension\" />
</ItemGroup>
</Project>

View File

@ -1,6 +0,0 @@
@Presence.Api_HostAddress = http://localhost:5028
GET {{Presence.Api_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -1,29 +0,0 @@
using Presence.Api.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCommomService();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@ -1,41 +0,0 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:32613",
"sslPort": 44302
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5028",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7098;http://localhost:5028",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -1,9 +0,0 @@
namespace Presence.Api.Response
{
public class GroupResponse
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<UserResponse>? Users { get; set; } = null;
}
}

View File

@ -1,8 +0,0 @@
namespace Presence.Api.Response
{
public class UserResponse
{
public Guid Guid { get; set; }
public string Name { get; set; }
}
}

View File

@ -1,13 +0,0 @@
namespace Presence.Api
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -1,9 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -6,5 +6,6 @@
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
</Application.Styles>
</Application>

View File

@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Data.DAO;
using Microsoft.Extensions.DependencyInjection;
using Presence.Desktop.DI;
using Presence.Desktop.ViewModels;
@ -18,15 +19,15 @@ namespace Presence.Desktop
public override void OnFrameworkInitializationCompleted()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddCommonService();
serviceCollection.AddPresenceService();
var services = serviceCollection.BuildServiceProvider();
var mainViewModel = services.GetRequiredService<GroupViewModel>();
var maimViewModel = services.GetRequiredService<PresenceViewModel>();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow()
desktop.MainWindow = new PresenceView()
{
DataContext = new MainWindowViewModel(services),
DataContext = maimViewModel,
};
}

View File

@ -21,7 +21,20 @@ namespace Presence.Desktop.DI
.AddDbContext<RemoteDatabaseContext>()
.AddSingleton<IGroupRepository, SQLGroupRepository>()
.AddTransient<IGroupUseCase, GroupService>()
.AddSingleton<SQLPresenceRepository>()
.AddTransient<PresenceService>()
.AddTransient<GroupViewModel>();
}
public static void AddPresenceService(this IServiceCollection collection)
{
collection
.AddDbContext<RemoteDatabaseContext>()
.AddSingleton<IGroupRepository, SQLGroupRepository>()
.AddTransient<IGroupUseCase, GroupService>()
.AddSingleton<SQLPresenceRepository>()
.AddTransient<PresenceService>()
.AddTransient<PresenceViewModel>();
}
}
}

View File

@ -1,17 +1,16 @@
using Avalonia.Controls;
using ReactiveUI;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presence.Desktop.Models
namespace Presense.Desktop.Models
{
public class GroupPresenter
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<UserPresenter>? users { get; set; } = null;
public int GroupId { get; set; }
public string GroupName { get; set; } = string.Empty;
public List<StudentPresenter>? Students { get; set; } = null;
public List<SubjectPresenter> Subjects { get; set; } = new();
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Data.DAO;
using Presense.Desktop.Models;
namespace Presence.Desktop.Models
{
public class GroupSubjectPresenter
{
public int GroupSubjectId { get; set; }
public int SemesterId { get; set; }
public SemesterPresenter Semester { get; set; }
public GroupPresenter Group { get; set; }
public SubjectPresenter Subject { get; set; }
public List<Attendance> Attendances { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Presense.Desktop.Models;
namespace Presence.Desktop.Models
{
public class PresencePresenter
{
public int AttendanceId { get; set; }
public DateOnly Date { get; set; }
public string Subject { get; set; }
public string StudentFullName { get; set; }
public string GroupName { get; set; }
public string PresenceType { get; set; }
public int LessonNumber { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presence.Desktop.Models
{
public class SemesterPresenter
{
public int SemesterId { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public List<GroupSubjectPresenter> GroupSubjects { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presense.Desktop.Models
{
public class StudentPresenter
{
public int Id { get; set; }
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string Patronymic { get; set; } = string.Empty;
// Ссылка на группу, к которой относится студент
public GroupPresenter? Group { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using domain.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presense.Desktop.Models
{
public class SubjectPresenter
{
public int SubjectId { get; set; }
public string SubjectName { get; set; }
public int GroupId { get; set; }
public GroupEntity Group { get; set; }
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presence.Desktop.Models
{
public class UserPresenter
{
public Guid Guid { get; set; }
public string Name { get; set; }
public GroupPresenter Group { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using Data.DAO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presence.Desktop.Models
{
public class VisitPresenter
{
public int VisitId { get; set; }
public string VisitName { get; set; }
public List<Attendance> Attendances { get; set; }
}
}

View File

@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.2.1" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.1" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.1">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\data\data.csproj" />
<ProjectReference Include="..\domain\domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
</Project>

View File

@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.1" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.2.1" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.1" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1" />

View File

@ -7,13 +7,24 @@ using ReactiveUI;
namespace Presence.Desktop
{
public class ViewLocator : IViewLocator
public class ViewLocator : IDataTemplate
{
public IViewFor? ResolveView<T>(T? viewModel, string? contract = null) => viewModel switch
public Control Build(object data)
{
GroupViewModel groupViewModel => new GroupView { DataContext = groupViewModel },
PresenceViewModel presenceViewModel => new PresenceView { DataContext = presenceViewModel },
_ => throw new ArgumentOutOfRangeException(nameof(viewModel))
};
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object data)
{
return data is ViewModelBase;
}
}
}

View File

@ -1,100 +1,290 @@
using domain.UseCase;
using Presence.Desktop.Models;
using Avalonia.Controls;
using domain.Request;
using domain.UseCase;
using Presense.Desktop.Models;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Presence.Desktop.ViewModels
{
public class GroupViewModel : ViewModelBase, IRoutableViewModel
public class GroupViewModel : ViewModelBase
{
public ICommand OpenFileDialog { get; }
public Interaction<string?, string?> SelectFileInteraction => _SelectFileInteraction;
public readonly Interaction<string?, string?> _SelectFileInteraction;
private string? _selectedFile;
public string? SelectedFile
{
get => _selectedFile;
set => this.RaiseAndSetIfChanged(ref _selectedFile, value);
}
private readonly IGroupUseCase _groupService;
private readonly List<GroupPresenter> _groupPresentersDataSource = new List<GroupPresenter>();
private readonly List<GroupPresenter> _groupPresentersDataSource = new();
private ObservableCollection<GroupPresenter> _groups;
public ObservableCollection<GroupPresenter> Groups => _groups;
private GroupPresenter? _selectedGroupItem;
public GroupPresenter? SelectedGroupItem
{
get => _selectedGroupItem;
set => this.RaiseAndSetIfChanged(ref _selectedGroupItem, value);
set
{
if (_selectedGroupItem != value)
{
_selectedGroupItem = value;
this.RaisePropertyChanged();
UpdateStudents();
}
}
}
private GroupPresenter? _selectedGroupItem;
private ObservableCollection<StudentPresenter> _students;
public ObservableCollection<StudentPresenter> Students => _students;
private IGroupUseCase _groupUseCase;
public ObservableCollection<UserPresenter> Users { get => _users; }
public ObservableCollection<UserPresenter> _users;
public GroupViewModel() : this(null!) { }
public GroupViewModel(IGroupUseCase groupUseCase)
{
_groupUseCase = groupUseCase;
_SelectFileInteraction = new Interaction<string?, string?>();
OpenFileDialog = ReactiveCommand.CreateFromTask(SelectFile);
_users = new ObservableCollection<UserPresenter>();
RefreshGroups();
this.WhenAnyValue(vm => vm.SelectedGroupItem)
.Subscribe(_ =>
{
RefreshGroups();
SetUsers();
});
_groupService = groupUseCase;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
ImportStudentsCommand = ReactiveCommand.CreateFromTask(ImportStudentsAsync);
LoadGroupsAndStudents();
_students = new ObservableCollection<StudentPresenter>();
RemoveAllStudentsCommand = ReactiveCommand.Create(RemoveAllStudents);
RemoveSelectedStudentsCommand = ReactiveCommand.Create(RemoveSelectedStudents);
}
private void SetUsers()
private void LoadGroupsAndStudents()
{
if (SelectedGroupItem == null) return;
Users.Clear();
var group = _groups.First(it => it.Id == SelectedGroupItem.Id);
if (group.users == null) return;
foreach (var item in group.users)
foreach (var groupEntity in _groupService.GetGroupsWithStudents())
{
Users.Add(item);
}
}
private void RefreshGroups()
{
_groupPresentersDataSource.Clear();
foreach (var item in _groupUseCase.GetGroupsWithStudents())
{
GroupPresenter groupPresenter = new GroupPresenter
var groupPresenter = new GroupPresenter
{
Id = item.Id,
Name = item.Name,
users = item.Users?.Select(user => new UserPresenter
GroupId = groupEntity.GroupId,
GroupName = groupEntity.GroupName,
Students = groupEntity.Students?.Select(student => new StudentPresenter
{
Name = user.Name,
Guid = user.Guid,
Group = new GroupPresenter { Id = item.Id, Name = item.Name }
}
).ToList()
Id = student.Id,
FirstName = student.FirstName,
LastName = student.LastName,
Patronymic = student.Patronymic,
Group = null
}).ToList(),
Subjects = groupEntity.Subjects.Select(subject => new SubjectPresenter
{
SubjectId = subject.SubjectId,
SubjectName = subject.SubjectName
}).ToList()
};
foreach (var student in groupPresenter.Students ?? Enumerable.Empty<StudentPresenter>())
{
student.Group = groupPresenter;
}
_groupPresentersDataSource.Add(groupPresenter);
}
_groups = new ObservableCollection<GroupPresenter>(_groupPresentersDataSource);
}
private async Task SelectFile()
private void UpdateStudents()
{
Console.WriteLine("clock");
SelectedFile = await _SelectFileInteraction.Handle("Chose csv file");
if (SelectedGroupItem?.Students == null) return;
Students.Clear();
foreach (var student in SelectedGroupItem.Students)
{
Students.Add(student);
}
}
private readonly string[] _sortingOptions = new[]
{
"Без сортировки",
"Фамилии (по возрастанию)",
"Фамилии (по убыванию)"
};
public string[] SortingOptions => _sortingOptions;
private string? _selectedSortingOption;
public string? SelectedSortingOption
{
get => _selectedSortingOption;
set
{
this.RaiseAndSetIfChanged(ref _selectedSortingOption, value);
ApplySorting();
}
}
private void ApplySorting()
{
if (SelectedGroupItem?.Students == null) return;
IEnumerable<StudentPresenter> sortedStudents = SelectedSortingOption switch
{
"Фамилии (по возрастанию)" => SelectedGroupItem.Students.OrderBy(s => s.LastName),
"Фамилии (по убыванию)" => SelectedGroupItem.Students.OrderByDescending(s => s.LastName),
_ => SelectedGroupItem.Students
};
Students.Clear();
foreach (var student in sortedStudents)
{
Students.Add(student);
}
}
public ReactiveCommand<Unit, Unit> RemoveAllStudentsCommand { get; }
private void RemoveAllStudents()
{
if (SelectedGroupItem == null || SelectedGroupItem.Students == null) return;
_groupService.RemoveStudentsFromGroup(SelectedGroupItem.GroupId);
SelectedGroupItem.Students.Clear();
UpdateStudents();
LoadGroupsAndStudents();
}
public ReactiveCommand<Unit, Unit> ImportStudentsCommand { get; }
public async Task ImportStudentsAsync()
{
var dialog = new OpenFileDialog
{
Title = "Выберите файл CSV:",
Filters = new List<FileDialogFilter>
{
new FileDialogFilter { Name = "CSV Files", Extensions = { "csv" } }
}
};
var result = await dialog.ShowAsync(new Window());
if (result != null && result.Any())
{
var filePath = result.First();
if (SelectedGroupItem == null)
{
Console.WriteLine("Группа не выбрана.");
return;
}
try
{
var csvLines = File.ReadAllLines(filePath, Encoding.GetEncoding("windows-1251"));
var studentsToAdd = new List<AddStudentRequest>();
foreach (var line in csvLines)
{
var data = line.Split(';');
if (data.Length != 3)
{
Console.WriteLine($"Либо разделитель либо хз: {line}");
continue;
}
studentsToAdd.Add(new AddStudentRequest
{
FirstName = data[0],
LastName = data[1],
Patronymic = data[2]
});
}
if (studentsToAdd.Any())
{
_groupService.AddStudentsToGroup(SelectedGroupItem.GroupId, studentsToAdd);
foreach (var studentRequest in studentsToAdd)
{
var studentPresenter = new StudentPresenter
{
FirstName = studentRequest.FirstName,
LastName = studentRequest.LastName,
Patronymic = studentRequest.Patronymic,
Group = SelectedGroupItem
};
SelectedGroupItem.Students.Add(studentPresenter);
Students.Add(studentPresenter);
}
UpdateStudents();
LoadGroupsAndStudents();
}
else
{
Console.WriteLine("Проблема с данными.");
}
}
catch (Exception ex)
{
Console.WriteLine($"...: {ex.Message}");
}
}
}
private ObservableCollection<StudentPresenter> _selectedStudents = new();
public ObservableCollection<StudentPresenter> SelectedStudents
{
get => _selectedStudents;
set
{
this.RaiseAndSetIfChanged(ref _selectedStudents, value);
UpdateSelectionStates();
}
}
private bool _isSingleSelection;
public bool IsSingleSelection
{
get => _isSingleSelection;
set => this.RaiseAndSetIfChanged(ref _isSingleSelection, value);
}
private bool _isMultipleSelection;
public bool IsMultipleSelection
{
get => _isMultipleSelection;
set => this.RaiseAndSetIfChanged(ref _isMultipleSelection, value);
}
public void UpdateSelectionStates()
{
IsSingleSelection = SelectedStudents.Count == 1;
IsMultipleSelection = SelectedStudents.Count > 1;
}
public ReactiveCommand<Unit, Unit> RemoveSelectedStudentsCommand { get; }
private void RemoveSelectedStudents()
{
if (SelectedStudents == null || SelectedStudents.Count == 0) return;
var studentIds = SelectedStudents.Select(s => s.Id).ToList();
_groupService.RemoveStudentsFromGroupByIds(SelectedGroupItem.GroupId, studentIds);
foreach (var student in SelectedStudents.ToList())
{
SelectedGroupItem.Students.Remove(student);
Students.Remove(student);
}
UpdateStudents();
LoadGroupsAndStudents();
}
public string? UrlPathSegment { get; }
public IScreen HostScreen { get; }
}
}

View File

@ -1,16 +0,0 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using ReactiveUI;
namespace Presence.Desktop.ViewModels;
public class MainWindowViewModel : ViewModelBase, IScreen
{
public RoutingState Router { get; } = new RoutingState();
public MainWindowViewModel(IServiceProvider serviceProvider)
{
var groupViewModel = serviceProvider.GetRequiredService<GroupViewModel>();
Router.Navigate.Execute(groupViewModel);
}
}

View File

@ -1,9 +1,127 @@
using ReactiveUI;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using data.Repository;
using Data.DAO;
using domain.Service;
using domain.UseCase;
using Presence.Desktop.Models;
using Presense.Desktop.Models;
using ReactiveUI;
namespace Presence.Desktop.ViewModels;
public class PresenceViewModel : ViewModelBase, IRoutableViewModel
public class PresenceViewModel : ViewModelBase
{
public string? UrlPathSegment { get; }
public IScreen HostScreen { get; }
private readonly PresenceService _presenceService;
private readonly IGroupUseCase _groupService;
private ObservableCollection<PresencePresenter> _presences;
private ObservableCollection<GroupPresenter> _groups;
private GroupPresenter? _selectedGroupItem;
private string? _selectedAttendanceType;
public ObservableCollection<PresencePresenter> Presences
{
get => _presences;
set => this.RaiseAndSetIfChanged(ref _presences, value);
}
public ObservableCollection<GroupPresenter> Groups => _groups;
public GroupPresenter? SelectedGroupItem
{
get => _selectedGroupItem;
set
{
if (_selectedGroupItem != value)
{
_selectedGroupItem = value;
this.RaisePropertyChanged();
UpdatePresences();
}
}
}
public string[] AttendanceTypes { get; } = { "Был", "Не был", "Болеет" };
public string? SelectedAttendanceType
{
get => _selectedAttendanceType;
set
{
this.RaiseAndSetIfChanged(ref _selectedAttendanceType, value);
FilterPresences();
}
}
public PresenceViewModel(IGroupUseCase groupService, PresenceService presenceService)
{
_groupService = groupService;
_presenceService = presenceService;
_presences = new ObservableCollection<PresencePresenter>();
_groups = new ObservableCollection<GroupPresenter>();
LoadGroups();
}
private void LoadGroups()
{
var groups = _groupService.GetGroupsWithStudents(); // Получаем все группы
_groups.Clear();
foreach (var group in groups)
{
_groups.Add(new GroupPresenter { GroupId = group.GroupId, GroupName = group.GroupName });
}
// Выбираем первую группу по умолчанию
if (_groups.Any())
{
SelectedGroupItem = _groups.First();
}
}
private void UpdatePresences()
{
if (SelectedGroupItem == null) return;
var PresencesListHere = _presenceService.GetAttendancesRelativeWithGroup(SelectedGroupItem.GroupId);
ObservableCollection<PresencePresenter> convertedList = new ObservableCollection<PresencePresenter>();
_presences.Clear();
foreach (var attendance in PresencesListHere)
{
convertedList.Add(convertToPresencePresenter(attendance));
}
Presences = convertedList;
}
private PresencePresenter convertToPresencePresenter(Attendance attendance)
{
return new PresencePresenter()
{
AttendanceId = attendance.AttendanceId,
StudentFullName = $"{attendance.Student.FirstName} {attendance.Student.LastName} {attendance.Student.Patronymic}",
Subject = attendance.GroupSubject.Subject.SubjectName,
Date = attendance.Date,
GroupName = attendance.Group.GroupName,
LessonNumber = attendance.LessonNumber,
PresenceType = attendance.Visit.VisitName
};
}
private void FilterPresences()
{
if (string.IsNullOrEmpty(SelectedAttendanceType)) return;
UpdatePresences();
var filteredPresences = _presences.Where(a => a.PresenceType == SelectedAttendanceType).ToList();
_presences.Clear();
foreach (var attendance in filteredPresences)
{
_presences.Add(attendance);
}
}
}

View File

@ -1,4 +1,4 @@
<UserControl xmlns="https://github.com/avaloniaui"
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -8,38 +8,75 @@
x:DataType="vm:GroupViewModel">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:GroupViewModel/>
</Design.DataContext>
<DockPanel Background="MediumAquamarine">
<StackPanel DockPanel.Dock="Bottom">
<TextBlock Text="List ↑" HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Spacing="10"
HorizontalAlignment="Center"
DockPanel.Dock="Top"
Orientation="Horizontal">
<TextBlock Text="Combobox ->"/>
<ComboBox ItemsSource="{Binding Groups}" SelectedValue="{Binding SelectedGroupItem}">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
<TextBlock Text="Group:" VerticalAlignment="Center" Margin="0,0,5,0" />
<ComboBox ItemsSource="{Binding Groups}"
SelectedItem="{Binding SelectedGroupItem}"
Width="200" Margin="0,0,10,0">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding GroupName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Width="100" Command="{Binding OpenFileDialog}"/>
<ComboBox/>
<TextBlock Text="Sort:" VerticalAlignment="Center" Margin="0,0,5,0" />
<ComboBox ItemsSource="{Binding SortingOptions}"
SelectedItem="{Binding SelectedSortingOption}"
Width="200" Margin="0,0,10,0" />
<Button Content="Remove all"
Command="{Binding RemoveAllStudentsCommand}"
Margin="10,0,0,0" />
<Button Content="Import students"
Command="{Binding ImportStudentsCommand}"
Margin="10,0,0,0"/>
<Button Content="Swap to presences"
Click="SwapToPresences"
Margin="10,0,0,0"/>
</StackPanel>
<Border>
<ListBox Background="Bisque" ItemsSource="{Binding Users}">
<Border BorderBrush="Gray" BorderThickness="1" Margin="10" CornerRadius="5">
<ListBox ItemsSource="{Binding Students}"
SelectionMode="Multiple"
SelectedItems="{Binding SelectedStudents}"
SelectionChanged="SelectingItemsControl_OnSelectionChanged"
BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Text="{Binding FirstName}" FontWeight="Bold" Margin="0,0,10,0" />
<TextBlock Text="{Binding LastName}" FontWeight="Bold" Margin="0,0,10,0" />
<TextBlock Text="{Binding Patronymic}" FontWeight="Bold" Margin="0,0,10,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete selected students"
Command="{Binding RemoveSelectedStudentsCommand}"
IsVisible="{Binding IsMultipleSelection}"
/>
<MenuItem Header="Remove"
Command="{Binding RemoveSelectedStudentsCommand}"
IsVisible="{Binding IsSingleSelection}"
/>
<MenuItem Header="Edit"
IsVisible="{Binding IsSingleSelection}"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</Border>
</DockPanel>
</UserControl>
</Window>

View File

@ -1,37 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using Avalonia.ReactiveUI;
using data;
using data.Repository;
using domain.Service;
using Microsoft.Extensions.DependencyInjection;
using Presence.Desktop.DI;
using Presence.Desktop.ViewModels;
using ReactiveUI;
namespace Presence.Desktop.Views
{
public partial class GroupView : ReactiveUserControl<GroupViewModel>
public partial class GroupView : Window
{
public GroupView()
{
this.WhenActivated(action =>
{
action(ViewModel!.SelectFileInteraction.RegisterHandler(ShowFileDialog));
});
AvaloniaXamlLoader.Load(this);
InitializeComponent();
}
private async Task ShowFileDialog(IInteractionContext<string?, string?> context)
private void SelectingItemsControl_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
var topLevel = TopLevel.GetTopLevel(this);
var storageFile = await topLevel.StorageProvider.OpenFilePickerAsync(
new FilePickerOpenOptions()
if (DataContext is GroupViewModel viewModel)
{
viewModel.UpdateSelectionStates();
}
}
private void SwapToPresences(object? sender, RoutedEventArgs e)
{
try
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddPresenceService();
var services = serviceCollection.BuildServiceProvider();
var presenceViewModel = services.GetRequiredService<PresenceViewModel>();
var window = new PresenceView
{
AllowMultiple = false,
Title = context.Input
}
);
context.SetOutput(storageFile.First().Path.ToString());
DataContext = presenceViewModel
};
window.Show();
}
catch (Exception ex)
{
}
}
}
}

View File

@ -1,19 +0,0 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:app="clr-namespace:Presence.Desktop"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Presence.Desktop.ViewModels"
xmlns:reactiveUi="http://reactiveui.net"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Presence.Desktop.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Title="MainWindow">
<DockPanel>
<reactiveUi:RoutedViewHost Router="{Binding Router}" DockPanel.Dock="Right" Background="AliceBlue">
<reactiveUi:RoutedViewHost.ViewLocator>
<app:ViewLocator/>
</reactiveUi:RoutedViewHost.ViewLocator>
</reactiveUi:RoutedViewHost>
</DockPanel>
</Window>

View File

@ -1,18 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using Presence.Desktop.ViewModels;
using ReactiveUI;
namespace Presence.Desktop.Views;
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
public MainWindow()
{
this.WhenActivated(disposables => { });
AvaloniaXamlLoader.Load(this);
}
}

View File

@ -2,7 +2,48 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Presence.Desktop.ViewModels"
x:DataType="vm:PresenceViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Presence.Desktop.Views.PresenceView">
Welcome to Avalonia!
<StackPanel>
<!-- Верхняя панель с выбором группы и типа посещаемости -->
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock Text="Группа:" VerticalAlignment="Center" Margin="0,0,5,0" />
<ComboBox ItemsSource="{Binding Groups}"
SelectedItem="{Binding SelectedGroupItem}"
Width="200" Margin="0,0,10,0">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding GroupName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="Тип посещаемости:" VerticalAlignment="Center" Margin="0,0,5,0" />
<ComboBox ItemsSource="{Binding AttendanceTypes}"
SelectedItem="{Binding SelectedAttendanceType}"
Width="200" Margin="0,0,10,0"/>
</StackPanel>
<TextBlock Text="PRivatik"/>
<Border BorderThickness="2" Background="Aqua">
<DataGrid Margin="20" ItemsSource="{Binding Presences}"
AutoGenerateColumns="False" IsReadOnly="True"
GridLinesVisibility="All" Height="300" CanUserSortColumns="True"
BorderThickness="1" BorderBrush="Gray">
<DataGrid.Columns>
<DataGridTextColumn Header="Ф.И.О." Binding="{Binding StudentFullName}" />
<DataGridTextColumn Header="Предмет" Binding="{Binding Subject}" />
<DataGridTextColumn Header="Дата" Binding="{Binding Date}" />
<DataGridTextColumn Header="Группа" Binding="{Binding GroupName}" />
<DataGridTextColumn Header="Номер урока" Binding="{Binding LessonNumber}" />
<DataGridTextColumn Header="Тип посещаемости" Binding="{Binding PresenceType}" />
</DataGrid.Columns>
</DataGrid>
</Border>
<!-- DataGrid для отображения посещаемости -->
</StackPanel>
</UserControl>

View File

@ -2,16 +2,17 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using domain.Service;
using domain.UseCase;
using Presence.Desktop.ViewModels;
using ReactiveUI;
namespace Presence.Desktop.Views;
public partial class PresenceView : ReactiveUserControl<PresenceViewModel>
public partial class PresenceView : Window
{
public PresenceView()
{
this.WhenActivated(disposables => { });
AvaloniaXamlLoader.Load(this);
InitializeComponent();
}
}

View File

@ -22,24 +22,5 @@ namespace console_ui
Console.WriteLine("Enter group name: ");
_groupService.AddGroup(new domain.Request.AddGroupRequest { Name = Console.ReadLine() });
}
public void AddGroupWithStudents()
{
Console.WriteLine("Enter group name: ");
AddGroupRequest addGroupRequest = new AddGroupRequest { Name = Console.ReadLine() };
List<AddStudentRequest> addStudentRequests = new List<AddStudentRequest>()
{
new AddStudentRequest{ StudentName = "StudentName1"},
new AddStudentRequest{ StudentName = "StudentName2"},
new AddStudentRequest{ StudentName = "StudentName3"},
new AddStudentRequest{ StudentName = "StudentName4"},
};
AddGroupWithStudentsRequest addGroupWithStudents = new AddGroupWithStudentsRequest
{
addGroupRequest = addGroupRequest,
addStudentRequests = addStudentRequests
};
_groupService.AddGroupWithStudents(addGroupWithStudents);
}
}
}

View File

@ -1,30 +1,30 @@
using console_ui;
using data;
using data.DAO;
using Data.DAO;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Microsoft.Extensions.DependencyInjection;
void printAllGroups(IGroupRepository groupRepository)
{
Console.WriteLine("Groups:");
foreach (var item in groupRepository.getAllGroup())
{
Console.WriteLine(item.Name);
}
}
//void printAllGroups(IGroupRepository groupRepository)
//{
// Console.WriteLine("Groups:");
// foreach (var item in groupRepository.getAllGroup())
// {
// Console.WriteLine(item.Name);
// }
//}
IServiceCollection serviceCollection = new ServiceCollection();
//IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection
.AddDbContext<RemoteDatabaseContext>()
.AddSingleton<IGroupRepository, SQLGroupRepository>()
.AddSingleton<IGroupUseCase, GroupService>()
.AddSingleton<GroupUI>();
//serviceCollection
// .AddDbContext<RemoteDatabaseContext>()
// .AddSingleton<IGroupRepository, SQLGroupRepository>()
// .AddSingleton<IGroupUseCase, GroupService>()
// .AddSingleton<GroupUI>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var groupUI = serviceProvider.GetService<GroupUI>();
groupUI?.AddGroup();
//var serviceProvider = serviceCollection.BuildServiceProvider();
//var groupUI = serviceProvider.GetService<GroupUI>();
//groupUI?.AddGroup();

View File

@ -1,320 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using data;
#nullable disable
namespace data.Migrations
{
[DbContext(typeof(RemoteDatabaseContext))]
[Migration("20241212071056_InitialCreate123")]
partial class InitialCreate123
{
/// <inheritdoc />
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("Data.DAO.Attendance", b =>
{
b.Property<int>("AttendanceId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("AttendanceId"));
b.Property<DateOnly>("Date")
.HasColumnType("date");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("GroupSubjectId")
.HasColumnType("integer");
b.Property<int>("LessonNumber")
.HasColumnType("integer");
b.Property<int>("StudentId")
.HasColumnType("integer");
b.Property<int>("VisitId")
.HasColumnType("integer");
b.HasKey("AttendanceId");
b.HasIndex("GroupId");
b.HasIndex("GroupSubjectId");
b.HasIndex("StudentId");
b.HasIndex("VisitId");
b.ToTable("Attendances");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Property<int>("GroupId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupId"));
b.Property<string>("GroupName")
.IsRequired()
.HasColumnType("text");
b.HasKey("GroupId");
b.ToTable("Groups");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Property<int>("GroupSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupSubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("SemesterId")
.HasColumnType("integer");
b.Property<int>("SubjectId")
.HasColumnType("integer");
b.HasKey("GroupSubjectId");
b.HasIndex("GroupId");
b.HasIndex("SemesterId");
b.HasIndex("SubjectId");
b.ToTable("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Property<int>("SemesterId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SemesterId"));
b.Property<DateTime>("EndTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("StartTime")
.HasColumnType("timestamp with time zone");
b.HasKey("SemesterId");
b.ToTable("Semesters");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Property<int>("StudentId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("StudentId"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.HasColumnType("text");
b.HasKey("StudentId");
b.HasIndex("GroupId");
b.ToTable("Students");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Property<int>("SubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("SubjectName")
.IsRequired()
.HasColumnType("text");
b.HasKey("SubjectId");
b.HasIndex("GroupId");
b.ToTable("Subjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Property<int>("VisitId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("VisitId"));
b.Property<string>("VisitName")
.IsRequired()
.HasColumnType("text");
b.HasKey("VisitId");
b.ToTable("Visits");
});
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.GroupSubject", "GroupSubject")
.WithMany("Attendances")
.HasForeignKey("GroupSubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Student", "Student")
.WithMany("Attendances")
.HasForeignKey("StudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Visit", "Visit")
.WithMany("Attendances")
.HasForeignKey("VisitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("GroupSubject");
b.Navigation("Student");
b.Navigation("Visit");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("GroupSubjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Semester", "Semester")
.WithMany("GroupSubjects")
.HasForeignKey("SemesterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Subject", "Subject")
.WithMany("GroupSubjects")
.HasForeignKey("SubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("Semester");
b.Navigation("Subject");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Students")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Subjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Navigation("GroupSubjects");
b.Navigation("Students");
b.Navigation("Subjects");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Navigation("Attendances");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,243 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate123 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Groups",
columns: table => new
{
GroupId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
GroupName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Groups", x => x.GroupId);
});
migrationBuilder.CreateTable(
name: "Semesters",
columns: table => new
{
SemesterId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
StartTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
EndTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Semesters", x => x.SemesterId);
});
migrationBuilder.CreateTable(
name: "Visits",
columns: table => new
{
VisitId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
VisitName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Visits", x => x.VisitId);
});
migrationBuilder.CreateTable(
name: "Students",
columns: table => new
{
StudentId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
FirstName = table.Column<string>(type: "text", nullable: false),
LastName = table.Column<string>(type: "text", nullable: false),
Patronymic = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Students", x => x.StudentId);
table.ForeignKey(
name: "FK_Students_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Subjects",
columns: table => new
{
SubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SubjectName = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Subjects", x => x.SubjectId);
table.ForeignKey(
name: "FK_Subjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GroupSubjects",
columns: table => new
{
GroupSubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SemesterId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
SubjectId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GroupSubjects", x => x.GroupSubjectId);
table.ForeignKey(
name: "FK_GroupSubjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Semesters_SemesterId",
column: x => x.SemesterId,
principalTable: "Semesters",
principalColumn: "SemesterId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Subjects_SubjectId",
column: x => x.SubjectId,
principalTable: "Subjects",
principalColumn: "SubjectId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Attendances",
columns: table => new
{
AttendanceId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Date = table.Column<DateOnly>(type: "date", nullable: false),
GroupSubjectId = table.Column<int>(type: "integer", nullable: false),
StudentId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
VisitId = table.Column<int>(type: "integer", nullable: false),
LessonNumber = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Attendances", x => x.AttendanceId);
table.ForeignKey(
name: "FK_Attendances_GroupSubjects_GroupSubjectId",
column: x => x.GroupSubjectId,
principalTable: "GroupSubjects",
principalColumn: "GroupSubjectId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Students_StudentId",
column: x => x.StudentId,
principalTable: "Students",
principalColumn: "StudentId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Visits_VisitId",
column: x => x.VisitId,
principalTable: "Visits",
principalColumn: "VisitId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupId",
table: "Attendances",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupSubjectId",
table: "Attendances",
column: "GroupSubjectId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_StudentId",
table: "Attendances",
column: "StudentId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_VisitId",
table: "Attendances",
column: "VisitId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_GroupId",
table: "GroupSubjects",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SemesterId",
table: "GroupSubjects",
column: "SemesterId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SubjectId",
table: "GroupSubjects",
column: "SubjectId");
migrationBuilder.CreateIndex(
name: "IX_Students_GroupId",
table: "Students",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Subjects_GroupId",
table: "Subjects",
column: "GroupId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Attendances");
migrationBuilder.DropTable(
name: "GroupSubjects");
migrationBuilder.DropTable(
name: "Students");
migrationBuilder.DropTable(
name: "Visits");
migrationBuilder.DropTable(
name: "Semesters");
migrationBuilder.DropTable(
name: "Subjects");
migrationBuilder.DropTable(
name: "Groups");
}
}
}

View File

@ -1,320 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using data;
#nullable disable
namespace data.Migrations
{
[DbContext(typeof(RemoteDatabaseContext))]
[Migration("20241212071851_InitialCreate2")]
partial class InitialCreate2
{
/// <inheritdoc />
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("Data.DAO.Attendance", b =>
{
b.Property<int>("AttendanceId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("AttendanceId"));
b.Property<DateOnly>("Date")
.HasColumnType("date");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("GroupSubjectId")
.HasColumnType("integer");
b.Property<int>("LessonNumber")
.HasColumnType("integer");
b.Property<int>("StudentId")
.HasColumnType("integer");
b.Property<int>("VisitId")
.HasColumnType("integer");
b.HasKey("AttendanceId");
b.HasIndex("GroupId");
b.HasIndex("GroupSubjectId");
b.HasIndex("StudentId");
b.HasIndex("VisitId");
b.ToTable("Attendances");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Property<int>("GroupId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupId"));
b.Property<string>("GroupName")
.IsRequired()
.HasColumnType("text");
b.HasKey("GroupId");
b.ToTable("Groups");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Property<int>("GroupSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupSubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("SemesterId")
.HasColumnType("integer");
b.Property<int>("SubjectId")
.HasColumnType("integer");
b.HasKey("GroupSubjectId");
b.HasIndex("GroupId");
b.HasIndex("SemesterId");
b.HasIndex("SubjectId");
b.ToTable("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Property<int>("SemesterId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SemesterId"));
b.Property<DateTime>("EndTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("StartTime")
.HasColumnType("timestamp with time zone");
b.HasKey("SemesterId");
b.ToTable("Semesters");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Property<int>("StudentId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("StudentId"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.HasColumnType("text");
b.HasKey("StudentId");
b.HasIndex("GroupId");
b.ToTable("Students");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Property<int>("SubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("SubjectName")
.IsRequired()
.HasColumnType("text");
b.HasKey("SubjectId");
b.HasIndex("GroupId");
b.ToTable("Subjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Property<int>("VisitId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("VisitId"));
b.Property<string>("VisitName")
.IsRequired()
.HasColumnType("text");
b.HasKey("VisitId");
b.ToTable("Visits");
});
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.GroupSubject", "GroupSubject")
.WithMany("Attendances")
.HasForeignKey("GroupSubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Student", "Student")
.WithMany("Attendances")
.HasForeignKey("StudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Visit", "Visit")
.WithMany("Attendances")
.HasForeignKey("VisitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("GroupSubject");
b.Navigation("Student");
b.Navigation("Visit");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("GroupSubjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Semester", "Semester")
.WithMany("GroupSubjects")
.HasForeignKey("SemesterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Subject", "Subject")
.WithMany("GroupSubjects")
.HasForeignKey("SubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("Semester");
b.Navigation("Subject");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Students")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Subjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Navigation("GroupSubjects");
b.Navigation("Students");
b.Navigation("Subjects");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Navigation("Attendances");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,243 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Groups",
columns: table => new
{
GroupId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
GroupName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Groups", x => x.GroupId);
});
migrationBuilder.CreateTable(
name: "Semesters",
columns: table => new
{
SemesterId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
StartTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
EndTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Semesters", x => x.SemesterId);
});
migrationBuilder.CreateTable(
name: "Visits",
columns: table => new
{
VisitId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
VisitName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Visits", x => x.VisitId);
});
migrationBuilder.CreateTable(
name: "Students",
columns: table => new
{
StudentId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
FirstName = table.Column<string>(type: "text", nullable: false),
LastName = table.Column<string>(type: "text", nullable: false),
Patronymic = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Students", x => x.StudentId);
table.ForeignKey(
name: "FK_Students_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Subjects",
columns: table => new
{
SubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SubjectName = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Subjects", x => x.SubjectId);
table.ForeignKey(
name: "FK_Subjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GroupSubjects",
columns: table => new
{
GroupSubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SemesterId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
SubjectId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GroupSubjects", x => x.GroupSubjectId);
table.ForeignKey(
name: "FK_GroupSubjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Semesters_SemesterId",
column: x => x.SemesterId,
principalTable: "Semesters",
principalColumn: "SemesterId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Subjects_SubjectId",
column: x => x.SubjectId,
principalTable: "Subjects",
principalColumn: "SubjectId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Attendances",
columns: table => new
{
AttendanceId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Date = table.Column<DateOnly>(type: "date", nullable: false),
GroupSubjectId = table.Column<int>(type: "integer", nullable: false),
StudentId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
VisitId = table.Column<int>(type: "integer", nullable: false),
LessonNumber = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Attendances", x => x.AttendanceId);
table.ForeignKey(
name: "FK_Attendances_GroupSubjects_GroupSubjectId",
column: x => x.GroupSubjectId,
principalTable: "GroupSubjects",
principalColumn: "GroupSubjectId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Students_StudentId",
column: x => x.StudentId,
principalTable: "Students",
principalColumn: "StudentId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Visits_VisitId",
column: x => x.VisitId,
principalTable: "Visits",
principalColumn: "VisitId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupId",
table: "Attendances",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupSubjectId",
table: "Attendances",
column: "GroupSubjectId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_StudentId",
table: "Attendances",
column: "StudentId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_VisitId",
table: "Attendances",
column: "VisitId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_GroupId",
table: "GroupSubjects",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SemesterId",
table: "GroupSubjects",
column: "SemesterId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SubjectId",
table: "GroupSubjects",
column: "SubjectId");
migrationBuilder.CreateIndex(
name: "IX_Students_GroupId",
table: "Students",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Subjects_GroupId",
table: "Subjects",
column: "GroupId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Attendances");
migrationBuilder.DropTable(
name: "GroupSubjects");
migrationBuilder.DropTable(
name: "Students");
migrationBuilder.DropTable(
name: "Visits");
migrationBuilder.DropTable(
name: "Semesters");
migrationBuilder.DropTable(
name: "Subjects");
migrationBuilder.DropTable(
name: "Groups");
}
}
}

View File

@ -12,8 +12,8 @@ using data;
namespace data.Migrations
{
[DbContext(typeof(RemoteDatabaseContext))]
[Migration("20241212072022_InitialCreate2")]
partial class InitialCreate2
[Migration("20241212072957_WorkWithData")]
partial class WorkWithData
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)

View File

@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate2 : Migration
public partial class WorkWithData : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Data.DAO;
using Microsoft.EntityFrameworkCore;
namespace data.Repository
{
public class SQLPresenceRepository
{
private readonly RemoteDatabaseContext _dbContext;
public SQLPresenceRepository(RemoteDatabaseContext remoteDatabaseContext)
{
_dbContext = remoteDatabaseContext;
}
public IEnumerable<Attendance> GetAllPresences()
{
var result = _dbContext.Attendances
.Include(attendance => attendance.GroupSubject)
.ThenInclude(groupSubject => groupSubject.Subject)
.Include(groupSubject => groupSubject.GroupSubject.Semester)
.Include(attendance => attendance.Student)
.Include(attendance => attendance.Group)
.Include(attendance => attendance.Visit);
return result;
}
}
}

View File

@ -6,11 +6,6 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Migrations\**" />
<EmbeddedResource Remove="Migrations\**" />
<None Remove="Migrations\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />

View File

@ -3,14 +3,17 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Domain.Entity;
namespace domain.Entity
{
public class GroupEntity
{
public int Id { get; set; }
public string Name { get; set; }
public List<UserEntity> Users { get; set; } = null;
public int GroupId { get; set; }
public string GroupName { get; set; }
public IEnumerable<StudentEntity>? Students { get; set; } = null;
public List<SubjectEntity> Subjects { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using domain.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.Entity
{
public class StudentEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Patronymic { get; set; }
public GroupEntity Group { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using domain.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.Entity
{
public class SubjectEntity
{
public int SubjectId { get; set; }
public string SubjectName { get; set; }
public int GroupId { get; set; }
public GroupEntity Group { get; set; }
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Entity
{
public class UserEntity
{
public Guid Guid { get; set; }
public string Name { get; set; }
public GroupEntity Group { get; set; }
}
}

View File

@ -8,6 +8,8 @@ namespace domain.Request
{
public class AddStudentRequest
{
public string StudentName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Patronymic { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.Request
{
public class AddSubjectRequest
{
public string SubjectName { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.Request
{
public class AttendanceRequest
{
public DateOnly Date { get; set; }
public string Subject { get; set; }
public int LessonNumber { get; set; }
public int StudentId { get; set; }
public int TypeAttendance { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.Request
{
public class AttendanceUpdateRequest
{
public DateTime Date { get; set; }
public int LessonNumber { get; set; }
public int StudentId { get; set; }
public int NewTypeAttendance { get; set; }
}
}

View File

@ -1,79 +1,207 @@
using data.DAO;
using data.Repository;
using data.Repository;
using Data.DAO;
using domain.Entity;
using domain.Request;
using domain.UseCase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Domain.Entity;
namespace domain.Service
{
public class GroupService : IGroupUseCase
{
private readonly IGroupRepository _groupRepository;
public GroupService(IGroupRepository groupRepository)
public GroupService(IGroupRepository repositoryGroup)
{
_groupRepository = groupRepository;
}
public void AddGroup(AddGroupRequest addGroupRequest)
{
_groupRepository.addGroup(new data.DAO.GroupDAO { Name = addGroupRequest.Name });
_groupRepository = repositoryGroup;
}
public void AddGroupWithStudents(AddGroupWithStudentsRequest addGroupWithStudents)
public void AddGroup(AddGroupRequest addGroupRequest)
{
GroupDAO groupDAO = new GroupDAO() { Name = addGroupWithStudents.addGroupRequest.Name };
List<UserDAO> users = addGroupWithStudents.addStudentRequests
.Select(it => new UserDAO { Name = it.StudentName })
_groupRepository.AddGroup(new Group { GroupName = addGroupRequest.Name });
}
public void AddGroupWithStudents(AddGroupWithStudentsRequest addGroupWithStudent)
{
Group groups = new Group { GroupName = addGroupWithStudent.addGroupRequest.Name };
List<Student> students = addGroupWithStudent
.addStudentRequests
.Select(it => new Student
{
FirstName = it.FirstName,
LastName = it.LastName,
Patronymic = it.Patronymic
})
.ToList();
_groupRepository.addGroupWithStudents(groupDAO, users);
_groupRepository.addGroupWithStudent(groups, students);
}
public void AddStudentsToGroup(int groupId, List<AddStudentRequest> students)
{
var group = _groupRepository.GetGroupById(groupId);
if (group == null)
{
throw new KeyNotFoundException($"Группа с ID {groupId} не найдена.");
}
var studentEntities = students.Select(student => new Student
{
FirstName = student.FirstName,
LastName = student.LastName,
Patronymic = student.Patronymic,
GroupId = groupId
}).ToList();
_groupRepository.AddStudentsToGroup(studentEntities);
}
public void DeleteGroup(int groupId)
{
_groupRepository.DeleteGroup(groupId);
}
public IEnumerable<GroupEntity> GetGroupsWithStudents()
{
return _groupRepository.getAllGroup().Select(
group => new GroupEntity()
return _groupRepository.GetAllGroup().Select(
group => new GroupEntity
{
Id = group.Id,
Name = group.Name,
Users = group.Users.Select(
user => new UserEntity
GroupId = group.GroupId,
GroupName = group.GroupName,
Students = group.Students.Select(
user => new StudentEntity
{
Guid = user.Guid,
Name = user.Name,
Id = user.StudentId,
FirstName = user.FirstName,
LastName = user.LastName,
Patronymic = user.Patronymic,
Group = new GroupEntity
{
Id = group.Id,
Name = group.Name,
GroupId = group.GroupId,
GroupName = group.GroupName,
}
}).ToList()
}).ToList(),
Subjects = group.GroupSubjects.Select(gs => new SubjectEntity
{
SubjectId = gs.Subject.SubjectId,
SubjectName = gs.Subject.SubjectName
}).ToList()
}).ToList();
}
public async Task<IEnumerable<GroupEntity>> GetGroupsWithStudentsAsync()
public List<SubjectEntity> GetSubjectsByGroupId(int groupId)
{
var result = await _groupRepository.getAllGroupAsync();
var group = _groupRepository.GetGroupWithSubjects(groupId);
if (group == null)
throw new KeyNotFoundException($"Группа с ID {groupId} не найдена.");
return result.Select(
group => new GroupEntity
{
Id = group.Id,
Name = group.Name,
Users = group.Users.Select(
user => new UserEntity
{
Guid = user.Guid,
Name = user.Name,
Group = new GroupEntity
{
Id = group.Id,
Name = group.Name,
}
}).ToList()
}).ToList();
return group.Subjects.Select(subject => new SubjectEntity
{
SubjectId = subject.SubjectId,
SubjectName = subject.SubjectName
}).ToList();
}
public Group GetGroupById(int groupId)
{
var group = _groupRepository.GetGroupById(groupId);
if (group == null)
{
throw new KeyNotFoundException($"Группа с ID {groupId} не найдена.");
}
return group;
}
public List<Subject> GetGroupSubjects(int groupId)
{
var subjects = _groupRepository.GetGroupSubjects(groupId);
if (subjects == null || subjects.Count == 0)
{
throw new KeyNotFoundException($"Предметы для группы с ID {groupId} не найдены.");
}
return subjects;
}
public bool AddSubjectToGroup(int groupId, string subjectName)
{
var subject = new Subject
{
SubjectName = subjectName,
};
return _groupRepository.AddSubjectToGroup(groupId, subject);
}
public void DeleteAllAttendances()
{
_groupRepository.DeleteAllAttendances();
}
public void DeleteAttendancesByGroup(int groupId)
{
_groupRepository.DeleteAttendancesByGroup(groupId);
}
public void AddAttendance(Attendance attendance)
{
if (attendance == null)
{
throw new ArgumentNullException(nameof(attendance));
}
_groupRepository.AddAttendance(attendance);
}
public Visit GetVisitById(int visitId)
{
return _groupRepository.GetVisitById(visitId);
}
public int GetGroupIdBySubjectName(string subjectName)
{
return _groupRepository.GetGroupIdBySubjectName(subjectName);
}
public Subject GetSubjectByName(string subjectName)
{
return _groupRepository.GetSubjectByName(subjectName);
}
public IEnumerable<Attendance> GetAttendances(int groupId, string? subject = null, DateTime? date = null, int? studentId = null)
{
return _groupRepository.GetAttendances(groupId, subject, date, studentId);
}
public Attendance GetAttendanceByDateStudentAndLesson(DateTime date, int studentId, int lessonNumber)
{
return _groupRepository.GetAttendanceByDateStudentAndLesson(date, studentId, lessonNumber);
}
public void UpdateAttendance(Attendance attendance)
{
_groupRepository.UpdateAttendance(attendance);
}
public void RemoveStudentsFromGroup(int groupId)
{
_groupRepository.RemoveStudentsFromGroup(groupId);
}
public void RemoveStudentsFromGroupByIds(int groupId, List<int> studentIds)
{
var group = _groupRepository.GetGroupById(groupId);
if (group == null)
{
throw new KeyNotFoundException($"Группа с ID {groupId} не найдена.");
}
_groupRepository.RemoveStudentsFromGroupByIds(groupId, studentIds);
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Data.DAO;
using data.Repository;
namespace domain.Service
{
public class PresenceService
{
private readonly SQLPresenceRepository _presenceRepository;
public PresenceService(SQLPresenceRepository presenceRepository)
{
_presenceRepository = presenceRepository;
}
public List<Attendance> GetAllAttendances()
{
return _presenceRepository.GetAllPresences().ToList();
}
public List<Attendance> GetAttendancesRelativeWithGroup(int groupId)
{
return _presenceRepository.GetAllPresences().Where(pres => pres.Group.GroupId == groupId).ToList();
}
}
}

View File

@ -1,5 +1,7 @@
using domain.Entity;
using Data.DAO;
using domain.Entity;
using domain.Request;
using Domain.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
@ -11,8 +13,47 @@ namespace domain.UseCase
public interface IGroupUseCase
{
public IEnumerable<GroupEntity> GetGroupsWithStudents();
public Task<IEnumerable<GroupEntity>> GetGroupsWithStudentsAsync();
public void AddGroup(AddGroupRequest addGroupRequest);
public void AddGroupWithStudents(AddGroupWithStudentsRequest addGroupWithStudents);
public void AddGroupWithStudents(AddGroupWithStudentsRequest addGroupWithStudent);
public void DeleteGroup(int groupId);
List<SubjectEntity> GetSubjectsByGroupId(int groupId);
public void AddStudentsToGroup(int groupId, List<AddStudentRequest> students);
public Group GetGroupById(int groupId);
List<Subject> GetGroupSubjects(int groupId);
bool AddSubjectToGroup(int groupId, string subjectName);
public void DeleteAllAttendances();
public void DeleteAttendancesByGroup(int groupId);
void AddAttendance(Attendance attendance);
Visit GetVisitById(int visitId);
Subject GetSubjectByName(string subjectName);
int GetGroupIdBySubjectName(string subjectName);
public IEnumerable<Attendance> GetAttendances(int groupId, string subject = null, DateTime? date = null, int? studentId = null);
public Attendance GetAttendanceByDateStudentAndLesson(DateTime date, int studentId, int lessonNumber);
public void UpdateAttendance(Attendance attendance);
void RemoveStudentsFromGroup(int groupId);
void RemoveStudentsFromGroupByIds(int groupId, List<int> studentIds);
}
}

View File

@ -9,12 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "data", "data\data.csproj",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "domain", "domain\domain.csproj", "{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Presence.Api", "Presence.Api\Presence.Api.csproj", "{0493354A-C0C0-49FC-A143-28F2268309E2}"
ProjectSection(ProjectDependencies) = postProject
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63} = {78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Presence.Desktop", "Presence.Desktop\Presence.Desktop.csproj", "{D646BC7E-8025-4985-AF9B-5E4474AD7F66}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Presence.Desktop", "Presence.Desktop\Presence.Desktop.csproj", "{D646BC7E-8025-4985-AF9B-5E4474AD7F66}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -34,10 +29,6 @@ Global
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}.Release|Any CPU.Build.0 = Release|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Release|Any CPU.Build.0 = Release|Any CPU
{D646BC7E-8025-4985-AF9B-5E4474AD7F66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D646BC7E-8025-4985-AF9B-5E4474AD7F66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D646BC7E-8025-4985-AF9B-5E4474AD7F66}.Release|Any CPU.ActiveCfg = Release|Any CPU