Functionnal program logic

features/training-svc
Leo TUAILLON 3 days ago
parent 1f0537d83e
commit b19e762d78

@ -1,10 +1,6 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Shared.DTOs;
using TrainingSvc.Data;
using TrainingSvc.DTOs;
using TrainingSvc.Entities;
using TrainingSvc.IServices;
namespace TrainingSvc.Controllers;
@ -12,105 +8,48 @@ namespace TrainingSvc.Controllers;
[Route("api/training/[controller]")]
public class SessionsController : ControllerBase
{
private readonly TrainingDbContext _context;
private readonly IMapper _mapper;
private readonly ISessionService _sessionService;
public SessionsController(TrainingDbContext context, IMapper mapper)
public SessionsController(ISessionService sessionService)
{
_context = context;
_mapper = mapper;
_sessionService = sessionService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<SessionDto>>> GetAll()
{
var list = await _context.Sessions
.Include(s => s.Exercices)
.ThenInclude(e => e.ExerciceTemplate)
.ToListAsync();
return Ok(_mapper.Map<IEnumerable<SessionDto>>(list));
var list = await _sessionService.GetAllAsync();
return Ok(list);
}
[HttpGet("{id}")]
public async Task<ActionResult<SessionDto>> GetById(string id)
{
var entity = await _context.Sessions
.Include(s => s.Exercices)
.ThenInclude(e => e.ExerciceTemplate)
.FirstOrDefaultAsync(s => s.Id == id);
if (entity == null) return NotFound();
return _mapper.Map<SessionDto>(entity);
var dto = await _sessionService.GetByIdAsync(id);
if (dto == null) return NotFound();
return Ok(dto);
}
[HttpPost]
public async Task<ActionResult<SessionDto>> Create([FromBody] CreateSessionDto dto)
{
var session = _mapper.Map<Session>(dto);
_context.Sessions.Add(session);
await _context.SaveChangesAsync();
// Crée les ExerciceInstance associées
foreach (var exoDto in dto.Exercices)
{
var exo = _mapper.Map<ExerciceInstance>(exoDto);
exo.SessionId = session.Id;
_context.ExerciceInstances.Add(exo);
}
await _context.SaveChangesAsync();
// Recharge la session avec les exercices et templates
var entity = await _context.Sessions
.Include(s => s.Exercices)
.ThenInclude(e => e.ExerciceTemplate)
.FirstOrDefaultAsync(s => s.Id == session.Id);
return CreatedAtAction(nameof(GetById), new { id = session.Id }, _mapper.Map<SessionDto>(entity));
var created = await _sessionService.CreateAsync(dto);
return CreatedAtAction(nameof(GetById), new { id = created.Id }, created);
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(string id, [FromBody] UpdateSessionDto dto)
{
var session = await _context.Sessions
.Include(s => s.Exercices)
.FirstOrDefaultAsync(s => s.Id == id);
if (session == null) return NotFound();
// Ne pas mapper TrainingProgramId pour éviter de casser la FK
session.Name = dto.Name;
session.Description = dto.Description;
session.Day = dto.Day;
session.Target = dto.Target;
// session.TrainingProgramId = dto.TrainingProgramId; // NE PAS TOUCHER
// Supprime tous les exercices existants et sauvegarde
_context.ExerciceInstances.RemoveRange(session.Exercices);
await _context.SaveChangesAsync();
// Ajoute les nouveaux exercices
foreach (var exoDto in dto.Exercices)
{
var exo = _mapper.Map<ExerciceInstance>(exoDto);
exo.SessionId = session.Id;
_context.ExerciceInstances.Add(exo);
}
await _context.SaveChangesAsync();
var success = await _sessionService.UpdateAsync(id, dto);
if (!success) return NotFound();
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(string id)
{
var session = await _context.Sessions
.Include(s => s.Exercices)
.FirstOrDefaultAsync(s => s.Id == id);
if (session == null) return NotFound();
_context.ExerciceInstances.RemoveRange(session.Exercices);
_context.Sessions.Remove(session);
await _context.SaveChangesAsync();
var success = await _sessionService.DeleteAsync(id);
if (!success) return NotFound();
return NoContent();
}
}

@ -0,0 +1,32 @@
using Microsoft.AspNetCore.Mvc;
using TrainingSvc.DTOs;
using TrainingSvc.IServices;
namespace TrainingSvc.Controllers;
[ApiController]
[Route("api/training/[controller]")]
public class TrainingProgramsController : ControllerBase
{
private readonly ITrainingProgramService _service;
public TrainingProgramsController(ITrainingProgramService service)
{
_service = service;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<TrainingProgramDto>>> GetAll()
{
var list = await _service.GetAllAsync();
return Ok(list);
}
[HttpGet("{id}")]
public async Task<ActionResult<TrainingProgramDto>> GetById(string id)
{
var dto = await _service.GetByIdAsync(id);
if (dto == null) return NotFound();
return Ok(dto);
}
}

@ -0,0 +1,17 @@
using Shared.Enum;
namespace TrainingSvc.DTOs;
public class TrainingProgramDto
{
public string Id { get; set; }
public string Lang { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public int WeekDuration { get; set; }
public int NbDays { get; set; }
public string OwnerId { get; set; }
public EGoal Goal { get; set; }
public EDifficulty Difficulty { get; set; }
public List<SessionDto> Sessions { get; set; } = new();
}

@ -9,5 +9,4 @@ public class UpdateSessionDto
public int Day { get; set; }
public ETarget? Target { get; set; }
public string TrainingProgramId { get; set; }
public List<UpdateExerciceInstanceDto> Exercices { get; set; } = new();
}

@ -0,0 +1,12 @@
using TrainingSvc.DTOs;
namespace TrainingSvc.IServices;
public interface ISessionService
{
Task<IEnumerable<SessionDto>> GetAllAsync();
Task<SessionDto?> GetByIdAsync(string id);
Task<SessionDto> CreateAsync(CreateSessionDto dto);
Task<bool> UpdateAsync(string id, UpdateSessionDto dto);
Task<bool> DeleteAsync(string id);
}

@ -0,0 +1,9 @@
using TrainingSvc.DTOs;
namespace TrainingSvc.IServices;
public interface ITrainingProgramService
{
Task<IEnumerable<TrainingProgramDto>> GetAllAsync();
Task<TrainingProgramDto?> GetByIdAsync(string id);
}

@ -11,7 +11,9 @@ builder.Services.AddScoped<IExerciceTemplateRepository, ExerciceTemplateReposito
builder.Services.AddScoped<IExerciceInstanceRepository, ExerciceInstanceRepository>();
builder.Services.AddScoped<IExerciceService, ExerciceService>();
builder.Services.AddScoped<ISessionRepository, SessionRepository>();
builder.Services.AddScoped<ISessionService, SessionService>();
builder.Services.AddScoped<ITrainingProgramRepository, TrainingProgramRepository>();
builder.Services.AddScoped<ITrainingProgramService, TrainingProgramService>();
// Add services to the container.
builder.Services.AddControllers()

@ -5,4 +5,6 @@ namespace TrainingSvc.Repositories;
public interface ITrainingProgramRepository : IRepository<TrainingProgram>
{
Task<IEnumerable<TrainingProgram>> GetAllWithSessionsAsync();
Task<TrainingProgram?> GetByIdWithSessionsAsync(string id);
}

@ -1,3 +1,4 @@
using Microsoft.EntityFrameworkCore;
using TrainingSvc.Data;
using TrainingSvc.Entities;
@ -8,4 +9,20 @@ public class SessionRepository : GenericRepository<Session>, ISessionRepository
public SessionRepository(TrainingDbContext context) : base(context)
{
}
public async Task<IEnumerable<Session>> GetAllWithExercicesAndTemplatesAsync()
{
return await context.Sessions
.Include(s => s.Exercices)
.ThenInclude(e => e.ExerciceTemplate)
.ToListAsync();
}
public async Task<Session?> GetByIdWithExercicesAndTemplatesAsync(string id)
{
return await context.Sessions
.Include(s => s.Exercices)
.ThenInclude(e => e.ExerciceTemplate)
.FirstOrDefaultAsync(s => s.Id == id);
}
}

@ -1,3 +1,4 @@
using Microsoft.EntityFrameworkCore;
using TrainingSvc.Data;
using TrainingSvc.Entities;
@ -8,4 +9,22 @@ public class TrainingProgramRepository : GenericRepository<TrainingProgram>, ITr
public TrainingProgramRepository(TrainingDbContext context) : base(context)
{
}
public async Task<IEnumerable<TrainingProgram>> GetAllWithSessionsAsync()
{
return await context.TrainingPrograms
.Include(tp => tp.Sessions)
.ThenInclude(s => s.Exercices)
.ThenInclude(e => e.ExerciceTemplate)
.ToListAsync();
}
public async Task<TrainingProgram?> GetByIdWithSessionsAsync(string id)
{
return await context.TrainingPrograms
.Include(tp => tp.Sessions)
.ThenInclude(s => s.Exercices)
.ThenInclude(e => e.ExerciceTemplate)
.FirstOrDefaultAsync(tp => tp.Id == id);
}
}

@ -11,7 +11,8 @@ public class SessionProfile : Profile
CreateMap<Session, SessionDto>()
.ForMember(dest => dest.Exercices, opt
=> opt.MapFrom(src => src.Exercices));
CreateMap<CreateSessionDto, Session>();
CreateMap<CreateSessionDto, Session>()
.ForMember(dest => dest.Exercices, opt => opt.Ignore()); // Ignore Exercices to handle them separately
CreateMap<UpdateSessionDto, Session>();
}
}

