diff --git a/.gitignore b/.gitignore index 9491a2f..a515779 100644 --- a/.gitignore +++ b/.gitignore @@ -360,4 +360,8 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd + +docker-compose/ + +postgres-data/ \ No newline at end of file diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 9d780da..9a9a078 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -1,5 +1,4 @@ using MethodologyMain.Application.DTO; -using MethodTeams.Models; //using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; //using System.Security.Claims; @@ -7,10 +6,12 @@ using AuthMetodology.Infrastructure.Models; using Serilog.Events; using RabbitMqPublisher.Interface; +using Microsoft.AspNetCore.Cors; namespace MethodologyMain.API.Controllers { [ApiController] - [Route("api/[controller]")] + [EnableCors("AllowFrontend")] + [Route("api/main/[controller]")] public class TeamController : ControllerBase { private readonly ITeamService teamService; @@ -29,292 +30,207 @@ public async Task GetDummyData(CancellationToken cancellationToke { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/Team/dummy-data was called", + Message = "POST api/main/Team/dummy-data was called", TimeStamp = DateTime.UtcNow }, cancellationToken); string data = "Dataaa"; return Ok(data); } - // Создание команды - [HttpPost] - //[Authorize] - public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) + // Получение списка команд + [HttpGet] + public async Task>> GetTeamsAll(CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/Team was called", + Message = "GET api/main/Team was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена - var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); - return CreatedAtAction(nameof(GetTeam), new { id = team.Id }, team); - //try - //{ - - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} + var teams = await teamService.GetTeamAllAsync(token); + return Ok(teams); } // Получение информации о команде - [HttpGet("{id}")] - public async Task> GetTeam(Guid id, CancellationToken token) + [HttpGet("hackathon/{hackId}")] + public async Task>> GetTeamsForHackathon(Guid hackId, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "GET api/Team/id was called", + Message = "GET api/main/Team/hackathon/id was called", TimeStamp = DateTime.UtcNow }, token); - var team = await teamService.GetTeamByIdAsync(id, token); - return Ok(team); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} + var teams = await teamService.GetTeamForHackathonAsync(hackId, token); + return Ok(teams); } - // Удаление команды - [HttpDelete("{id}")] + // Создание команды + [HttpPost] //[Authorize] - public async Task DeleteTeam(Guid id, CancellationToken token) + public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "DELETE api/Team/id was called", + Message = "POST api/main/Team was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора - - await teamService.DeleteTeamAsync(id, currentUserId, token, isAdmin); - return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} + // Получение ID текущего пользователя из токена + var team = await teamService.CreateTeamAsync(dto, dto.CreatedBy, token); + return CreatedAtAction(nameof(GetTeamById), new { id = team.Id }, team); } - // Добавление пользователя в команду - [HttpPost("{id}/users")] - //[Authorize] - public async Task AddMember(Guid id, [FromBody] AddUserDto dto, CancellationToken token) + // Получение информации о команде + [HttpGet("{id}")] + public async Task> GetTeamById(Guid id, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/Team/id/members was called", + Message = "GET api/main/Team/id was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - await teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId, token); - return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} + var team = await teamService.GetTeamByIdAsync(id, token); + return Ok(team); } - // Удаление пользователя из команды - [HttpDelete("{id}/users/{userId}")] + // Добавление пользователя в команду + [HttpPost("{id}/users/{userId}")] //[Authorize] - public async Task RemoveMember(Guid id, Guid userId, CancellationToken token) + public async Task JoinMember(Guid id, Guid userId, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "DELETE api/Team/id/members/userId was called", + Message = "POST api/main/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - await teamService.RemoveUserFromTeamAsync(id, userId, currentUserId, token); + await teamService.JoinUserToTeamAsync(id, userId, token); return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} - } - - // Получение списка участников команды - [HttpGet("{id}/users")] - public async Task>> GetTeamMembers(Guid id, CancellationToken token) - { - _ = logPublishService.SendEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "GET api/Team/id/members was called", - TimeStamp = DateTime.UtcNow - }, token); - var members = await teamService.GetTeamMembersAsync(id, token); - return Ok(members); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} } - // Передача прав капитана - [HttpPut("{id}/captain")] + // Удаление пользователя из команды + [HttpDelete("{id}/users/{userId}")] //[Authorize] - public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto, CancellationToken token) + public async Task LeaveMember(Guid id, Guid userId, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "PUT api/Team/id/captain was called", + Message = "DELETE api/main/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - await teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId, token); + await teamService.LeaveUserFromTeamAsync(id, userId, token); return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} - } - - // Получение списка команд - [HttpGet] - public async Task>> GetTeamsAll(CancellationToken token) - { - _ = logPublishService.SendEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "GET api/Team was called", - TimeStamp = DateTime.UtcNow - }, token); - var teams = await teamService.GetTeamAllAsync(token); - return Ok(teams); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} } - //// Получение списка команд для события - //[HttpGet("event/{eventId}")] - //public async Task>> GetTeamsByEvent(Guid eventId) + //[HttpPut] + ////[Authorize] + //public async Task UpdateTeam([FromBody] UpdateTeamDto dto, CancellationToken token) //{ - // await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish // { // ServiceName = "Main service", // LogLevel = LogEventLevel.Information, - // Message = "GET api/Team/event/eventId was called", + // Message = "Update api/Team/id was called", // TimeStamp = DateTime.UtcNow - // }); - // var teams = await _teamService.GetTeamsByEventIdAsync(eventId); - // return Ok(teams); + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.UpdateTeamAsync(dto, currentUserId, token); + // return NoContent(); //} - //// Получение команды пользователя для конкретного события - //[HttpGet("event/{eventId}/user")] + //// Удаление команды + //[HttpDelete("{id}")] ////[Authorize] - //public async Task> GetUserTeamForEvent(Guid eventId) + //public async Task DeleteTeam(Guid id, CancellationToken token) //{ - // await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish // { // ServiceName = "Main service", // LogLevel = LogEventLevel.Information, - // Message = "GET api/Team/event/eventId/user was called", + // Message = "DELETE api/Team/id was called", // TimeStamp = DateTime.UtcNow - // }); + // }, token); // Guid currentUserId = GetCurrentUserId(); - // var team = await _teamService.GetUserTeamForEventAsync(currentUserId, eventId); - - // if (team == null) - // { - // return NotFound(); - // } + // bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора - // return Ok(team); + // await teamService.DeleteTeamAsync(id, currentUserId, token, isAdmin); + // return NoContent(); + //} - //try + //// Добавление пользователя в команду + //[HttpPost("{id}/users")] + ////[Authorize] + //public async Task AddMember(Guid id, [FromBody] AddUserDto dto, CancellationToken token) //{ - + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "POST api/Team/id/members was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId, token); + // return NoContent(); //} - //catch (Exception ex) + + //// Удаление пользователя из команды + //[HttpDelete("{id}/users/{userId}")] + ////[Authorize] + //public async Task RemoveMember(Guid id, Guid userId, CancellationToken token) //{ - // return BadRequest(ex.Message); + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "DELETE api/Team/id/members/userId was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.RemoveUserFromTeamAsync(id, userId, currentUserId, token); + // return NoContent(); //} + + //// Получение списка участников команды + //[HttpGet("{id}/users")] + //public async Task>> GetTeamMembers(Guid id, CancellationToken token) + //{ + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "GET api/Team/id/members was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // var members = await teamService.GetTeamMembersAsync(id, token); + // return Ok(members); //} + //// Передача прав капитана + //[HttpPut("{id}/captain")] + ////[Authorize] + //public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto, CancellationToken token) + //{ + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "PUT api/Team/id/captain was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId, token); + // return NoContent(); + //} // Вспомогательный метод для получения ID текущего пользователя //private int GetCurrentUserId() //{ @@ -322,9 +238,9 @@ public async Task>> GetTeamsAll(CancellationToken token) // var userIdClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier); // return int.Parse(userIdClaim.Value); //} - private Guid GetCurrentUserId() - { - return Guid.Parse("1"); - } + //private Guid GetCurrentUserId() + //{ + // return Guid.Parse("d5a492ca-9611-4fda-9ace-10ec38bb4d48"); + //} } } diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs new file mode 100644 index 0000000..7644283 --- /dev/null +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -0,0 +1,83 @@ +using MethodologyMain.Application.DTO; +using Microsoft.AspNetCore.Mvc; +using MethodologyMain.Application.Interface; +using AuthMetodology.Infrastructure.Models; +using Serilog.Events; +using RabbitMqPublisher.Interface; +using Microsoft.AspNetCore.Cors; + +namespace MethodologyMain.API.Controllers +{ + [ApiController] + [EnableCors("AllowFrontend")] + [Route("api/main/[controller]")] + public class UserController : ControllerBase + { + private readonly IUserService userService; + private readonly IRabbitMqPublisherBase logPublishService; + public UserController(IUserService userService, IRabbitMqPublisherBase logPublishService) + { + this.userService = userService; + this.logPublishService = logPublishService; + } + + [HttpGet] + public async Task>> GetUsers(CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/main/User was called", + TimeStamp = DateTime.UtcNow + }); + var users = await userService.GetUsersAllAsync(token); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(users); + } + + [HttpGet("{id}")] + public async Task> GetUsersById([FromRoute] Guid id, CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/main/User was called", + TimeStamp = DateTime.UtcNow + }); + var user = await userService.GetUserByIdAsync(id, token); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(user); + } + [HttpPost] + public async Task> CreateUser([FromBody] GetUserDto dto, CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "POST api/main/User was called", + TimeStamp = DateTime.UtcNow + }); + var user = await userService.CreateUserAsync(dto, token); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(user); + } + + [HttpPut] + public async Task UpdateUser([FromBody] GetUserDto dto, CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "PUT api/main/User was called", + TimeStamp = DateTime.UtcNow + }); + await userService.UpdateUserAsync(dto, token); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(); + } + } +} diff --git a/MethodologyMain.API/Dockerfile.original b/MethodologyMain.API/Dockerfile.original new file mode 100644 index 0000000..12a01a3 --- /dev/null +++ b/MethodologyMain.API/Dockerfile.original @@ -0,0 +1,30 @@ +# См. статью по ссылке https://aka.ms/customizecontainer, чтобы узнать как настроить контейнер отладки и как Visual Studio использует этот Dockerfile для создания образов для ускорения отладки. + +# Этот этап используется при запуске из VS в быстром режиме (по умолчанию для конфигурации отладки) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER $APP_UID +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + + +# Этот этап используется для сборки проекта службы +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["MethodTeams1/MethodTeams1.csproj", "MethodTeams1/"] +RUN dotnet restore "./MethodTeams1/MethodTeams1.csproj" +COPY . . +WORKDIR "/src/MethodTeams1" +RUN dotnet build "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# Этот этап используется для публикации проекта службы, который будет скопирован на последний этап +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +# Этот этап используется в рабочей среде или при запуске из VS в обычном режиме (по умолчанию, когда конфигурация отладки не используется) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "MethodTeams1.dll"] \ No newline at end of file diff --git a/MethodologyMain.API/Extensions/AuthExtensions.cs b/MethodologyMain.API/Extensions/AuthExtensions.cs index c65b833..ff86409 100644 --- a/MethodologyMain.API/Extensions/AuthExtensions.cs +++ b/MethodologyMain.API/Extensions/AuthExtensions.cs @@ -36,6 +36,17 @@ public static void AddApiAuthentication( } }; }); + services.AddCors(options => + { + options.AddPolicy("AllowFrontend", builder => + { + builder.WithOrigins("http://localhost:8083") + .AllowCredentials() + .AllowAnyHeader() + .AllowAnyMethod() + .WithExposedHeaders("Set-Cookie"); + }); + }); services.AddAuthorizationBuilder() //.AddPolicy("AdminOnly", policy => policy.RequireRole(nameof(UserRole.Admin))) .AddPolicy("BearerOnly", policy => { policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); policy.RequireAuthenticatedUser(); }); diff --git a/MethodologyMain.API/MethodologyMain.API.csproj b/MethodologyMain.API/MethodologyMain.API.csproj index f777033..1fb77ba 100644 --- a/MethodologyMain.API/MethodologyMain.API.csproj +++ b/MethodologyMain.API/MethodologyMain.API.csproj @@ -20,6 +20,8 @@ + + diff --git a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs index b758ea2..4964945 100644 --- a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs +++ b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs @@ -27,7 +27,7 @@ public async Task InvokeAsync(HttpContext context) { ServiceName = "Main service", LogLevel = LogEventLevel.Error, - Message = $"Exception was thrown.\nMessage: {ex.Message}\nSource: {ex.Source}", + Message = $"Exception was thrown.\nMessage: {ex.Message}, {ex.InnerException}\nSource: {ex.Source}", TimeStamp = DateTime.UtcNow }); diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 584abd4..b42589a 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -8,7 +8,6 @@ using MethodologyMain.Infrastructure.Services; using MethodologyMain.Persistence.Interfaces; using MethodologyMain.Persistence.Repository; -using MethodTeams.DTO; using System.Reflection; using MethodologyMain.Application.Profiles; using Microsoft.EntityFrameworkCore; @@ -20,9 +19,19 @@ using Microsoft.Extensions.Options; using RabbitMqListener.Interfaces; using MethodologyMain.Infrastructure.Listeners; +using MethodologyMain.Application.DTO; +using MethodologyMain.Logic.Entities; +using Serilog; var builder = WebApplication.CreateBuilder(args); +var logger = new LoggerConfiguration() + .WriteTo.Console() + .CreateLogger(); + +builder.Logging.ClearProviders(); +builder.Logging.AddSerilog(logger); + builder.Services.AddControllers(); builder.Services.AddControllers() .AddJsonOptions(options => @@ -35,10 +44,21 @@ var configuration = new MapperConfiguration(static cfg => { cfg.AddMaps(Assembly.GetExecutingAssembly()); + cfg.CreateMap() + .ForMember(dto => dto.CreatedBy, conf => conf.MapFrom(t => t.CaptainId)) + .ForMember(dto => dto.Members, conf => conf.MapFrom(t => t.Members.Select(s => s.User.UserName).ToList())) + .ForMember(dto => dto.Tags, conf => conf.MapFrom(t => t.Tags.Select(s => s.Tag.TagName).ToList())) + .ForMember(dto => dto.CreatedAt, conf => conf.MapFrom(t => t.TeamCreatedAt)); + cfg.CreateMap() + .ForMember(dto => dto.Tags, conf => conf.MapFrom(t => t.Tags.Select(s => s.Tag.TagName).ToList())) + .ForMember(dto => dto.Name, conf => conf.MapFrom(t => t.UserName)) + .ForMember(dto => dto.Bio, conf => conf.MapFrom(t => t.Education)); + cfg.AllowNullCollections = true; cfg.AddGlobalIgnore("Item"); } ); +configuration.AssertConfigurationIsValid(); IMapper mapper = configuration.CreateMapper(); builder.Services.AddSingleton(mapper); @@ -48,9 +68,12 @@ builder.Services.AddApiAuthentication(builder.Services.BuildServiceProvider().GetRequiredService>()); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddAutoMapper(typeof(TeamProfile).Assembly, typeof(TeamInfoDto).Assembly); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton, LogQueueService>(); @@ -70,6 +93,7 @@ app.UseHttpsRedirection(); +app.UseCors("AllowFrontend"); app.UseAuthorization(); app.UseAuthentication(); diff --git a/MethodologyMain.API/Properties/serviceDependencies.local.json b/MethodologyMain.API/Properties/serviceDependencies.local.json index 33703d5..6064c5b 100644 --- a/MethodologyMain.API/Properties/serviceDependencies.local.json +++ b/MethodologyMain.API/Properties/serviceDependencies.local.json @@ -1,3 +1,21 @@ { - "dependencies": {} + "dependencies": { + "rabbitmq1": { + "containerPorts": "5672:5672,15672:15672", + "secretStore": "LocalSecretsFile", + "containerName": "rabbitmq", + "containerImage": "rabbitmq:3-management-alpine", + "type": "rabbitmq.container", + "connectionId": "QueueConnection" + }, + "postgresql1": { + "containerPorts": "5432:5432", + "secretStore": "LocalSecretsFile", + "containerName": "postgresql", + "containerImage": "postgres", + "resourceId": null, + "type": "postgresql.container", + "connectionId": "ConnectionStrings:DatabaseConnection" + } + } } \ No newline at end of file diff --git a/MethodologyMain.Application/DTO/CreateTeamDto.cs b/MethodologyMain.Application/DTO/CreateTeamDto.cs index e442c52..592925a 100644 --- a/MethodologyMain.Application/DTO/CreateTeamDto.cs +++ b/MethodologyMain.Application/DTO/CreateTeamDto.cs @@ -2,8 +2,12 @@ { public class CreateTeamDto { + public Guid HackathonId { get; set; } public required string Name { get; set; } - public required string Description { get; set; } - public Guid EventId { get; set; } + public string Description { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public List Members { get; set; } = null!; + public required int MaxMembers { get; set; } + public Guid CreatedBy { get; set; } } } diff --git a/MethodologyMain.Application/DTO/GetHackathonDto.cs b/MethodologyMain.Application/DTO/GetHackathonDto.cs new file mode 100644 index 0000000..d1cba9e --- /dev/null +++ b/MethodologyMain.Application/DTO/GetHackathonDto.cs @@ -0,0 +1,23 @@ +using MethodologyMain.Logic.Models; + +namespace MethodologyMain.Application.DTO +{ + public class GetHackathonDto + { + public Guid Id { get; set; } + public required string Name { get; set; } + public string Description { get; set; } = string.Empty; + public required DateOnly StartDate { get; set; } + public required DateOnly EndDate { get; set; } + public string Location { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public string ImageUrl { get; set; } = string.Empty; + public string OrganizerName { get; set; } = string.Empty; + public string OrganizerLogo { get; set; } = string.Empty; + public TeamSize TeamSize { get; set; } = null!; + public string Website { get; set; } = string.Empty; + public List Prizes { get; set; } = null!; + public List Schedule { get; set; } = null!; + + } +} diff --git a/MethodologyMain.Application/DTO/GetTeamDto.cs b/MethodologyMain.Application/DTO/GetTeamDto.cs new file mode 100644 index 0000000..6816fd4 --- /dev/null +++ b/MethodologyMain.Application/DTO/GetTeamDto.cs @@ -0,0 +1,15 @@ +namespace MethodologyMain.Application.DTO +{ + public class GetTeamDto + { + public Guid Id { get; set; } + public Guid HackathonId { get; set; } + public required string Name { get; set; } + public string Description { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public List Members { get; set; } = null!; + public int MaxMembers { get; set; } + public Guid CreatedBy { get; set; } + public DateTime CreatedAt { get; set; } + } +} diff --git a/MethodologyMain.Application/DTO/GetUserDto.cs b/MethodologyMain.Application/DTO/GetUserDto.cs new file mode 100644 index 0000000..50cb669 --- /dev/null +++ b/MethodologyMain.Application/DTO/GetUserDto.cs @@ -0,0 +1,19 @@ + + +namespace MethodologyMain.Application.DTO +{ + public class GetUserDto + { + public Guid Id { get; set; } + public required string Name { get; set; } + public string Email { get; set; } = string.Empty; + public string Bio { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public string PhotoUrl { get; set; } = string.Empty; + public DateTime CreatedAt { get; set; } + public string Location { get; set; } = string.Empty; + public string Github { get; set; } = string.Empty; + public string Website { get; set; } = string.Empty; + public string Skills { get; set; } = string.Empty; + } +} diff --git a/MethodologyMain.Application/DTO/HackathonFilterDto.cs b/MethodologyMain.Application/DTO/HackathonFilterDto.cs index abb135c..ddaf5f0 100644 --- a/MethodologyMain.Application/DTO/HackathonFilterDto.cs +++ b/MethodologyMain.Application/DTO/HackathonFilterDto.cs @@ -10,9 +10,9 @@ public class HackathonFilterDto public int? MaxTeamSize { get; set; } - public DateTime? StartDateFrom { get; set; } + public DateOnly? StartDateFrom { get; set; } - public DateTime? StartDateTo { get; set; } + public DateOnly? StartDateTo { get; set; } public int Page { get; set; } = 1; public int PageSize { get; set; } = 10; } diff --git a/MethodologyMain.Application/DTO/TeamInfoDto.cs b/MethodologyMain.Application/DTO/TeamInfoDto.cs index 182b720..68d702a 100644 --- a/MethodologyMain.Application/DTO/TeamInfoDto.cs +++ b/MethodologyMain.Application/DTO/TeamInfoDto.cs @@ -1,11 +1,11 @@ -namespace MethodTeams.DTO +namespace MethodologyMain.Application.DTO { // DTO для информации о команде public class TeamInfoDto { public Guid Id { get; set; } - public string Name { get; set; } + public required string Name { get; set; } public string? Description { get; set; } public Guid CaptainId { get; set; } public Guid HackathonId { get; set; } diff --git a/MethodologyMain.Application/DTO/UpdateTeamDto.cs b/MethodologyMain.Application/DTO/UpdateTeamDto.cs new file mode 100644 index 0000000..8d30d8f --- /dev/null +++ b/MethodologyMain.Application/DTO/UpdateTeamDto.cs @@ -0,0 +1,10 @@ +namespace MethodologyMain.Application.DTO +{ + public class UpdateTeamDto + { + public Guid Id { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } + public Guid? HackathonId { get; set; } + } +} diff --git a/MethodologyMain.Application/DTO/UserInfoDto.cs b/MethodologyMain.Application/DTO/UserInfoDto.cs new file mode 100644 index 0000000..a76e30a --- /dev/null +++ b/MethodologyMain.Application/DTO/UserInfoDto.cs @@ -0,0 +1,17 @@ +using MethodologyMain.Logic.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Application.DTO +{ + public class UserInfoDto + { + public Guid Id { get; set; } + public required string UserName { get; set; } + public string? Education { get; set; } + public List? Tags { get; set; } + } +} diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index b5480b3..420ac5a 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -1,20 +1,22 @@ -using MethodologyMain.Logic.Entities; -using MethodTeams.DTO; +using MethodologyMain.Application.DTO; +using MethodologyMain.Logic.Entities; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Model; namespace MethodologyMain.Application.Interface { public interface ITeamService { - Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); - Task CreateTeamAsync(string name, string description, Guid captainId, Guid eventId, CancellationToken token); + Task CreateTeamAsync(CreateTeamDto dto, Guid captainId, CancellationToken token); Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, CancellationToken token, bool isAdmin = false); - Task GetTeamByIdAsync(Guid teamId, CancellationToken token); - Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); - Task> GetTeamAllAsync(CancellationToken token); - //Task> GetTeamsByEventIdAsync(Guid eventId); - //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); - //Task IsUserTeamCaptainAsync(Guid teamId, Guid userId); - Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); + Task GetTeamByIdAsync(Guid teamId, CancellationToken token); + Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task> GetTeamAllAsync(CancellationToken token); + Task> GetTeamForHackathonAsync(Guid hackathonId, CancellationToken token); + Task UpdateTeamAsync(UpdateTeamDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false); + Task JoinUserToTeamAsync(Guid teamId, Guid userId, CancellationToken token); + Task LeaveUserFromTeamAsync(Guid teamId, Guid userId, CancellationToken token); + //Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); + //Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); Task TransferCaptainRightsAsync(Guid teamId, Guid newCaptainId, Guid currentCaptainId, CancellationToken token); } } \ No newline at end of file diff --git a/MethodologyMain.Application/Interface/IUserService.cs b/MethodologyMain.Application/Interface/IUserService.cs new file mode 100644 index 0000000..84845c6 --- /dev/null +++ b/MethodologyMain.Application/Interface/IUserService.cs @@ -0,0 +1,14 @@ +using MethodologyMain.Application.DTO; +using MethodologyMain.Logic.Entities; + +namespace MethodologyMain.Application.Interface +{ + public interface IUserService + { + Task CreateUserAsync(GetUserDto dto, CancellationToken token); + Task DeleteUserAsync(Guid userId, CancellationToken token); + Task GetUserByIdAsync(Guid userId, CancellationToken token); + Task> GetUsersAllAsync(CancellationToken token); + Task UpdateUserAsync(GetUserDto dto, CancellationToken token); + } +} diff --git a/MethodologyMain.Application/Profiles/TeamProfile.cs b/MethodologyMain.Application/Profiles/TeamProfile.cs index 087fae9..ab75b33 100644 --- a/MethodologyMain.Application/Profiles/TeamProfile.cs +++ b/MethodologyMain.Application/Profiles/TeamProfile.cs @@ -1,11 +1,7 @@ using AutoMapper; +using MethodologyMain.Application.DTO; using MethodologyMain.Logic.Entities; using MethodTeams.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MethodologyMain.Application.Profiles { @@ -13,9 +9,12 @@ public class TeamProfile : Profile { public TeamProfile() { - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(t => t.CreatedAt, conf => conf.MapFrom(t => t.TeamCreatedAt)); + + CreateMap() + .ForMember(t => t.TeamCreatedAt, conf => conf.MapFrom(t => t.CreatedAt)); } } } diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index dfeb4a7..9ed0be8 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -5,44 +5,46 @@ using MethodTeams.Models; using AutoMapper; using MethodologyMain.Logic.Models; -using MethodTeams.DTO; +using MethodologyMain.Application.DTO; namespace MethodTeams.Services { public class TeamService: ITeamService { private readonly ITeamRepository teamRepo; + private readonly ITagRepository tagRepo; private readonly ITeamValidationService validation; private readonly IMapper mapper; public TeamService( ITeamRepository teamRepo, + ITagRepository tagRepo, ITeamValidationService validation, IMapper mapper) { this.teamRepo = teamRepo; + this.tagRepo = tagRepo; this.validation = validation; this.mapper = mapper; } // Создание новой команды - public async Task CreateTeamAsync( - string name, - string description, + public async Task CreateTeamAsync( + CreateTeamDto dto, Guid captainId, - Guid HackathonId, CancellationToken token ) { // Проверка, что у пользователя нет другой команды для этого - await validation.CheckUserNotInAnyTeamForHackathonAsync(captainId, HackathonId, token); + await validation.CheckUserNotInAnyTeamForHackathonAsync(captainId, dto.HackathonId, token); // Создание команды var team = new TeamEntity { + Id = Guid.NewGuid(), - Name = name, - Description = description, + HackathonId = dto.HackathonId, + Name = dto.Name, + Description = dto.Description, CaptainId = captainId, - HackathonId = HackathonId, TeamCreatedAt = DateTime.UtcNow }; // Добавление капитана как участника команды @@ -54,7 +56,8 @@ CancellationToken token }; team.Members.Add(member); await teamRepo.AddAsync(team, token); - return team; + await tagRepo.AddTeamTags(team.Id, dto.Tags, token); + return mapper.Map(team); } // Удаление команды (только капитаном или администратором) @@ -70,6 +73,26 @@ public async Task DeleteTeamAsync( await teamRepo.RemoveTeamAsync(teamId, token); } + public async Task UpdateTeamAsync( + UpdateTeamDto team, + Guid requestingUserId, + CancellationToken token, + bool isAdmin = false + ) + { + await validation.CheckTeamExistsAsync(team.Id, token); + await validation.CheckUserIsCaptainOrAdminAsync(team.Id, requestingUserId, isAdmin, token); + var teamEntity = await teamRepo.GetByIdAsync(team.Id, token); + if (string.IsNullOrEmpty(team.Description) && teamEntity.Description != team.Description) + teamEntity.Description = team.Description; + if (string.IsNullOrEmpty(team.Name) && teamEntity.Name != team.Name) + teamEntity.Name = team.Name; + if (team.HackathonId != null && teamEntity.HackathonId != team.HackathonId) + teamEntity.HackathonId = (Guid)team.HackathonId; + await teamRepo.UpdateTeamAsync(teamEntity, token); + + } + // Добавление пользователя в команду public async Task AddUserToTeamAsync( Guid teamId, @@ -102,6 +125,34 @@ CancellationToken token await validation.CheckUserInTeamAsync(userId, teamId, token); await teamRepo.RemoveMemberAsync(userId, teamId, token); } + + // Добавление пользователя в команду + public async Task JoinUserToTeamAsync( + Guid teamId, + Guid userId, + CancellationToken token + ) + { + await validation.CheckTeamExistsAsync(teamId, token); + Guid hackathonId = (Guid)await teamRepo.GetHackathonIdAsync(teamId, token); + await validation.CheckUserNotInTeamAsync(userId, teamId, token); + await validation.CheckUserNotInAnyTeamForHackathonAsync(userId, hackathonId, token); + await teamRepo.AddMemberAsync(userId, teamId, token); + } + + // Удаление пользователя из команды + public async Task LeaveUserFromTeamAsync( + Guid teamId, + Guid userId, + CancellationToken token + ) + { + await validation.CheckTeamExistsAsync(teamId, token); + // Нельзя удалить капитана + await validation.CheckCaptainKick(teamId, userId, token); + await validation.CheckUserInTeamAsync(userId, teamId, token); + await teamRepo.RemoveMemberAsync(userId, teamId, token); + } // Передача прав капитана public async Task TransferCaptainRightsAsync( Guid teamId, @@ -116,24 +167,35 @@ CancellationToken token await teamRepo.TransferCaptainAsync(newCaptainId, teamId, token); } // Получение информации о команде по ID - public async Task GetTeamByIdAsync(Guid teamId, CancellationToken token) + public async Task GetTeamByIdAsync(Guid teamId, CancellationToken token) { await validation.CheckTeamExistsAsync(teamId, token); - return await teamRepo.GetByIdAsync(teamId, token); + var team = await teamRepo.GetTeamAsync(teamId, token); + return mapper.Map(team); } // Получение списка участников команды - public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken token) + public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken token) { await validation.CheckTeamExistsAsync(teamId, token); return await teamRepo.GetTeamMembersAsync(teamId, token); } + // Получение команды пользователя для конкретного события + public async Task> GetTeamForHackathonAsync(Guid hackathonId, CancellationToken token) + { + var teams = await teamRepo.GetTeamByHackathonAsync(hackathonId, token); + if (teams is null) return []; + return mapper.ProjectTo(teams.AsQueryable()).ToList(); + } + // Получение списка команд - public async Task> GetTeamAllAsync(CancellationToken token) + public async Task> GetTeamAllAsync(CancellationToken token) { - - var teams = await teamRepo.GetAllAsync(token); - return mapper.Map>(teams); + + var teams = await teamRepo.GetTeamsAllAsync(token); + if (teams is null) return []; + //return mapper.Map>(teams); + return mapper.ProjectTo(teams.AsQueryable()).ToList(); } //// Проверка, является ли пользователь капитаном команды diff --git a/MethodologyMain.Application/Services/UserService.cs b/MethodologyMain.Application/Services/UserService.cs new file mode 100644 index 0000000..2386c8a --- /dev/null +++ b/MethodologyMain.Application/Services/UserService.cs @@ -0,0 +1,58 @@ +using AutoMapper; +using MethodologyMain.Application.DTO; +using MethodologyMain.Logic.Entities; +using MethodologyMain.Application.Interface; +using MethodologyMain.Persistence.Interfaces; + +namespace MethodologyMain.Application.Services +{ + public class UserService : IUserService + { + private readonly IUserRepository userRepo; + private readonly IMapper mapper; + public UserService(IUserRepository userRepo, IMapper mapper) + { + this.userRepo = userRepo; + this.mapper = mapper; + } + + // Создание нового пользователя + public async Task CreateUserAsync(GetUserDto dto, CancellationToken token) + { + var user = mapper.Map(dto); + await userRepo.AddAsync(user, token); + return dto; + } + public async Task DeleteUserAsync(Guid userId, CancellationToken token) + { + await userRepo.RemoveAsync(userId, token); + // await validation.CheckTeamExistsAsync(teamId, token); + // await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); + // await userRepo.RemoveAsync(teamId, token); + } + public async Task UpdateUserAsync(GetUserDto dto, CancellationToken token) + { + var user = mapper.Map(dto); + await userRepo.UpdateAsync(user, token); + // await validation.CheckTeamExistsAsync(teamId, token); + // await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); + // await userRepo.RemoveAsync(teamId, token); + } + + // Получение информации о пользователе по ID + public async Task GetUserByIdAsync(Guid userId, CancellationToken token) + { + // await validation.CheckTeamExistsAsync(teamId, token); + var user = await userRepo.GetByIdAsync(userId, token); + return mapper.Map(user); + } + + // Получение списка пользователей + public async Task> GetUsersAllAsync(CancellationToken token) + { + + var users = await userRepo.GetAllAsync(token); + return mapper.Map>(users); + } + } +} diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll index 91b9c2c..4ce721a 100644 Binary files a/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll and b/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll differ diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll index 114d943..0e1da0a 100644 Binary files a/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll and b/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll differ diff --git a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs index 70fea0b..5f0d9df 100644 --- a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs +++ b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs @@ -39,10 +39,11 @@ public override async Task ProcessMessageAsync(string message) var context = scope.ServiceProvider.GetRequiredService(); await context.AddAsync(new UserMainEntity { - Id = data.UserId + Id = data.UserId, + UserName = data.UserName, + Email = data.Email, }); - } - + } } } } diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs index 6c87699..ea9ca3b 100644 --- a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs +++ b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs @@ -6,6 +6,10 @@ public class RabbitMqUserRegisterRecieve : IEvent { public Guid UserId { get; set; } + public string UserName { get; set; } + + public string Email { get; set; } + public string EventType => "RecieveUserRegister"; } } diff --git a/MethodologyMain.Logic/Entities/HackathonEntity.cs b/MethodologyMain.Logic/Entities/HackathonEntity.cs index 1baa552..3b8f979 100644 --- a/MethodologyMain.Logic/Entities/HackathonEntity.cs +++ b/MethodologyMain.Logic/Entities/HackathonEntity.cs @@ -1,4 +1,5 @@ -using System; +using MethodologyMain.Logic.Models; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -21,8 +22,20 @@ public class HackathonEntity [Column("name")] public required string Name { get; set; } - [Column("prize")] - public required decimal Prize { get; set; } + [Column("description")] + public string Description { get; set; } = string.Empty; + + [Column("startDate")] + public required DateOnly StartDate { get; set; } + + [Column("endDate")] + public required DateOnly EndDate { get; set; } + + [Column("location")] + public string Location { get; set; } = string.Empty; + + [Column("imageUrl")] + public string ImageUrl { get; set; } = string.Empty; [Column("minTeamSize")] public required int MinTeamSize { get; set; } @@ -30,21 +43,19 @@ public class HackathonEntity [Column("maxTeamSize")] public required int MaxTeamSize { get; set; } - [Column("startDate")] - public required DateTime StartDate { get; set; } + [Column("website")] + public string Website { get; set; } = string.Empty; - [Column("endDate")] - public required DateTime EndDate { get; set; } + [Column("prize")] + public required string Prizes { get; set; } - [Column("additionalInfo")] - public string AdditionalInfo { get; set; } = string.Empty; + [Column("schedule")] + public required string Schedule { get; set; } public OrganizationEntity Organization { get; set; } = null!; public List Teams { get; set; } = new List(); public List Tags { get; set; } = new List(); - - public List Tracks { get; set; } = new List(); } } diff --git a/MethodologyMain.Logic/Entities/HackathonTagEntity.cs b/MethodologyMain.Logic/Entities/HackathonTagEntity.cs index 479a012..bad04c5 100644 --- a/MethodologyMain.Logic/Entities/HackathonTagEntity.cs +++ b/MethodologyMain.Logic/Entities/HackathonTagEntity.cs @@ -8,7 +8,7 @@ namespace MethodologyMain.Logic.Entities { - [Table("hackthonTag")] + [Table("hackathonTag", Schema = "mainSchema")] public class HackathonTagEntity { [Column("hackathonId")] diff --git a/MethodologyMain.Logic/Entities/OrganizationEntity.cs b/MethodologyMain.Logic/Entities/OrganizationEntity.cs index 5655bee..ff8fb61 100644 --- a/MethodologyMain.Logic/Entities/OrganizationEntity.cs +++ b/MethodologyMain.Logic/Entities/OrganizationEntity.cs @@ -1,10 +1,5 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MethodologyMain.Logic.Entities { @@ -19,10 +14,10 @@ public class OrganizationEntity public required string Name { get; set; } [Column("description")] - public required string Description { get; set; } + public string Description { get; set; } = string.Empty; - [Column("linkToWebsite")] - public required string LinkToWebSite { get; set; } = string.Empty; + [Column("logo")] + public string Logo { get; set; } = string.Empty; public List Hackathons { get; set; } = new List(); } diff --git a/MethodologyMain.Logic/Entities/TagEntity.cs b/MethodologyMain.Logic/Entities/TagEntity.cs index 6a22c84..a70cb32 100644 --- a/MethodologyMain.Logic/Entities/TagEntity.cs +++ b/MethodologyMain.Logic/Entities/TagEntity.cs @@ -24,5 +24,7 @@ public class TagEntity public List Users { get; set; } = new List(); public List Hacksthons { get; set; } = new List(); + + public List Teams { get; set; } = new List(); } } diff --git a/MethodologyMain.Logic/Entities/TeamEntity.cs b/MethodologyMain.Logic/Entities/TeamEntity.cs index 8ef81ba..ee45c58 100644 --- a/MethodologyMain.Logic/Entities/TeamEntity.cs +++ b/MethodologyMain.Logic/Entities/TeamEntity.cs @@ -14,18 +14,22 @@ public class TeamEntity public required Guid HackathonId { get; set; } [Column("name")] - public required string Name { get; set; } = string.Empty; + public required string Name { get; set; } [Column("description")] public string Description { get; set; } = string.Empty; [Column("captainId")] public required Guid CaptainId { get; set; } + + [Column("maxMembers")] + public int MaxMembers { get; set; } [Column("teamCreatedAt")] - public DateTime TeamCreatedAt { get; set; } + public DateTime TeamCreatedAt { get; set; } = DateTime.UtcNow; // Навигационное свойство для связи с участниками + public List Tags { get; set; } = new List(); public List Members { get; set; } = new List(); public HackathonEntity Hackathon { get; set; } = null!; } diff --git a/MethodologyMain.Logic/Entities/TeamTagEntity.cs b/MethodologyMain.Logic/Entities/TeamTagEntity.cs new file mode 100644 index 0000000..76211ac --- /dev/null +++ b/MethodologyMain.Logic/Entities/TeamTagEntity.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Logic.Entities +{ + [Table("teamTag", Schema = "mainSchema")] + public class TeamTagEntity + { + [Column("teamId")] + public Guid TeamId { get; set; } + + [Column("tagId")] + public Guid TagId { get; set; } + + public TeamEntity Team { get; set; } = null!; + + public TagEntity Tag { get; set; } = null!; + } +} diff --git a/MethodologyMain.Logic/Entities/UserMainEntity.cs b/MethodologyMain.Logic/Entities/UserMainEntity.cs index 10d3b2e..7fdc349 100644 --- a/MethodologyMain.Logic/Entities/UserMainEntity.cs +++ b/MethodologyMain.Logic/Entities/UserMainEntity.cs @@ -9,21 +9,49 @@ public class UserMainEntity [Key] [Column("id")] public required Guid Id { get; set; } + [Column("birthDate")] public DateTime BirthDate { get; set; } = DateTime.MinValue; + [Column("education")] public string Education { get; set; } = string.Empty; + [Column("firstName")] public string FirstName { get; set; } = string.Empty; + [Column("lastName")] public string LastName { get; set; } = string.Empty; + [Column("middleName")] - public string Surname { get; set; } = string.Empty; + public string MiddleName { get; set; } = string.Empty; + + [Column("email")] + public string Email { get; set; } = string.Empty; + [Column("userName")] public string UserName { get; set; } = string.Empty; - [Column("Telegram")] + + [Column("photoUrl")] + public string PhotoUrl { get; set; } = string.Empty; + + [Column("createdAt")] + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + [Column("location")] + public string Location { get; set; } = string.Empty; + + [Column("telegram")] public string Telegram { get; set; } = string.Empty; + [Column("github")] + public string Github { get; set; } = string.Empty; + + [Column("website")] + public string Website { get; set; } = string.Empty; + + [Column("skills")] + public string Skills { get; set; } = string.Empty; + public List Teams { get; set; } = new List(); diff --git a/MethodologyMain.Logic/Models/Hackathon.cs b/MethodologyMain.Logic/Models/Hackathon.cs index 7a367f6..22ffd3f 100644 --- a/MethodologyMain.Logic/Models/Hackathon.cs +++ b/MethodologyMain.Logic/Models/Hackathon.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,30 +11,22 @@ namespace MethodologyMain.Logic.Models { public class Hackathon { - public required Guid Id { get; set; } - - public required Guid OrganizationId { get; set; } - + public Guid Id { get; set; } public required string Name { get; set; } - - public required decimal Prize { get; set; } - - public required int MinTeamSize { get; set; } - - public required int MaxTeamSize { get; set; } - - public required DateTime StartDate { get; set; } - - public required DateTime EndDate { get; set; } - - public string AdditionalInfo { get; set; } = string.Empty; - + public string Description { get; set; } = string.Empty; + public required Guid OrganizationId { get; set; } + public required DateOnly StartDate { get; set; } + public required DateOnly EndDate { get; set; } + public string Location { get; set; } = string.Empty; + public string ImageUrl { get; set; } = string.Empty; + public string Website { get; set; } = string.Empty; + public TeamSize TeamSize { get; set; } = null!; + public int MinMembers { get; set; } = 2; + public int MaxMembers { get; set; } = 8; + public List Prizes { get; set; } = null!; + public List Schedule { get; set; } = null!; public OrganizationEntity Organization { get; set; } = null!; - - public List Teams { get; set; } = new List(); - public List Tags { get; set; } = new List(); - - public List Tracks { get; set; } = new List(); + public List Teams { get; set; } = new List(); } } diff --git a/MethodologyMain.Logic/Models/Organization.cs b/MethodologyMain.Logic/Models/Organization.cs index 3c06cf0..3299fd6 100644 --- a/MethodologyMain.Logic/Models/Organization.cs +++ b/MethodologyMain.Logic/Models/Organization.cs @@ -14,9 +14,9 @@ public class Organization public required string Name { get; set; } - public required string Description { get; set; } + public string Description { get; set; } = string.Empty; - public required string LinkToWebSite { get; set; } = string.Empty; + public string Logo { get; set; } = string.Empty; public List Hackathons { get; set; } = new List(); } diff --git a/MethodologyMain.Logic/Models/Prize.cs b/MethodologyMain.Logic/Models/Prize.cs new file mode 100644 index 0000000..4fd07dd --- /dev/null +++ b/MethodologyMain.Logic/Models/Prize.cs @@ -0,0 +1,8 @@ +namespace MethodologyMain.Logic.Models +{ + public class Prize + { + public required string Place { get; set; } + public required string Description { get; set; } + } +} diff --git a/MethodologyMain.Logic/Models/ScheduleItem.cs b/MethodologyMain.Logic/Models/ScheduleItem.cs new file mode 100644 index 0000000..2eb4d28 --- /dev/null +++ b/MethodologyMain.Logic/Models/ScheduleItem.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Logic.Models +{ + public class ScheduleItem + { + public required DateOnly Date { get; set; } + public required TimeOnly Time { get; set; } + public required string Title { get; set; } + public string Description { get; set; } = string.Empty; + } +} diff --git a/MethodologyMain.Logic/Models/Team.cs b/MethodologyMain.Logic/Models/Team.cs index a10f2d3..2d05dfc 100644 --- a/MethodologyMain.Logic/Models/Team.cs +++ b/MethodologyMain.Logic/Models/Team.cs @@ -6,17 +6,15 @@ namespace MethodTeams.Models public class Team { public required Guid Id { get; set; } - public required Guid HackathonId { get; set; } - - public required string Name { get; set; } = string.Empty; - + public required string Name { get; set; } public string Description { get; set; } = string.Empty; + public required int MaxMembers { get; set; } public required Guid CaptainId { get; set; } - - public DateTime CreatedAt { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Навигационное свойство для связи с участниками + public List Tags { get; set; } = new List(); public List Members { get; set; } = new List(); public HackathonEntity Hackathon { get; set; } = null!; } diff --git a/MethodologyMain.Logic/Models/TeamSize.cs b/MethodologyMain.Logic/Models/TeamSize.cs new file mode 100644 index 0000000..6afa829 --- /dev/null +++ b/MethodologyMain.Logic/Models/TeamSize.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Logic.Models +{ + public class TeamSize + { + public int Min { get; set; } + public int Max { get; set; } + } +} diff --git a/MethodologyMain.Logic/Models/UserMain.cs b/MethodologyMain.Logic/Models/UserMain.cs index 3ba043f..03157dc 100644 --- a/MethodologyMain.Logic/Models/UserMain.cs +++ b/MethodologyMain.Logic/Models/UserMain.cs @@ -18,7 +18,15 @@ public class UserMain public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string MiddleName { get; set; } = string.Empty; + public string Email { get; set; } = string.Empty; public string UserName { get; set; } = string.Empty; + public string PhotoUrl { get; set; } = string.Empty; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public string Location { get; set; } = string.Empty; + public string Telegram { get; set; } = string.Empty; + public string Github { get; set; } = string.Empty; + public string Website { get; set; } = string.Empty; + public string Skills { get; set; } = string.Empty; public List Teams { get; set; } = new List(); diff --git a/MethodologyMain.Persistence/Data/TeamDbContext.cs b/MethodologyMain.Persistence/Data/MyDbContext.cs similarity index 86% rename from MethodologyMain.Persistence/Data/TeamDbContext.cs rename to MethodologyMain.Persistence/Data/MyDbContext.cs index d50ca31..6da0ced 100644 --- a/MethodologyMain.Persistence/Data/TeamDbContext.cs +++ b/MethodologyMain.Persistence/Data/MyDbContext.cs @@ -1,4 +1,5 @@ using MethodologyMain.Logic.Entities; +using MethodologyMain.Logic.Models; using Microsoft.EntityFrameworkCore; namespace MethodTeams.Data @@ -8,11 +9,8 @@ public class MyDbContext : DbContext public MyDbContext(DbContextOptions options) : base(options) { } public DbSet Teams { get; set; } public DbSet Users { get; set; } - public DbSet Organizations { get; set; } - public DbSet Hackathons { get; set; } - public DbSet Tags { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -22,6 +20,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity() .HasKey(e => new {e.TagId, e.UserId}); + modelBuilder.Entity() + .HasKey(e => new { e.TagId, e.TeamId }); + modelBuilder.Entity() .HasKey(e => new {e.UserId, e.TeamId}); @@ -36,16 +37,26 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .WithMany(e => e.Tags) .HasForeignKey(e => e.HackathonId); + modelBuilder.Entity() + .HasOne(e => e.Tag) + .WithMany(e => e.Users) + .HasForeignKey(e => e.TagId); + modelBuilder.Entity() .HasOne(e => e.User) .WithMany(e => e.Tags) .HasForeignKey(e => e.UserId); - modelBuilder.Entity() + modelBuilder.Entity() .HasOne(e => e.Tag) - .WithMany(e => e.Users) + .WithMany(e => e.Teams) .HasForeignKey(e => e.TagId); + modelBuilder.Entity() + .HasOne(e => e.Team) + .WithMany(e => e.Tags) + .HasForeignKey(e => e.TeamId); + modelBuilder.Entity() .HasOne(e => e.User) .WithMany(e => e.Teams) @@ -79,11 +90,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasOne(e => e.Organization) .WithMany(e => e.Hackathons) .HasForeignKey(e => e.OrganizationId); - - modelBuilder.Entity() - .HasOne(e => e.Hackathon) - .WithMany(e => e.Tracks) - .HasForeignKey(e => e.HackathonId); } } } diff --git a/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs b/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs index 2fdc564..0afcbcf 100644 --- a/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs @@ -5,12 +5,10 @@ namespace MethodologyMain.Persistence.Interfaces { public interface IHackathonRepository { - Task GetByIdAsync(Guid id); - - Task> GetAllCurrentHackathonsAsync(int page = 1, int pageSize = 10); - - Task> GetAllHackathonsAsync(int page = 1, int pageSize = 10); - - Task> GetHackathonsByFlexibleSearchAsync(int page, int pageSize, Expression> filter = null); + Task GetByIdAsync(Guid id, CancellationToken token = default); + Task> GetAllCurrentHackathonsAsync(int page = 1, int pageSize = 10, CancellationToken token = default); + Task> GetAllHackathonsAsync(CancellationToken token = default); + Task> GetAllHackathonsPagedAsync(int page = 1, int pageSize = 10, CancellationToken token = default); + Task> GetHackathonsByFlexibleSearchAsync(int page, int pageSize, Expression> filter = null, CancellationToken token = default); } } diff --git a/MethodologyMain.Persistence/Interfaces/ITagRepository.cs b/MethodologyMain.Persistence/Interfaces/ITagRepository.cs new file mode 100644 index 0000000..6445421 --- /dev/null +++ b/MethodologyMain.Persistence/Interfaces/ITagRepository.cs @@ -0,0 +1,9 @@ +namespace MethodologyMain.Persistence.Interfaces +{ + public interface ITagRepository + { + Task AddTeamTags(Guid teamId, List tagNames, CancellationToken token); + Task AddUserTags(Guid userId, List tagNames, CancellationToken token); + Task AddHackTags(Guid hackId, List tagNames, CancellationToken token); + } +} \ No newline at end of file diff --git a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs index ed7d7b7..592c281 100644 --- a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs @@ -10,7 +10,11 @@ public interface ITeamRepository : IGenericRepository Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token); Task GetCaptainIdAsync(Guid teamId, CancellationToken token); Task GetHackathonIdAsync(Guid teamId, CancellationToken token); - Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task?> GetTeamByHackathonAsync(Guid HackathonId, CancellationToken token); + Task UpdateTeamAsync(TeamEntity team, CancellationToken token); + Task> GetTeamsAllAsync(CancellationToken token); + Task GetTeamAsync(Guid teamId, CancellationToken token); Task RemoveMemberAsync(Guid userId, Guid teamId, CancellationToken token); Task RemoveTeamAsync(Guid teamId, CancellationToken token); Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, CancellationToken token); diff --git a/MethodologyMain.Persistence/Interfaces/IUserRepository.cs b/MethodologyMain.Persistence/Interfaces/IUserRepository.cs index a53ee09..0759910 100644 --- a/MethodologyMain.Persistence/Interfaces/IUserRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/IUserRepository.cs @@ -9,5 +9,9 @@ namespace MethodologyMain.Persistence.Interfaces { public interface IUserRepository : IGenericRepository { + Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token); + Task UpdateAsync(UserMainEntity user, CancellationToken token); + Task RemoveAsync(Guid userId, CancellationToken token); + } } diff --git a/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj b/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj index 0dbfb18..c06086d 100644 --- a/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj +++ b/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj @@ -11,10 +11,6 @@ - - - - @@ -24,4 +20,8 @@ + + + + diff --git a/MethodologyMain.Persistence/Migrations/20250423104019_Init.Designer.cs b/MethodologyMain.Persistence/Migrations/20250423104019_Init.Designer.cs new file mode 100644 index 0000000..13b7cb8 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250423104019_Init.Designer.cs @@ -0,0 +1,415 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250423104019_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("additionalInfo"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("endDate"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prize") + .HasColumnType("numeric") + .HasColumnName("prize"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("startDate"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackthonTag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("LinkToWebSite") + .IsRequired() + .HasColumnType("text") + .HasColumnName("linkToWebsite"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("TrackAdditionalInfo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trackAdditionalInfo"); + + b.Property("TrackName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trackName"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("track", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Surname") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tracks") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + + b.Navigation("Tracks"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250423104019_Init.cs b/MethodologyMain.Persistence/Migrations/20250423104019_Init.cs new file mode 100644 index 0000000..6f0dcd2 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250423104019_Init.cs @@ -0,0 +1,294 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "mainSchema"); + + migrationBuilder.CreateTable( + name: "organization", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "text", nullable: false), + description = table.Column(type: "text", nullable: false), + linkToWebsite = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_organization", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "tag", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + tagName = table.Column(type: "text", nullable: false), + tagClassName = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_tag", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "teamMember", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + birthDate = table.Column(type: "timestamp with time zone", nullable: false), + education = table.Column(type: "text", nullable: false), + firstName = table.Column(type: "text", nullable: false), + lastName = table.Column(type: "text", nullable: false), + middleName = table.Column(type: "text", nullable: false), + userName = table.Column(type: "text", nullable: false), + Telegram = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_teamMember", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "hackathon", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + organizationId = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "text", nullable: false), + prize = table.Column(type: "numeric", nullable: false), + minTeamSize = table.Column(type: "integer", nullable: false), + maxTeamSize = table.Column(type: "integer", nullable: false), + startDate = table.Column(type: "timestamp with time zone", nullable: false), + endDate = table.Column(type: "timestamp with time zone", nullable: false), + additionalInfo = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_hackathon", x => x.id); + table.ForeignKey( + name: "FK_hackathon_organization_organizationId", + column: x => x.organizationId, + principalSchema: "mainSchema", + principalTable: "organization", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "userTag", + schema: "mainSchema", + columns: table => new + { + userId = table.Column(type: "uuid", nullable: false), + tagId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_userTag", x => new { x.tagId, x.userId }); + table.ForeignKey( + name: "FK_userTag_tag_tagId", + column: x => x.tagId, + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_userTag_teamMember_userId", + column: x => x.userId, + principalSchema: "mainSchema", + principalTable: "teamMember", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "hackthonTag", + columns: table => new + { + hackathonId = table.Column(type: "uuid", nullable: false), + tagId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_hackthonTag", x => new { x.tagId, x.hackathonId }); + table.ForeignKey( + name: "FK_hackthonTag_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_hackthonTag_tag_tagId", + column: x => x.tagId, + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "team", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + hackathonId = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "text", nullable: false), + description = table.Column(type: "text", nullable: false), + captainId = table.Column(type: "uuid", nullable: false), + teamCreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_team", x => x.id); + table.ForeignKey( + name: "FK_team_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "track", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + hackathonId = table.Column(type: "uuid", nullable: false), + trackName = table.Column(type: "text", nullable: false), + trackAdditionalInfo = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_track", x => x.id); + table.ForeignKey( + name: "FK_track_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "userTeam", + schema: "mainSchema", + columns: table => new + { + userId = table.Column(type: "uuid", nullable: false), + teamId = table.Column(type: "uuid", nullable: false), + joinedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_userTeam", x => new { x.userId, x.teamId }); + table.ForeignKey( + name: "FK_userTeam_teamMember_userId", + column: x => x.userId, + principalSchema: "mainSchema", + principalTable: "teamMember", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_userTeam_team_teamId", + column: x => x.teamId, + principalSchema: "mainSchema", + principalTable: "team", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_hackathon_organizationId", + schema: "mainSchema", + table: "hackathon", + column: "organizationId"); + + migrationBuilder.CreateIndex( + name: "IX_hackthonTag_hackathonId", + table: "hackthonTag", + column: "hackathonId"); + + migrationBuilder.CreateIndex( + name: "IX_team_hackathonId", + schema: "mainSchema", + table: "team", + column: "hackathonId"); + + migrationBuilder.CreateIndex( + name: "IX_track_hackathonId", + schema: "mainSchema", + table: "track", + column: "hackathonId"); + + migrationBuilder.CreateIndex( + name: "IX_userTag_userId", + schema: "mainSchema", + table: "userTag", + column: "userId"); + + migrationBuilder.CreateIndex( + name: "IX_userTeam_teamId", + schema: "mainSchema", + table: "userTeam", + column: "teamId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "hackthonTag"); + + migrationBuilder.DropTable( + name: "track", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "userTag", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "userTeam", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "tag", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "teamMember", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "team", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "hackathon", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "organization", + schema: "mainSchema"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250426165549_Init1.Designer.cs b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.Designer.cs new file mode 100644 index 0000000..8ca7779 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.Designer.cs @@ -0,0 +1,464 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250426165549_Init1")] + partial class Init1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackthonTag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250426165549_Init1.cs b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.cs new file mode 100644 index 0000000..83246f6 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.cs @@ -0,0 +1,308 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class Init1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "track", + schema: "mainSchema"); + + migrationBuilder.RenameColumn( + name: "Telegram", + schema: "mainSchema", + table: "teamMember", + newName: "telegram"); + + migrationBuilder.RenameColumn( + name: "linkToWebsite", + schema: "mainSchema", + table: "organization", + newName: "logo"); + + migrationBuilder.RenameColumn( + name: "additionalInfo", + schema: "mainSchema", + table: "hackathon", + newName: "website"); + + migrationBuilder.AddColumn( + name: "createdAt", + schema: "mainSchema", + table: "teamMember", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "github", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "location", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "photoUrl", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "skills", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "website", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AlterColumn( + name: "startDate", + schema: "mainSchema", + table: "hackathon", + type: "date", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AlterColumn( + name: "prize", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric"); + + migrationBuilder.AlterColumn( + name: "endDate", + schema: "mainSchema", + table: "hackathon", + type: "date", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AddColumn( + name: "description", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "imageUrl", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "location", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "schedule", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.CreateTable( + name: "teamTag", + schema: "mainSchema", + columns: table => new + { + teamId = table.Column(type: "uuid", nullable: false), + tagId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_teamTag", x => new { x.tagId, x.teamId }); + table.ForeignKey( + name: "FK_teamTag_tag_tagId", + column: x => x.tagId, + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_teamTag_team_teamId", + column: x => x.teamId, + principalSchema: "mainSchema", + principalTable: "team", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_teamTag_teamId", + schema: "mainSchema", + table: "teamTag", + column: "teamId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "teamTag", + schema: "mainSchema"); + + migrationBuilder.DropColumn( + name: "createdAt", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "github", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "location", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "photoUrl", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "skills", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "website", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "description", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.DropColumn( + name: "imageUrl", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.DropColumn( + name: "location", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.DropColumn( + name: "schedule", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.RenameColumn( + name: "telegram", + schema: "mainSchema", + table: "teamMember", + newName: "Telegram"); + + migrationBuilder.RenameColumn( + name: "logo", + schema: "mainSchema", + table: "organization", + newName: "linkToWebsite"); + + migrationBuilder.RenameColumn( + name: "website", + schema: "mainSchema", + table: "hackathon", + newName: "additionalInfo"); + + migrationBuilder.AlterColumn( + name: "startDate", + schema: "mainSchema", + table: "hackathon", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateOnly), + oldType: "date"); + + migrationBuilder.AlterColumn( + name: "prize", + schema: "mainSchema", + table: "hackathon", + type: "numeric", + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "endDate", + schema: "mainSchema", + table: "hackathon", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateOnly), + oldType: "date"); + + migrationBuilder.CreateTable( + name: "track", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + hackathonId = table.Column(type: "uuid", nullable: false), + trackAdditionalInfo = table.Column(type: "text", nullable: false), + trackName = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_track", x => x.id); + table.ForeignKey( + name: "FK_track_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_track_hackathonId", + schema: "mainSchema", + table: "track", + column: "hackathonId"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250426165819_Init2.Designer.cs b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.Designer.cs new file mode 100644 index 0000000..832fc21 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.Designer.cs @@ -0,0 +1,464 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250426165819_Init2")] + partial class Init2 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackathonTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250426165819_Init2.cs b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.cs new file mode 100644 index 0000000..55950ef --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.cs @@ -0,0 +1,115 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class Init2 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_hackthonTag_hackathon_hackathonId", + table: "hackthonTag"); + + migrationBuilder.DropForeignKey( + name: "FK_hackthonTag_tag_tagId", + table: "hackthonTag"); + + migrationBuilder.DropPrimaryKey( + name: "PK_hackthonTag", + table: "hackthonTag"); + + migrationBuilder.RenameTable( + name: "hackthonTag", + newName: "hackathonTag", + newSchema: "mainSchema"); + + migrationBuilder.RenameIndex( + name: "IX_hackthonTag_hackathonId", + schema: "mainSchema", + table: "hackathonTag", + newName: "IX_hackathonTag_hackathonId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_hackathonTag", + schema: "mainSchema", + table: "hackathonTag", + columns: new[] { "tagId", "hackathonId" }); + + migrationBuilder.AddForeignKey( + name: "FK_hackathonTag_hackathon_hackathonId", + schema: "mainSchema", + table: "hackathonTag", + column: "hackathonId", + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_hackathonTag_tag_tagId", + schema: "mainSchema", + table: "hackathonTag", + column: "tagId", + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_hackathonTag_hackathon_hackathonId", + schema: "mainSchema", + table: "hackathonTag"); + + migrationBuilder.DropForeignKey( + name: "FK_hackathonTag_tag_tagId", + schema: "mainSchema", + table: "hackathonTag"); + + migrationBuilder.DropPrimaryKey( + name: "PK_hackathonTag", + schema: "mainSchema", + table: "hackathonTag"); + + migrationBuilder.RenameTable( + name: "hackathonTag", + schema: "mainSchema", + newName: "hackthonTag"); + + migrationBuilder.RenameIndex( + name: "IX_hackathonTag_hackathonId", + table: "hackthonTag", + newName: "IX_hackthonTag_hackathonId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_hackthonTag", + table: "hackthonTag", + columns: new[] { "tagId", "hackathonId" }); + + migrationBuilder.AddForeignKey( + name: "FK_hackthonTag_hackathon_hackathonId", + table: "hackthonTag", + column: "hackathonId", + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_hackthonTag_tag_tagId", + table: "hackthonTag", + column: "tagId", + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.Designer.cs b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.Designer.cs new file mode 100644 index 0000000..58908cf --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.Designer.cs @@ -0,0 +1,468 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250427122659_TeamEntityFix")] + partial class TeamEntityFix + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackathonTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("MaxMembers") + .HasColumnType("integer") + .HasColumnName("maxMembers"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.cs b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.cs new file mode 100644 index 0000000..1b20c15 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class TeamEntityFix : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "maxMembers", + schema: "mainSchema", + table: "team", + type: "integer", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "maxMembers", + schema: "mainSchema", + table: "team"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.Designer.cs b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.Designer.cs new file mode 100644 index 0000000..ea12941 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.Designer.cs @@ -0,0 +1,473 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250428193128_AddUserEmail")] + partial class AddUserEmail + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackathonTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("MaxMembers") + .HasColumnType("integer") + .HasColumnName("maxMembers"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .HasColumnName("email"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.cs b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.cs new file mode 100644 index 0000000..cb74655 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class AddUserEmail : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "email", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "email", + schema: "mainSchema", + table: "teamMember"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs new file mode 100644 index 0000000..a11516b --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs @@ -0,0 +1,472 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + partial class MyDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackathonTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("MaxMembers") + .HasColumnType("integer") + .HasColumnName("maxMembers"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .HasColumnName("email"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + + b.Navigation("Tracks"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Repository/GenericRepository.cs b/MethodologyMain.Persistence/Repository/GenericRepository.cs index 8b57920..a6f2cd5 100644 --- a/MethodologyMain.Persistence/Repository/GenericRepository.cs +++ b/MethodologyMain.Persistence/Repository/GenericRepository.cs @@ -15,13 +15,13 @@ public GenericRepository(MyDbContext context) public async Task AddAsync(T entity, CancellationToken token) { - _context.Set().Add(entity); + await _context.Set().AddAsync(entity, token); await _context.SaveChangesAsync(token); } public async Task AddRangeAsync(IEnumerable entities, CancellationToken token) { - _context.Set().AddRange(entities); + await _context.Set().AddRangeAsync(entities, token); await _context.SaveChangesAsync(token); } @@ -32,7 +32,7 @@ public async Task> FindAsync(Expression> expression public async Task> GetAllAsync(CancellationToken token) { - return await _context.Set().ToListAsync(token); + return await _context.Set().AsNoTracking().ToListAsync(token); } public async Task GetByIdAsync(Guid id, CancellationToken token) diff --git a/MethodologyMain.Persistence/Repository/HackathonRepository.cs b/MethodologyMain.Persistence/Repository/HackathonRepository.cs index e1155b8..f1cfd7a 100644 --- a/MethodologyMain.Persistence/Repository/HackathonRepository.cs +++ b/MethodologyMain.Persistence/Repository/HackathonRepository.cs @@ -3,6 +3,7 @@ using MethodTeams.Data; using Microsoft.EntityFrameworkCore; using System.Linq.Expressions; +using System.Threading; namespace MethodologyMain.Persistence.Repository { @@ -13,30 +14,46 @@ public HackathonRepository(MyDbContext context) { this.context = context; } - public async Task> GetAllCurrentHackathonsAsync(int page = 1, int pageSize = 10) + public async Task> GetAllCurrentHackathonsAsync( + int page = 1, + int pageSize = 10, + CancellationToken token = default + ) { return await context.Hackathons .AsNoTracking() - .Where(h => h.EndDate > DateTime.UtcNow) + .Where(h => h.EndDate > DateOnly.FromDateTime(DateTime.Now)) .Skip((page - 1) * pageSize) .Take(pageSize) - .ToListAsync(); + .ToListAsync(token); } - public async Task GetByIdAsync(Guid id) + public async Task GetByIdAsync(Guid id, CancellationToken token = default) { - return await context.Hackathons.FindAsync(id); + return await context.Hackathons.FindAsync([id], token); } - - public async Task> GetAllHackathonsAsync(int page = 1, int pageSize = 10) + public async Task> GetAllHackathonsAsync(CancellationToken token = default) + { + return await context.Hackathons.AsNoTracking().ToListAsync(token); + } + public async Task> GetAllHackathonsPagedAsync( + int page = 1, + int pageSize = 10, + CancellationToken token = default + ) { return await context.Hackathons.AsNoTracking() .Skip((page - 1) * pageSize) .Take(pageSize) - .ToListAsync(); + .ToListAsync(token); } - public async Task> GetHackathonsByFlexibleSearchAsync(int page,int pageSize, Expression> filter = null) + public async Task> GetHackathonsByFlexibleSearchAsync( + int page, + int pageSize, + Expression> filter = null, + CancellationToken token = default + ) { var query = context.Hackathons.AsQueryable(); @@ -47,7 +64,7 @@ public async Task> GetHackathonsByFlexibleSearchAsync(int return await query .Skip((page - 1) * pageSize) .Take(pageSize) - .ToListAsync(); + .ToListAsync(token); } } } diff --git a/MethodologyMain.Persistence/Repository/TagRepository.cs b/MethodologyMain.Persistence/Repository/TagRepository.cs new file mode 100644 index 0000000..def0c47 --- /dev/null +++ b/MethodologyMain.Persistence/Repository/TagRepository.cs @@ -0,0 +1,190 @@ +using MethodologyMain.Logic.Entities; +using MethodologyMain.Persistence.Interfaces; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; + +namespace MethodologyMain.Persistence.Repository +{ + public class TagRepository : GenericRepository, ITagRepository + { + private readonly ITeamRepository teamRepo; + private readonly IUserRepository userRepo; + private readonly IHackathonRepository hackRepo; + public TagRepository( + MyDbContext context, + ITeamRepository teamRepo, + IUserRepository userRepo, + IHackathonRepository hackRepo) : base(context) + { + this.teamRepo = teamRepo; + this.userRepo = userRepo; + this.hackRepo = hackRepo; + } + + public async Task AddTeamTags(Guid teamId, List tagNames, CancellationToken token) + { + token.ThrowIfCancellationRequested(); + var team = await teamRepo.GetByIdAsync(teamId, token); + var existTags = await _context.Tags + .Where(m => m.TagClassName == "team") + .Where(m => tagNames.Contains(m.TagName)) + .ToDictionaryAsync(m => m.TagName, t => t, cancellationToken: token); + var newTagsToAdd = new List(); + var tagUserRelations = new List(); + + foreach (var tagName in tagNames) + { + // Если тег уже существует, используем его + if (existTags.TryGetValue(tagName, out var tag)) + { + // Проверяем, что связь еще не существует + if (!team.Tags.Any(t => t.TagId == tag.Id)) + { + team.Tags.Add(new TeamTagEntity + { + TeamId = teamId, + TagId = tag.Id + }); + } + } + else + { + // Создаем новый тег + var newTag = new TagEntity + { + TagName = tagName, + TagClassName = "team" + }; + newTagsToAdd.Add(newTag); + + // Добавляем связь с новым тегом + // (ID тега будет установлен после сохранения) + team.Tags.Add(new TeamTagEntity + { + TeamId = teamId, + Tag = newTag + }); + } + + } + // Добавляем новые теги в контекст + if (newTagsToAdd.Count != 0) + { + await _context.Tags.AddRangeAsync(newTagsToAdd, token); + } + + // Сохраняем изменения + await _context.SaveChangesAsync(token); + } + + public async Task AddUserTags(Guid userId, List tagNames, CancellationToken token) + { + token.ThrowIfCancellationRequested(); + var user = await userRepo.GetByIdAsync(userId, token); + var existTags = await _context.Tags + .Where(m => m.TagClassName == "user") + .Where(m => tagNames.Contains(m.TagName)) + .ToDictionaryAsync(m => m.TagName, t => t, cancellationToken: token); + var newTagsToAdd = new List(); + + foreach (var tagName in tagNames) + { + // Если тег уже существует, используем его + if (existTags.TryGetValue(tagName, out var tag)) + { + // Проверяем, что связь еще не существует + if (!user.Tags.Any(t => t.TagId == tag.Id)) + { + user.Tags.Add(new UserTagEntity + { + UserId = userId, + TagId = tag.Id + }); + } + } + else + { + // Создаем новый тег + var newTag = new TagEntity + { + TagName = tagName, + TagClassName = "user" + }; + newTagsToAdd.Add(newTag); + + // Добавляем связь с новым тегом + // (ID тега будет установлен после сохранения) + user.Tags.Add(new UserTagEntity + { + UserId = userId, + Tag = newTag + }); + } + + } + // Добавляем новые теги в контекст + if (newTagsToAdd.Count != 0) + { + await _context.Tags.AddRangeAsync(newTagsToAdd, token); + } + + // Сохраняем изменения + await _context.SaveChangesAsync(token); + } + + public async Task AddHackTags(Guid hackId, List tagNames, CancellationToken token) + { + token.ThrowIfCancellationRequested(); + var hack = await hackRepo.GetByIdAsync(hackId, token); + var existTags = await _context.Tags + .Where(m => m.TagClassName == "hack") + .Where(m => tagNames.Contains(m.TagName)) + .ToDictionaryAsync(m => m.TagName, t => t, cancellationToken: token); + var newTagsToAdd = new List(); + + foreach (var tagName in tagNames) + { + // Если тег уже существует, используем его + if (existTags.TryGetValue(tagName, out var tag)) + { + // Проверяем, что связь еще не существует + if (!hack.Tags.Any(t => t.TagId == tag.Id)) + { + hack.Tags.Add(new HackathonTagEntity + { + HackathonId = hackId, + TagId = tag.Id + }); + } + } + else + { + // Создаем новый тег + var newTag = new TagEntity + { + TagName = tagName, + TagClassName = "hack" + }; + newTagsToAdd.Add(newTag); + + // Добавляем связь с новым тегом + // (ID тега будет установлен после сохранения) + hack.Tags.Add(new HackathonTagEntity + { + HackathonId = hackId, + TagId = tag.Id + }); + } + + } + // Добавляем новые теги в контекст + if (newTagsToAdd.Count != 0) + { + await _context.Tags.AddRangeAsync(newTagsToAdd, token); + } + + // Сохраняем изменения + await _context.SaveChangesAsync(token); + } + } +} diff --git a/MethodologyMain.Persistence/Repository/TeamRepository.cs b/MethodologyMain.Persistence/Repository/TeamRepository.cs index 0ea85d4..72a88b5 100644 --- a/MethodologyMain.Persistence/Repository/TeamRepository.cs +++ b/MethodologyMain.Persistence/Repository/TeamRepository.cs @@ -1,6 +1,7 @@ using MethodologyMain.Logic.Entities; using MethodologyMain.Persistence.Interfaces; using MethodTeams.Data; +using MethodTeams.Models; using Microsoft.EntityFrameworkCore; namespace MethodologyMain.Persistence.Repository @@ -15,7 +16,8 @@ public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CheckCancellation(token); var user = await _context.Users .AsNoTracking() - .FirstAsync(e => e.Id == userId, token); + .FirstOrDefaultAsync(e => e.Id == userId, token); + if (user == null) return true; return user.Teams.Find(m => m.Team.HackathonId == hackathonId) != null; } public async Task CheckUserInTeamAsync(Guid userId, Guid teamId, CancellationToken token) @@ -44,6 +46,7 @@ public async Task RemoveTeamAsync(Guid teamId, CancellationToken token) var team = await GetTeamAsync(teamId, token); if (team.Members is not null) { var _ = team.Members.RemoveAll; } _context.Teams.Remove(team); + await SaveChangesAsync(token); } public async Task RemoveMemberAsync(Guid userId, Guid teamId, CancellationToken token) @@ -70,10 +73,38 @@ public async Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, Cancellat var team = await GetTeamNoTrackingAsync(teamId, token); return team.HackathonId; } - public async Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token) + public async Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token) { var team = await GetTeamAsync(teamId, token); - return team.Members.Select(m => m.UserId).ToList(); + return team.Members.Select(m => m.User.UserName).ToList(); + } + public async Task?> GetTeamByHackathonAsync(Guid HackathonId, CancellationToken token) + { + CheckCancellation(token); + var team = await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) + .Where(m => m.HackathonId == HackathonId) + .ToListAsync(token); + return team; + } + public async Task UpdateTeamAsync(TeamEntity team, CancellationToken token) + { + CheckCancellation(token); + _context.Update(team); + await _context.SaveChangesAsync(token); + } + public async Task> GetTeamsAllAsync(CancellationToken token) + { + CheckCancellation(token); + return await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) + .ToListAsync(token); } private static void CheckCancellation(CancellationToken token) { @@ -83,13 +114,22 @@ private async Task GetTeamNoTrackingAsync(Guid teamId, CancellationT { CheckCancellation(token); return await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) .AsNoTracking() - .FirstAsync(e => e.Id == teamId, token); + .FirstOrDefaultAsync(e => e.Id == teamId, token); } - private async Task GetTeamAsync(Guid teamId, CancellationToken token) + public async Task GetTeamAsync(Guid teamId, CancellationToken token) { CheckCancellation(token); - return await _context.Teams.FindAsync([teamId], token); + return await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) + .FirstOrDefaultAsync(m => m.Id == teamId); } private async Task SaveChangesAsync(CancellationToken token) { diff --git a/MethodologyMain.Persistence/Repository/UserRepository.cs b/MethodologyMain.Persistence/Repository/UserRepository.cs index 8bb81b2..9f93f4e 100644 --- a/MethodologyMain.Persistence/Repository/UserRepository.cs +++ b/MethodologyMain.Persistence/Repository/UserRepository.cs @@ -1,6 +1,14 @@ using MethodologyMain.Logic.Entities; +using MethodologyMain.Logic.Models; using MethodologyMain.Persistence.Interfaces; using MethodTeams.Data; +using MethodTeams.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace MethodologyMain.Persistence.Repository { @@ -9,7 +17,36 @@ public class UserRepository: GenericRepository, IUserRepository public UserRepository(MyDbContext context) : base(context) { } - + public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token) + { + CheckCancellation(token); + var user = await _context.Users + .AsNoTracking() + .FirstOrDefaultAsync(e => e.Id == userId, token); + return user.Teams.Find(m => m.Team.HackathonId == hackathonId) != null; + } + public async Task RemoveAsync(Guid userId, CancellationToken token) + { + CheckCancellation(token); + var user = await _context.Users.FindAsync([userId], token); + _context.Users.Remove(user); + await SaveChangesAsync(token); + } + public async Task UpdateAsync(UserMainEntity user, CancellationToken token) + { + CheckCancellation(token); + _context.Update(user); + await SaveChangesAsync(token); + } + private static void CheckCancellation(CancellationToken token) + { + token.ThrowIfCancellationRequested(); + } + private async Task SaveChangesAsync(CancellationToken token) + { + CheckCancellation(token); + await _context.SaveChangesAsync(token); + } } } diff --git a/docker-compose.dcproj b/docker-compose.dcproj new file mode 100644 index 0000000..87e67a7 --- /dev/null +++ b/docker-compose.dcproj @@ -0,0 +1,19 @@ + + + + 2.1 + Linux + False + 81dded9d-158b-e303-5f62-77a2896d2a5a + LaunchBrowser + {Scheme}://localhost:{ServicePort}/swagger + methodologymain.api + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..062650e --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,14 @@ +services: + methodologymain.api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_HTTP_PORTS=8080 + - ASPNETCORE_HTTPS_PORTS=8081 + ports: + - "8080" + - "8081" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d292808 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,82 @@ +name: authMetodologyService + +services: + methodologymain.api: + image: ${DOCKER_REGISTRY-}methodologymainapi + build: + context: . + dockerfile: MethodologyMain.API/Dockerfile + + postgres: + container_name: auth_db + image: postgres:latest + volumes: + - postgres-data:/var/lib/postgresql/data + environment: + POSTGRES_DB: authdb + POSTGRES_USER: admin + POSTGRES_PASSWORD: password123! + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U admin -d authdb"] + interval: 10s + timeout: 3s + retries: 3 + networks: + - authNet + restart: unless-stopped + + pgadmin: + container_name: pgadmin + image: dpage/pgadmin4:latest + environment: + PGADMIN_DEFAULT_EMAIL: admin@example.com + PGADMIN_DEFAULT_PASSWORD: password + ports: + - "5050:80" + depends_on: + postgres: + condition: service_healthy + networks: + - authNet + restart: unless-stopped + + rabbitmq: + image: rabbitmq:management-alpine + container_name: rabbitmqForAuth + volumes: + - rabbit-data:/var/lib/rabbitmq + restart: always + ports: + - 5672:5672 + - 15672:15672 + networks: + - authNet + depends_on: + postgres: + condition: service_healthy + + redis: + image: redis + restart: always + volumes: + - redis-data:/data + ports: + - "6379:6379" + networks: + - authNet + depends_on: + postgres: + condition: service_healthy + +networks: + authNet: + name: authNet + driver: bridge + +volumes: + postgres-data: + rabbit-data: + redis-data: + grafana-data: \ No newline at end of file diff --git a/launchSettings.json b/launchSettings.json new file mode 100644 index 0000000..428a8d9 --- /dev/null +++ b/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "Docker Compose": { + "commandName": "DockerCompose", + "commandVersion": "1.0", + "serviceActions": { + "methodologymain.api": "StartDebugging" + } + } + } +} \ No newline at end of file