manager-service/ManagerService/Controllers/SectionParcoursController.cs
2026-07-08 17:00:43 +02:00

383 lines
16 KiB
C#

using Manager.DTOs;
using ManagerService.Data;
using ManagerService.Data.SubSection;
using ManagerService.DTOs;
using ManagerService.Helpers;
using ManagerService.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NSwag.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ManagerService.Controllers
{
[Authorize(Policy = ManagerService.Service.Security.Policies.ContentEditor)]
[ApiController, Route("api/[controller]")]
[OpenApiTag("Section parcours", Description = "Section parcours management")]
public class SectionParcoursController : ControllerBase
{
private readonly MyInfoMateDbContext _myInfoMateDbContext;
private readonly ILogger<SectionParcoursController> _logger;
private readonly IConfiguration _configuration;
IHexIdGeneratorService idService = new HexIdGeneratorService();
public SectionParcoursController(IConfiguration configuration, ILogger<SectionParcoursController> logger, MyInfoMateDbContext myInfoMateDbContext)
{
_logger = logger;
_configuration = configuration;
_myInfoMateDbContext = myInfoMateDbContext;
}
/// <summary>
/// Get all guided paths from a parcours section
/// </summary>
[AllowAnonymous]
[ProducesResponseType(typeof(List<GuidedPathDTO>), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{sectionParcoursId}/guided-path")]
public ObjectResult GetAllGuidedPathFromSection(string sectionParcoursId)
{
try
{
List<GuidedPath> guidedPaths = _myInfoMateDbContext.GuidedPaths
.Include(gp => gp.ImageResource)
.Include(gp => gp.Steps).ThenInclude(s => s.QuizQuestions).ThenInclude(q => q.PuzzleImage)
.Where(gp => gp.SectionParcoursId == sectionParcoursId)
.OrderBy(gp => gp.Order)
.ToList();
return new OkObjectResult(guidedPaths.Select(gp => gp.ToDTO()));
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create a new guided path in a parcours section
/// </summary>
[ProducesResponseType(typeof(GuidedPathDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("{sectionParcoursId}/guided-path")]
public ObjectResult CreateGuidedPath(string sectionParcoursId, [FromBody] GuidedPathDTO guidedPathDTO)
{
try
{
if (sectionParcoursId == null)
throw new ArgumentNullException("SectionParcoursId param is null");
if (guidedPathDTO == null)
throw new ArgumentNullException("GuidedPath param is null");
var sectionParcours = _myInfoMateDbContext.Sections.OfType<SectionParcours>().FirstOrDefault(sp => sp.Id == sectionParcoursId);
if (sectionParcours == null)
throw new KeyNotFoundException("SectionParcours does not exist");
GuidedPath guidedPath = new GuidedPath().FromDTO(guidedPathDTO);
guidedPath.Id = idService.GenerateHexId();
guidedPath.SectionParcoursId = sectionParcoursId;
guidedPath.Order = _myInfoMateDbContext.GuidedPaths.Count(gp => gp.SectionParcoursId == sectionParcoursId);
guidedPath.Steps = new List<GuidedStep>();
foreach (var stepDTO in guidedPathDTO.steps ?? new List<GuidedStepDTO>())
{
GuidedStep step = new GuidedStep().FromDTO(stepDTO);
step.Id = idService.GenerateHexId();
step.GuidedPathId = guidedPath.Id;
guidedPath.Steps.Add(step);
}
_myInfoMateDbContext.GuidedPaths.Add(guidedPath);
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(guidedPath.ToDTO());
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message);
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Update a guided path
/// </summary>
[ProducesResponseType(typeof(GuidedPathDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut("guided-path")]
public ObjectResult UpdateGuidedPath([FromBody] GuidedPathDTO guidedPathDTO)
{
try
{
if (guidedPathDTO == null)
throw new ArgumentNullException("GuidedPath param is null");
var existingGuidedPath = _myInfoMateDbContext.GuidedPaths
.Include(gp => gp.Steps).ThenInclude(s => s.QuizQuestions)
.FirstOrDefault(gp => gp.Id == guidedPathDTO.id);
if (existingGuidedPath == null)
throw new KeyNotFoundException("GuidedPath does not exist");
existingGuidedPath.InstanceId = guidedPathDTO.instanceId;
existingGuidedPath.Title = guidedPathDTO.title ?? new List<TranslationDTO>();
existingGuidedPath.Description = guidedPathDTO.description ?? new List<TranslationDTO>();
existingGuidedPath.IsLinear = guidedPathDTO.isLinear;
existingGuidedPath.RequireSuccessToAdvance = guidedPathDTO.requireSuccessToAdvance;
existingGuidedPath.HideNextStepsUntilComplete = guidedPathDTO.hideNextStepsUntilComplete;
existingGuidedPath.EstimatedDurationMinutes = guidedPathDTO.estimatedDurationMinutes;
existingGuidedPath.ImageResourceId = guidedPathDTO.imageResourceId;
existingGuidedPath.Order = guidedPathDTO.order.GetValueOrDefault();
existingGuidedPath.IsGameMode = guidedPathDTO.isGameMode;
existingGuidedPath.GameMessageDebut = guidedPathDTO.gameMessageDebut ?? new List<TranslationAndResourceDTO>();
existingGuidedPath.GameMessageFin = guidedPathDTO.gameMessageFin ?? new List<TranslationAndResourceDTO>();
// Sync steps
var dtoStepIds = (guidedPathDTO.steps ?? new List<GuidedStepDTO>())
.Where(s => s.id != null)
.Select(s => s.id)
.ToHashSet();
var stepsToRemove = existingGuidedPath.Steps
.Where(s => !dtoStepIds.Contains(s.Id))
.ToList();
foreach (var s in stepsToRemove)
existingGuidedPath.Steps.Remove(s);
foreach (var stepDTO in guidedPathDTO.steps ?? new List<GuidedStepDTO>())
{
var existing = existingGuidedPath.Steps.FirstOrDefault(s => s.Id == stepDTO.id);
if (existing != null)
{
existing.FromDTO(stepDTO);
existing.GuidedPathId = existingGuidedPath.Id;
}
else
{
var newStep = new GuidedStep().FromDTO(stepDTO);
newStep.Id = idService.GenerateHexId();
newStep.GuidedPathId = existingGuidedPath.Id;
existingGuidedPath.Steps.Add(newStep);
}
}
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(existingGuidedPath.ToDTO());
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message);
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Delete a guided path
/// </summary>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("guided-path/{guidedPathId}")]
public ObjectResult DeleteGuidedPath(string guidedPathId)
{
try
{
var guidedPath = _myInfoMateDbContext.GuidedPaths.Include(gp => gp.Steps).FirstOrDefault(gp => gp.Id == guidedPathId);
if (guidedPath == null)
throw new KeyNotFoundException("GuidedPath does not exist");
_myInfoMateDbContext.RemoveRange(guidedPath.Steps);
_myInfoMateDbContext.Remove(guidedPath);
_myInfoMateDbContext.SaveChanges();
return new ObjectResult("The guidedPath has been deleted") { StatusCode = 202 };
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get all steps from a guided path
/// </summary>
[AllowAnonymous]
[ProducesResponseType(typeof(List<GuidedStepDTO>), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("guided-path/{guidedPathId}/guided-step")]
public ObjectResult GetAllGuidedStepFromGuidedPath(string guidedPathId)
{
try
{
List<GuidedStep> guidedSteps = _myInfoMateDbContext.GuidedSteps
.Include(gs => gs.QuizQuestions)
.Where(gs => gs.GuidedPathId == guidedPathId)
.OrderBy(gs => gs.Order)
.ToList();
return new OkObjectResult(guidedSteps.Select(gs => gs.ToDTO()));
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create a new step in a guided path
/// </summary>
[ProducesResponseType(typeof(GuidedStepDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("guided-path/{guidedPathId}/guided-step")]
public ObjectResult CreateGuidedStep(string guidedPathId, [FromBody] GuidedStepDTO guidedStepDTO)
{
try
{
if (guidedPathId == null)
throw new ArgumentNullException("GuidedPathId param is null");
if (guidedStepDTO == null)
throw new ArgumentNullException("GuidedStep param is null");
var guidedPath = _myInfoMateDbContext.GuidedPaths.FirstOrDefault(gp => gp.Id == guidedPathId);
if (guidedPath == null)
throw new KeyNotFoundException("GuidedPath does not exist");
GuidedStep guidedStep = new GuidedStep().FromDTO(guidedStepDTO);
guidedStep.Id = idService.GenerateHexId();
guidedStep.GuidedPathId = guidedPathId;
guidedStep.Order = _myInfoMateDbContext.GuidedSteps.Count(gs => gs.GuidedPathId == guidedPathId);
_myInfoMateDbContext.GuidedSteps.Add(guidedStep);
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(guidedStep.ToDTO());
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message);
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Update a guided step
/// </summary>
[ProducesResponseType(typeof(GuidedStepDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut("guided-step")]
public ObjectResult UpdateGuidedStep([FromBody] GuidedStepDTO guidedStepDTO)
{
try
{
if (guidedStepDTO == null)
throw new ArgumentNullException("GuidedStep param is null");
var existingGuidedStep = _myInfoMateDbContext.GuidedSteps
.Include(gs => gs.QuizQuestions)
.FirstOrDefault(gs => gs.Id == guidedStepDTO.id);
if (existingGuidedStep == null)
throw new KeyNotFoundException("GuidedStep does not exist");
existingGuidedStep.FromDTO(guidedStepDTO);
_myInfoMateDbContext.SaveChanges();
return new OkObjectResult(existingGuidedStep.ToDTO());
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message);
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Delete a guided step
/// </summary>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("guided-step/{guidedStepId}")]
public ObjectResult DeleteGuidedStep(string guidedStepId)
{
try
{
var guidedStep = _myInfoMateDbContext.GuidedSteps.Include(gs => gs.QuizQuestions).FirstOrDefault(gs => gs.Id == guidedStepId);
if (guidedStep == null)
throw new KeyNotFoundException("GuidedStep does not exist");
guidedStep.QuizQuestions?.Clear();
_myInfoMateDbContext.Remove(guidedStep);
_myInfoMateDbContext.SaveChanges();
return new ObjectResult("The guidedStep has been deleted") { StatusCode = 202 };
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
}
}