@ -0,0 +1,13 @@
using AutoMapper;
using TrainingSvc.DTOs;
using TrainingSvc.Entities;
namespace TrainingSvc.RequestHelpers;
public class TrainingProgramProfile : Profile
{
public TrainingProgramProfile()
{
CreateMap<TrainingProgram, TrainingProgramDto>();
}
}

@ -0,0 +1,95 @@
using AutoMapper;
using TrainingSvc.DTOs;
using TrainingSvc.Entities;
using TrainingSvc.Repositories;
using TrainingSvc.IServices;
namespace TrainingSvc.Services;
public class SessionService : ISessionService
{
private readonly ISessionRepository _sessionRepo;
private readonly IExerciceInstanceRepository _exerciceRepo;
private readonly IExerciceTemplateRepository _exerciceTemplateRepo;
private readonly IMapper _mapper;
public SessionService(
ISessionRepository sessionRepo,
IExerciceInstanceRepository exerciceRepo,
IExerciceTemplateRepository exerciceTemplateRepo,
IMapper mapper)
{
_sessionRepo = sessionRepo;
_exerciceRepo = exerciceRepo;
_exerciceTemplateRepo = exerciceTemplateRepo;
_mapper = mapper;
}
public async Task<IEnumerable<SessionDto>> GetAllAsync()
{
var sessions = await ((SessionRepository)_sessionRepo).GetAllWithExercicesAndTemplatesAsync();
return _mapper.Map<IEnumerable<SessionDto>>(sessions);
}
public async Task<SessionDto?> GetByIdAsync(string id)
{
var entity = await ((SessionRepository)_sessionRepo).GetByIdWithExercicesAndTemplatesAsync(id);
return entity == null ? null : _mapper.Map<SessionDto>(entity);
}
public async Task<SessionDto> CreateAsync(CreateSessionDto dto)
{
// Ne mappe pas les exercices ici
var session = _mapper.Map<Session>(dto);
session.Exercices.Clear(); // S'assure qu'il n'y a pas d'exercices liés
await _sessionRepo.InsertAsync(session);
await _sessionRepo.SaveChangesAsync();
foreach (var exoDto in dto.Exercices)
{
if (!string.IsNullOrEmpty(exoDto.ExerciceTemplateId))
{
var exists = await _exerciceTemplateRepo.ExistsAsync(t => t.Id == exoDto.ExerciceTemplateId);
if (!exists)
throw new ArgumentException("ExerciceTemplateId invalide.");
}
var exo = _mapper.Map<ExerciceInstance>(exoDto);
exo.SessionId = session.Id;
await _exerciceRepo.InsertAsync(exo);
}
await _exerciceRepo.SaveChangesAsync();
var entity = await ((SessionRepository)_sessionRepo).GetByIdWithExercicesAndTemplatesAsync(session.Id);
return _mapper.Map<SessionDto>(entity);
}
public async Task<bool> UpdateAsync(string id, UpdateSessionDto dto)
{
var session = await ((SessionRepository)_sessionRepo).GetByIdWithExercicesAndTemplatesAsync(id);
if (session == null) return false;
_mapper.Map(dto, session);
_sessionRepo.Update(session);
await _sessionRepo.SaveChangesAsync();
return true;
}
public async Task<bool> DeleteAsync(string id)
{
var session = await _sessionRepo.GetByIdAsync(id, s => s.Exercices);
if (session == null) return false;
foreach (var ex in session.Exercices.ToList())
{
_exerciceRepo.Delete(ex.Id);
}
await _exerciceRepo.SaveChangesAsync();
_sessionRepo.Delete(id);
await _sessionRepo.SaveChangesAsync();
return true;
}
}

@ -0,0 +1,30 @@
using AutoMapper;
using TrainingSvc.DTOs;
using TrainingSvc.IServices;
using TrainingSvc.Repositories;
namespace TrainingSvc.Services;
public class TrainingProgramService : ITrainingProgramService
{
private readonly ITrainingProgramRepository _repo;
private readonly IMapper _mapper;
public TrainingProgramService(ITrainingProgramRepository repo, IMapper mapper)
{
_repo = repo;
_mapper = mapper;
}
public async Task<IEnumerable<TrainingProgramDto>> GetAllAsync()
{
var list = await _repo.GetAllWithSessionsAsync();
return _mapper.Map<IEnumerable<TrainingProgramDto>>(list);
}
public async Task<TrainingProgramDto?> GetByIdAsync(string id)
{
var entity = await _repo.GetByIdWithSessionsAsync(id);
return entity == null ? null : _mapper.Map<TrainingProgramDto>(entity);
}
}
Loading…
Cancel
Save