diff --git a/Tsi1.Api/Tsi1.Api/Controllers/StudentCourseResultController.cs b/Tsi1.Api/Tsi1.Api/Controllers/StudentCourseResultController.cs new file mode 100644 index 0000000000000000000000000000000000000000..7767d5b87727735ca8caa605ab26fd7bcb55fb6b --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/StudentCourseResultController.cs @@ -0,0 +1,105 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class StudentCourseResultController : ControllerBase + { + private readonly IStudentCourseResultService _studentCourseResultService; + + public StudentCourseResultController(IStudentCourseResultService studentCourseResultService) + { + _studentCourseResultService = studentCourseResultService; + } + + [Authorize(Roles = UserTypes.Student)] + [HttpGet("GetMyHistoricResults/{courseId}")] + public async Task<IActionResult> GetMyHistoricResults(int courseId) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + var result = await _studentCourseResultService.GetMyHistoricResults(courseId, userId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.Student)] + [HttpGet("GetMyLastResult/{courseId}")] + public async Task<IActionResult> GetMyLastResult(int courseId) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + var result = await _studentCourseResultService.GetMyLastResult(courseId, userId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.Professor)] + [HttpGet("GetLastStudentCourseResults/{courseId}")] + public async Task<IActionResult> GetLastStudentCourseResults(int courseId) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + var result = await _studentCourseResultService.GetLastStudentCourseResults(courseId, userId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.Professor)] + [HttpPost("Create")] + public async Task<IActionResult> Create(StudentCourseResultCreateDto studentCourseResultDto) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + var result = await _studentCourseResultService.Create(studentCourseResultDto, userId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.Professor)] + [HttpDelete("Delete/{studentCourseResultId}")] + public async Task<IActionResult> Delete(int studentCourseResultId) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + var result = await _studentCourseResultService.Delete(studentCourseResultId, userId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + } +} diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index c576fdeb3e4a0cf4abd97780a4dee362b6850e03..8a5b0b1ef8174918c249ece4d321278ee909be30 100644 --- a/Tsi1.Api/Tsi1.Api/Startup.cs +++ b/Tsi1.Api/Tsi1.Api/Startup.cs @@ -108,6 +108,7 @@ namespace Tsi1.Api services.AddScoped<IActivityService, ActivityService>(); services.AddScoped<IEvaluationService, EvaluationService>(); services.AddScoped<IEvaluationTypeService, EvaluationTypeService>(); + services.AddScoped<IStudentCourseResultService, StudentCourseResultService>(); services.AddSingleton<PresenceTracker>(); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IStudentCourseResultService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IStudentCourseResultService.cs new file mode 100644 index 0000000000000000000000000000000000000000..5fdec183e893622ae5a4ca376d12e8ef2bb828ba --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IStudentCourseResultService.cs @@ -0,0 +1,22 @@ +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 IStudentCourseResultService + { + Task<ServiceResult<int>> Create(StudentCourseResultCreateDto studentCourseResultDto, int userId); + + Task<ServiceResult<int>> Delete(int studentCourseResultId, int userId); + + Task<ServiceResult<List<StudentCourseResultPreviewDto>>> GetMyHistoricResults(int courseId, int userId); + + Task<ServiceResult<StudentCourseResultPreviewDto>> GetMyLastResult(int courseId, int userId); + + Task<ServiceResult<List<StudentCourseResultPreviewDto>>> GetLastStudentCourseResults(int courseId, int userId); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/ActivityService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/ActivityService.cs index ff629d1eaee7cfffdfc00419d14273957ef18405..67c239ff615099c447889b0e9ff8b1b6cb0e3328 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/ActivityService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/ActivityService.cs @@ -151,7 +151,11 @@ namespace Tsi1.BusinessLayer.Services return result; } - var activities = await _context.Activities.AsNoTracking().Where(x => x.CourseId == courseId).ToListAsync(); + var activities = await _context.Activities + .AsNoTracking() + .Where(x => x.CourseId == courseId) + .OrderBy(x => x.Date) + .ToListAsync(); result.Data = _mapper.Map<List<ActivityDto>>(activities); return result; diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/StudentCourseResultService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/StudentCourseResultService.cs new file mode 100644 index 0000000000000000000000000000000000000000..1f2a16dca15d27e8ec3a6761c5896f3f3e7a2937 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/StudentCourseResultService.cs @@ -0,0 +1,307 @@ +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 StudentCourseResultService : IStudentCourseResultService + { + private readonly Tsi1Context _context; + private readonly IMapper _mapper; + + public StudentCourseResultService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task<ServiceResult<int>> Create(StudentCourseResultCreateDto studentCourseResultDto, int userId) + { + var result = new ServiceResult<int>(); + + var studentValidation = await this.StudentCourseResultValidations(studentCourseResultDto.CourseId, studentCourseResultDto.StudentId); + + if (studentValidation.HasError) + { + result.HasError = true; + result.AddMessage(studentValidation.Message); + return result; + } + + var courseResult = await _context.StudentCourseResults + .AsNoTracking() + .FirstOrDefaultAsync(x => x.StudentId == studentCourseResultDto.StudentId + && x.CourseId == studentCourseResultDto.CourseId + && x.Result >= CourseApproval.MinimumApproval); + + if (courseResult != null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.CourseAlreadyApproved, studentCourseResultDto.StudentId, studentCourseResultDto.CourseId)); + return result; + } + + var professorValidation = await this.ProfessorValidations(studentCourseResultDto.CourseId, userId); + + if (professorValidation.HasError) + { + result.HasError = true; + result.AddMessage(professorValidation.Message); + return result; + } + + var studentCourseResult = _mapper.Map<StudentCourseResult>(studentCourseResultDto); + studentCourseResult.Date = DateTime.Now; + + _context.StudentCourseResults.Add(studentCourseResult); + + await _context.SaveChangesAsync(); + + result.Data = studentCourseResult.Id; + return result; + } + + public async Task<ServiceResult<int>> Delete(int studentCourseResultId, int userId) + { + var result = new ServiceResult<int>(); + + var studentCourseResult = await _context.StudentCourseResults.FirstOrDefaultAsync(x => x.Id == studentCourseResultId); + + if (studentCourseResult == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.StudentCourseResultDoesNotExist, studentCourseResultId)); + return result; + } + + var professorValidation = await this.ProfessorValidations(studentCourseResult.CourseId, userId); + + if (professorValidation.HasError) + { + result.HasError = true; + result.AddMessage(professorValidation.Message); + return result; + } + + _context.StudentCourseResults.Remove(studentCourseResult); + + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<List<StudentCourseResultPreviewDto>>> GetLastStudentCourseResults(int courseId, int userId) + { + var result = new ServiceResult<List<StudentCourseResultPreviewDto>>(); + + var professorValidation = await this.ProfessorValidations(courseId, userId); + + if (professorValidation.HasError) + { + result.HasError = true; + result.AddMessage(professorValidation.Message); + return result; + } + + var studentIds = await _context.StudentCourses + .AsNoTracking() + .Where(x => x.CourseId == courseId) + .Select(x => x.StudentId) + .ToListAsync(); + + var auxStudentCourseResults = await _context.StudentCourseResults + .AsNoTracking() + .Where(x => x.CourseId == courseId && studentIds.Contains(x.StudentId)) + .ToListAsync(); + + var studentCourseResults = auxStudentCourseResults.GroupBy(x => new { x.StudentId, x.CourseId }) + .Select(x => x.OrderByDescending(g => g.Date).First()) + .ToList(); + + result.Data = _mapper.Map<List<StudentCourseResultPreviewDto>>(studentCourseResults); + + return result; + } + + public async Task<ServiceResult<List<StudentCourseResultPreviewDto>>> GetMyHistoricResults(int courseId, int userId) + { + var result = new ServiceResult<List<StudentCourseResultPreviewDto>>(); + + var userValidation = await this.UserValidation(userId); + + if (userValidation.HasError) + { + result.HasError = true; + result.AddMessage(userValidation.Message); + return result; + } + + var studentId = userValidation.Data; + + var studentValidation = await this.StudentCourseResultValidations(courseId, studentId); + + if (studentValidation.HasError) + { + result.HasError = true; + result.AddMessage(studentValidation.Message); + return result; + } + + var studentCourseResults = await _context.StudentCourseResults + .AsNoTracking() + .Where(x => x.CourseId == courseId && x.StudentId == studentId) + .OrderByDescending(x => x.Date) + .ToListAsync(); + + result.Data = _mapper.Map<List<StudentCourseResultPreviewDto>>(studentCourseResults); + + return result; + } + + public async Task<ServiceResult<StudentCourseResultPreviewDto>> GetMyLastResult(int courseId, int userId) + { + var result = new ServiceResult<StudentCourseResultPreviewDto>(); + + var userValidation = await this.UserValidation(userId); + + if (userValidation.HasError) + { + result.HasError = true; + result.AddMessage(userValidation.Message); + return result; + } + + var studentId = userValidation.Data; + + var studentValidation = await this.StudentCourseResultValidations(courseId, studentId); + + if (studentValidation.HasError) + { + result.HasError = true; + result.AddMessage(studentValidation.Message); + return result; + } + + var studentCourseResult = await _context.StudentCourseResults + .AsNoTracking() + .Where(x => x.CourseId == courseId && x.StudentId == studentId) + .OrderByDescending(x => x.Date) + .FirstOrDefaultAsync(); + + result.Data = _mapper.Map<StudentCourseResultPreviewDto>(studentCourseResult); + + return result; + } + + private async Task<ServiceResult<int>> StudentCourseResultValidations(int courseId, int studentId) + { + var result = new ServiceResult<int>(); + + var student = await _context.Students + .AsNoTracking() + .FirstOrDefaultAsync(x => x.Id == studentId); + + if (student == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.StudentDoesNotExist, studentId)); + return result; + } + + var course = await _context.Courses + .AsNoTracking() + .FirstOrDefaultAsync(x => x.Id == courseId); + + if (course == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.CourseDoesNotExist, courseId)); + return result; + } + + var studentCourse = await _context.StudentCourses + .AsNoTracking() + .FirstOrDefaultAsync(x => x.CourseId == courseId && x.StudentId == studentId); + + if (studentCourse == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.StudentCourseDoesNotExists, studentId, courseId)); + return result; + } + + return result; + } + + private async Task<ServiceResult<int>> ProfessorValidations(int courseId, int userId) + { + var result = new ServiceResult<int>(); + + var user = await _context.Users + .AsNoTracking() + .Include(x => x.Professor) + .FirstOrDefaultAsync(x => x.Id == userId); + + if (user == null || user.Professor == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.UserDoesNotExist, userId)); + return result; + } + + var course = await _context.Courses + .AsNoTracking() + .FirstOrDefaultAsync(x => x.Id == courseId); + + if (course == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.CourseDoesNotExist, course)); + return result; + } + + var professorCourse = await _context.ProfessorCourses + .AsNoTracking() + .FirstOrDefaultAsync(x => x.CourseId == courseId && x.ProfessorId == user.ProfessorId); + + if (professorCourse == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.ProfessorCourseDoesNotExists, user.ProfessorId, courseId)); + return result; + } + + + + return result; + } + + private async Task<ServiceResult<int>> UserValidation(int userId) + { + var result = new ServiceResult<int>(); + + var user = await _context.Users + .AsNoTracking() + .FirstOrDefaultAsync(x => x.Id == userId); + + if (user == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.UserDoesNotExist, userId)); + return result; + } + + result.Data = (int)user.StudentId; + return result; + } + } +}