diff --git a/Tsi1.Api/Tsi1.Api/Controllers/SurveyController.cs b/Tsi1.Api/Tsi1.Api/Controllers/SurveyController.cs new file mode 100644 index 0000000000000000000000000000000000000000..c05513baa8b3a89a686e1959d220d37defa0377f --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/SurveyController.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class SurveyController : ControllerBase + { + private readonly ISurveyService _surveyService; + + public SurveyController(ISurveyService surveyService) + { + _surveyService = surveyService; + } + + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)] + [HttpPost("Create")] + public async Task<IActionResult> Create(SurveyCreateDto newSurvey, int tenantId) + { + var userType = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value; + if (userType == UserTypes.FacultyAdmin) + { + tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + } + + newSurvey.TenantId = tenantId; + newSurvey.IsGlobal = true; + + var result = await _surveyService.CreateGlobalSurvey(newSurvey); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)] + [HttpDelete("Delete/{surveyId}")] + public async Task<IActionResult> Delete(int surveyId) + { + var userType = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value; + var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + + var result = await _surveyService.DeleteGlobalSurvey(surveyId, userType, tenantId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)] + [HttpGet("GetAll")] + public async Task<IActionResult> GetAll(int tenantId) + { + var userType = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value; + if (userType == UserTypes.FacultyAdmin) + { + tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + } + + var result = await _surveyService.GetAllGlobalSurvey(tenantId, userType); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)] + [HttpGet("Get/{surveyId}")] + public async Task<IActionResult> Get(int surveyId) + { + var result = await _surveyService.GetGlobalSurvey(surveyId); + + if (result.HasError) + { + return NotFound(result.Message); + } + + return Ok(result.Data); + } + + } +} diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index f095493994a5b4c950542864524b7f21e5199dd5..e184faab868f1eb3db376a555f92bf0c9ab0d66d 100644 --- a/Tsi1.Api/Tsi1.Api/Startup.cs +++ b/Tsi1.Api/Tsi1.Api/Startup.cs @@ -81,6 +81,7 @@ namespace Tsi1.Api services.AddScoped<ISectionItemService, SectionItemService>(); services.AddScoped<ISectionItemTypeService, SectionItemTypeService>(); services.AddScoped<IDataLoad, DataLoad>(); + services.AddScoped<ISurveyService, SurveyService>(); services.Configure<MailSettings>(Configuration.GetSection("MailSettings")); services.AddScoped<IEmailService, EmailService>(); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..9ef1eef2348f743caa5fe4a70168ff38c28f0881 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyCreateDto.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SurveyCreateDto + { + public string Name { get; set; } + + [JsonIgnore] + public bool IsGlobal { get; set; } + + [JsonIgnore] + public int TenantId { get; set; } + + public ICollection<SurveyQuestionCreateDto> SurveyQuestions { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyDetailDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyDetailDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..8d265956a3ff56d3e342d832bc83f161608f1b40 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyDetailDto.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SurveyDetailDto + { + public int Id { get; set; } + public string Name { get; set; } + public bool IsGlobal { get; set; } + public int TenantId { get; set; } + + public ICollection<SurveyQuestionPreviewDto> SurveyQuestions { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyPreviewDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..ddcdc32828e3c655db1cccf858e9ce065adcbc7c --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyPreviewDto.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SurveyPreviewDto + { + public int Id { get; set; } + public string Name { get; set; } + public int TenantId { get; set; } + + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyQuestionCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyQuestionCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..e9b9f89a41fde5227c6b670e096025933563f98d --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyQuestionCreateDto.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SurveyQuestionCreateDto + { + public string Question { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyQuestionPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyQuestionPreviewDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..3767f926acf956024b1a427caec6ad8dc9879051 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SurveyQuestionPreviewDto.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SurveyQuestionPreviewDto + { + public int Id { get; set; } + public string Question { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs index 41b7cf04530200739506f9fc996dff91c0ac3b81..0f99100c3ee37acf131bedaab038d08f55ab333f 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs @@ -54,5 +54,7 @@ namespace Tsi1.BusinessLayer.Helpers public const string ForumIsNull = "El foro es nulo"; public const string FileIsNull = "El archivo es nulo"; public const string InvalidSectionItemData = "El tipo de item de seccion '{0}' no coincide con su contenido '{1}'"; + + public const string SurveyDoesNotExist = "La encuesta con id '{0}' no existe"; } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs index 4d7d53b30ba60bfd543f4520cac5d16b0a07d6c2..b6da4ce693a5224e87f7a5cb192e09723a3c58b7 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -35,13 +35,16 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<File, FileDto>(); CreateMap<SectionItem, SectionItemCreateDto>(); CreateMap<Section, SectionCreateDto>(); - CreateMap<SectionItemType, SectionItemTypeDto>(); - + CreateMap<SectionItemType, SectionItemTypeDto>(); CreateMap<Course, CourseDetailDto>(); CreateMap<Section, SectionDetailDto>(); CreateMap<SectionItem, SectionItemDetailDto>(); CreateMap<File, FileDetailDto>(); - + CreateMap<Survey, SurveyCreateDto>(); + CreateMap<Survey, SurveyPreviewDto>(); + CreateMap<Survey, SurveyDetailDto>(); + CreateMap<SurveyQuestion, SurveyQuestionCreateDto>(); + CreateMap<SurveyQuestion, SurveyQuestionPreviewDto>(); CreateMap<ForumCreateDto, Forum>(); CreateMap<ForumPreviewDto, Forum>(); @@ -67,11 +70,16 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<SectionItemCreateDto, SectionItem>(); CreateMap<SectionCreateDto, Section>(); CreateMap<SectionItemTypeDto, SectionItemType>(); - CreateMap<CourseDetailDto, Course>(); CreateMap<SectionDetailDto, Section>(); CreateMap<SectionItemDetailDto, SectionItem>(); CreateMap<FileDetailDto, File>(); + CreateMap<SurveyCreateDto, Survey>(); + CreateMap<SurveyDetailDto, Survey>(); + CreateMap<SurveyPreviewDto, Survey>(); + CreateMap<SurveyQuestionCreateDto, SurveyQuestion>(); + CreateMap<SurveyQuestionPreviewDto, SurveyQuestion>(); + } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISurveyService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISurveyService.cs new file mode 100644 index 0000000000000000000000000000000000000000..d77f1be63ab064dab9326b30cfc69134ae67d175 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISurveyService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface ISurveyService + { + Task<ServiceResult<bool>> CreateGlobalSurvey(SurveyCreateDto newSurvey); + Task<ServiceResult<bool>> DeleteGlobalSurvey(int surveyId, string userType, int tenantId); + Task<ServiceResult<List<SurveyPreviewDto>>> GetAllGlobalSurvey(int tenantId, string userType); + Task<ServiceResult<SurveyDetailDto>> GetGlobalSurvey(int surveyId); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/SurveyService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/SurveyService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b442eb88a30ada87472ab07edc8002590222e3ba --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/SurveyService.cs @@ -0,0 +1,118 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; +using Tsi1.DataLayer; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Services +{ + public class SurveyService : ISurveyService + { + private readonly Tsi1Context _context; + private readonly IMapper _mapper; + + public SurveyService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task<ServiceResult<bool>> CreateGlobalSurvey(SurveyCreateDto newSurvey) + { + var result = new ServiceResult<bool>(); + + var tenant = await _context.Tenants.FirstOrDefaultAsync(x => x.Id == newSurvey.TenantId); + + if (tenant == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.TenantDoesNotExist, newSurvey.TenantId)); + return result; + } + + var survey = _mapper.Map<Survey>(newSurvey); + + _context.Surveys.Add(survey); + + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<bool>> DeleteGlobalSurvey(int surveyId, string userType, int tenantId) + { + var result = new ServiceResult<bool>(); + + var survey = await _context.Surveys.FirstOrDefaultAsync(x => x.Id == surveyId); + + if (survey == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SurveyDoesNotExist, surveyId)); + return result; + } + + if (userType == UserTypes.FacultyAdmin && survey.TenantId != tenantId) + { + result.HasError = true; + result.AddMessage("No se puede borrar una encuesta de otra facultad"); + return result; + } + + _context.Surveys.Remove(survey); + + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<List<SurveyPreviewDto>>> GetAllGlobalSurvey(int tenantId, string userType) + { + var result = new ServiceResult<List<SurveyPreviewDto>>(); + + var tenant = await _context.Tenants.FirstOrDefaultAsync(x => x.Id == tenantId); + var tenantAdmin = await _context.Tenants.FirstOrDefaultAsync(x => x.Name == TenantAdmin.Name); + + if (tenant == null || userType == UserTypes.UdelarAdmin && tenantAdmin.Id == tenantId) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.TenantDoesNotExist, tenantId)); + return result; + } + + var surveys = await _context.Surveys + .Where(x => x.TenantId == tenantId && x.IsGlobal) + .ToListAsync(); + + result.Data = _mapper.Map<List<SurveyPreviewDto>>(surveys); + + return result; + } + + public async Task<ServiceResult<SurveyDetailDto>> GetGlobalSurvey(int surveyId) + { + var result = new ServiceResult<SurveyDetailDto>(); + + var survey = await _context.Surveys + .Include(x => x.SurveyQuestions) + .FirstOrDefaultAsync(x => x.Id == surveyId); + + if (survey == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SurveyDoesNotExist, surveyId)); + return result; + } + + result.Data = _mapper.Map<SurveyDetailDto>(survey); + return result; + } + } +}