diff --git a/SurveyBackend/SurveyBackend.API/Contexts/UserContext.cs b/SurveyBackend/SurveyBackend.API/Contexts/UserContext.cs index de5e7f1..337e9e1 100644 --- a/SurveyBackend/SurveyBackend.API/Contexts/UserContext.cs +++ b/SurveyBackend/SurveyBackend.API/Contexts/UserContext.cs @@ -24,8 +24,19 @@ public class UserContext : IUserContext /// Возвращает UserId из токена, при отсуствии кидает Unauthorized /// /// - public int UserId => - int.Parse( - _httpContextAccessor.HttpContext?.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier) - ?.Value ?? throw new UnauthorizedException("Where's your token mister")); + //public int UserId => + // int.Parse( + // _httpContextAccessor.HttpContext?.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? throw new UnauthorizedException("Where's your token mister")); + private string? ClaimValue + => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); + + public int UserId + => int.TryParse(ClaimValue, out var id) + ? id + : throw new UnauthorizedException("User ID claim missing or malformed"); + + public int? NullableUserId + => int.TryParse(ClaimValue, out var id) + ? id + : null; } \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/Controllers/AnswerController.cs b/SurveyBackend/SurveyBackend.API/Controllers/AnswerController.cs new file mode 100644 index 0000000..27453e6 --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/Controllers/AnswerController.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using SurveyBackend.Mappers; +using SurveyLib.Core.Services; + +namespace SurveyBackend.Controllers; + +[ApiController] +public class AnswerController : ControllerBase +{ + private readonly IAnswerService _answerService; + + public AnswerController(IAnswerService answerService) + { + _answerService = answerService; + } + + [Authorize] + [HttpGet] + [Route("api/questions/{id:int}/answers")] + public async Task GetAnswersByQuestionId(int id) + { + var models = await _answerService.GetAnswersByQuestionIdAsync(id); + var result = models.Select(AnswerMapper.ModelToOutputDto); + return Ok(result); + } + + [Authorize] + [HttpGet] + [Route("api/completions/{id:int}/answers")] + public async Task GetAnswersByCompletionId(int id) + { + var models = await _answerService.GetAnswersByCompletionIdAsync(id); + var result = models.Select(AnswerMapper.ModelToOutputDto); + return Ok(result); + } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/Controllers/AnswerVariantsController.cs b/SurveyBackend/SurveyBackend.API/Controllers/AnswerVariantsController.cs index fe44196..1aca7f9 100644 --- a/SurveyBackend/SurveyBackend.API/Controllers/AnswerVariantsController.cs +++ b/SurveyBackend/SurveyBackend.API/Controllers/AnswerVariantsController.cs @@ -52,16 +52,15 @@ public class AnswerVariantsController : ControllerBase /// /// Обновить вариант ответа на вопрос /// - /// Идентификатор опроса - /// Идентификатор вопроса /// Идентификатор варианта ответа /// Объект с данными для обновления варианта ответа /// Результат обновленного варианта ответа [Authorize] - [HttpPut("{id}")] - public async Task Update(int surveyId, int questionId, int id, [FromBody] AnswerVariantUpdateDto dto) + [HttpPut] + [Route("/api/answerVariants/{id:int}")] + public async Task Update(int id, [FromBody] AnswerVariantUpdateDto dto) { - var model = AnswerVariantMapper.UpdateDtoToModel(dto, questionId, id); + var model = AnswerVariantMapper.UpdateDtoToModel(dto, id); await _answerVariantsService.UpdateAnswerVariantAsync(model); var result = AnswerVariantMapper.ModelToOutputDto(model); return Ok(result); @@ -70,13 +69,12 @@ public class AnswerVariantsController : ControllerBase /// /// Удалить вариант ответа на вопрос /// - /// Идентификатор опроса - /// Идентификатор вопроса /// Идентификатор варианта ответа /// Результат операции удаления [Authorize] - [HttpDelete("{id}")] - public async Task Delete(int surveyId, int questionId, int id) + [HttpDelete] + [Route("/api/answerVariants/{id:int}")] + public async Task Delete(int id) { await _answerVariantsService.DeleteAnswerVariantAsync(id); return Ok(); diff --git a/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs b/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs index 5eb80ad..3457741 100644 --- a/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs +++ b/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs @@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using SurveyBackend.Core.Contexts; using SurveyBackend.Core.Services; -using SurveyBackend.DTOs; using SurveyBackend.DTOs.User; using SurveyBackend.Mappers; using IAuthorizationService = SurveyBackend.Core.Services.IAuthorizationService; diff --git a/SurveyBackend/SurveyBackend.API/Controllers/CompletionController.cs b/SurveyBackend/SurveyBackend.API/Controllers/CompletionController.cs new file mode 100644 index 0000000..162fda4 --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/Controllers/CompletionController.cs @@ -0,0 +1,51 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using SurveyBackend.Core.Contexts; +using SurveyBackend.DTOs.Completion; +using SurveyBackend.Mappers; +using SurveyLib.Core.Services; + +namespace SurveyBackend.Controllers; + +[ApiController] +[Route("api/surveys/{surveyId:int}/completions")] +public class CompletionController : ControllerBase +{ + private readonly ICompletionService _completionService; + private readonly IUserContext _userContext; + + public CompletionController(ICompletionService completionService, IUserContext userContext) + { + _completionService = completionService; + _userContext = userContext; + } + + [HttpGet] + [Authorize] + public async Task GetCompletionsAsync(int surveyId) + { + var models = await _completionService.GetCompletionsBySurveyIdAsync(surveyId); + var result = models.Select(CompletionMapper.ModelToOutputDto); + return Ok(result); + } + + [HttpGet] + [Route("/api/completions/{id:int}")] + [Authorize] + public async Task GetCompletionAsync(int id) + { + var model = await _completionService.GetCompletionByIdAsync(id); + var result = CompletionMapper.ModelToOutputDto(model); + return Ok(result); + } + + [HttpPost] + [AllowAnonymous] + public async Task PostCompletionAsync([FromBody] CompletionCreateDto dto, [FromRoute] int surveyId) + { + var userId = _userContext.NullableUserId; + var model = CompletionMapper.CreateDtoToModel(dto, surveyId, userId); + await _completionService.AddCompletionAsync(model); + return Ok(); + } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/Controllers/QuestionController.cs b/SurveyBackend/SurveyBackend.API/Controllers/QuestionController.cs index ee94aab..9f1b5dc 100644 --- a/SurveyBackend/SurveyBackend.API/Controllers/QuestionController.cs +++ b/SurveyBackend/SurveyBackend.API/Controllers/QuestionController.cs @@ -64,11 +64,11 @@ public class QuestionController : ControllerBase /// /// [Authorize] - [HttpPut("{id}")] - public async Task UpdateQuestion([FromBody] QuestionUpdateDto dto, [FromRoute] int id, - [FromRoute] int surveyId) + [HttpPut] + [Route("/api/questions/{id:int}")] + public async Task UpdateQuestion([FromBody] QuestionUpdateDto dto, [FromRoute] int id) { - var question = QuestionMapper.QuestionUpdateToModel(dto, surveyId, id); + var question = QuestionMapper.QuestionUpdateToModel(dto, id); await _questionService.UpdateQuestionAsync(question); var result = QuestionMapper.ModelToQuestionDto(question); return Ok(result); @@ -81,8 +81,9 @@ public class QuestionController : ControllerBase /// /// [Authorize] - [HttpDelete("{id}")] - public async Task DeleteQuestion([FromRoute] int id, [FromRoute] int surveyId) + [HttpDelete] + [Route("/api/questions/{id:int}")] + public async Task DeleteQuestion([FromRoute] int id) { await _questionService.DeleteQuestionAsync(id); return Ok(); diff --git a/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs b/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs index 6dbf611..1440bf8 100644 --- a/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs +++ b/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs @@ -1,11 +1,8 @@ -using System.Security.Claims; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using SurveyBackend.Core.Contexts; using SurveyBackend.DTOs.Survey; using SurveyBackend.Mappers; -using SurveyBackend.Services.Exceptions; -using SurveyLib.Core.Models; using SurveyLib.Core.Services; namespace SurveyBackend.Controllers; diff --git a/SurveyBackend/SurveyBackend.API/DTOs/Answer/AnswerCreateDto.cs b/SurveyBackend/SurveyBackend.API/DTOs/Answer/AnswerCreateDto.cs new file mode 100644 index 0000000..f2040f1 --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/DTOs/Answer/AnswerCreateDto.cs @@ -0,0 +1,7 @@ +namespace SurveyBackend.DTOs.Answer; + +public class AnswerCreateDto +{ + public int QuestionId { get; set; } + public required string AnswerText { get; set; } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/DTOs/Answer/AnswerOutputDto.cs b/SurveyBackend/SurveyBackend.API/DTOs/Answer/AnswerOutputDto.cs new file mode 100644 index 0000000..a3dec70 --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/DTOs/Answer/AnswerOutputDto.cs @@ -0,0 +1,8 @@ +namespace SurveyBackend.DTOs.Answer; + +public class AnswerOutputDto +{ + public int QuestionId { get; set; } + public int CompletionId { get; set; } + public required string AnswerText { get; set; } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/DTOs/Completion/CompletionCreateDto.cs b/SurveyBackend/SurveyBackend.API/DTOs/Completion/CompletionCreateDto.cs new file mode 100644 index 0000000..daac77f --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/DTOs/Completion/CompletionCreateDto.cs @@ -0,0 +1,8 @@ +using SurveyBackend.DTOs.Answer; + +namespace SurveyBackend.DTOs.Completion; + +public class CompletionCreateDto +{ + public List Answers { get; set; } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/DTOs/Completion/CompletionOutputDto.cs b/SurveyBackend/SurveyBackend.API/DTOs/Completion/CompletionOutputDto.cs new file mode 100644 index 0000000..c83305c --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/DTOs/Completion/CompletionOutputDto.cs @@ -0,0 +1,9 @@ +namespace SurveyBackend.DTOs.Completion; + +public class CompletionOutputDto +{ + public int Id { get; set; } + public int SurveyId { get; set; } + public int? CompletedBy { get; set; } + public DateTime FinishedAt { get; set; } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/Mappers/AnswerMapper.cs b/SurveyBackend/SurveyBackend.API/Mappers/AnswerMapper.cs new file mode 100644 index 0000000..c5fd2bd --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/Mappers/AnswerMapper.cs @@ -0,0 +1,20 @@ +using SurveyBackend.DTOs.Answer; +using SurveyLib.Core.Models; + +namespace SurveyBackend.Mappers; + +public static class AnswerMapper +{ + public static Answer CreateDtoToModel(AnswerCreateDto dto) => new Answer + { + QuestionId = dto.QuestionId, + AnswerText = dto.AnswerText, + }; + + public static AnswerOutputDto ModelToOutputDto(Answer model) => new AnswerOutputDto + { + QuestionId = model.QuestionId, + AnswerText = model.AnswerText, + CompletionId = model.CompletionId, + }; +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/Mappers/AnswerVariantMapper.cs b/SurveyBackend/SurveyBackend.API/Mappers/AnswerVariantMapper.cs index 337f043..97e6892 100644 --- a/SurveyBackend/SurveyBackend.API/Mappers/AnswerVariantMapper.cs +++ b/SurveyBackend/SurveyBackend.API/Mappers/AnswerVariantMapper.cs @@ -11,10 +11,9 @@ public static class AnswerVariantMapper Text = dto.Text }; - public static AnswerVariant UpdateDtoToModel(AnswerVariantUpdateDto dto, int questionId, int answerVariantId) => + public static AnswerVariant UpdateDtoToModel(AnswerVariantUpdateDto dto, int answerVariantId) => new AnswerVariant { - QuestionId = questionId, Id = answerVariantId, Text = dto.Text }; diff --git a/SurveyBackend/SurveyBackend.API/Mappers/CompletionMapper.cs b/SurveyBackend/SurveyBackend.API/Mappers/CompletionMapper.cs new file mode 100644 index 0000000..3eb1edf --- /dev/null +++ b/SurveyBackend/SurveyBackend.API/Mappers/CompletionMapper.cs @@ -0,0 +1,22 @@ +using SurveyBackend.DTOs.Completion; +using SurveyLib.Core.Models; + +namespace SurveyBackend.Mappers; + +public static class CompletionMapper +{ + public static Completion CreateDtoToModel(CompletionCreateDto dto, int surveyId, int? performerId) => new Completion + { + SurveyId = surveyId, + CompletedBy = performerId, + Answers = dto.Answers.Select(AnswerMapper.CreateDtoToModel).ToList(), + }; + + public static CompletionOutputDto ModelToOutputDto(Completion model) => new CompletionOutputDto + { + Id = model.Id, + SurveyId = model.SurveyId, + CompletedBy = model.CompletedBy, + FinishedAt = model.FinishedAt + }; +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/Mappers/QuestionMapper.cs b/SurveyBackend/SurveyBackend.API/Mappers/QuestionMapper.cs index 6d50d50..6cc41dc 100644 --- a/SurveyBackend/SurveyBackend.API/Mappers/QuestionMapper.cs +++ b/SurveyBackend/SurveyBackend.API/Mappers/QuestionMapper.cs @@ -61,7 +61,7 @@ public static class QuestionMapper }; } - public static QuestionBase QuestionUpdateToModel(QuestionCreateDto dto, int surveyId, int questionId) + public static QuestionBase QuestionUpdateToModel(QuestionCreateDto dto, int questionId) { return dto.QuestionType.ToLower() switch { @@ -69,21 +69,16 @@ public static class QuestionMapper { Id = questionId, Title = dto.Title, - SurveyId = surveyId, }, "singleanswerquestion" => new SingleAnswerQuestion { Id = questionId, Title = dto.Title, - SurveyId = surveyId, - AnswerVariants = [], }, "multipleanswerquestion" => new MultipleAnswerQuestion { Id = questionId, Title = dto.Title, - SurveyId = surveyId, - AnswerVariants = [] }, _ => throw new BadRequestException("Unknown question type") }; diff --git a/SurveyBackend/SurveyBackend.API/Mappers/UserMapper.cs b/SurveyBackend/SurveyBackend.API/Mappers/UserMapper.cs index 0d9a216..87340ac 100644 --- a/SurveyBackend/SurveyBackend.API/Mappers/UserMapper.cs +++ b/SurveyBackend/SurveyBackend.API/Mappers/UserMapper.cs @@ -1,5 +1,4 @@ using SurveyBackend.Core.Models; -using SurveyBackend.DTOs; using SurveyBackend.DTOs.User; namespace SurveyBackend.Mappers; diff --git a/SurveyBackend/SurveyBackend.API/Program.cs b/SurveyBackend/SurveyBackend.API/Program.cs index 829f13f..3c66899 100644 --- a/SurveyBackend/SurveyBackend.API/Program.cs +++ b/SurveyBackend/SurveyBackend.API/Program.cs @@ -5,18 +5,13 @@ using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using SurveyBackend.Contexts; using SurveyBackend.Core.Contexts; -using SurveyBackend.Core.Repositories; -using SurveyBackend.Core.Services; using SurveyBackend.Filters; +using SurveyBackend.Infrastructure; using SurveyBackend.Infrastructure.Data; -using SurveyBackend.Infrastructure.Repositories; using SurveyBackend.Middlewares; using SurveyBackend.Services; -using SurveyBackend.Services.Services; -using SurveyLib.Core.Repositories; -using SurveyLib.Core.Services; +using SurveyLib.Infrastructure.EFCore; using SurveyLib.Infrastructure.EFCore.Data; -using SurveyLib.Infrastructure.EFCore.Repositories; namespace SurveyBackend; @@ -39,21 +34,9 @@ public class Program builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - - builder.Services.AddScoped(); - - builder.Services.AddScoped(); - - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - + builder.Services.AddSurveyBackendInfrastructure(); + builder.Services.AddSurveyLibInfrastructure(); + builder.Services.AddSurveyBackendServices(); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => diff --git a/SurveyBackend/SurveyBackend.Core/Contexts/IUserContext.cs b/SurveyBackend/SurveyBackend.Core/Contexts/IUserContext.cs index 4cd9127..2cc0cfa 100644 --- a/SurveyBackend/SurveyBackend.Core/Contexts/IUserContext.cs +++ b/SurveyBackend/SurveyBackend.Core/Contexts/IUserContext.cs @@ -3,4 +3,5 @@ namespace SurveyBackend.Core.Contexts; public interface IUserContext { int UserId { get; } + int? NullableUserId { get; } } \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.Core/Models/User.cs b/SurveyBackend/SurveyBackend.Core/Models/User.cs index 257d4fa..bf0ad21 100644 --- a/SurveyBackend/SurveyBackend.Core/Models/User.cs +++ b/SurveyBackend/SurveyBackend.Core/Models/User.cs @@ -1,5 +1,3 @@ -using Microsoft.AspNetCore.Identity; - namespace SurveyBackend.Core.Models; public class User diff --git a/SurveyBackend/SurveyBackend.Infrastructure/DependencyInjection.cs b/SurveyBackend/SurveyBackend.Infrastructure/DependencyInjection.cs new file mode 100644 index 0000000..b39ef85 --- /dev/null +++ b/SurveyBackend/SurveyBackend.Infrastructure/DependencyInjection.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.DependencyInjection; +using SurveyBackend.Core.Repositories; +using SurveyBackend.Infrastructure.Repositories; + +namespace SurveyBackend.Infrastructure; + +public static class DependencyInjection +{ + public static IServiceCollection AddSurveyBackendInfrastructure(this IServiceCollection services) + { + services.AddScoped(); + + return services; + } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.Services/DependencyInjection.cs b/SurveyBackend/SurveyBackend.Services/DependencyInjection.cs new file mode 100644 index 0000000..6523f4f --- /dev/null +++ b/SurveyBackend/SurveyBackend.Services/DependencyInjection.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.DependencyInjection; +using SurveyBackend.Core.Services; +using SurveyBackend.Services.Helpers; +using SurveyBackend.Services.Services; +using SurveyLib.Core.Services; + +namespace SurveyBackend.Services; + +public static class DependencyInjection +{ + public static IServiceCollection AddSurveyBackendServices(this IServiceCollection services) + { + services.AddScoped(); + + services.AddScoped(); + + services.AddScoped(); + + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + return services; + } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.Services/Services/Sha256PasswordHasher.cs b/SurveyBackend/SurveyBackend.Services/Helpers/Sha256PasswordHasher.cs similarity index 97% rename from SurveyBackend/SurveyBackend.Services/Services/Sha256PasswordHasher.cs rename to SurveyBackend/SurveyBackend.Services/Helpers/Sha256PasswordHasher.cs index ed54508..ec91b8b 100644 --- a/SurveyBackend/SurveyBackend.Services/Services/Sha256PasswordHasher.cs +++ b/SurveyBackend/SurveyBackend.Services/Helpers/Sha256PasswordHasher.cs @@ -1,7 +1,7 @@ using System.Security.Cryptography; using SurveyBackend.Core.Services; -namespace SurveyBackend.Services.Services; +namespace SurveyBackend.Services.Helpers; public class Sha256PasswordHasher : IPasswordHasher { diff --git a/SurveyBackend/SurveyBackend.Services/Services/AnswerService.cs b/SurveyBackend/SurveyBackend.Services/Services/AnswerService.cs new file mode 100644 index 0000000..e3fba4e --- /dev/null +++ b/SurveyBackend/SurveyBackend.Services/Services/AnswerService.cs @@ -0,0 +1,58 @@ +using SurveyBackend.Services.Exceptions; +using SurveyLib.Core.Models; +using SurveyLib.Core.Repositories; +using SurveyLib.Core.Services; + +namespace SurveyBackend.Services.Services; + +public class AnswerService : IAnswerService +{ + private readonly IAnswerRepository _answerRepository; + private readonly IQuestionRepository _questionRepository; + private readonly ICompletionRepository _completionRepository; + + public AnswerService(IAnswerRepository answerRepository, IQuestionRepository questionRepository, + ICompletionRepository completionRepository) + { + _answerRepository = answerRepository; + _questionRepository = questionRepository; + _completionRepository = completionRepository; + } + + public async Task AddAnswerAsync(Answer answer) + { + await _answerRepository.AddAsync(answer); + } + + public async Task UpdateAnswerAsync(Answer answer) + { + await _answerRepository.UpdateAsync(answer); + } + + public async Task DeleteAnswerAsync(int id) + { + await _answerRepository.DeleteAsync(id); + } + + public async Task> GetAnswersByCompletionIdAsync(int completionId) + { + var completion = await _completionRepository.GetByIdAsync(completionId); + if (completion is null) + { + throw new NotFoundException("Completion not found"); + } + + return await _answerRepository.GetAnswersByCompletionIdAsync(completionId); + } + + public async Task> GetAnswersByQuestionIdAsync(int questionId) + { + var question = await _questionRepository.GetByIdAsync(questionId); + if (question is null) + { + throw new NotFoundException("Question not found"); + } + + return await _answerRepository.GetAnswersByQuestionIdAsync(questionId); + } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.Services/Services/AnswerVariantsService.cs b/SurveyBackend/SurveyBackend.Services/Services/AnswerVariantsService.cs index bd46cba..091d1f7 100644 --- a/SurveyBackend/SurveyBackend.Services/Services/AnswerVariantsService.cs +++ b/SurveyBackend/SurveyBackend.Services/Services/AnswerVariantsService.cs @@ -1,3 +1,4 @@ +using SurveyBackend.Services.Exceptions; using SurveyLib.Core.Models; using SurveyLib.Core.Repositories; using SurveyLib.Core.Services; @@ -7,34 +8,76 @@ namespace SurveyBackend.Services.Services; public class AnswerVariantsService : IAnswerVariantsService { private readonly IAnswerVariantsRepository _answerVariantsRepository; + private readonly IQuestionRepository _questionRepository; - public AnswerVariantsService(IAnswerVariantsRepository answerVariantsRepository) + public AnswerVariantsService(IAnswerVariantsRepository answerVariantsRepository, + IQuestionRepository questionRepository) { _answerVariantsRepository = answerVariantsRepository; + _questionRepository = questionRepository; } + // TODO: любой кто будет читать этот код, я понимаю проблему дублирования, не злитесь пожалуйста, я потом пишу на адекватные валидаторы и не будет дублирования public async Task AddAnswerVariantAsync(AnswerVariant answerVariant) { + var question = await _questionRepository.GetByIdAsync(answerVariant.QuestionId); + if (question is null) + { + throw new NotFoundException("Question not found"); + } + await _answerVariantsRepository.AddAsync(answerVariant); } public async Task UpdateAnswerVariantAsync(AnswerVariant answerVariant) { + var question = await _questionRepository.GetByIdAsync(answerVariant.QuestionId); + if (question is null) + { + throw new NotFoundException("Question not found"); + } + + var answerVariantBase = await _answerVariantsRepository.GetByIdAsNoTrackingAsync(answerVariant.Id); + if (answerVariantBase is null) + { + throw new NotFoundException("Answer Variant not found"); + } + + answerVariant.QuestionId = answerVariantBase.QuestionId; + await _answerVariantsRepository.UpdateAsync(answerVariant); } public async Task DeleteAnswerVariantAsync(int id) { + var answerVariantBase = await _answerVariantsRepository.GetByIdAsNoTrackingAsync(id); + if (answerVariantBase is null) + { + throw new NotFoundException("Answer Variant not found"); + } + await _answerVariantsRepository.DeleteAsync(id); } public async Task GetAnswerVariantByIdAsync(int id) { - return await _answerVariantsRepository.GetByIdAsync(id); + var answerVariant = await _answerVariantsRepository.GetByIdAsync(id); + if (answerVariant is null) + { + throw new NotFoundException("Answer Variant not found"); + } + + return answerVariant; } public async Task> GetAnswerVariantsByQuestionIdAsync(int questionId) { + var question = await _questionRepository.GetByIdAsync(questionId); + if (question is null) + { + throw new NotFoundException("Question not found"); + } + return await _answerVariantsRepository.GetAnswerVariantsByQuestionIdAsync(questionId); } } \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.Services/Services/CompletionService.cs b/SurveyBackend/SurveyBackend.Services/Services/CompletionService.cs new file mode 100644 index 0000000..6aee2dc --- /dev/null +++ b/SurveyBackend/SurveyBackend.Services/Services/CompletionService.cs @@ -0,0 +1,64 @@ +using SurveyBackend.Services.Exceptions; +using SurveyLib.Core.Models; +using SurveyLib.Core.Repositories; +using SurveyLib.Core.Services; + +namespace SurveyBackend.Services.Services; + +public class CompletionService : ICompletionService +{ + private readonly ICompletionRepository _completionRepository; + private readonly ISurveyRepository _surveyRepository; + + public CompletionService(ICompletionRepository completionRepository, ISurveyRepository surveyRepository) + { + _completionRepository = completionRepository; + _surveyRepository = surveyRepository; + } + + public async Task AddCompletionAsync(Completion completion) + { + var survey = await _surveyRepository.GetByIdAsync(completion.SurveyId); + if (survey is null) + { + throw new NotFoundException("Survey not found"); + } + + await _completionRepository.AddAsync(completion); + } + + public async Task UpdateCompletionAsync(Completion completion) + { + // TODO: лол а что вообще значит ОбновитьВыполнение, надо выпилить из SurveyLib + await _completionRepository.UpdateAsync(completion); + } + + public async Task DeleteCompletionAsync(int id) + { + // TODO: да и удалять их как-то бессмысленно + await _completionRepository.DeleteAsync(id); + } + + public async Task GetCompletionByIdAsync(int id) + { + var completion = await _completionRepository.GetByIdAsync(id); + if (completion is null) + { + throw new NotFoundException("Completion not found"); + } + + return completion; + } + + public async Task> GetCompletionsBySurveyIdAsync(int surveyId) + { + var survey = await _surveyRepository.GetByIdAsync(surveyId); + if (survey is null) + { + throw new NotFoundException("Survey not found"); + } + + // TODO: проверить что запрашивает создатель (хз как) + return await _completionRepository.GetCompletionsBySurveyIdAsync(surveyId); + } +} \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.Services/Services/QuestionService.cs b/SurveyBackend/SurveyBackend.Services/Services/QuestionService.cs index a726427..2dcf297 100644 --- a/SurveyBackend/SurveyBackend.Services/Services/QuestionService.cs +++ b/SurveyBackend/SurveyBackend.Services/Services/QuestionService.cs @@ -22,11 +22,25 @@ public class QuestionService : IQuestionService public async Task AddQuestionAsync(QuestionBase question) { + var survey = await _surveyRepository.GetByIdAsync(question.SurveyId); + if (survey is null) + { + throw new NotFoundException("Survey not found"); + } + await _questionRepository.AddAsync(question); } public async Task UpdateQuestionAsync(QuestionBase question) { + var questionBase = await _questionRepository.GetByIdAsNoTrackingAsync(question.Id); + if (questionBase is null) + { + throw new NotFoundException("Question not found"); + } + + question.SurveyId = questionBase.SurveyId; + await _questionRepository.UpdateAsync(question); } diff --git a/SurveyBackend/SurveyBackend.Services/Services/SurveyService.cs b/SurveyBackend/SurveyBackend.Services/Services/SurveyService.cs index b39c371..78e0da8 100644 --- a/SurveyBackend/SurveyBackend.Services/Services/SurveyService.cs +++ b/SurveyBackend/SurveyBackend.Services/Services/SurveyService.cs @@ -1,5 +1,4 @@ using SurveyBackend.Core.Contexts; -using SurveyBackend.Core.Repositories; using SurveyBackend.Services.Exceptions; using SurveyLib.Core.Models; using SurveyLib.Core.Repositories; @@ -64,6 +63,7 @@ public class SurveyService : ISurveyService public async Task> GetSurveysByUserIdAsync(int userId) { + // TODO: проверить существование юзера return await _surveyRepository.GetSurveysByUserIdAsync(userId); } } \ No newline at end of file diff --git a/SurveyLib b/SurveyLib index 7d47ab9..d9f16ee 160000 --- a/SurveyLib +++ b/SurveyLib @@ -1 +1 @@ -Subproject commit 7d47ab9e60645032bc41daee5535aba2b7eeebdf +Subproject commit d9f16ee761e31bb7af7a067c38f5fa02083f9d6c