diff --git a/src/api/VoteMonitor.Api.Form/Commands/DeleteQuestionOptionCommand.cs b/src/api/VoteMonitor.Api.Form/Commands/DeleteQuestionOptionCommand.cs new file mode 100644 index 00000000..41180747 --- /dev/null +++ b/src/api/VoteMonitor.Api.Form/Commands/DeleteQuestionOptionCommand.cs @@ -0,0 +1,17 @@ +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace VoteMonitor.Api.Form.Commands +{ + public class DeleteQuestionOptionCommand : IRequest + { + public int SectionId { get; set; } + + public int QuestionId { get; set; } + + public int OptionId { get; set; } + } +} diff --git a/src/api/VoteMonitor.Api.Form/Controllers/FormController.cs b/src/api/VoteMonitor.Api.Form/Controllers/FormController.cs index 67522ed8..0d063d99 100644 --- a/src/api/VoteMonitor.Api.Form/Controllers/FormController.cs +++ b/src/api/VoteMonitor.Api.Form/Controllers/FormController.cs @@ -174,5 +174,28 @@ public async Task DeleteQuestionAsync(int sectionId, int question return Ok(); } + + [HttpDelete("section/{sectionId}/question/{questionId}/option/{optionId}")] + [Authorize("Organizer")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DeleteQuestionOptionAsync(int sectionId, int questionId, int optionId) + { + + var deleted = await _mediator.Send(new DeleteQuestionOptionCommand() + { + QuestionId = questionId, + SectionId = sectionId, + OptionId = optionId + }); + + if (!deleted) + { + return BadRequest("The option could not be deleted. Make sure the option exists."); + } + + return Ok(); + } + } } diff --git a/src/api/VoteMonitor.Api.Form/Handlers/DeleteQuestionOptionHandler.cs b/src/api/VoteMonitor.Api.Form/Handlers/DeleteQuestionOptionHandler.cs new file mode 100644 index 00000000..c0761b58 --- /dev/null +++ b/src/api/VoteMonitor.Api.Form/Handlers/DeleteQuestionOptionHandler.cs @@ -0,0 +1,94 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using VoteMonitor.Api.Form.Commands; +using VoteMonitor.Entities; + +namespace VoteMonitor.Api.Form.Handlers +{ + public class DeleteQuestionOptionHandler : IRequestHandler + { + private readonly VoteMonitorContext _context; + public DeleteQuestionOptionHandler(VoteMonitorContext context) + { + _context = context; + } + + public async Task Handle(DeleteQuestionOptionCommand request, CancellationToken cancellationToken) + { + using (var transaction = await _context.Database.BeginTransactionAsync(cancellationToken)) + { + + var optionToBeRemoved = _context.Options.FirstOrDefault(o => o.Id == request.OptionId); + + if (optionToBeRemoved == null) + { + return false; + } + + + if (await OptionToBeDeleted(request.OptionId)) + { + if (await OptionHasAnswers(request.OptionId)) + { + return false; + } + + await DeleteQuestionsToOption(request.OptionId); + DeleteOption(optionToBeRemoved); + + } + else + { + RemoveOptionFromQuestion(request.SectionId, request.QuestionId, request.OptionId); + } + + await _context.SaveChangesAsync(); + await transaction.CommitAsync(cancellationToken); + + return true; + } + } + + private void RemoveOptionFromQuestion(int sectionId, int questionId, int optionId) + { + var questionOptionLinkToBeRemoved = _context.Questions.Where(q => q.IdSection == sectionId && q.Id == questionId) + .SelectMany(q => q.OptionsToQuestions) + .Where(otq => otq.IdOption == optionId).FirstOrDefault(); + + _context.Remove(questionOptionLinkToBeRemoved); + } + + private async Task OptionToBeDeleted(int optiondId) + { + var atMostOnOneQuestion = await _context.OptionsToQuestions + .Where(o => o.IdOption == optiondId).CountAsync() <= 1; + + return atMostOnOneQuestion; + + } + + + private async Task OptionHasAnswers(int optionId) + { + return await _context + .Answers.Where(a => a.OptionAnswered.IdOption == optionId).AnyAsync(); + } + + private async Task DeleteQuestionsToOption(int optionId) + { + var questionsToOptions = await _context.OptionsToQuestions.Where(otq => otq.IdOption == optionId).ToListAsync(); + + _context.RemoveRange(questionsToOptions); + } + + private void DeleteOption(Option option) + { + _context.Remove(option); + } + } +}