using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using AutoMapper; using AutoMapper.QueryableExtensions; using InternshipSystem.Api.Queries; using InternshipSystem.Api.Queries.SearchQuery; using InternshipSystem.Api.Result; using InternshipSystem.Api.Security; using InternshipSystem.Core; using InternshipSystem.Repository; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace InternshipSystem.Api.Controllers { [ApiController] [Route("editionManagement")] public class EditionManagementController : ControllerBase { private InternshipDbContext Context { get; } private IMapper Mapper { get; } public EditionManagementController(IMapper mapper, InternshipDbContext context) { Context = context; Mapper = mapper; } [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [Authorize(Policy = Policies.IsOverseer)] public async Task>> GetEditions([FromQuery] EditionSearchQuery searchQuery, CancellationToken token) => await Context.Editions .Include(e => e.Course) .ProjectTo(Mapper.ConfigurationProvider) .Skip(searchQuery.Page * searchQuery.PerPage) .Take(searchQuery.PerPage) .ToListAsync(token); [HttpGet("{editionId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Policy = Policies.IsOverseer)] public async Task> GetFullEdition(Guid editionId, CancellationToken token) { var edition = await Context.Editions .Include(e => e.Course) .Include(e => e.AvailableSubjects) .ThenInclude(s => s.Subject) .Include(e => e.AvailableInternshipTypes) .ThenInclude(i => i.InternshipType) .Where(e => e.Id == editionId) .ProjectTo(Mapper.ConfigurationProvider) .FirstOrDefaultAsync(token); if (edition == null) { return NotFound(); } return Ok(edition); } [HttpPut] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Policy = Policies.IsOverseer)] public async Task UpsertEdition(EditionForm editionForm, CancellationToken token) { var validator = new EditionForm.Validator(); var validationResult = await validator.ValidateAsync(editionForm, token); if (!validationResult.IsValid) { return BadRequest(validationResult.ToString()); } //TODO: resolve courses (one for each edition or dictionary) editionForm.Course.Id = 0; if (editionForm.Id.HasValue) { var editionToUpdate = await Context.Editions .Include(e => e.AvailableSubjects) .Include(e => e.AvailableInternshipTypes) .FirstOrDefaultAsync(e => e.Id == editionForm.Id.Value, token); if (editionToUpdate == null) { return NotFound(); } editionToUpdate.UpdateEdition(editionForm.EditionStart, editionForm.EditionFinish, editionForm.ReportingStart, editionForm.Course, editionForm.AvailableSubjectsIds, editionForm.AvailableInternshipTypesIds); if (!editionToUpdate.IsValidDates) { return BadRequest(); } } else { var newEdition = Edition.CreateEdition(editionForm.EditionStart.Value, editionForm.EditionFinish.Value, editionForm.ReportingStart.Value, editionForm.Course, editionForm.AvailableSubjectsIds, editionForm.AvailableInternshipTypesIds); if (!newEdition.IsValidDates) { return BadRequest(); } await Context.Editions.AddAsync(newEdition, token); } await Context.SaveChangesAsync(token); return Ok(); } [HttpDelete("{editionId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status409Conflict)] [Authorize(Policy = Policies.IsOverseer)] public async Task DeleteEdition(Guid editionId, CancellationToken token) { var editionToDelete = await Context.Editions .Include(e => e.AvailableSubjects) .Include(e => e.AvailableInternshipTypes) .FirstOrDefaultAsync(e => e.Id.Equals(editionId), token); if (editionToDelete == null) { return NotFound(); } var referencedInternships = await Context .Entry(editionToDelete) .Collection(e => e.Internships) .Query() .CountAsync(token); if (referencedInternships > 0) { return Conflict(); } Context.Editions.Attach(editionToDelete); Context.Editions.Remove(editionToDelete); await Context.SaveChangesAsync(token); return Ok(); } } }